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 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/MSVS/MSVSSettings.py b/gyp/MSVS/MSVSSettings.py index db61bb08..8f79502a 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,8 +870,7 @@ 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 diff --git a/gyp/XCodeDetect.py b/gyp/XCodeDetect.py index cc7b8fac..2cf1ed6f 100644 --- a/gyp/XCodeDetect.py +++ b/gyp/XCodeDetect.py @@ -1,65 +1,83 @@ +"""Simplify access to Xcode information.""" import subprocess -import sys + +from gyp.common import memoize, DebugOutput, DEBUG_GENERAL 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() + + +@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 + + +@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 as e: + DebugOutput(DEBUG_GENERAL, 'cmd=%s\nstatus=%s\noutput=%s' % (' '.join(e.cmd), e.returncode, e.output)) + return None -class XCodeDetect(object): - """Simplify access to Xcode information.""" - _cache = {} +@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 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 IPhoneSDKPath(): + try: + path = GetSdkVersionInfoItem('iphoneos', '--show-sdk-path') + except subprocess.CalledProcessError: + return None + return path - @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 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: + 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 - @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 BuildMachineOSBuild(): + return run('sw_vers', '-buildVersion') diff --git a/gyp/__init__.py b/gyp/__init__.py index 68e047f7..2c1d7e0d 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,11 @@ def gyp_main(args): if g_o: options.generator_output = g_o - for mode in options.debug: - gyp.debug[mode] = 1 + if options.debug: + 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 +373,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 +399,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/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/common.py b/gyp/common.py index 0f073b0b..9e08b6b9 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 = set() + +# 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/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. diff --git a/gyp/input.py b/gyp/input.py index 81246a6b..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.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.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.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.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': # = '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 +1146,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 +1167,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 +1190,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 +1208,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 +1250,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 +1274,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 +1296,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 +1312,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 +1364,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 +1383,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 +1399,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,29 +1408,32 @@ 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) + 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'] = '' 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 +1444,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 +1463,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 +1484,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 +1525,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 +1541,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 +1559,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 +1590,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/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/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', }, }, diff --git a/test/ios/gyptest-app-ios-assets-catalog.py b/test/ios/gyptest-app-ios-assets-catalog.py index 537adc0b..1066fc21 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 +from gyp import XCodeDetect test = TestGyp.TestGyp(formats=['xcode', 'ninja'], platforms=['darwin']) @@ -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-app-ios.py b/test/ios/gyptest-app-ios.py index 04944f4d..4db855bf 100755 --- a/test/ios/gyptest-app-ios.py +++ b/test/ios/gyptest-app-ios.py @@ -5,11 +5,11 @@ import subprocess import TestGyp -import XCodeDetect +from gyp import XCodeDetect 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..d4b13856 100644 --- a/test/ios/gyptest-archs.py +++ b/test/ios/gyptest-archs.py @@ -8,28 +8,25 @@ Verifies that device and simulator bundles are built correctly. """ -import collections - import TestGyp -import XCodeDetect +from gyp 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']), ('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']), @@ -40,12 +37,12 @@ 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('-') 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-copies-with-xcode-envvars.py b/test/ios/gyptest-copies-with-xcode-envvars.py index c7ae79d5..707357b1 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() +from gyp 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-deployment-target.py b/test/ios/gyptest-deployment-target.py index 0e652e47..0f2e419d 100644 --- a/test/ios/gyptest-deployment-target.py +++ b/test/ios/gyptest-deployment-target.py @@ -9,11 +9,11 @@ """ import TestGyp -import XCodeDetect +from gyp import XCodeDetect 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..2da328c7 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 +from gyp 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..7920ad17 100755 --- a/test/ios/gyptest-framework.py +++ b/test/ios/gyptest-framework.py @@ -3,15 +3,15 @@ """ import TestGyp -from XCodeDetect import XCodeDetect +from gyp import XCodeDetect test = TestGyp.TestGyp(formats=['ninja'], platforms=['darwin']) 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/ios/gyptest-per-config-settings.py b/test/ios/gyptest-per-config-settings.py index c10d1f6e..3f8c0c70 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 +from gyp 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..610f99fd 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 +from gyp 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..e33c4536 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 +from gyp 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..a34384e1 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 +from gyp 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..ac8da4b5 100644 --- a/test/mac/gyptest-archs.py +++ b/test/mac/gyptest-archs.py @@ -11,7 +11,7 @@ import subprocess import TestGyp -import XCodeDetect +from gyp import XCodeDetect test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], platforms=['darwin']) @@ -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..9150583d 100644 --- a/test/mac/gyptest-clang-cxx-library.py +++ b/test/mac/gyptest-clang-cxx-library.py @@ -9,11 +9,11 @@ """ import TestGyp -import XCodeDetect +from gyp import XCodeDetect 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-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() diff --git a/test/mac/gyptest-objc-gc.py b/test/mac/gyptest-objc-gc.py index b6bcb6bc..91d26638 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 +from gyp 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..9dbeb6a3 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 +from gyp 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..28a03c69 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 +from gyp 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..be52b524 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 +from gyp 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..680003e7 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 +from gyp 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..e40acbf4 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..7cc980c7 --- /dev/null +++ b/test/win/gyptest-msbuild-cl-optimizations.py @@ -0,0 +1,85 @@ +#!/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(formats=['ninja'], 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_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() 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: