From 37be34d8099289ca224afb4dacd065149b58bb0b Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Tue, 2 Apr 2019 19:00:10 -0400 Subject: [PATCH 01/12] mac, libtest: cleanup & dedup detection code --- gyp/MSVS/MSVSSettings.py | 96 ++- gyp/XCodeDetect.py | 120 +-- gyp/xcode_emulation.py | 740 +++++++------------ pylib/__init__.py | 0 pylib/util.py | 21 + test/ios/gyptest-app-ios-assets-catalog.py | 2 +- test/ios/gyptest-app-ios.py | 2 +- test/ios/gyptest-archs.py | 6 +- test/ios/gyptest-deployment-target.py | 2 +- test/ios/gyptest-extension.py | 2 +- test/ios/gyptest-framework.py | 2 +- test/ios/gyptest-per-config-settings.py | 2 +- test/ios/gyptest-watch.py | 2 +- test/mac/gyptest-app-assets-catalog.py | 2 +- test/mac/gyptest-app.py | 2 +- test/mac/gyptest-archs.py | 2 +- test/mac/gyptest-clang-cxx-library.py | 2 +- test/mac/gyptest-objc-gc.py | 2 +- test/mac/gyptest-postbuild-fail.py | 2 +- test/mac/gyptest-strip.py | 2 +- test/mac/gyptest-swift-library.py | 2 +- test/mac/gyptest-xcode-env-order.py | 2 +- test/win/compiler-flags/optimizations.gyp | 24 +- test/win/gyptest-msbuild-cl-optimizations.py | 89 +++ 24 files changed, 531 insertions(+), 597 deletions(-) create mode 100644 pylib/__init__.py create mode 100644 pylib/util.py create mode 100644 test/win/gyptest-msbuild-cl-optimizations.py diff --git a/gyp/MSVS/MSVSSettings.py b/gyp/MSVS/MSVSSettings.py index db61bb08..41b0360d 100644 --- a/gyp/MSVS/MSVSSettings.py +++ b/gyp/MSVS/MSVSSettings.py @@ -196,10 +196,11 @@ class _Enumeration(_Type): def __init__(self, label_list, new=None): _Type.__init__(self) self._label_list = label_list - self._msbuild_values = set(value for value in label_list - if value is not None) + self._label_list_new = label_list + self._msbuild_values = set(value for value in label_list if value is not None) if new is not None: self._msbuild_values.update(new) + self._label_list_new += new def ValidateMSVS(self, value): # Try to convert. It will raise an exception if not valid. @@ -211,10 +212,10 @@ def ValidateMSBuild(self, value): def ConvertToMSBuild(self, value): index = int(value) - if index < 0 or index >= len(self._label_list): - raise ValueError('index value (%d) not in expected range [0, %d)' % - (index, len(self._label_list))) - label = self._label_list[index] + # Conversion is done by the new list (including new values) + if index < 0 or index >= len(self._label_list_new): + raise ValueError('index value (%d) not in expected range [0, %d)' % (index, len(self._label_list_new))) + label = self._label_list_new[index] if label is None: raise ValueError('converted value for %s not specified.' % value) return label @@ -460,27 +461,21 @@ def ConvertToMSBuildSettings(msvs_settings, stderr=sys.stderr): """ msbuild_settings = {} for msvs_tool_name, msvs_tool_settings in msvs_settings.items(): - if msvs_tool_name in _msvs_to_msbuild_converters: - msvs_tool = _msvs_to_msbuild_converters[msvs_tool_name] - for msvs_setting, msvs_value in msvs_tool_settings.items(): - if msvs_setting in msvs_tool: - # Invoke the translation function. - try: - msvs_tool[msvs_setting](msvs_value, msbuild_settings) - except ValueError as e: - print(('Warning: while converting %s/%s to MSBuild, ' - '%s' % (msvs_tool_name, msvs_setting, e)), - file=stderr) - else: - _ValidateExclusionSetting(msvs_setting, - msvs_tool, - ('Warning: unrecognized setting %s/%s ' - 'while converting to MSBuild.' % - (msvs_tool_name, msvs_setting)), - stderr) - else: - print(('Warning: unrecognized tool %s while converting to ' - 'MSBuild.' % msvs_tool_name), file=stderr) + msvs_tool = _msvs_to_msbuild_converters.get(msvs_tool_name) + if msvs_tool is None: + print('Warning: unrecognized tool %s while converting to MSBuild.' % msvs_tool_name, file=stderr) + continue + for msvs_setting, msvs_value in msvs_tool_settings.items(): + setting_converter = msvs_tool.get(msvs_setting) + if setting_converter is None: + exclusion_message = 'Warning: unrecognized setting %s/%s while converting to MSBuild.' % (msvs_tool_name, msvs_setting) + _ValidateExclusionSetting(msvs_setting, msvs_tool, exclusion_message, stderr) + continue + # Invoke the translation function. + try: + setting_converter(msvs_value, msbuild_settings) + except ValueError as e: + print('Warning: while converting %s/%s to MSBuild, %s' % (msvs_tool_name, msvs_setting, e), file=stderr) return msbuild_settings @@ -507,35 +502,31 @@ def ValidateMSBuildSettings(settings, stderr=sys.stderr): def _ValidateSettings(validators, settings, stderr): - """Validates that the settings are valid for MSBuild or MSVS. + """ + Validates that the settings are valid for MSBuild or MSVS. We currently only validate the names of the settings, not their values. Args: validators: A dictionary of tools and their validators. - settings: A dictionary. The key is the tool name. The values are - themselves dictionaries of settings and their values. + settings: A dictionary. The key is the tool name, values are dictionaries of settings and their values. stderr: The stream receiving the error messages. """ for tool_name in settings: - if tool_name in validators: - tool_validators = validators[tool_name] - for setting, value in settings[tool_name].items(): - if setting in tool_validators: - try: - tool_validators[setting](value) - except ValueError as e: - print(('Warning: for %s/%s, %s' % - (tool_name, setting, e)), file=stderr) - else: - _ValidateExclusionSetting(setting, - tool_validators, - ('Warning: unrecognized setting %s/%s' % - (tool_name, setting)), - stderr) - - else: - print(('Warning: unrecognized tool %s' % tool_name), file=stderr) + tool_validators = validators.get(tool_name) + if tool_validators is None: + print('Warning: unrecognized tool %s' % tool_name, file=stderr) + continue + for setting, value in settings[tool_name].items(): + validator = tool_validators.get(setting) + if validator is None: + exclusion_message = 'Warning: unrecognized setting %s/%s' % (tool_name, setting) + _ValidateExclusionSetting(setting, tool_validators, exclusion_message, stderr) + continue + try: + validator(value) + except ValueError as e: + print('Warning: for %s/%s, %s' % (tool_name, setting, e), file=stderr) # MSVS and MBuild names of the tools. @@ -879,14 +870,13 @@ def _ValidateSettings(validators, settings, stderr): 'PromptImmediately', # /ERRORREPORT:PROMPT 'QueueForNextLogin'], # /ERRORREPORT:QUEUE new=['SendErrorReport'])) # /ERRORREPORT:SEND -_Renamed(_link, 'IgnoreDefaultLibraryNames', 'IgnoreSpecificDefaultLibraries', - _file_list) # /NODEFAULTLIB +_Renamed(_link, 'IgnoreDefaultLibraryNames', 'IgnoreSpecificDefaultLibraries', _file_list) # /NODEFAULTLIB _Renamed(_link, 'ResourceOnlyDLL', 'NoEntryPoint', _boolean) # /NOENTRY _Renamed(_link, 'SwapRunFromNet', 'SwapRunFromNET', _boolean) # /SWAPRUN:NET -_Moved(_link, 'GenerateManifest', '', _boolean) -_Moved(_link, 'IgnoreImportLibrary', '', _boolean) -_Moved(_link, 'LinkIncremental', '', _newly_boolean) +_Moved(_link, 'GenerateManifest', 'GenerateManifest', _boolean) +_Moved(_link, 'IgnoreImportLibrary', 'IgnoreImportLibrary', _boolean) +_Moved(_link, 'LinkIncremental', 'LinkIncremental', _newly_boolean) _Moved(_link, 'LinkLibraryDependencies', 'ProjectReference', _boolean) _Moved(_link, 'UseLibraryDependencyInputs', 'ProjectReference', _boolean) diff --git a/gyp/XCodeDetect.py b/gyp/XCodeDetect.py index cc7b8fac..a8a23461 100644 --- a/gyp/XCodeDetect.py +++ b/gyp/XCodeDetect.py @@ -1,65 +1,79 @@ +"""Simplify access to Xcode information.""" import subprocess -import sys +from common import memoize def run(*cmd_args): - return subprocess.check_output(cmd_args, stderr=subprocess.PIPE).decode('utf-8') + return subprocess.check_output(cmd_args, stderr=subprocess.PIPE).decode('utf-8').strip() -class XCodeDetect(object): - """Simplify access to Xcode information.""" - _cache = {} +@memoize +def Version(): + version = '' + try: + lines = run('xcodebuild', '-version').splitlines() + version = ''.join(lines[0].split()[-1].split('.')) + version = (version + '0' * (3 - len(version))).zfill(4) + except subprocess.CalledProcessError: + pass + try: + lines = run('pkgutil', '--pkg-info=com.apple.pkg.CLTools_Executables').splitlines() + for l in lines: + n, v = l.split(': ', 1) + if n != 'version': + continue + parts = v.split('.', 4) + version = '%s%s%s%s' % tuple(parts[0:4]) + break + except subprocess.CalledProcessError: + pass + return version - @staticmethod - def Version(): - if 'Version' not in XCodeDetect._cache: - version = '' - try: - lines = run('xcodebuild', '-version').splitlines() - version = ''.join(lines[0].decode('utf-8').split()[-1].split('.')) - version = (version + '0' * (3 - len(version))).zfill(4) - except subprocess.CalledProcessError: - pass - try: - lines = run('pkgutil', '--pkg-info=com.apple.pkg.CLTools_Executables').splitlines() - for l in lines: - n, v = l.split(': ', 1) - if n != 'version': - continue - parts = v.split('.',4) - version = '%s%s%s%s' % tuple(parts[0:4]) - break - except subprocess.CalledProcessError: - pass - XCodeDetect._cache['Version'] = version - return XCodeDetect._cache['Version'] +@memoize +def GetSdkVersionInfoItem(sdk, item): + # xcodebuild requires Xcode and can't run on Command Line Tools-only systems from 10.7 onward. + # Since the CLT has no SDK paths anyway, returning None is the most sensible route and should still do the right thing. + try: + return run('xcrun', '--sdk', sdk, item) + except subprocess.CalledProcessError: + return None - @staticmethod - def SDKVersion(): - if 'SDKVersion' not in XCodeDetect._cache: - out = '' - try: - out = run('xcrun', '--show-sdk-version') - except subprocess.CalledProcessError: - pass - try: - out = run('xcodebuild', '-version', '-sdk', '', 'SDKVersion') - except subprocess.CalledProcessError: - pass - XCodeDetect._cache['SDKVersion'] = out.strip() - return XCodeDetect._cache['SDKVersion'] +@memoize +def SDKVersion(): + try: + out = run('xcrun', '--show-sdk-version') + except subprocess.CalledProcessError: + try: + out = run('xcodebuild', '-version', '-sdk', '', 'SDKVersion') + except subprocess.CalledProcessError: + return None + version = out.strip() + return version - @staticmethod - def HasIPhoneSDK(): - if not sys.platform == 'darwin': - return False - if 'HasIPhoneSDK' not in XCodeDetect._cache: - try: - out = run('xcrun', '--sdk', 'iphoneos', '--show-sdk-path') - except subprocess.CalledProcessError: - out = 1 - XCodeDetect._cache['HasIPhoneSDK'] = out == 0 - return XCodeDetect._cache['HasIPhoneSDK'] +@memoize +def IPhoneSDKPath(): + try: + path = GetSdkVersionInfoItem('iphoneos', '--show-sdk-path') + except subprocess.CalledProcessError: + return None + return path + + +@memoize +def GetIOSCodeSignIdentityKey(identity): + if not identity: + return None + output = run('security', 'find-identity', '-p', 'codesigning', '-v') + output_lines = output.splitlines() + match_lines = [line for line in output_lines if identity in line] + assert len(match_lines) == 1, ("Not exactly one codesigning fingerprints for identity: %s \n%s" % (identity, output)) + fingerprint = match_lines[0].split()[1] + return fingerprint + + +@memoize +def BuildMachineOSBuild(): + return run('sw_vers', '-buildVersion') diff --git a/gyp/xcode_emulation.py b/gyp/xcode_emulation.py index d284c396..7d96a5e7 100644 --- a/gyp/xcode_emulation.py +++ b/gyp/xcode_emulation.py @@ -10,90 +10,16 @@ from __future__ import print_function import copy -import gyp.common import os import os.path import re import shlex -import subprocess -import sys -from gyp.common import GypError - -# Populated lazily by XcodeVersion, for efficiency, and to fix an issue when -# "xcodebuild" is called too quickly (it has been found to return incorrect -# version number). -XCODE_VERSION_CACHE = None - -# Populated lazily by GetXcodeArchsDefault, to an |XcodeArchsDefault| instance -# corresponding to the installed version of Xcode. -XCODE_ARCHS_DEFAULT_CACHE = None - - -def XcodeArchsVariableMapping(archs, archs_including_64_bit=None): - """Constructs a dictionary with expansion for $(ARCHS_STANDARD) variable, - and optionally for $(ARCHS_STANDARD_INCLUDING_64_BIT).""" - mapping = {'$(ARCHS_STANDARD)': archs} - if archs_including_64_bit: - mapping['$(ARCHS_STANDARD_INCLUDING_64_BIT)'] = archs_including_64_bit - return mapping - -class XcodeArchsDefault(object): - """A class to resolve ARCHS variable from xcode_settings, resolving Xcode - macros and implementing filtering by VALID_ARCHS. The expansion of macros - depends on the SDKROOT used ("macosx", "iphoneos", "iphonesimulator") and - on the version of Xcode. - """ - - # Match variable like $(ARCHS_STANDARD). - variable_pattern = re.compile(r'\$\([a-zA-Z_][a-zA-Z0-9_]*\)$') - - def __init__(self, default, mac, iphonesimulator, iphoneos): - self._default = (default,) - self._archs = {'mac': mac, 'ios': iphoneos, 'iossim': iphonesimulator} - def _VariableMapping(self, sdkroot): - """Returns the dictionary of variable mapping depending on the SDKROOT.""" - sdkroot = sdkroot.lower() - if 'iphoneos' in sdkroot: - return self._archs['ios'] - elif 'iphonesimulator' in sdkroot: - return self._archs['iossim'] - else: - return self._archs['mac'] - - def _ExpandArchs(self, archs, sdkroot): - """Expands variables references in ARCHS, and remove duplicates.""" - variable_mapping = self._VariableMapping(sdkroot) - expanded_archs = [] - for arch in archs: - if self.variable_pattern.match(arch): - variable = arch - try: - variable_expansion = variable_mapping[variable] - for arch in variable_expansion: - if arch not in expanded_archs: - expanded_archs.append(arch) - except KeyError as e: - print('Warning: Ignoring unsupported variable "%s".' % variable) - print(e) - elif arch not in expanded_archs: - expanded_archs.append(arch) - return expanded_archs - - def ActiveArchs(self, archs, valid_archs, sdkroot): - """Expands variables references in ARCHS, and filter by VALID_ARCHS if it - is defined (if not set, Xcode accept any value in ARCHS, otherwise, only - values present in VALID_ARCHS are kept).""" - expanded_archs = self._ExpandArchs(archs or self._default, sdkroot or '') - if valid_archs: - filtered_archs = [] - for arch in expanded_archs: - if arch in valid_archs: - filtered_archs.append(arch) - expanded_archs = filtered_archs - return expanded_archs +from gyp.common import GypError, TopologicallySorted, EncodePOSIXShellList, CycleError, memoize +import XCodeDetect +@memoize def GetXcodeArchsDefault(): """Returns the |XcodeArchsDefault| object to use to expand ARCHS for the installed version of Xcode. The default values used by Xcode for ARCHS @@ -114,35 +40,137 @@ def GetXcodeArchsDefault(): All thoses rules are coded in the construction of the |XcodeArchsDefault| object to use depending on the version of Xcode detected. The object is for performance reason.""" - global XCODE_ARCHS_DEFAULT_CACHE - if XCODE_ARCHS_DEFAULT_CACHE: - return XCODE_ARCHS_DEFAULT_CACHE - xcode_version, _ = XcodeVersion() + + class XcodeArchsDefault(object): + """A class to resolve ARCHS variable from xcode_settings, resolving Xcode + macros and implementing filtering by VALID_ARCHS. The expansion of macros + depends on the SDKROOT used ("macosx", "iphoneos", "iphonesimulator") and + on the version of Xcode. + """ + + # Match variable like $(ARCHS_STANDARD). + variable_pattern = re.compile(r'\$\([a-zA-Z_][a-zA-Z0-9_]*\)$') + + def __init__(self, default, mac, iphonesimulator, iphoneos): + self._default = (default,) + self._archs = {'mac': mac, 'ios': iphoneos, 'iossim': iphonesimulator} + + def _VariableMapping(self, sdkroot): + """Returns the dictionary of variable mapping depending on the SDKROOT.""" + sdkroot = sdkroot.lower() + if 'iphoneos' in sdkroot: + return self._archs['ios'] + elif 'iphonesimulator' in sdkroot: + return self._archs['iossim'] + else: + return self._archs['mac'] + + def _ExpandArchs(self, archs, sdkroot): + """Expands variables references in ARCHS, and remove duplicates.""" + variable_mapping = self._VariableMapping(sdkroot) + expanded_archs = [] + for arch in archs: + if self.variable_pattern.match(arch): + variable = arch + try: + variable_expansion = variable_mapping[variable] + for arch2 in variable_expansion: + if arch2 not in expanded_archs: + expanded_archs.append(arch2) + except KeyError as e: + print('Warning: Ignoring unsupported variable "%s".' % variable) + print(e) + elif arch not in expanded_archs: + expanded_archs.append(arch) + return expanded_archs + + def ActiveArchs(self, archs, valid_archs, sdkroot): + """Expands variables references in ARCHS, and filter by VALID_ARCHS if it + is defined (if not set, Xcode accept any value in ARCHS, otherwise, only + values present in VALID_ARCHS are kept).""" + expanded_archs = self._ExpandArchs(archs or self._default, sdkroot or '') + if valid_archs: + filtered_archs = [] + for arch in expanded_archs: + if arch in valid_archs: + filtered_archs.append(arch) + expanded_archs = filtered_archs + return expanded_archs + + def XcodeArchsVariableMapping(archs, archs_including_64_bit=None): + """Constructs a dictionary with expansion for $(ARCHS_STANDARD) variable, + and optionally for $(ARCHS_STANDARD_INCLUDING_64_BIT).""" + mapping = {'$(ARCHS_STANDARD)': archs} + if archs_including_64_bit: + mapping['$(ARCHS_STANDARD_INCLUDING_64_BIT)'] = archs_including_64_bit + return mapping + + xcode_version = XCodeDetect.Version() if xcode_version < '0500': XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault( - '$(ARCHS_STANDARD)', - XcodeArchsVariableMapping(['i386']), - XcodeArchsVariableMapping(['i386']), - XcodeArchsVariableMapping(['armv7'])) + '$(ARCHS_STANDARD)', + XcodeArchsVariableMapping(['i386']), + XcodeArchsVariableMapping(['i386']), + XcodeArchsVariableMapping(['armv7']) + ) elif xcode_version < '0510': XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault( - '$(ARCHS_STANDARD_INCLUDING_64_BIT)', - XcodeArchsVariableMapping(['x86_64'], ['x86_64']), - XcodeArchsVariableMapping(['i386'], ['i386', 'x86_64']), - XcodeArchsVariableMapping( - ['armv7', 'armv7s'], - ['armv7', 'armv7s', 'arm64'])) + '$(ARCHS_STANDARD_INCLUDING_64_BIT)', + XcodeArchsVariableMapping(['x86_64'], ['x86_64']), + XcodeArchsVariableMapping(['i386'], ['i386', 'x86_64']), + XcodeArchsVariableMapping(['armv7', 'armv7s'], ['armv7', 'armv7s', 'arm64']) + ) else: XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault( - '$(ARCHS_STANDARD)', - XcodeArchsVariableMapping(['x86_64'], ['x86_64']), - XcodeArchsVariableMapping(['i386', 'x86_64'], ['i386', 'x86_64']), - XcodeArchsVariableMapping( - ['armv7', 'armv7s', 'arm64'], - ['armv7', 'armv7s', 'arm64'])) + '$(ARCHS_STANDARD)', + XcodeArchsVariableMapping(['x86_64'], ['x86_64']), + XcodeArchsVariableMapping(['i386', 'x86_64'], ['i386', 'x86_64']), + XcodeArchsVariableMapping(['armv7', 'armv7s', 'arm64'], ['armv7', 'armv7s', 'arm64']) + ) return XCODE_ARCHS_DEFAULT_CACHE +def _StandardizePath(path): + """Do :standardizepath processing for path.""" + # I'm not quite sure what :standardizepath does. Just call normpath(), + # but don't let @executable_path/../foo collapse to foo. + if '/' in path: + prefix, rest = '', path + if path.startswith('@'): + prefix, rest = path.split('/', 1) + rest = os.path.normpath(rest) # :standardizepath + path = os.path.join(prefix, rest) + return path + + +def _MapLinkerFlagFilename(ldflag, gyp_to_build_path): + """Checks if ldflag contains a filename and if so remaps it from + gyp-directory-relative to build-directory-relative.""" + # This list is expanded on demand. + # They get matched as: + # -exported_symbols_list file + # -Wl,exported_symbols_list file + # -Wl,exported_symbols_list,file + LINKER_FILE = r'(\S+)' + WORD = r'\S+' + linker_flags = [ + ['-exported_symbols_list', LINKER_FILE], # Needed for NaCl. + ['-unexported_symbols_list', LINKER_FILE], + ['-reexported_symbols_list', LINKER_FILE], + ['-sectcreate', WORD, WORD, LINKER_FILE], # Needed for remoting. + ] + for flag_pattern in linker_flags: + regex = re.compile('(?:-Wl,)?' + '[ ,]'.join(flag_pattern)) + m = regex.match(ldflag) + if m: + ldflag = ldflag[:m.start(1)] + gyp_to_build_path(m.group(1)) + ldflag[m.end(1):] + # Required for ffmpeg (no idea why they don't use LIBRARY_SEARCH_PATHS, + # TODO(thakis): Update ffmpeg.gyp): + if ldflag.startswith('-L'): + ldflag = '-L' + gyp_to_build_path(ldflag[len('-L'):]) + return ldflag + + class XcodeSettings(object): """A class that understands the gyp 'xcode_settings' object.""" @@ -176,8 +204,7 @@ def __init__(self, spec): for configname, config in configs.items(): self.xcode_settings[configname] = config.get('xcode_settings', {}) self._ConvertConditionalKeys(configname) - if self.xcode_settings[configname].get('IPHONEOS_DEPLOYMENT_TARGET', - None): + if self.xcode_settings[configname].get('IPHONEOS_DEPLOYMENT_TARGET', None): self.isIOS = True # This is only non-None temporarily during the execution of some methods. @@ -221,16 +248,14 @@ def _WarnUnimplemented(self, test_key): def IsBinaryOutputFormat(self, configname): default = "binary" if self.isIOS else "xml" - format = self.xcode_settings[configname].get('INFOPLIST_OUTPUT_FORMAT', default) - return format == "binary" + fmt = self.xcode_settings[configname].get('INFOPLIST_OUTPUT_FORMAT', default) + return fmt == "binary" def IsIosFramework(self): - return self.spec['type'] == 'shared_library' and self._IsBundle() and \ - self.isIOS + return self.spec['type'] == 'shared_library' and self._IsBundle() and self.isIOS def _IsBundle(self): - return int(self.spec.get('mac_bundle', 0)) != 0 or self._IsXCTest() or \ - self._IsXCUiTest() + return int(self.spec.get('mac_bundle', 0)) != 0 or self._IsXCTest() or self._IsXCUiTest() def _IsXCTest(self): return int(self.spec.get('mac_xctest_bundle', 0)) != 0 @@ -263,7 +288,7 @@ def GetWrapperExtension(self): 'shared_library': 'framework', }[self.spec['type']] wrapper_extension = self.GetPerTargetSetting( - 'WRAPPER_EXTENSION', default=default_wrapper_extension) + 'WRAPPER_EXTENSION', default=default_wrapper_extension) return '.' + self.spec.get('product_extension', wrapper_extension) elif self.spec['type'] == 'executable': if self._IsIosAppExtension() or self._IsIosWatchKitExtension(): @@ -272,7 +297,7 @@ def GetWrapperExtension(self): return '.' + self.spec.get('product_extension', 'app') else: assert False, "Don't know extension for '%s', target '%s'" % ( - self.spec['type'], self.spec['target_name']) + self.spec['type'], self.spec['target_name']) def GetProductName(self): """Returns PRODUCT_NAME.""" @@ -299,7 +324,7 @@ def GetBundleContentsFolderPath(self): assert self._IsBundle() if self.spec['type'] == 'shared_library': return os.path.join( - self.GetWrapperName(), 'Versions', self.GetFrameworkVersion()) + self.GetWrapperName(), 'Versions', self.GetFrameworkVersion()) else: # loadable_modules have a 'Contents' folder like executables. return os.path.join(self.GetWrapperName(), 'Contents') @@ -316,7 +341,7 @@ def GetBundleExecutableFolderPath(self): """Returns the qualified path to the bundle's executables folder. E.g. Chromium.app/Contents/MacOS. Only valid for bundles.""" assert self._IsBundle() - if self.spec['type'] in ('shared_library') or self.isIOS: + if self.spec['type'] == 'shared_library' or self.isIOS: return self.GetBundleContentsFolderPath() elif self.spec['type'] in ('executable', 'loadable_module'): return os.path.join(self.GetBundleContentsFolderPath(), 'MacOS') @@ -347,8 +372,7 @@ def GetBundleSharedSupportFolderPath(self): if self.spec['type'] == 'shared_library': return self.GetBundleResourceFolder() else: - return os.path.join(self.GetBundleContentsFolderPath(), - 'SharedSupport') + return os.path.join(self.GetBundleContentsFolderPath(), 'SharedSupport') def GetBundlePlugInsFolderPath(self): """Returns the qualified path to the bundle's plugins folder. E.g, @@ -366,30 +390,28 @@ def GetBundlePlistPath(self): """Returns the qualified path to the bundle's plist file. E.g. Chromium.app/Contents/Info.plist. Only valid for bundles.""" assert self._IsBundle() - if self.spec['type'] in ('executable', 'loadable_module') or \ - self.IsIosFramework(): + if self.spec['type'] in ('executable', 'loadable_module') or self.IsIosFramework(): return os.path.join(self.GetBundleContentsFolderPath(), 'Info.plist') else: - return os.path.join(self.GetBundleContentsFolderPath(), - 'Resources', 'Info.plist') + return os.path.join(self.GetBundleContentsFolderPath(), 'Resources', 'Info.plist') def GetProductType(self): """Returns the PRODUCT_TYPE of this target.""" if self._IsIosAppExtension(): assert self._IsBundle(), ('ios_app_extension flag requires mac_bundle ' - '(target %s)' % self.spec['target_name']) + '(target %s)' % self.spec['target_name']) return 'com.apple.product-type.app-extension' if self._IsIosWatchKitExtension(): assert self._IsBundle(), ('ios_watchkit_extension flag requires ' - 'mac_bundle (target %s)' % self.spec['target_name']) + 'mac_bundle (target %s)' % self.spec['target_name']) return 'com.apple.product-type.watchkit-extension' if self._IsIosWatchApp(): assert self._IsBundle(), ('ios_watch_app flag requires mac_bundle ' - '(target %s)' % self.spec['target_name']) + '(target %s)' % self.spec['target_name']) return 'com.apple.product-type.application.watchapp' if self._IsXCUiTest(): assert self._IsBundle(), ('mac_xcuitest_bundle flag requires mac_bundle ' - '(target %s)' % self.spec['target_name']) + '(target %s)' % self.spec['target_name']) return 'com.apple.product-type.bundle.ui-testing' if self._IsBundle(): return { @@ -448,7 +470,7 @@ def _GetStandaloneBinaryPath(self): E.g. hello_world. Only valid for non-bundles.""" assert not self._IsBundle() assert self.spec['type'] in ( - 'executable', 'shared_library', 'static_library', 'loadable_module'), ( + 'executable', 'shared_library', 'static_library', 'loadable_module'), ( 'Unexpected type %s' % self.spec['type']) target = self.spec['target_name'] if self.spec['type'] == 'static_library': @@ -483,20 +505,7 @@ def GetActiveArchs(self, configname): """Returns the architectures this target should be built for.""" config_settings = self.xcode_settings[configname] xcode_archs_default = GetXcodeArchsDefault() - return xcode_archs_default.ActiveArchs( - config_settings.get('ARCHS'), - config_settings.get('VALID_ARCHS'), - config_settings.get('SDKROOT')) - - def _GetSdkVersionInfoItem(self, sdk, infoitem): - # xcodebuild requires Xcode and can't run on Command Line Tools-only - # systems from 10.7 onward. - # Since the CLT has no SDK paths anyway, returning None is the - # most sensible route and should still do the right thing. - try: - return GetStdout(['xcrun', '--sdk', sdk, infoitem]) - except: - pass + return xcode_archs_default.ActiveArchs(config_settings.get('ARCHS'), config_settings.get('VALID_ARCHS'), config_settings.get('SDKROOT')) def _SdkRoot(self, configname): if configname is None: @@ -506,7 +515,7 @@ def _SdkRoot(self, configname): def _XcodePlatformPath(self, configname=None): sdk_root = self._SdkRoot(configname) if sdk_root not in XcodeSettings._platform_path_cache: - platform_path = self._GetSdkVersionInfoItem(sdk_root, '--show-sdk-platform-path') + platform_path = XCodeDetect.GetSdkVersionInfoItem(sdk_root, '--show-sdk-platform-path') XcodeSettings._platform_path_cache[sdk_root] = platform_path return XcodeSettings._platform_path_cache[sdk_root] @@ -514,15 +523,7 @@ def _SdkPath(self, configname=None): sdk_root = self._SdkRoot(configname) if sdk_root.startswith('/'): return sdk_root - return self._XcodeSdkPath(sdk_root) - - def _XcodeSdkPath(self, sdk_root): - if sdk_root not in XcodeSettings._sdk_path_cache: - sdk_path = self._GetSdkVersionInfoItem(sdk_root, '--show-sdk-path') - XcodeSettings._sdk_path_cache[sdk_root] = sdk_path - if sdk_root: - XcodeSettings._sdk_root_cache[sdk_path] = sdk_root - return XcodeSettings._sdk_path_cache[sdk_root] + return XCodeDetect.GetSdkVersionInfoItem(sdk_root, '--show-sdk-path') def _AppendPlatformVersionMinFlags(self, lst): self._Appendf(lst, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s') @@ -530,11 +531,9 @@ def _AppendPlatformVersionMinFlags(self, lst): # TODO: Implement this better? sdk_path_basename = os.path.basename(self._SdkPath()) if sdk_path_basename.lower().startswith('iphonesimulator'): - self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET', - '-mios-simulator-version-min=%s') + self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET', '-mios-simulator-version-min=%s') else: - self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET', - '-miphoneos-version-min=%s') + self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET', '-miphoneos-version-min=%s') def GetCflags(self, configname, arch=None): """Returns flags that need to be added to .c, .cc, .m, and .mm @@ -633,8 +632,7 @@ def GetCflags(self, configname, arch=None): if archs[0] in ('i386', 'x86_64'): if self._Test('GCC_ENABLE_SSE3_EXTENSIONS', 'YES', default='NO'): cflags.append('-msse3') - if self._Test('GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS', 'YES', - default='NO'): + if self._Test('GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS', 'YES', default='NO'): cflags.append('-mssse3') # Note 3rd 's'. if self._Test('GCC_ENABLE_SSE41_EXTENSIONS', 'YES', default='NO'): cflags.append('-msse4.1') @@ -647,10 +645,7 @@ def GetCflags(self, configname, arch=None): if platform_root and self._IsXCTest(): cflags.append('-F' + platform_root + '/Developer/Library/Frameworks/') - if sdk_root: - framework_root = sdk_root - else: - framework_root = '' + framework_root = sdk_root or '' config = self.spec['configurations'][self.configname] framework_dirs = config.get('mac_framework_dirs', []) for directory in framework_dirs: @@ -677,7 +672,7 @@ def GetCflagsCC(self, configname): cflags_cc = [] clang_cxx_language_standard = self._Settings().get( - 'CLANG_CXX_LANGUAGE_STANDARD') + 'CLANG_CXX_LANGUAGE_STANDARD') # Note: Don't make c++0x to c++11 so that c++0x can be used with older # clangs that don't understand c++11 yet (like Xcode 4.2's). if clang_cxx_language_standard: @@ -724,8 +719,7 @@ def _AddObjectiveCARCFlags(self, flags): flags.append('-fobjc-arc') def _AddObjectiveCMissingPropertySynthesisFlags(self, flags): - if self._Test('CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS', - 'YES', default='NO'): + if self._Test('CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS', 'YES', default='NO'): flags.append('-Wobjc-missing-property-synthesis') def GetCflagsObjC(self, configname): @@ -756,88 +750,38 @@ def GetInstallNameBase(self): if (self.spec['type'] != 'shared_library' and (self.spec['type'] != 'loadable_module' or self._IsBundle())): return None - install_base = self.GetPerTargetSetting( - 'DYLIB_INSTALL_NAME_BASE', - default='/Library/Frameworks' if self._IsBundle() else '/usr/local/lib') + lib_path = '/Library/Frameworks' if self._IsBundle() else '/usr/local/lib' + install_base = self.GetPerTargetSetting('DYLIB_INSTALL_NAME_BASE', default=lib_path) return install_base - def _StandardizePath(self, path): - """Do :standardizepath processing for path.""" - # I'm not quite sure what :standardizepath does. Just call normpath(), - # but don't let @executable_path/../foo collapse to foo. - if '/' in path: - prefix, rest = '', path - if path.startswith('@'): - prefix, rest = path.split('/', 1) - rest = os.path.normpath(rest) # :standardizepath - path = os.path.join(prefix, rest) - return path - def GetInstallName(self): """Return LD_DYLIB_INSTALL_NAME for this target.""" # Xcode sets this for shared_libraries, and for nonbundled loadable_modules. - if (self.spec['type'] != 'shared_library' and - (self.spec['type'] != 'loadable_module' or self._IsBundle())): + if self.spec['type'] != 'shared_library' and (self.spec['type'] != 'loadable_module' or self._IsBundle()): return None - default_install_name = \ - '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)' - install_name = self.GetPerTargetSetting( - 'LD_DYLIB_INSTALL_NAME', default=default_install_name) + default_install_name = '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)' + install_name = self.GetPerTargetSetting('LD_DYLIB_INSTALL_NAME', default=default_install_name) # Hardcode support for the variables used in chromium for now, to # unblock people using the make build. if '$' in install_name: - assert install_name in ('$(DYLIB_INSTALL_NAME_BASE:standardizepath)/' - '$(WRAPPER_NAME)/$(PRODUCT_NAME)', default_install_name), ( - 'Variables in LD_DYLIB_INSTALL_NAME are not generally supported ' - 'yet in target \'%s\' (got \'%s\')' % - (self.spec['target_name'], install_name)) - - install_name = install_name.replace( - '$(DYLIB_INSTALL_NAME_BASE:standardizepath)', - self._StandardizePath(self.GetInstallNameBase())) - if self._IsBundle(): - # These are only valid for bundles, hence the |if|. - install_name = install_name.replace( - '$(WRAPPER_NAME)', self.GetWrapperName()) - install_name = install_name.replace( - '$(PRODUCT_NAME)', self.GetProductName()) - else: - assert '$(WRAPPER_NAME)' not in install_name - assert '$(PRODUCT_NAME)' not in install_name + assert install_name in ( + '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(WRAPPER_NAME)/$(PRODUCT_NAME)', + default_install_name + ), "Variables in LD_DYLIB_INSTALL_NAME are not generally supported yet in target '%s' (got '%s')" % (self.spec['target_name'], install_name) - install_name = install_name.replace( - '$(EXECUTABLE_PATH)', self.GetExecutablePath()) - return install_name + install_name = install_name.replace('$(DYLIB_INSTALL_NAME_BASE:standardizepath)', _StandardizePath(self.GetInstallNameBase())) + if self._IsBundle(): + # These are only valid for bundles, hence the |if|. + install_name = install_name.replace('$(WRAPPER_NAME)', self.GetWrapperName()) + install_name = install_name.replace('$(PRODUCT_NAME)', self.GetProductName()) + else: + assert '$(WRAPPER_NAME)' not in install_name + assert '$(PRODUCT_NAME)' not in install_name - def _MapLinkerFlagFilename(self, ldflag, gyp_to_build_path): - """Checks if ldflag contains a filename and if so remaps it from - gyp-directory-relative to build-directory-relative.""" - # This list is expanded on demand. - # They get matched as: - # -exported_symbols_list file - # -Wl,exported_symbols_list file - # -Wl,exported_symbols_list,file - LINKER_FILE = r'(\S+)' - WORD = r'\S+' - linker_flags = [ - ['-exported_symbols_list', LINKER_FILE], # Needed for NaCl. - ['-unexported_symbols_list', LINKER_FILE], - ['-reexported_symbols_list', LINKER_FILE], - ['-sectcreate', WORD, WORD, LINKER_FILE], # Needed for remoting. - ] - for flag_pattern in linker_flags: - regex = re.compile('(?:-Wl,)?' + '[ ,]'.join(flag_pattern)) - m = regex.match(ldflag) - if m: - ldflag = ldflag[:m.start(1)] + gyp_to_build_path(m.group(1)) + \ - ldflag[m.end(1):] - # Required for ffmpeg (no idea why they don't use LIBRARY_SEARCH_PATHS, - # TODO(thakis): Update ffmpeg.gyp): - if ldflag.startswith('-L'): - ldflag = '-L' + gyp_to_build_path(ldflag[len('-L'):]) - return ldflag + install_name = install_name.replace('$(EXECUTABLE_PATH)', self.GetExecutablePath()) + return install_name def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None): """Returns flags that need to be passed to the linker. @@ -848,6 +792,7 @@ def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None): libraries are placed. This is added to the library search path. gyp_to_build_path: A function that converts paths relative to the current gyp file to paths relative to the build direcotry. + arch: CPU architecture """ self.configname = configname ldflags = [] @@ -855,7 +800,7 @@ def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None): # The xcode build is relative to a gyp file's directory, and OTHER_LDFLAGS # can contain entries that depend on this. Explicitly absolutify these. for ldflag in self._Settings().get('OTHER_LDFLAGS', []): - ldflags.append(self._MapLinkerFlagFilename(ldflag, gyp_to_build_path)) + ldflags.append(_MapLinkerFlagFilename(ldflag, gyp_to_build_path)) if self._Test('DEAD_CODE_STRIPPING', 'YES', default='NO'): ldflags.append('-Wl,-dead_strip') @@ -863,10 +808,8 @@ def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None): if self._Test('PREBINDING', 'YES', default='NO'): ldflags.append('-Wl,-prebind') - self._Appendf( - ldflags, 'DYLIB_COMPATIBILITY_VERSION', '-compatibility_version %s') - self._Appendf( - ldflags, 'DYLIB_CURRENT_VERSION', '-current_version %s') + self._Appendf(ldflags, 'DYLIB_COMPATIBILITY_VERSION', '-compatibility_version %s') + self._Appendf(ldflags, 'DYLIB_CURRENT_VERSION', '-current_version %s') self._AppendPlatformVersionMinFlags(ldflags) @@ -879,7 +822,7 @@ def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None): if 'ORDER_FILE' in self._Settings(): ldflags.append('-Wl,-order_file ' + '-Wl,' + gyp_to_build_path( - self._Settings()['ORDER_FILE'])) + self._Settings()['ORDER_FILE'])) if arch is not None: archs = [arch] @@ -922,10 +865,10 @@ def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None): # extensions and provide loader and main function. # These flags reflect the compilation options used by xcode to compile # extensions. - if XcodeVersion() < '0900': + if XCodeDetect.Version() < '0900': ldflags.append('-lpkstart') ldflags.append(sdk_root + - '/System/Library/PrivateFrameworks/PlugInKit.framework/PlugInKit') + '/System/Library/PrivateFrameworks/PlugInKit.framework/PlugInKit') else: ldflags.append('-e _NSExtensionMain') ldflags.append('-fapplication-extension') @@ -1036,7 +979,7 @@ def _GetDebugInfoPostbuilds(self, configname, output, output_binary, quiet): result = [] if (self._Test('GCC_GENERATE_DEBUGGING_SYMBOLS', 'YES', default='YES') and self._Test( - 'DEBUG_INFORMATION_FORMAT', 'dwarf-with-dsym', default='dwarf') and + 'DEBUG_INFORMATION_FORMAT', 'dwarf-with-dsym', default='dwarf') and self.spec['type'] != 'static_library'): if not quiet: result.append('echo DSYMUTIL\\(%s\\)' % self.spec['target_name']) @@ -1045,8 +988,7 @@ def _GetDebugInfoPostbuilds(self, configname, output, output_binary, quiet): self.configname = None return result - def _GetTargetPostbuilds(self, configname, output, output_binary, - quiet=False): + def _GetTargetPostbuilds(self, configname, output, output_binary, quiet=False): """Returns a list of shell commands that contain the shell commands to run as postbuilds for this target, before the actual postbuilds.""" # dSYMs need to build before stripping happens. @@ -1059,8 +1001,8 @@ def _GetIOSPostbuilds(self, configname): be deployed to a device. This should be run as the very last step of the build.""" if not (self.isIOS and - (self.spec['type'] == 'executable' or self._IsXCTest()) or - self.IsIosFramework()): + (self.spec['type'] == 'executable' or self._IsXCTest()) or + self.IsIosFramework()): return [] postbuilds = [] @@ -1074,7 +1016,8 @@ def _GetIOSPostbuilds(self, configname): xctest_destination = os.path.join(test_host, 'PlugIns', product_name) postbuilds.extend(['ditto %s %s' % (source, xctest_destination)]) - key = self._GetIOSCodeSignIdentityKey(settings) + identity = settings.get('CODE_SIGN_IDENTITY') + key = XCodeDetect.GetIOSCodeSignIdentityKey(identity) if not key: return postbuilds @@ -1083,16 +1026,17 @@ def _GetIOSPostbuilds(self, configname): unimpl = set(unimpl) & set(self.xcode_settings[configname].keys()) if unimpl: print('Warning: Some codesign keys not implemented, ignoring: %s' % ( - ', '.join(sorted(unimpl)))) + ', '.join(sorted(unimpl)))) if self._IsXCTest(): # For device xctests, Xcode copies two extra frameworks into $TEST_HOST. test_host = os.path.dirname(settings.get('TEST_HOST')) frameworks_dir = os.path.join(test_host, 'Frameworks') platform_root = self._XcodePlatformPath(configname) - frameworks = \ - ['Developer/Library/PrivateFrameworks/IDEBundleInjection.framework', - 'Developer/Library/Frameworks/XCTest.framework'] + frameworks = [ + 'Developer/Library/PrivateFrameworks/IDEBundleInjection.framework', + 'Developer/Library/Frameworks/XCTest.framework' + ] for framework in frameworks: source = os.path.join(platform_root, framework) destination = os.path.join(frameworks_dir, os.path.basename(framework)) @@ -1100,43 +1044,27 @@ def _GetIOSPostbuilds(self, configname): # Then re-sign everything with 'preserve=True' postbuilds.extend(['%s code-sign-bundle "%s" "%s" "%s" "%s" %s' % ( - os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key, - settings.get('CODE_SIGN_ENTITLEMENTS', ''), - settings.get('PROVISIONING_PROFILE', ''), destination, True) - ]) + os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key, + settings.get('CODE_SIGN_ENTITLEMENTS', ''), + settings.get('PROVISIONING_PROFILE', ''), destination, True) + ]) plugin_dir = os.path.join(test_host, 'PlugIns') targets = [os.path.join(plugin_dir, product_name), test_host] for target in targets: postbuilds.extend(['%s code-sign-bundle "%s" "%s" "%s" "%s" %s' % ( - os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key, - settings.get('CODE_SIGN_ENTITLEMENTS', ''), - settings.get('PROVISIONING_PROFILE', ''), target, True) - ]) + os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key, + settings.get('CODE_SIGN_ENTITLEMENTS', ''), + settings.get('PROVISIONING_PROFILE', ''), target, True) + ]) postbuilds.extend(['%s code-sign-bundle "%s" "%s" "%s" "%s" %s' % ( - os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key, - settings.get('CODE_SIGN_ENTITLEMENTS', ''), - settings.get('PROVISIONING_PROFILE', ''), - os.path.join("${BUILT_PRODUCTS_DIR}", product_name), False) - ]) + os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key, + settings.get('CODE_SIGN_ENTITLEMENTS', ''), + settings.get('PROVISIONING_PROFILE', ''), + os.path.join("${BUILT_PRODUCTS_DIR}", product_name), False) + ]) return postbuilds - def _GetIOSCodeSignIdentityKey(self, settings): - identity = settings.get('CODE_SIGN_IDENTITY') - if not identity: - return None - if identity not in XcodeSettings._codesigning_key_cache: - output = subprocess.check_output( - ['security', 'find-identity', '-p', 'codesigning', '-v']) - for line in output.splitlines(): - if identity in line: - fingerprint = line.split()[1] - cache = XcodeSettings._codesigning_key_cache - assert identity not in cache or fingerprint == cache[identity], ( - "Multiple codesigning fingerprints for identity: %s" % identity) - XcodeSettings._codesigning_key_cache[identity] = fingerprint - return XcodeSettings._codesigning_key_cache.get(identity, '') - def AddImplicitPostbuilds(self, configname, output, output_binary, postbuilds=None, quiet=False): """ Returns a list of shell commands that should run before and after |postbuilds|. @@ -1187,9 +1115,6 @@ def AdjustLibraries(self, libraries, config_name=None): for library in libraries] return libraries - def _BuildMachineOSBuild(self): - return GetStdout(['sw_vers', '-buildVersion']) - def _XcodeIOSDeviceFamily(self, configname): family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1') return [int(x) for x in family.split(',')] @@ -1197,24 +1122,22 @@ def _XcodeIOSDeviceFamily(self, configname): def GetExtraPlistItems(self, configname=None): """Returns a dictionary with extra items to insert into Info.plist.""" if configname not in XcodeSettings._plist_cache: - cache = {} - cache['BuildMachineOSBuild'] = self._BuildMachineOSBuild() - - xcode, xcode_build = XcodeVersion() - cache['DTXcode'] = xcode - cache['DTXcodeBuild'] = xcode_build + xcode = XCodeDetect.Version() + cache = { + 'BuildMachineOSBuild': XCodeDetect.BuildMachineOSBuild(), + 'DTXcode': xcode + } compiler = self.xcode_settings[configname].get('GCC_VERSION') if compiler is not None: cache['DTCompiler'] = compiler sdk_root = self._SdkRoot(configname) if not sdk_root: - sdk_root = self._DefaultSdkRoot() - sdk_version = self._GetSdkVersionInfoItem(sdk_root, '--show-sdk-version') + sdk_root = XCodeDetect.GetSdkVersionInfoItem('macosx', '--show-sdk-path') + sdk_version = XCodeDetect.GetSdkVersionInfoItem(sdk_root, '--show-sdk-version') cache['DTSDKName'] = sdk_root + (sdk_version or '') if xcode >= '0720': - cache['DTSDKBuild'] = self._GetSdkVersionInfoItem( - sdk_root, '--show-sdk-build-version') + cache['DTSDKBuild'] = XCodeDetect.GetSdkVersionInfoItem(sdk_root, '--show-sdk-build-version') elif xcode >= '0430': cache['DTSDKBuild'] = sdk_version else: @@ -1222,7 +1145,7 @@ def GetExtraPlistItems(self, configname=None): if self.isIOS: cache['MinimumOSVersion'] = self.xcode_settings[configname].get( - 'IPHONEOS_DEPLOYMENT_TARGET') + 'IPHONEOS_DEPLOYMENT_TARGET') cache['DTPlatformName'] = sdk_root cache['DTPlatformVersion'] = sdk_version @@ -1243,34 +1166,6 @@ def GetExtraPlistItems(self, configname=None): items['UIDeviceFamily'] = self._XcodeIOSDeviceFamily(configname) return items - def _DefaultSdkRoot(self): - """Returns the default SDKROOT to use. - - Prior to version 5.0.0, if SDKROOT was not explicitly set in the Xcode - project, then the environment variable was empty. Starting with this - version, Xcode uses the name of the newest SDK installed. - """ - xcode_version, xcode_build = XcodeVersion() - if xcode_version < '0500': - return '' - default_sdk_path = self._XcodeSdkPath('') - default_sdk_root = XcodeSettings._sdk_root_cache.get(default_sdk_path) - if default_sdk_root: - return default_sdk_root - try: - all_sdks = GetStdout(['xcodebuild', '-showsdks']) - except: - # If xcodebuild fails, there will be no valid SDKs - return '' - for line in all_sdks.splitlines(): - items = line.split() - if len(items) >= 3 and items[-2] == '-sdk': - sdk_root = items[-1] - sdk_path = self._XcodeSdkPath(sdk_root) - if sdk_path == default_sdk_path: - return sdk_root - return '' - class MacPrefixHeader(object): """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature. @@ -1294,8 +1189,8 @@ class MacPrefixHeader(object): system for writing dependencies to the gch files, for writing build commands for the gch files, and for figuring out the location of the gch files. """ - def __init__(self, xcode_settings, - gyp_path_to_build_path, gyp_path_to_build_output): + + def __init__(self, xcode_settings, gyp_path_to_build_path, gyp_path_to_build_output): """If xcode_settings is None, all methods on this class are no-ops. Args: @@ -1312,14 +1207,12 @@ def __init__(self, xcode_settings, self.compile_headers = False if xcode_settings: self.header = xcode_settings.GetPerTargetSetting('GCC_PREFIX_HEADER') - self.compile_headers = xcode_settings.GetPerTargetSetting( - 'GCC_PRECOMPILE_PREFIX_HEADER', default='NO') != 'NO' + self.compile_headers = xcode_settings.GetPerTargetSetting('GCC_PRECOMPILE_PREFIX_HEADER', default='NO') != 'NO' self.compiled_headers = {} if self.header: if self.compile_headers: for lang in ['c', 'cc', 'm', 'mm']: - self.compiled_headers[lang] = gyp_path_to_build_output( - self.header, lang) + self.compiled_headers[lang] = gyp_path_to_build_output(self.header, lang) self.header = gyp_path_to_build_path(self.header) def _CompiledHeader(self, lang, arch): @@ -1356,7 +1249,9 @@ def GetObjDependencies(self, sources, objs, arch=None): ext = os.path.splitext(source)[1] lang = { '.c': 'c', - '.cpp': 'cc', '.cc': 'cc', '.cxx': 'cc', + '.cpp': 'cc', + '.cc': 'cc', + '.cxx': 'cc', '.m': 'm', '.mm': 'mm', }.get(ext, None) @@ -1378,85 +1273,6 @@ def GetPchBuildCommands(self, arch=None): ] -def XcodeVersion(): - """Returns a tuple of version and build version of installed Xcode.""" - # `xcodebuild -version` output looks like - # Xcode 4.6.3 - # Build version 4H1503 - # or like - # Xcode 3.2.6 - # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0 - # BuildVersion: 10M2518 - # Convert that to '0463', '4H1503'. - global XCODE_VERSION_CACHE - if XCODE_VERSION_CACHE: - return XCODE_VERSION_CACHE - try: - version_list = GetStdout(['xcodebuild', '-version']).splitlines() - # In some circumstances xcodebuild exits 0 but doesn't return - # the right results; for example, a user on 10.7 or 10.8 with - # a bogus path set via xcode-select - # In that case this may be a CLT-only install so fall back to - # checking that version. - if len(version_list) < 2: - raise GypError("xcodebuild returned unexpected results") - except: - version = CLTVersion() - if version: - version = re.search(r'^(\d{1,2}\.\d(\.\d+)?)', version).groups()[0] - else: - raise GypError("No Xcode or CLT version detected!") - # The CLT has no build information, so we return an empty string. - version_list = [version, ''] - version = version_list[0] - build = version_list[-1] - # Be careful to convert "4.2" to "0420" and "10.0" to "1000": - version = format(''.join((version.split()[-1].split('.') + ['0', '0'])[:3]), - '>04s') - if build: - build = build.split()[-1] - XCODE_VERSION_CACHE = (version, build) - return XCODE_VERSION_CACHE - - -# This function ported from the logic in Homebrew's CLT version check -def CLTVersion(): - """Returns the version of command-line tools from pkgutil.""" - # pkgutil output looks like - # package-id: com.apple.pkg.CLTools_Executables - # version: 5.0.1.0.1.1382131676 - # volume: / - # location: / - # install-time: 1382544035 - # groups: com.apple.FindSystemFiles.pkg-group com.apple.DevToolsBoth.pkg-group com.apple.DevToolsNonRelocatableShared.pkg-group - STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo" - FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI" - MAVERICKS_PKG_ID = "com.apple.pkg.CLTools_Executables" - - regex = re.compile('version: (?P.+)') - for key in [MAVERICKS_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID]: - try: - output = GetStdout(['/usr/sbin/pkgutil', '--pkg-info', key]) - return re.search(regex, output).groupdict()['version'] - except: - continue - - -def GetStdout(cmdlist, with_stderr=False): - """ - Returns the content of standard output returned by invoking |cmdlist|. - Raises |GypError| if the command return with a non-zero return code. - """ - job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out, err = job.communicate() - if job.returncode != 0: - if with_stderr: - print(out, file=sys.stderr) - print(err, file=sys.stderr) - raise GypError('Error %d running %s' % (job.returncode, cmdlist[0])) - return out.rstrip('\n') - - def MergeGlobalXcodeSettingsToSpec(global_dict, spec): """Merges the global xcode_settings dictionary into each configuration of the target represented by spec. For keys that are both in the global and the local @@ -1479,14 +1295,14 @@ def IsMacBundle(flavor, spec): Bundles are directories with a certain subdirectory structure, instead of just a single file. Bundle rules do not produce a binary but also package resources into that directory.""" - is_mac_bundle = int(spec.get('mac_xctest_bundle', 0)) != 0 or \ - int(spec.get('mac_xcuitest_bundle', 0)) != 0 or \ + is_mac_bundle = ( + int(spec.get('mac_xctest_bundle', 0)) != 0 or + int(spec.get('mac_xcuitest_bundle', 0)) != 0 or (int(spec.get('mac_bundle', 0)) != 0 and flavor == 'mac') + ) if is_mac_bundle: - assert spec['type'] != 'none', ( - 'mac_bundle targets cannot have type none (target "%s")' % - spec['target_name']) + assert spec['type'] != 'none', 'mac_bundle targets cannot have type none (target "%s")' % spec['target_name'] return is_mac_bundle @@ -1495,20 +1311,17 @@ def GetMacBundleResources(product_dir, xcode_settings, resources): Only call this for mac bundle targets. Args: - product_dir: Path to the directory containing the output bundle, - relative to the build directory. + product_dir: Path to the directory containing the output bundle, relative to the build directory. xcode_settings: The XcodeSettings of the current target. resources: A list of bundle resources, relative to the build directory. """ - dest = os.path.join(product_dir, - xcode_settings.GetBundleResourceFolder()) + dest = os.path.join(product_dir, xcode_settings.GetBundleResourceFolder()) for res in resources: output = dest # The make generator doesn't support it, so forbid it everywhere # to keep the generators more interchangable. - assert ' ' not in res, ( - "Spaces in resource filenames not supported (%s)" % res) + assert ' ' not in res, "Spaces in resource filenames not supported (%s)" % res # Split into (path,file). res_parts = os.path.split(res) @@ -1550,19 +1363,16 @@ def GetMacInfoPlist(product_dir, xcode_settings, gyp_path_to_build_path): return None, None, [], {} # The make generator doesn't support it, so forbid it everywhere - # to keep the generators more interchangable. - assert ' ' not in info_plist, ( - "Spaces in Info.plist filenames not supported (%s)" % info_plist) + # to keep the generators more interchangeable. + assert ' ' not in info_plist, "Spaces in Info.plist filenames not supported (%s)" % info_plist info_plist = gyp_path_to_build_path(info_plist) # If explicitly set to preprocess the plist, invoke the C preprocessor and # specify any defines as -D flags. - if xcode_settings.GetPerTargetSetting( - 'INFOPLIST_PREPROCESS', default='NO') == 'YES': + if xcode_settings.GetPerTargetSetting('INFOPLIST_PREPROCESS', default='NO') == 'YES': # Create an intermediate file based on the path. - defines = shlex.split(xcode_settings.GetPerTargetSetting( - 'INFOPLIST_PREPROCESSOR_DEFINITIONS', default='')) + defines = shlex.split(xcode_settings.GetPerTargetSetting('INFOPLIST_PREPROCESSOR_DEFINITIONS', default='')) else: defines = [] @@ -1572,9 +1382,9 @@ def GetMacInfoPlist(product_dir, xcode_settings, gyp_path_to_build_path): return info_plist, dest_plist, defines, extra_env -def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, - additional_settings=None): - """Return the environment variables that Xcode would set. See +def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, additional_settings=None): + """ + Return the environment variables that Xcode would set. See http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW153 for a full list. @@ -1588,7 +1398,8 @@ def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, result. """ - if not xcode_settings: return {} + if not xcode_settings: + return {} # This function is considered a friend of XcodeSettings, so let it reach into # its implementation details. @@ -1596,18 +1407,18 @@ def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, # These are filled in on an as-needed basis. env = { - 'BUILT_FRAMEWORKS_DIR' : built_products_dir, - 'BUILT_PRODUCTS_DIR' : built_products_dir, - 'CONFIGURATION' : configuration, - 'PRODUCT_NAME' : xcode_settings.GetProductName(), + 'BUILT_FRAMEWORKS_DIR': built_products_dir, + 'BUILT_PRODUCTS_DIR': built_products_dir, + 'CONFIGURATION': configuration, + 'PRODUCT_NAME': xcode_settings.GetProductName(), # See /Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX\ Product\ Types.xcspec for FULL_PRODUCT_NAME - 'SRCROOT' : srcroot, + 'SRCROOT': srcroot, 'SOURCE_ROOT': '${SRCROOT}', # This is not true for static libraries, but currently the env is only # written for bundles: - 'TARGET_BUILD_DIR' : built_products_dir, - 'TEMP_DIR' : '${TMPDIR}', - 'XCODE_VERSION_ACTUAL' : XcodeVersion()[0], + 'TARGET_BUILD_DIR': built_products_dir, + 'TEMP_DIR': '${TMPDIR}', + 'XCODE_VERSION_ACTUAL': XCodeDetect.Version(), } if xcode_settings.GetPerConfigSetting('SDKROOT', configuration): env['SDKROOT'] = xcode_settings._SdkPath(configuration) @@ -1617,8 +1428,7 @@ def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, if xcode_settings.mac_toolchain_dir: env['DEVELOPER_DIR'] = xcode_settings.mac_toolchain_dir - if spec['type'] in ( - 'executable', 'static_library', 'shared_library', 'loadable_module'): + if spec['type'] in ('executable', 'static_library', 'shared_library', 'loadable_module'): env['EXECUTABLE_NAME'] = xcode_settings.GetExecutableName() env['EXECUTABLE_PATH'] = xcode_settings.GetExecutablePath() env['FULL_PRODUCT_NAME'] = xcode_settings.GetFullProductName() @@ -1629,25 +1439,16 @@ def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, if xcode_settings._IsBundle(): # xcodeproj_file.py sets the same Xcode subfolder value for this as for # FRAMEWORKS_FOLDER_PATH so Xcode builds will actually use FFP's value. - env['BUILT_FRAMEWORKS_DIR'] = \ - os.path.join(built_products_dir + os.sep \ - + xcode_settings.GetBundleFrameworksFolderPath()) - env['CONTENTS_FOLDER_PATH'] = \ - xcode_settings.GetBundleContentsFolderPath() - env['EXECUTABLE_FOLDER_PATH'] = \ - xcode_settings.GetBundleExecutableFolderPath() - env['UNLOCALIZED_RESOURCES_FOLDER_PATH'] = \ - xcode_settings.GetBundleResourceFolder() + env['BUILT_FRAMEWORKS_DIR'] = os.path.join(built_products_dir + os.sep + xcode_settings.GetBundleFrameworksFolderPath()) + env['CONTENTS_FOLDER_PATH'] = xcode_settings.GetBundleContentsFolderPath() + env['EXECUTABLE_FOLDER_PATH'] = xcode_settings.GetBundleExecutableFolderPath() + env['UNLOCALIZED_RESOURCES_FOLDER_PATH'] = xcode_settings.GetBundleResourceFolder() env['JAVA_FOLDER_PATH'] = xcode_settings.GetBundleJavaFolderPath() - env['FRAMEWORKS_FOLDER_PATH'] = \ - xcode_settings.GetBundleFrameworksFolderPath() - env['SHARED_FRAMEWORKS_FOLDER_PATH'] = \ - xcode_settings.GetBundleSharedFrameworksFolderPath() - env['SHARED_SUPPORT_FOLDER_PATH'] = \ - xcode_settings.GetBundleSharedSupportFolderPath() + env['FRAMEWORKS_FOLDER_PATH'] = xcode_settings.GetBundleFrameworksFolderPath() + env['SHARED_FRAMEWORKS_FOLDER_PATH'] = xcode_settings.GetBundleSharedFrameworksFolderPath() + env['SHARED_SUPPORT_FOLDER_PATH'] = xcode_settings.GetBundleSharedSupportFolderPath() env['PLUGINS_FOLDER_PATH'] = xcode_settings.GetBundlePlugInsFolderPath() - env['XPCSERVICES_FOLDER_PATH'] = \ - xcode_settings.GetBundleXPCServicesFolderPath() + env['XPCSERVICES_FOLDER_PATH'] = xcode_settings.GetBundleXPCServicesFolderPath() env['INFOPLIST_PATH'] = xcode_settings.GetBundlePlistPath() env['WRAPPER_NAME'] = xcode_settings.GetWrapperName() @@ -1657,10 +1458,10 @@ def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, install_name_base = xcode_settings.GetInstallNameBase() if install_name_base: env['DYLIB_INSTALL_NAME_BASE'] = install_name_base - if XcodeVersion() >= '0500' and not env.get('SDKROOT'): + if XCodeDetect.Version() >= '0500' and not env.get('SDKROOT'): sdk_root = xcode_settings._SdkRoot(configuration) if not sdk_root: - sdk_root = xcode_settings._XcodeSdkPath('') + sdk_root = XCodeDetect.GetSdkVersionInfoItem('', '--show-sdk-path') env['SDKROOT'] = sdk_root if not additional_settings: @@ -1678,21 +1479,22 @@ def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, return additional_settings -def _NormalizeEnvVarReferences(str): - """Takes a string containing variable references in the form ${FOO}, $(FOO), - or $FOO, and returns a string with all variable references in the form ${FOO}. +def _NormalizeEnvVarReferences(string_arg): + """ + Takes a string containing variable references in the form ${FOO}, $(FOO), or $FOO, + and returns a string with all variable references in the form ${FOO}. """ # $FOO -> ${FOO} - str = re.sub(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', r'${\1}', str) + string_arg = re.sub(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', r'${\1}', string_arg) # $(FOO) -> ${FOO} - matches = re.findall(r'(\$\(([a-zA-Z0-9\-_]+)\))', str) + matches = re.findall(r'(\$\(([a-zA-Z0-9\-_]+)\))', string_arg) for match in matches: to_replace, variable = match assert '$(' not in match, '$($(FOO)) variables not supported: ' + match - str = str.replace(to_replace, '${' + variable + '}') + string_arg = string_arg.replace(to_replace, '${' + variable + '}') - return str + return string_arg def ExpandEnvVars(string, expansions): @@ -1718,6 +1520,7 @@ def _TopologicallySortedEnvVarKeys(env): # order is important. Below is the logic to compute the dependency graph # and sort it. regex = re.compile(r'\${([a-zA-Z0-9\-_]+)\}') + def GetEdges(node): # Use a definition of edges such that user_of_variable -> used_varible. # This happens to be easier in this case, since a variable's @@ -1733,18 +1536,15 @@ def GetEdges(node): # Topologically sort, and then reverse, because we used an edge definition # that's inverted from the expected result of this function (see comment # above). - order = gyp.common.TopologicallySorted(env.keys(), GetEdges) + order = TopologicallySorted(env.keys(), GetEdges) order.reverse() return order - except gyp.common.CycleError as e: - raise GypError( - 'Xcode environment variables are cyclically dependent: ' + str(e.nodes)) + except CycleError as e: + raise GypError('Xcode environment variables are cyclically dependent: ' + str(e.nodes)) -def GetSortedXcodeEnv(xcode_settings, built_products_dir, srcroot, - configuration, additional_settings=None): - env = _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, - additional_settings) +def GetSortedXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, additional_settings=None): + env = _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, additional_settings) return [(key, env[key]) for key in _TopologicallySortedEnvVarKeys(env)] @@ -1754,9 +1554,8 @@ def GetSpecPostbuildCommands(spec, quiet=False): postbuilds = [] for postbuild in spec.get('postbuilds', []): if not quiet: - postbuilds.append('echo POSTBUILD\\(%s\\) %s' % ( - spec['target_name'], postbuild['postbuild_name'])) - postbuilds.append(gyp.common.EncodePOSIXShellList(postbuild['action'])) + postbuilds.append('echo POSTBUILD\\(%s\\) %s' % (spec['target_name'], postbuild['postbuild_name'])) + postbuilds.append(EncodePOSIXShellList(postbuild['action'])) return postbuilds @@ -1786,6 +1585,7 @@ def _AddIOSDeviceConfigurations(targets): iphoneos_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' return targets + def CloneConfigurationForDeviceAndEmulator(target_dicts): """If |target_dicts| contains any iOS targets, automatically create -iphoneos targets for iOS device builds.""" diff --git a/pylib/__init__.py b/pylib/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pylib/util.py b/pylib/util.py new file mode 100644 index 00000000..45571652 --- /dev/null +++ b/pylib/util.py @@ -0,0 +1,21 @@ +from functools import wraps +from subprocess import check_output, PIPE + +def memoize(function): + memo = {} + + @wraps(function) + def wrapper(*args): + if args in memo: + return memo[args] + else: + rv = function(*args) + memo[args] = rv + return rv + return wrapper + + +def run(*cmd_args): + return check_output(cmd_args, stderr=PIPE).decode('utf-8') + + diff --git a/test/ios/gyptest-app-ios-assets-catalog.py b/test/ios/gyptest-app-ios-assets-catalog.py index 537adc0b..d16b2c82 100755 --- a/test/ios/gyptest-app-ios-assets-catalog.py +++ b/test/ios/gyptest-app-ios-assets-catalog.py @@ -5,7 +5,7 @@ import os.path import TestGyp -from XCodeDetect import XCodeDetect +import XCodeDetect test = TestGyp.TestGyp(formats=['xcode', 'ninja'], platforms=['darwin']) diff --git a/test/ios/gyptest-app-ios.py b/test/ios/gyptest-app-ios.py index 04944f4d..f3c617b6 100755 --- a/test/ios/gyptest-app-ios.py +++ b/test/ios/gyptest-app-ios.py @@ -9,7 +9,7 @@ test = TestGyp.TestGyp(formats=['xcode', 'ninja'], platforms=['darwin']) -if not XCodeDetect.XCodeDetect.HasIPhoneSDK(): +if not XCodeDetect.IPhoneSDKPath(): test.skip_test('IPhone SDK not installed') diff --git a/test/ios/gyptest-archs.py b/test/ios/gyptest-archs.py index 8c2f86a8..151c1675 100644 --- a/test/ios/gyptest-archs.py +++ b/test/ios/gyptest-archs.py @@ -24,12 +24,12 @@ ('Default-iphoneos', 'TestArch32Bits', ['armv7']), ] -if XCodeDetect.XCodeDetect.Version() < '0510': +if XCodeDetect.Version() < '0510': test_cases.extend([ ('Default', 'TestNoArchs', ['i386']), ('Default-iphoneos', 'TestNoArchs', ['armv7'])]) -if XCodeDetect.XCodeDetect.Version() >= '0500': +if XCodeDetect.Version() >= '0500': test_cases.extend([ ('Default', 'TestArch64Bits', ['x86_64']), ('Default', 'TestMultiArchs', ['i386', 'x86_64']), @@ -45,7 +45,7 @@ if is_device_build: configuration, sdk = configuration.split('-') kwds['arguments'].extend(['-sdk', sdk]) - if XCodeDetect.XCodeDetect.Version() < '0500': + if XCodeDetect.Version() < '0500': kwds['arguments'].extend(['-arch', archs[0]]) test.set_configuration(configuration) diff --git a/test/ios/gyptest-deployment-target.py b/test/ios/gyptest-deployment-target.py index 0e652e47..a3e6ecd4 100644 --- a/test/ios/gyptest-deployment-target.py +++ b/test/ios/gyptest-deployment-target.py @@ -13,7 +13,7 @@ test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode'], platforms=['darwin']) -if not XCodeDetect.XCodeDetect.HasIPhoneSDK(): +if not XCodeDetect.IPhoneSDKPath(): test.skip_test('IPhone SDK not installed') test.run_gyp('deployment-target.gyp', chdir='deployment-target') diff --git a/test/ios/gyptest-extension.py b/test/ios/gyptest-extension.py index c03dd4a4..2606e7da 100755 --- a/test/ios/gyptest-extension.py +++ b/test/ios/gyptest-extension.py @@ -13,7 +13,7 @@ import subprocess import TestGyp -from XCodeDetect import XCodeDetect +import XCodeDetect test = TestGyp.TestGyp(formats=['ninja', 'xcode'], platforms=['darwin']) diff --git a/test/ios/gyptest-framework.py b/test/ios/gyptest-framework.py index 571163a6..bed6ae62 100755 --- a/test/ios/gyptest-framework.py +++ b/test/ios/gyptest-framework.py @@ -3,7 +3,7 @@ """ import TestGyp -from XCodeDetect import XCodeDetect +import XCodeDetect test = TestGyp.TestGyp(formats=['ninja'], platforms=['darwin']) diff --git a/test/ios/gyptest-per-config-settings.py b/test/ios/gyptest-per-config-settings.py index c10d1f6e..a19d2cad 100644 --- a/test/ios/gyptest-per-config-settings.py +++ b/test/ios/gyptest-per-config-settings.py @@ -17,7 +17,7 @@ import tempfile import TestGyp -from XCodeDetect import XCodeDetect +import XCodeDetect test = TestGyp.TestGyp(formats=['ninja', 'xcode'], platforms=['darwin'], disable="This test is currently disabled: https://crbug.com/483696.") diff --git a/test/ios/gyptest-watch.py b/test/ios/gyptest-watch.py index 93e4150b..d95bf83d 100755 --- a/test/ios/gyptest-watch.py +++ b/test/ios/gyptest-watch.py @@ -5,7 +5,7 @@ from __future__ import print_function import TestGyp -from XCodeDetect import XCodeDetect +import XCodeDetect test = TestGyp.TestGyp(formats=['ninja', 'xcode'], platforms=['darwin'], disable="This test is currently disabled: https://crbug.com/483696.") diff --git a/test/mac/gyptest-app-assets-catalog.py b/test/mac/gyptest-app-assets-catalog.py index 7a215e93..cfda496f 100755 --- a/test/mac/gyptest-app-assets-catalog.py +++ b/test/mac/gyptest-app-assets-catalog.py @@ -15,7 +15,7 @@ import subprocess import TestGyp -from XCodeDetect import XCodeDetect +import XCodeDetect test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], platforms=['darwin'], disable="This test is currently disabled: https://crbug.com/483696.") diff --git a/test/mac/gyptest-app.py b/test/mac/gyptest-app.py index 1351bca8..aaf89424 100755 --- a/test/mac/gyptest-app.py +++ b/test/mac/gyptest-app.py @@ -16,7 +16,7 @@ import sys import TestGyp -from XCodeDetect import XCodeDetect +import XCodeDetect test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], platforms=['darwin'], disable="This test is currently disabled: https://crbug.com/483696.") diff --git a/test/mac/gyptest-archs.py b/test/mac/gyptest-archs.py index 3bbd68fc..1dd8633e 100644 --- a/test/mac/gyptest-archs.py +++ b/test/mac/gyptest-archs.py @@ -20,7 +20,7 @@ result_file = test.built_file_path('Test', chdir='archs') test.must_exist(result_file) -if XCodeDetect.XCodeDetect.Version() >= '0500': +if XCodeDetect.Version() >= '0500': expected_type = ['x86_64'] else: expected_type = ['i386'] diff --git a/test/mac/gyptest-clang-cxx-library.py b/test/mac/gyptest-clang-cxx-library.py index 2c4b0d8f..8aa77e90 100644 --- a/test/mac/gyptest-clang-cxx-library.py +++ b/test/mac/gyptest-clang-cxx-library.py @@ -13,7 +13,7 @@ test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode'], platforms=['darwin']) # Xcode 4.2 on OS X 10.6 doesn't install the libc++ headers, don't run this test there. -if XCodeDetect.XCodeDetect.Version() <= '0420': +if XCodeDetect.Version() <= '0420': test.skip_test('test only on XCode > 0420') if test.format == 'make': diff --git a/test/mac/gyptest-objc-gc.py b/test/mac/gyptest-objc-gc.py index b6bcb6bc..ee604e8d 100644 --- a/test/mac/gyptest-objc-gc.py +++ b/test/mac/gyptest-objc-gc.py @@ -9,7 +9,7 @@ """ import TestGyp -from XCodeDetect import XCodeDetect +import XCodeDetect # set |match| to ignore build stderr output. test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], match=lambda a, b: True, platforms=['darwin']) diff --git a/test/mac/gyptest-postbuild-fail.py b/test/mac/gyptest-postbuild-fail.py index 5d448579..d21572cc 100755 --- a/test/mac/gyptest-postbuild-fail.py +++ b/test/mac/gyptest-postbuild-fail.py @@ -13,7 +13,7 @@ import sys import TestGyp -from XCodeDetect import XCodeDetect +import XCodeDetect # set |match| to ignore build stderr output. test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], match=lambda a, b: True, platforms=['darwin']) diff --git a/test/mac/gyptest-strip.py b/test/mac/gyptest-strip.py index 96157e62..a970ec89 100755 --- a/test/mac/gyptest-strip.py +++ b/test/mac/gyptest-strip.py @@ -14,7 +14,7 @@ import subprocess import TestGyp -from XCodeDetect import XCodeDetect +import XCodeDetect test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], disable="This test is currently disabled: https://crbug.com/483696.", platforms=['darwin']) diff --git a/test/mac/gyptest-swift-library.py b/test/mac/gyptest-swift-library.py index 08a6f456..a225ca44 100644 --- a/test/mac/gyptest-swift-library.py +++ b/test/mac/gyptest-swift-library.py @@ -14,7 +14,7 @@ import subprocess import TestGyp -from XCodeDetect import XCodeDetect +import XCodeDetect test = TestGyp.TestGyp(formats=['xcode'], disable="This test is currently disabled: https://crbug.com/483696.", platforms=['darwin']) diff --git a/test/mac/gyptest-xcode-env-order.py b/test/mac/gyptest-xcode-env-order.py index a2d0ea9b..e84467c9 100755 --- a/test/mac/gyptest-xcode-env-order.py +++ b/test/mac/gyptest-xcode-env-order.py @@ -8,7 +8,7 @@ Verifies that dependent Xcode settings are processed correctly. """ import TestGyp -from XCodeDetect import XCodeDetect +import XCodeDetect test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], disable="This test is currently disabled: https://crbug.com/483696.", platforms=['darwin']) diff --git a/test/win/compiler-flags/optimizations.gyp b/test/win/compiler-flags/optimizations.gyp index e63096f0..0dbc3921 100644 --- a/test/win/compiler-flags/optimizations.gyp +++ b/test/win/compiler-flags/optimizations.gyp @@ -124,15 +124,35 @@ 'sources': ['hello.cc'], }, { - 'target_name': 'test_opt_neither', + 'target_name': 'test_opt_inline_disable', 'type': 'executable', 'msvs_settings': { 'VCCLCompilerTool': { - 'FavorSizeOrSpeed': '0' + 'InlineFunctionExpansion': '3' } }, 'sources': ['hello.cc'], }, + { + 'target_name': 'test_opt_msbuild_inline_disable', + 'type': 'executable', + 'msbuild_settings': { + 'ClCompile': { + 'InlineFunctionExpansion': 'Disabled' + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_link_msbuild_link_incremental', + 'type': 'executable', + 'msbuild_settings': { + 'Link': { + 'LinkIncremental': 'false', + }, + }, + 'sources': ['hello.cc'], + }, { 'target_name': 'test_opt_speed', 'type': 'executable', diff --git a/test/win/gyptest-msbuild-cl-optimizations.py b/test/win/gyptest-msbuild-cl-optimizations.py new file mode 100644 index 00000000..9e1ee970 --- /dev/null +++ b/test/win/gyptest-msbuild-cl-optimizations.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure optimization settings are extracted properly. +""" + +import TestGyp + +test = TestGyp.TestGyp(platforms=['win32']) + +CHDIR = 'compiler-flags' +test.run_gyp('optimizations.gyp', chdir=CHDIR) + +# It's hard to map flags to output contents in a non-fragile way (especially +# handling both 2008/2010), so just verify the correct ninja command line +# contents. + +ninja_file = test.built_file_path('obj/test_opt_off.ninja', chdir=CHDIR) +test.must_contain(ninja_file, 'cflags = /Od') + +ninja_file = test.built_file_path('obj/test_opt_lev_size.ninja', chdir=CHDIR) +test.must_contain(ninja_file, 'cflags = /O1') + +ninja_file = test.built_file_path('obj/test_opt_lev_speed.ninja', chdir=CHDIR) +test.must_contain(ninja_file, 'cflags = /O2') + +ninja_file = test.built_file_path('obj/test_opt_lev_max.ninja', chdir=CHDIR) +test.must_contain(ninja_file, 'cflags = /Ox') + +ninja_file = test.built_file_path('obj/test_opt_unset.ninja', chdir=CHDIR) +test.must_not_contain(ninja_file, '/Od') +test.must_not_contain(ninja_file, '/O1') +test.must_not_contain(ninja_file, '/Ox') +# Set by default if none specified. +test.must_contain(ninja_file, '/O2') + +ninja_file = test.built_file_path('obj/test_opt_fpo.ninja', chdir=CHDIR) +test.must_contain(ninja_file, '/Oy') +test.must_not_contain(ninja_file, '/Oy-') + +ninja_file = test.built_file_path('obj/test_opt_fpo_off.ninja', chdir=CHDIR) +test.must_contain(ninja_file, '/Oy-') + +ninja_file = test.built_file_path('obj/test_opt_intrinsic.ninja', chdir=CHDIR) +test.must_contain(ninja_file, '/Oi') +test.must_not_contain(ninja_file, '/Oi-') + +ninja_file = test.built_file_path('obj/test_opt_intrinsic_off.ninja', chdir=CHDIR) +test.must_contain(ninja_file, '/Oi-') + +ninja_file = test.built_file_path('obj/test_opt_inline_off.ninja', chdir=CHDIR) +test.must_contain(ninja_file, '/Ob0') + +ninja_file = test.built_file_path('obj/test_opt_inline_manual.ninja', chdir=CHDIR) +test.must_contain(ninja_file, '/Ob1') + +ninja_file = test.built_file_path('obj/test_opt_inline_auto.ninja', chdir=CHDIR) +test.must_contain(ninja_file, '/Ob2') + +ninja_file = test.built_file_path('obj/test_opt_neither.ninja', chdir=CHDIR) +test.must_not_contain(ninja_file, '/Os') +test.must_not_contain(ninja_file, '/Ot') + +ninja_file = test.built_file_path('obj/test_opt_size.ninja', chdir=CHDIR) +test.must_contain(ninja_file, '/Os') + +ninja_file = test.built_file_path('obj/test_opt_speed.ninja', chdir=CHDIR) +test.must_contain(ninja_file, '/Ot') + +ninja_file = test.built_file_path('obj/test_opt_wpo.ninja', chdir=CHDIR) +test.must_contain(ninja_file, '/GL') + +ninja_file = test.built_file_path('obj/test_opt_sp.ninja', chdir=CHDIR) +test.must_contain(ninja_file, '/GF') + +ninja_file = test.built_file_path('obj/test_opt_sp_off.ninja', chdir=CHDIR) +test.must_not_contain(ninja_file, '/GF') + +ninja_file = test.built_file_path('obj/test_opt_fso.ninja', chdir=CHDIR) +test.must_contain(ninja_file, '/GT') + +ninja_file = test.built_file_path('obj/test_opt_fso_off.ninja', chdir=CHDIR) +test.must_not_contain(ninja_file, '/GT') + +test.pass_test() From 658e7a3a0c68ff8e89b2f8cc9fc6b13661df15e3 Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Thu, 11 Apr 2019 19:08:24 -0400 Subject: [PATCH 02/12] test: fix msvs conversion wanrings fixtures --- gyp/MSVS/MSVSSettings.py | 8 ++++---- gyp/unit_tests/MSVSSettings_test.py | 27 +++++++++------------------ 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/gyp/MSVS/MSVSSettings.py b/gyp/MSVS/MSVSSettings.py index 41b0360d..8f79502a 100644 --- a/gyp/MSVS/MSVSSettings.py +++ b/gyp/MSVS/MSVSSettings.py @@ -475,7 +475,7 @@ def ConvertToMSBuildSettings(msvs_settings, stderr=sys.stderr): try: setting_converter(msvs_value, msbuild_settings) except ValueError as e: - print('Warning: while converting %s/%s to MSBuild, %s' % (msvs_tool_name, msvs_setting, e), file=stderr) + print('Warning: while converting %s/%s to MSBuild, %s' % (msvs_tool_name, msvs_setting, e), file=stderr) return msbuild_settings @@ -874,9 +874,9 @@ def _ValidateSettings(validators, settings, stderr): _Renamed(_link, 'ResourceOnlyDLL', 'NoEntryPoint', _boolean) # /NOENTRY _Renamed(_link, 'SwapRunFromNet', 'SwapRunFromNET', _boolean) # /SWAPRUN:NET -_Moved(_link, 'GenerateManifest', 'GenerateManifest', _boolean) -_Moved(_link, 'IgnoreImportLibrary', 'IgnoreImportLibrary', _boolean) -_Moved(_link, 'LinkIncremental', 'LinkIncremental', _newly_boolean) +_Moved(_link, 'GenerateManifest', '', _boolean) +_Moved(_link, 'IgnoreImportLibrary', '', _boolean) +_Moved(_link, 'LinkIncremental', '', _newly_boolean) _Moved(_link, 'LinkLibraryDependencies', 'ProjectReference', _boolean) _Moved(_link, 'UseLibraryDependencyInputs', 'ProjectReference', _boolean) diff --git a/gyp/unit_tests/MSVSSettings_test.py b/gyp/unit_tests/MSVSSettings_test.py index caf2e994..d0383db9 100644 --- a/gyp/unit_tests/MSVSSettings_test.py +++ b/gyp/unit_tests/MSVSSettings_test.py @@ -644,24 +644,15 @@ def testConvertToMSBuildSettings_warnings(self): actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(msvs_settings, self.stderr) self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) self._ExpectedWarnings([ - 'Warning: while converting VCCLCompilerTool/BasicRuntimeChecks to ' - 'MSBuild, index value (12) not in expected range [0, 4)', - 'Warning: while converting VCCLCompilerTool/BrowseInformation to ' - 'MSBuild, index value (21) not in expected range [0, 3)', - 'Warning: while converting VCCLCompilerTool/UsePrecompiledHeader to ' - 'MSBuild, index value (13) not in expected range [0, 3)', - 'Warning: while converting VCCLCompilerTool/GeneratePreprocessedFile to ' - 'MSBuild, value must be one of [0, 1, 2]; got 14', - - 'Warning: while converting VCLinkerTool/Driver to ' - 'MSBuild, index value (10) not in expected range [0, 4)', - 'Warning: while converting VCLinkerTool/LinkTimeCodeGeneration to ' - 'MSBuild, index value (31) not in expected range [0, 5)', - 'Warning: while converting VCLinkerTool/ErrorReporting to ' - 'MSBuild, index value (21) not in expected range [0, 3)', - 'Warning: while converting VCLinkerTool/FixedBaseAddress to ' - 'MSBuild, index value (6) not in expected range [0, 3)', - ]) + 'Warning: while converting VCCLCompilerTool/BasicRuntimeChecks to MSBuild, index value (12) not in expected range [0, 4)', + 'Warning: while converting VCCLCompilerTool/BrowseInformation to MSBuild, index value (21) not in expected range [0, 3)', + 'Warning: while converting VCCLCompilerTool/GeneratePreprocessedFile to MSBuild, value must be one of [0, 1, 2]; got 14', + 'Warning: while converting VCCLCompilerTool/UsePrecompiledHeader to MSBuild, index value (13) not in expected range [0, 3)', + 'Warning: while converting VCLinkerTool/Driver to MSBuild, index value (10) not in expected range [0, 4)', + 'Warning: while converting VCLinkerTool/ErrorReporting to MSBuild, index value (21) not in expected range [0, 4)', + 'Warning: while converting VCLinkerTool/FixedBaseAddress to MSBuild, index value (6) not in expected range [0, 3)', + 'Warning: while converting VCLinkerTool/LinkTimeCodeGeneration to MSBuild, index value (31) not in expected range [0, 5)', + ]) def testConvertToMSBuildSettings_full_synthetic(self): """Tests conversion of all the MSBuild settings.""" From 303086e1aad79e29f8888d8aaa0a9bf46b2cbac5 Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Fri, 12 Apr 2019 19:30:23 -0400 Subject: [PATCH 03/12] test: mac yak shaving --- gyp/XCodeDetect.py | 5 +- gyp/buildtime_helpers/mac_tool.py | 10 ++- gyp/xcode_emulation.py | 11 ++- gyptest.py | 2 +- pylib/__init__.py | 0 pylib/util.py | 21 ----- test/ios/gyptest-app-ios-assets-catalog.py | 3 + test/ios/gyptest-archs.py | 9 +-- test/ios/gyptest-copies-with-xcode-envvars.py | 79 +++++++++---------- test/ios/gyptest-framework.py | 4 +- test/mac/gyptest-deployment-target.py | 15 +--- 11 files changed, 70 insertions(+), 89 deletions(-) delete mode 100644 pylib/__init__.py delete mode 100644 pylib/util.py diff --git a/gyp/XCodeDetect.py b/gyp/XCodeDetect.py index a8a23461..fe6b5a77 100644 --- a/gyp/XCodeDetect.py +++ b/gyp/XCodeDetect.py @@ -36,7 +36,10 @@ def GetSdkVersionInfoItem(sdk, item): # Since the CLT has no SDK paths anyway, returning None is the most sensible route and should still do the right thing. try: return run('xcrun', '--sdk', sdk, item) - except subprocess.CalledProcessError: + except subprocess.CalledProcessError as e: + stdout = e.output + status = e.returncode + cmd = ' '.join(e.cmd) return None diff --git a/gyp/buildtime_helpers/mac_tool.py b/gyp/buildtime_helpers/mac_tool.py index 84f88639..8769ff72 100644 --- a/gyp/buildtime_helpers/mac_tool.py +++ b/gyp/buildtime_helpers/mac_tool.py @@ -137,7 +137,9 @@ def _CopyStringsFile(self, source, dest): # on invalid files. Do the same kind of validation. import CoreFoundation s = open(source, 'rb').read() + # noinspection PyUnresolvedReferences d = CoreFoundation.CFDataCreate(None, s, len(s)) + # noinspection PyUnresolvedReferences _, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None) if error: return @@ -175,7 +177,9 @@ def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys): # Insert synthesized key/value pairs (e.g. BuildMachineOSBuild). plist = plistlib.readPlistFromString(lines) if keys: - plist.update(json.loads(keys[0])) + j = json.loads(keys[0]) + j = dict([i for i in j.items() if i[0] and i[1]]) + plist.update(j) lines = plistlib.writePlistToString(plist) # Go through all the environment variables and replace them as variables in @@ -284,7 +288,7 @@ def ExecFilterLibtool(self, *cmd_list): def ExecPackageIosFramework(self, framework): # Find the name of the binary based on the part before the ".framework". binary = os.path.basename(framework).split('.')[0] - module_path = os.path.join(framework, 'Modules'); + module_path = os.path.join(framework, 'Modules') if not os.path.exists(module_path): os.mkdir(module_path) module_template = 'framework module %s {\n' \ @@ -345,7 +349,7 @@ def ExecCompileIosFrameworkHeaderMap(self, out, framework, *all_headers): WriteHmap(out, filelist) def ExecCopyIosFrameworkHeaders(self, framework, *copy_headers): - header_path = os.path.join(framework, 'Headers'); + header_path = os.path.join(framework, 'Headers') if not os.path.exists(header_path): os.makedirs(header_path) for header in copy_headers: diff --git a/gyp/xcode_emulation.py b/gyp/xcode_emulation.py index 7d96a5e7..ca7380a5 100644 --- a/gyp/xcode_emulation.py +++ b/gyp/xcode_emulation.py @@ -529,7 +529,8 @@ def _AppendPlatformVersionMinFlags(self, lst): self._Appendf(lst, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s') if 'IPHONEOS_DEPLOYMENT_TARGET' in self._Settings(): # TODO: Implement this better? - sdk_path_basename = os.path.basename(self._SdkPath()) + skd_path = self._SdkPath() + sdk_path_basename = os.path.basename(skd_path) if sdk_path_basename.lower().startswith('iphonesimulator'): self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET', '-mios-simulator-version-min=%s') else: @@ -1420,8 +1421,12 @@ def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, add 'TEMP_DIR': '${TMPDIR}', 'XCODE_VERSION_ACTUAL': XCodeDetect.Version(), } - if xcode_settings.GetPerConfigSetting('SDKROOT', configuration): - env['SDKROOT'] = xcode_settings._SdkPath(configuration) + wanted_sdk = xcode_settings.GetPerConfigSetting('SDKROOT', configuration) + if wanted_sdk: + sdk_root = xcode_settings._SdkPath(configuration) + if sdk_root is None: + raise GypError('Could not find `%s` SDK' % wanted_sdk) + env['SDKROOT'] = sdk_root else: env['SDKROOT'] = '' diff --git a/gyptest.py b/gyptest.py index 4c9e9c40..ac5d3e5c 100755 --- a/gyptest.py +++ b/gyptest.py @@ -132,7 +132,7 @@ def print_configuration_info(): if sys.platform == 'darwin': print(' Mac %s %s' % (platform.mac_ver()[0], platform.mac_ver()[2])) try: - from XCodeDetect import XCodeDetect + import XCodeDetect print(' Xcode %s' % XCodeDetect.Version()) except: pass diff --git a/pylib/__init__.py b/pylib/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pylib/util.py b/pylib/util.py deleted file mode 100644 index 45571652..00000000 --- a/pylib/util.py +++ /dev/null @@ -1,21 +0,0 @@ -from functools import wraps -from subprocess import check_output, PIPE - -def memoize(function): - memo = {} - - @wraps(function) - def wrapper(*args): - if args in memo: - return memo[args] - else: - rv = function(*args) - memo[args] = rv - return rv - return wrapper - - -def run(*cmd_args): - return check_output(cmd_args, stderr=PIPE).decode('utf-8') - - diff --git a/test/ios/gyptest-app-ios-assets-catalog.py b/test/ios/gyptest-app-ios-assets-catalog.py index d16b2c82..1bb1ba84 100755 --- a/test/ios/gyptest-app-ios-assets-catalog.py +++ b/test/ios/gyptest-app-ios-assets-catalog.py @@ -13,6 +13,9 @@ if XCodeDetect.Version() < '0600': test.skip_test('Skip test on XCode < 0600') +if not XCodeDetect.IPhoneSDKPath(): + test.skip_test('Skip test when no IPhone SDK') + test_gyp_path = 'test-assets-catalog.gyp' test_app_path = 'Test App Assets Catalog Gyp.app' test.run_gyp(test_gyp_path, chdir='app-bundle') diff --git a/test/ios/gyptest-archs.py b/test/ios/gyptest-archs.py index 151c1675..726da786 100644 --- a/test/ios/gyptest-archs.py +++ b/test/ios/gyptest-archs.py @@ -8,16 +8,13 @@ Verifies that device and simulator bundles are built correctly. """ -import collections - import TestGyp import XCodeDetect test = TestGyp.TestGyp(formats=['ninja', 'xcode'], platforms=['darwin']) -if test.format == 'xcode': - # This test appears to hang flakily. - test.skip_test() # bug=532 +if not XCodeDetect.IPhoneSDKPath(): + test.skip_test('Skip test when no IPhone SDK') test_cases = [ ('Default', 'TestArch32Bits', ['i386']), @@ -40,7 +37,7 @@ for configuration, target, archs in test_cases: is_device_build = configuration.endswith('-iphoneos') - kwds = collections.defaultdict(list) + kwds = {} if test.format == 'xcode': if is_device_build: configuration, sdk = configuration.split('-') diff --git a/test/ios/gyptest-copies-with-xcode-envvars.py b/test/ios/gyptest-copies-with-xcode-envvars.py index c7ae79d5..53ebe8e7 100644 --- a/test/ios/gyptest-copies-with-xcode-envvars.py +++ b/test/ios/gyptest-copies-with-xcode-envvars.py @@ -11,44 +11,41 @@ """ import TestGyp - -import os -import stat -import sys - - -test = TestGyp.TestGyp(formats=['ninja', 'xcode']) - -if sys.platform == 'darwin': - test.run_gyp('copies-with-xcode-envvars.gyp', - chdir='copies-with-xcode-envvars') - - test.build('copies-with-xcode-envvars.gyp', chdir='copies-with-xcode-envvars') - - wrapper_name = 'copies-with-xcode-envvars.app/' - contents_path = wrapper_name - out_path = test.built_file_path('file0', chdir='copies-with-xcode-envvars') - test.must_contain(out_path, 'file0 contents\n') - out_path = test.built_file_path(wrapper_name + 'file1', chdir='copies-with-xcode-envvars') - test.must_contain(out_path, 'file1 contents\n') - out_path = test.built_file_path(contents_path + 'file2', chdir='copies-with-xcode-envvars') - test.must_contain(out_path, 'file2 contents\n') - out_path = test.built_file_path(contents_path + 'file3', chdir='copies-with-xcode-envvars') - test.must_contain(out_path, 'file3 contents\n') - out_path = test.built_file_path(contents_path + 'testimages/file4', chdir='copies-with-xcode-envvars') - test.must_contain(out_path, 'file4 contents\n') - out_path = test.built_file_path(contents_path + 'Java/file5', chdir='copies-with-xcode-envvars') - test.must_contain(out_path, 'file5 contents\n') - out_path = test.built_file_path(contents_path + 'Frameworks/file6', chdir='copies-with-xcode-envvars') - test.must_contain(out_path, 'file6 contents\n') - out_path = test.built_file_path(contents_path + 'Frameworks/file7', chdir='copies-with-xcode-envvars') - test.must_contain(out_path, 'file7 contents\n') - out_path = test.built_file_path(contents_path + 'SharedFrameworks/file8', chdir='copies-with-xcode-envvars') - test.must_contain(out_path, 'file8 contents\n') - out_path = test.built_file_path(contents_path + 'SharedSupport/file9', chdir='copies-with-xcode-envvars') - test.must_contain(out_path, 'file9 contents\n') - out_path = test.built_file_path(contents_path + 'PlugIns/file10', chdir='copies-with-xcode-envvars') - test.must_contain(out_path, 'file10 contents\n') - out_path = test.built_file_path(contents_path + 'XPCServices/file11', chdir='copies-with-xcode-envvars') - test.must_contain(out_path, 'file11 contents\n') - test.pass_test() +import XCodeDetect + +test = TestGyp.TestGyp(formats=['ninja', 'xcode'], platforms=['darwin']) + +if not XCodeDetect.IPhoneSDKPath(): + test.skip_test('Skip test when no IPhone SDK') + +test.run_gyp('copies-with-xcode-envvars.gyp', chdir='copies-with-xcode-envvars') + +test.build('copies-with-xcode-envvars.gyp', chdir='copies-with-xcode-envvars') + +wrapper_name = 'copies-with-xcode-envvars.app/' +contents_path = wrapper_name +out_path = test.built_file_path('file0', chdir='copies-with-xcode-envvars') +test.must_contain(out_path, 'file0 contents\n') +out_path = test.built_file_path(wrapper_name + 'file1', chdir='copies-with-xcode-envvars') +test.must_contain(out_path, 'file1 contents\n') +out_path = test.built_file_path(contents_path + 'file2', chdir='copies-with-xcode-envvars') +test.must_contain(out_path, 'file2 contents\n') +out_path = test.built_file_path(contents_path + 'file3', chdir='copies-with-xcode-envvars') +test.must_contain(out_path, 'file3 contents\n') +out_path = test.built_file_path(contents_path + 'testimages/file4', chdir='copies-with-xcode-envvars') +test.must_contain(out_path, 'file4 contents\n') +out_path = test.built_file_path(contents_path + 'Java/file5', chdir='copies-with-xcode-envvars') +test.must_contain(out_path, 'file5 contents\n') +out_path = test.built_file_path(contents_path + 'Frameworks/file6', chdir='copies-with-xcode-envvars') +test.must_contain(out_path, 'file6 contents\n') +out_path = test.built_file_path(contents_path + 'Frameworks/file7', chdir='copies-with-xcode-envvars') +test.must_contain(out_path, 'file7 contents\n') +out_path = test.built_file_path(contents_path + 'SharedFrameworks/file8', chdir='copies-with-xcode-envvars') +test.must_contain(out_path, 'file8 contents\n') +out_path = test.built_file_path(contents_path + 'SharedSupport/file9', chdir='copies-with-xcode-envvars') +test.must_contain(out_path, 'file9 contents\n') +out_path = test.built_file_path(contents_path + 'PlugIns/file10', chdir='copies-with-xcode-envvars') +test.must_contain(out_path, 'file10 contents\n') +out_path = test.built_file_path(contents_path + 'XPCServices/file11', chdir='copies-with-xcode-envvars') +test.must_contain(out_path, 'file11 contents\n') +test.pass_test() diff --git a/test/ios/gyptest-framework.py b/test/ios/gyptest-framework.py index bed6ae62..db4b6db4 100755 --- a/test/ios/gyptest-framework.py +++ b/test/ios/gyptest-framework.py @@ -10,8 +10,8 @@ if XCodeDetect.Version() < '0700': test.skip_test('Skip test on XCode < 0700') -if test.format == 'xcode-ninja': - test.skip_test() +if not XCodeDetect.IPhoneSDKPath(): + test.skip_test('Skip test when no IPhone SDK') test.run_gyp('framework.gyp', chdir='framework') diff --git a/test/mac/gyptest-deployment-target.py b/test/mac/gyptest-deployment-target.py index c7eabde6..05d9695b 100644 --- a/test/mac/gyptest-deployment-target.py +++ b/test/mac/gyptest-deployment-target.py @@ -10,18 +10,11 @@ import TestGyp -import sys +test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode'], platforms=['darwin']) -if sys.platform == 'darwin': - test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode']) +test.run_gyp('deployment-target.gyp', chdir='deployment-target') - if test.format == 'make': - # This is failing because of a deprecation warning for libstdc++. - test.skip_test() # bug=533 +test.build('deployment-target.gyp', test.ALL, chdir='deployment-target') - test.run_gyp('deployment-target.gyp', chdir='deployment-target') - - test.build('deployment-target.gyp', test.ALL, chdir='deployment-target') - - test.pass_test() +test.pass_test() From 7db71f7fcb1e24ece87ad4b66efc52d551d41671 Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Thu, 11 Apr 2019 18:08:54 -0400 Subject: [PATCH 04/12] meta: more macOS on travis --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.travis.yml b/.travis.yml index feed5970..2cb8613c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -63,6 +63,17 @@ matrix: <<: *osx-setup-steps script: pipenv run -v test -f make,ninja + - name: "macOS: XCode10.2 test with make and ninja on Python 3.7" + os: osx + osx_image: xcode10.2 # provides Python 3.7.2 + language: cpp # 'language: python' is not yet supported on macOS + install: + - HOMEBREW_NO_AUTO_UPDATE=1 brew install ninja + - pip3 install --upgrade pip pipenv + - pipenv install --dev + - pipenv install PyObjC # This is not in the Pipfile because it breaks other platforms https://github.com/pypa/pipenv/issues/3187 + script: pipenv run -v test -f make,ninja + - name: "lint with Python 2.7" python: '2.7' <<: *linux-setup-steps From 2a26c00c4469cd997e92b9f1dc71da0c6d9c9aa3 Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Mon, 29 Apr 2019 11:14:07 -0400 Subject: [PATCH 05/12] fixup! delint --- gyp/XCodeDetect.py | 6 ++-- gyp/__init__.py | 68 ++++++++++++---------------------------------- gyp/common.py | 36 ++++++++++++++++++++++-- gyp/input.py | 14 +++++----- 4 files changed, 61 insertions(+), 63 deletions(-) diff --git a/gyp/XCodeDetect.py b/gyp/XCodeDetect.py index fe6b5a77..11a70453 100644 --- a/gyp/XCodeDetect.py +++ b/gyp/XCodeDetect.py @@ -1,6 +1,6 @@ """Simplify access to Xcode information.""" import subprocess -from common import memoize +from gyp.common import memoize, DebugOutput, DEBUG_GENERAL def run(*cmd_args): @@ -37,9 +37,7 @@ def GetSdkVersionInfoItem(sdk, item): try: return run('xcrun', '--sdk', sdk, item) except subprocess.CalledProcessError as e: - stdout = e.output - status = e.returncode - cmd = ' '.join(e.cmd) + DebugOutput(DEBUG_GENERAL, 'cmd=%s\nstatus=%s\noutput=%s' % (' '.join(e.cmd), e.returncode, e.output)) return None diff --git a/gyp/__init__.py b/gyp/__init__.py index 68e047f7..0cad50fa 100644 --- a/gyp/__init__.py +++ b/gyp/__init__.py @@ -13,45 +13,15 @@ import re import shlex import sys -import traceback from collections import OrderedDict -from gyp.common import GypError -if not 'basestring' in __builtins__: - basestring = str - -# Default debug modes for GYP -debug = {} - -# List of "official" debug modes, but you can use anything you like. -DEBUG_GENERAL = 'general' -DEBUG_VARIABLES = 'variables' -DEBUG_INCLUDES = 'includes' - - -def DebugOutput(mode, message, *args): - if 'all' in gyp.debug or mode in gyp.debug: - ctx = ('unknown', 0, 'unknown') - try: - f = traceback.extract_stack(limit=2) - if f: - ctx = f[0][:3] - except: - pass - if args: - message %= args - print('%s:%s:%d:%s %s' % (mode.upper(), os.path.basename(ctx[0]), ctx[1], ctx[2], message)) - - -def FindBuildFiles(): - extension = '.gyp' - files = os.listdir(os.getcwd()) - build_files = [] - for file in files: - if file.endswith(extension): - build_files.append(file) - return build_files +from gyp.common import debug_modes, GypError, DebugOutput, FindBuildFiles, DEBUG_GENERAL +try: + # noinspection PyUnresolvedReferences,PyUnboundLocalVariable + basestring +except NameError: + basestring = str def Load(build_files, output_format, default_variables, includes, params, depth): """ @@ -197,8 +167,7 @@ def FixPath(path): return os.path.curdir return path - def Noop(value): - return value + Noop = lambda x: x # We always want to ignore the environment when regenerating, to avoid # duplicate or changed flags in the environment at the time of regeneration. @@ -217,7 +186,7 @@ def Noop(value): elif options.use_environment and env_name and os.environ.get(env_name): flags.append(FormatOpt(opt, value_predicate(os.environ.get(env_name)))) elif action in ('store_true', 'store_false'): - if ((action == 'store_true' and value) or (action == 'store_false' and not value)): + if (action == 'store_true' and value) or (action == 'store_false' and not value): flags.append(opt) elif options.use_environment and env_name: print('Warning: environment regeneration unimplemented for %s flag %r env_name %r' % (action, opt, env_name), file=sys.stderr) @@ -250,13 +219,13 @@ def add_option(self, *args, **kw): # The path type is needed for regenerating, for optparse we can just treat # it as a string. - type = kw.get('type') - if type == 'path': + type_arg = kw.get('type') + if type_arg == 'path': kw['type'] = 'string' self.__regeneratable_options[dest] = { 'action': kw.get('action'), - 'type': type, + 'type': type_arg, 'env_name': env_name, 'opt': args[0], } @@ -325,9 +294,9 @@ def gyp_main(args): # If no output_format was given on the command line, then check the env variable. generate_formats = [] if options.use_environment: - generate_formats = os.environ.get('GYP_GENERATORS', []) - if generate_formats: - generate_formats = re.split(r'[\s,]', generate_formats) + env_generator_formats = os.environ.get('GYP_GENERATORS') + if env_generator_formats: + generate_formats = re.split(r'[\s,]', env_generator_formats) if generate_formats: options.formats = generate_formats else: @@ -344,11 +313,10 @@ def gyp_main(args): if g_o: options.generator_output = g_o - for mode in options.debug: - gyp.debug[mode] = 1 + debug_modes.update(options.debug) # Do an extra check to avoid work when we're not debugging. - if DEBUG_GENERAL in gyp.debug: + if DEBUG_GENERAL in debug_modes: DebugOutput(DEBUG_GENERAL, 'running with these options:') for option, value in sorted(options.__dict__.items()): if option[0] == '_': @@ -404,7 +372,7 @@ def gyp_main(args): if options.defines: defines += options.defines cmdline_default_variables = NameValueListToDict(defines) - if DEBUG_GENERAL in gyp.debug: + if DEBUG_GENERAL in gyp.debug_modes: DebugOutput(DEBUG_GENERAL, "cmdline_default_variables: %s", cmdline_default_variables) # Set up includes. @@ -430,7 +398,7 @@ def gyp_main(args): if options.generator_flags: gen_flags += options.generator_flags generator_flags = NameValueListToDict(gen_flags) - if DEBUG_GENERAL in gyp.debug: + if DEBUG_GENERAL in gyp.debug_modes: DebugOutput(DEBUG_GENERAL, "generator_flags: %s", generator_flags) # Generate all requested formats (use a set in case we got one output_format request twice) diff --git a/gyp/common.py b/gyp/common.py index 0f073b0b..5fb5f5fe 100644 --- a/gyp/common.py +++ b/gyp/common.py @@ -8,10 +8,10 @@ import errno import filecmp import os -import os.path import re -import tempfile import sys +import tempfile +import traceback # A minimal memoizing decorator. It'll blow up if the args aren't immutable, among other "problems". @@ -619,3 +619,35 @@ def IsStrCanonicalInt(string): return str(i) == string except: return False + + +# Default debug modes for GYP +debug_modes = {} + +# List of "official" debug modes, but you can use anything you like. +DEBUG_GENERAL = 'general' +DEBUG_VARIABLES = 'variables' +DEBUG_INCLUDES = 'includes' + +def DebugOutput(mode, message, *args): + if 'all' in debug_modes or mode in debug_modes: + ctx = ('unknown', 0, 'unknown') + try: + f = traceback.extract_stack(limit=2) + if f: + ctx = f[0][:3] + except: + pass + if args: + message %= args + print('%s:%s:%d:%s %s' % (mode.upper(), os.path.basename(ctx[0]), ctx[1], ctx[2], message)) + + +def FindBuildFiles(): + extension = '.gyp' + files = os.listdir(os.getcwd()) + build_files = [] + for file in files: + if file.endswith(extension): + build_files.append(file) + return build_files diff --git a/gyp/input.py b/gyp/input.py index 81246a6b..ee05a3b7 100644 --- a/gyp/input.py +++ b/gyp/input.py @@ -271,7 +271,7 @@ def LoadBuildFileIncludesIntoDict(subdict, subdict_path, data, aux_data, include aux_data[subdict_path]['included'] = [] aux_data[subdict_path]['included'].append(include) - gyp.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Included File: '%s'", include) + gyp.common.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Included File: '%s'", include) MergeDicts(subdict, LoadOneBuildFile(include, data, aux_data, None), subdict_path, include) @@ -356,7 +356,7 @@ def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, de return False data['target_build_files'].add(build_file_path) - gyp.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Target Build File '%s'", build_file_path) + gyp.common.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Target Build File '%s'", build_file_path) build_file_data = LoadOneBuildFile(build_file_path, data, aux_data, includes) @@ -559,7 +559,7 @@ def ExpandVariables(input, phase, variables, build_file): matches.reverse() for match_group in matches: match = match_group.groupdict() - gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Matches: %r", match) + gyp.common.DebugOutput(gyp.DEBUG_VARIABLES, "Matches: %r", match) # match['replace'] is the substring to look for, match['type'] # is the character code for the replacement type (< > ! <| >| <@ # >@ !@), match['is_array'] contains a '[' for command @@ -681,7 +681,7 @@ def ExpandVariables(input, phase, variables, build_file): cache_key = (str(contents), build_file_dir) cached_value = cached_command_results.get(cache_key, None) if cached_value is None: - gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Executing command '%s' in directory '%s'", contents, build_file_dir) + gyp.common.DebugOutput(gyp.DEBUG_VARIABLES, "Executing command '%s' in directory '%s'", contents, build_file_dir) if command_string == 'pymod_do_main': # Date: Mon, 29 Apr 2019 11:14:24 -0400 Subject: [PATCH 06/12] fixup! msvs compiler flags --- test/win/compiler-flags/optimizations.gyp | 20 ++++++++++---------- test/win/gyptest-msbuild-cl-optimizations.py | 6 +----- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/test/win/compiler-flags/optimizations.gyp b/test/win/compiler-flags/optimizations.gyp index 0dbc3921..e40acbf4 100644 --- a/test/win/compiler-flags/optimizations.gyp +++ b/test/win/compiler-flags/optimizations.gyp @@ -143,16 +143,16 @@ }, 'sources': ['hello.cc'], }, - { - 'target_name': 'test_link_msbuild_link_incremental', - 'type': 'executable', - 'msbuild_settings': { - 'Link': { - 'LinkIncremental': 'false', - }, - }, - 'sources': ['hello.cc'], - }, + # { + # 'target_name': 'test_link_msbuild_link_incremental', + # 'type': 'executable', + # 'msbuild_settings': { + # 'Link': { + # 'LinkIncremental': 'false', + # }, + # }, + # 'sources': ['hello.cc'], + # }, { 'target_name': 'test_opt_speed', 'type': 'executable', diff --git a/test/win/gyptest-msbuild-cl-optimizations.py b/test/win/gyptest-msbuild-cl-optimizations.py index 9e1ee970..7cc980c7 100644 --- a/test/win/gyptest-msbuild-cl-optimizations.py +++ b/test/win/gyptest-msbuild-cl-optimizations.py @@ -10,7 +10,7 @@ import TestGyp -test = TestGyp.TestGyp(platforms=['win32']) +test = TestGyp.TestGyp(formats=['ninja'], platforms=['win32']) CHDIR = 'compiler-flags' test.run_gyp('optimizations.gyp', chdir=CHDIR) @@ -61,10 +61,6 @@ ninja_file = test.built_file_path('obj/test_opt_inline_auto.ninja', chdir=CHDIR) test.must_contain(ninja_file, '/Ob2') -ninja_file = test.built_file_path('obj/test_opt_neither.ninja', chdir=CHDIR) -test.must_not_contain(ninja_file, '/Os') -test.must_not_contain(ninja_file, '/Ot') - ninja_file = test.built_file_path('obj/test_opt_size.ninja', chdir=CHDIR) test.must_contain(ninja_file, '/Os') From 5016275c757be067a3955b5be60e75f88bf68314 Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Mon, 29 Apr 2019 11:22:20 -0400 Subject: [PATCH 07/12] fixup! module scoping --- gyp/input.py | 18 +++++++++--------- gyp/xcode_emulation.py | 2 +- test/ios/gyptest-app-ios-assets-catalog.py | 2 +- test/ios/gyptest-app-ios.py | 2 +- test/ios/gyptest-archs.py | 2 +- test/ios/gyptest-copies-with-xcode-envvars.py | 2 +- test/ios/gyptest-deployment-target.py | 2 +- test/ios/gyptest-extension.py | 2 +- test/ios/gyptest-framework.py | 2 +- test/ios/gyptest-per-config-settings.py | 2 +- test/ios/gyptest-watch.py | 2 +- test/mac/gyptest-app-assets-catalog.py | 2 +- test/mac/gyptest-app.py | 2 +- test/mac/gyptest-archs.py | 2 +- test/mac/gyptest-clang-cxx-library.py | 2 +- test/mac/gyptest-objc-gc.py | 2 +- test/mac/gyptest-postbuild-fail.py | 2 +- test/mac/gyptest-strip.py | 2 +- test/mac/gyptest-swift-library.py | 2 +- test/mac/gyptest-xcode-env-order.py | 2 +- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/gyp/input.py b/gyp/input.py index ee05a3b7..0fddadd1 100644 --- a/gyp/input.py +++ b/gyp/input.py @@ -15,7 +15,7 @@ import gyp.common import gyp.lib.simple_copy -from gyp.common import GypError, OrderedSet +from gyp.common import GypError, OrderedSet, DebugOutput, DEBUG_INCLUDES, DEBUG_VARIABLES if not 'unicode' in __builtins__: unicode = str @@ -271,7 +271,7 @@ def LoadBuildFileIncludesIntoDict(subdict, subdict_path, data, aux_data, include aux_data[subdict_path]['included'] = [] aux_data[subdict_path]['included'].append(include) - gyp.common.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Included File: '%s'", include) + DebugOutput(DEBUG_INCLUDES, "Loading Included File: '%s'", include) MergeDicts(subdict, LoadOneBuildFile(include, data, aux_data, None), subdict_path, include) @@ -356,7 +356,7 @@ def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, de return False data['target_build_files'].add(build_file_path) - gyp.common.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Target Build File '%s'", build_file_path) + DebugOutput(DEBUG_INCLUDES, "Loading Target Build File '%s'", build_file_path) build_file_data = LoadOneBuildFile(build_file_path, data, aux_data, includes) @@ -432,7 +432,7 @@ def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, de gyp.common.ExceptionAppend(e, 'while loading dependencies of %s' % build_file_path) raise else: - return (build_file_path, dependencies) + return build_file_path, dependencies # Look for the bracket that matches the first bracket seen in a @@ -559,7 +559,7 @@ def ExpandVariables(input, phase, variables, build_file): matches.reverse() for match_group in matches: match = match_group.groupdict() - gyp.common.DebugOutput(gyp.DEBUG_VARIABLES, "Matches: %r", match) + DebugOutput(DEBUG_VARIABLES, "Matches: %r", match) # match['replace'] is the substring to look for, match['type'] # is the character code for the replacement type (< > ! <| >| <@ # >@ !@), match['is_array'] contains a '[' for command @@ -681,7 +681,7 @@ def ExpandVariables(input, phase, variables, build_file): cache_key = (str(contents), build_file_dir) cached_value = cached_command_results.get(cache_key, None) if cached_value is None: - gyp.common.DebugOutput(gyp.DEBUG_VARIABLES, "Executing command '%s' in directory '%s'", contents, build_file_dir) + DebugOutput(DEBUG_VARIABLES, "Executing command '%s' in directory '%s'", contents, build_file_dir) if command_string == 'pymod_do_main': # Date: Mon, 29 Apr 2019 15:00:03 -0400 Subject: [PATCH 08/12] test: macOS shaving --- gyp/XCodeDetect.py | 4 +++- test/ios/app-bundle/test.gyp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gyp/XCodeDetect.py b/gyp/XCodeDetect.py index 11a70453..938b72ef 100644 --- a/gyp/XCodeDetect.py +++ b/gyp/XCodeDetect.py @@ -1,5 +1,6 @@ """Simplify access to Xcode information.""" import subprocess + from gyp.common import memoize, DebugOutput, DEBUG_GENERAL @@ -70,7 +71,8 @@ def GetIOSCodeSignIdentityKey(identity): output = run('security', 'find-identity', '-p', 'codesigning', '-v') output_lines = output.splitlines() match_lines = [line for line in output_lines if identity in line] - assert len(match_lines) == 1, ("Not exactly one codesigning fingerprints for identity: %s \n%s" % (identity, output)) + if len(match_lines) != 1: + DebugOutput(DEBUG_GENERAL, 'Not exactly one codesigning fingerprints for identity: %s\n output=\n%s' % (identity, output)) fingerprint = match_lines[0].split()[1] return fingerprint diff --git a/test/ios/app-bundle/test.gyp b/test/ios/app-bundle/test.gyp index 1b2bb0cc..396d73b1 100644 --- a/test/ios/app-bundle/test.gyp +++ b/test/ios/app-bundle/test.gyp @@ -67,7 +67,7 @@ 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', 'INFOPLIST_OUTPUT_FORMAT':'xml', 'SDKROOT': 'iphonesimulator', # -isysroot - 'IPHONEOS_DEPLOYMENT_TARGET': '5.0', + 'IPHONEOS_DEPLOYMENT_TARGET': '7.0', 'CONFIGURATION_BUILD_DIR':'build/Default', }, }, From 71cdfb9ca9365f9fc75a066448f0807cf292cb1a Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Mon, 29 Apr 2019 18:07:17 -0400 Subject: [PATCH 09/12] fixup! stable tests --- testlib/TestGyp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testlib/TestGyp.py b/testlib/TestGyp.py index dc4a2c9f..9ac31589 100644 --- a/testlib/TestGyp.py +++ b/testlib/TestGyp.py @@ -140,7 +140,7 @@ def __init__(self, gyp=None, **kw): bt = [t[0] for t in traceback.extract_stack() if 'gyptest' in t[0]] kw['description'] = bt and bt.pop() # kw_workdir = kw.get('workdir') - kw['workdir'] = mk_temp_dir(kw['description']) + kw['workdir'] = mk_temp_dir(self.format + '_' + kw['description']) kw_formats = kw.pop('formats', []) if not gyp: From aa14664fb4bcc8ac09bd0c0a5b70c11536bdb007 Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Mon, 29 Apr 2019 18:07:34 -0400 Subject: [PATCH 10/12] fixup! DebugOutput refactor --- gyp/__init__.py | 3 ++- gyp/common.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gyp/__init__.py b/gyp/__init__.py index 0cad50fa..2c1d7e0d 100644 --- a/gyp/__init__.py +++ b/gyp/__init__.py @@ -313,7 +313,8 @@ def gyp_main(args): if g_o: options.generator_output = g_o - debug_modes.update(options.debug) + if options.debug: + debug_modes.update(options.debug) # Do an extra check to avoid work when we're not debugging. if DEBUG_GENERAL in debug_modes: diff --git a/gyp/common.py b/gyp/common.py index 5fb5f5fe..9e08b6b9 100644 --- a/gyp/common.py +++ b/gyp/common.py @@ -622,7 +622,7 @@ def IsStrCanonicalInt(string): # Default debug modes for GYP -debug_modes = {} +debug_modes = set() # List of "official" debug modes, but you can use anything you like. DEBUG_GENERAL = 'general' From 481d1cfc16c2589f8b326da7fe69e0039cb2686c Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Thu, 30 May 2019 17:54:50 -0400 Subject: [PATCH 11/12] src: use pprintpp --- Pipfile | 3 ++- Pipfile.lock | 45 +++++++++---------------------------------- gyp/generator/gypd.py | 7 ++++++- 3 files changed, 17 insertions(+), 38 deletions(-) diff --git a/Pipfile b/Pipfile index 01cc9480..16aeb60e 100644 --- a/Pipfile +++ b/Pipfile @@ -5,7 +5,8 @@ name = "pypi" [dev-packages] flake8 = "*" -pywin32 = { version = "*", sys_platform = "=='win32'" } +pywin32 = {version = "*",sys_platform = "=='win32'"} +pprintpp = "*" [packages] diff --git a/Pipfile.lock b/Pipfile.lock index 6d731897..d0fdfc76 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "a506a5e632ab6e8dee1ad077d7ef24e4639a263a2cf09960f5a22affd1990de0" + "sha256": "e7e2aff6db6054694474bdecb6bb393fc78702ec6f08258d1db84a1518000bde" }, "pipfile-spec": 6, "requires": {}, @@ -15,14 +15,6 @@ }, "default": {}, "develop": { - "configparser": { - "hashes": [ - "sha256:27594cf4fc279f321974061ac69164aaebd2749af962ac8686b20503ac0bcf2d", - "sha256:9d51fe0a382f05b6b117c5e601fc219fede4a8c71703324af3f7d883aef476a3" - ], - "markers": "python_version < '3.2'", - "version": "==3.7.3" - }, "entrypoints": { "hashes": [ "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", @@ -30,16 +22,6 @@ ], "version": "==0.3" }, - "enum34": { - "hashes": [ - "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850", - "sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a", - "sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79", - "sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1" - ], - "markers": "python_version < '3.4'", - "version": "==1.1.6" - }, "flake8": { "hashes": [ "sha256:859996073f341f2670741b51ec1e67a01da142831aa1fdc6242dbf88dffbe661", @@ -48,14 +30,6 @@ "index": "pypi", "version": "==3.7.7" }, - "functools32": { - "hashes": [ - "sha256:89d824aa6c358c421a234d7f9ee0bd75933a67c29588ce50aaa3acdf4d403fa0", - "sha256:f6253dfbe0538ad2e387bd8fdfd9293c925d63553f5813c4e587745416501e6d" - ], - "markers": "python_version < '3.2'", - "version": "==3.2.3.post2" - }, "mccabe": { "hashes": [ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", @@ -63,6 +37,14 @@ ], "version": "==0.6.1" }, + "pprintpp": { + "hashes": [ + "sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d", + "sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403" + ], + "index": "pypi", + "version": "==0.4.0" + }, "pycodestyle": { "hashes": [ "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", @@ -91,15 +73,6 @@ "index": "pypi", "markers": "sys_platform == 'win32'", "version": "==224" - }, - "typing": { - "hashes": [ - "sha256:4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d", - "sha256:57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4", - "sha256:a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a" - ], - "markers": "python_version < '3.5'", - "version": "==3.6.6" } } } diff --git a/gyp/generator/gypd.py b/gyp/generator/gypd.py index 568f6d11..12f88cc0 100644 --- a/gyp/generator/gypd.py +++ b/gyp/generator/gypd.py @@ -32,7 +32,12 @@ import gyp.common -import pprint + +try: + import pprintpp as pprint +except ImportError: + import pprint + # These variables should just be spit back out as variable references. From 01b9a47ef9fd16e1d9d733d2fcb99de6f6ce8b64 Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Thu, 30 May 2019 17:55:27 -0400 Subject: [PATCH 12/12] add todo --- gyp/XCodeDetect.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gyp/XCodeDetect.py b/gyp/XCodeDetect.py index 938b72ef..2cf1ed6f 100644 --- a/gyp/XCodeDetect.py +++ b/gyp/XCodeDetect.py @@ -69,6 +69,7 @@ def GetIOSCodeSignIdentityKey(identity): if not identity: return None output = run('security', 'find-identity', '-p', 'codesigning', '-v') + # TODO(refack):could also be '0 valid identities found' output_lines = output.splitlines() match_lines = [line for line in output_lines if identity in line] if len(match_lines) != 1: