diff --git a/tools/gyp/pylib/gyp/MSVSNew.py b/tools/gyp/pylib/gyp/MSVSNew.py index 740ef2c73fa71b..76c4b95c0c3e82 100644 --- a/tools/gyp/pylib/gyp/MSVSNew.py +++ b/tools/gyp/pylib/gyp/MSVSNew.py @@ -7,7 +7,6 @@ import hashlib import os import random -from operator import attrgetter import gyp.common @@ -60,6 +59,9 @@ def __cmp__(self, other): # Sort by name then guid (so things are in order on vs2008). return cmp((self.name, self.get_guid()), (other.name, other.get_guid())) + def __lt__(self, other): + return self.__cmp__(other) < 0 + class MSVSFolder(MSVSSolutionEntry): """Folder in a Visual Studio project or solution.""" @@ -87,7 +89,7 @@ def __init__(self, path, name = None, entries = None, self.guid = guid # Copy passed lists (or set to empty lists) - self.entries = sorted(entries or [], key=attrgetter('path')) + self.entries = sorted(list(entries or [])) self.items = list(items or []) self.entry_type_guid = ENTRY_TYPE_GUIDS['folder'] @@ -231,7 +233,7 @@ def Write(self, writer=gyp.common.WriteOnDiff): if isinstance(e, MSVSFolder): entries_to_check += e.entries - all_entries = sorted(all_entries, key=attrgetter('path')) + all_entries = sorted(all_entries) # Open file and print header f = writer(self.path) diff --git a/tools/gyp/pylib/gyp/MSVSSettings.py b/tools/gyp/pylib/gyp/MSVSSettings.py index 0f53ff87c77d54..065a339a8025e5 100644 --- a/tools/gyp/pylib/gyp/MSVSSettings.py +++ b/tools/gyp/pylib/gyp/MSVSSettings.py @@ -467,7 +467,7 @@ def ConvertToMSBuildSettings(msvs_settings, stderr=sys.stderr): 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) + '%s' % (msvs_tool_name, msvs_setting, e), file=stderr) else: _ValidateExclusionSetting(msvs_setting, msvs_tool, @@ -477,7 +477,7 @@ def ConvertToMSBuildSettings(msvs_settings, stderr=sys.stderr): stderr) else: print('Warning: unrecognized tool %s while converting to ' - 'MSBuild.' % msvs_tool_name, file=stderr) + 'MSBuild.' % msvs_tool_name, file=stderr) return msbuild_settings @@ -522,8 +522,8 @@ def _ValidateSettings(validators, settings, stderr): try: tool_validators[setting](value) except ValueError as e: - print('Warning: for %s/%s, %s' % (tool_name, setting, e), - file=stderr) + print('Warning: for %s/%s, %s' % + (tool_name, setting, e), file=stderr) else: _ValidateExclusionSetting(setting, tool_validators, @@ -598,7 +598,6 @@ def _ValidateSettings(validators, settings, stderr): _Same(_compile, 'UseFullPaths', _boolean) # /FC _Same(_compile, 'WholeProgramOptimization', _boolean) # /GL _Same(_compile, 'XMLDocumentationFileName', _file_name) -_Same(_compile, 'CompileAsWinRT', _boolean) # /ZW _Same(_compile, 'AssemblerOutput', _Enumeration(['NoListing', @@ -976,7 +975,9 @@ def _ValidateSettings(validators, settings, stderr): _Enumeration(['NotSet', 'Win32', # /env win32 'Itanium', # /env ia64 - 'X64'])) # /env x64 + 'X64', # /env x64 + 'ARM64', # /env arm64 + ])) _Same(_midl, 'EnableErrorChecks', _Enumeration(['EnableCustom', 'None', # /error none diff --git a/tools/gyp/pylib/gyp/MSVSSettings_test.py b/tools/gyp/pylib/gyp/MSVSSettings_test.py index 245478c8dae4ed..ce71c38a9b94fa 100755 --- a/tools/gyp/pylib/gyp/MSVSSettings_test.py +++ b/tools/gyp/pylib/gyp/MSVSSettings_test.py @@ -6,13 +6,13 @@ """Unit tests for the MSVSSettings.py file.""" -import unittest -import gyp.MSVSSettings as MSVSSettings - try: - from StringIO import StringIO # Python 2 + from cStringIO import StringIO except ImportError: - from io import StringIO # Python 3 + from io import StringIO + +import unittest +import gyp.MSVSSettings as MSVSSettings class TestSequenceFunctions(unittest.TestCase): @@ -1085,6 +1085,7 @@ def testConvertToMSBuildSettings_full_synthetic(self): 'GenerateManifest': 'true', 'IgnoreImportLibrary': 'true', 'LinkIncremental': 'false'}} + self.maxDiff = 9999 # on failure display a long diff actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( msvs_settings, self.stderr) @@ -1476,6 +1477,7 @@ def testConvertToMSBuildSettings_actual(self): 'ResourceOutputFileName': '$(IntDir)$(TargetFileName).embed.manifest.resfdsf'} } + self.maxDiff = 9999 # on failure display a long diff actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( msvs_settings, self.stderr) diff --git a/tools/gyp/pylib/gyp/MSVSUtil.py b/tools/gyp/pylib/gyp/MSVSUtil.py index f24530b275f7cd..c8187eb3314471 100644 --- a/tools/gyp/pylib/gyp/MSVSUtil.py +++ b/tools/gyp/pylib/gyp/MSVSUtil.py @@ -14,7 +14,6 @@ 'loadable_module': 'dll', 'shared_library': 'dll', 'static_library': 'lib', - 'windows_driver': 'sys', } @@ -111,7 +110,7 @@ def ShardTargets(target_list, target_dicts): else: new_target_dicts[t] = target_dicts[t] # Shard dependencies. - for t in sorted(new_target_dicts): + for t in new_target_dicts: for deptype in ('dependencies', 'dependencies_original'): dependencies = copy.copy(new_target_dicts[t].get(deptype, [])) new_dependencies = [] diff --git a/tools/gyp/pylib/gyp/MSVSVersion.py b/tools/gyp/pylib/gyp/MSVSVersion.py index f89f1d0fc2efd6..c7cf68d3a1ba90 100644 --- a/tools/gyp/pylib/gyp/MSVSVersion.py +++ b/tools/gyp/pylib/gyp/MSVSVersion.py @@ -12,9 +12,7 @@ import gyp import glob - -def JoinPath(*args): - return os.path.normpath(os.path.join(*args)) +PY3 = bytes != str class VisualStudioVersion(object): @@ -22,7 +20,7 @@ class VisualStudioVersion(object): def __init__(self, short_name, description, solution_version, project_version, flat_sln, uses_vcxproj, - path, sdk_based, default_toolset=None, compatible_sdks=None): + path, sdk_based, default_toolset=None): self.short_name = short_name self.description = description self.solution_version = solution_version @@ -32,9 +30,6 @@ def __init__(self, short_name, description, self.path = path self.sdk_based = sdk_based self.default_toolset = default_toolset - compatible_sdks = compatible_sdks or [] - compatible_sdks.sort(key=lambda v: float(v.replace('v', '')), reverse=True) - self.compatible_sdks = compatible_sdks def ShortName(self): return self.short_name @@ -75,67 +70,43 @@ def DefaultToolset(self): of a user override.""" return self.default_toolset - - def _SetupScriptInternal(self, target_arch): + def SetupScript(self, target_arch): """Returns a command (with arguments) to be used to set up the environment.""" - assert target_arch in ('x86', 'x64'), "target_arch not supported" - # If WindowsSDKDir is set and SetEnv.Cmd exists then we are using the - # depot_tools build tools and should run SetEnv.Cmd to set up the - # environment. The check for WindowsSDKDir alone is not sufficient because - # this is set by running vcvarsall.bat. - sdk_dir = os.environ.get('WindowsSDKDir', '') - setup_path = JoinPath(sdk_dir, 'Bin', 'SetEnv.Cmd') - if self.sdk_based and sdk_dir and os.path.exists(setup_path): - return [setup_path, '/' + target_arch] - - is_host_arch_x64 = ( - os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or - os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64' - ) - - # For VS2017 (and newer) it's fairly easy - if self.short_name >= '2017': - script_path = JoinPath(self.path, - 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat') - - # Always use a native executable, cross-compiling if necessary. - host_arch = 'amd64' if is_host_arch_x64 else 'x86' - msvc_target_arch = 'amd64' if target_arch == 'x64' else 'x86' - arg = host_arch - if host_arch != msvc_target_arch: - arg += '_' + msvc_target_arch - - return [script_path, arg] - - # We try to find the best version of the env setup batch. - vcvarsall = JoinPath(self.path, 'VC', 'vcvarsall.bat') - if target_arch == 'x86': - if self.short_name >= '2013' and self.short_name[-1] != 'e' and \ - is_host_arch_x64: - # VS2013 and later, non-Express have a x64-x86 cross that we want - # to prefer. - return [vcvarsall, 'amd64_x86'] + # Check if we are running in the SDK command line environment and use + # the setup script from the SDK if so. |target_arch| should be either + # 'x86' or 'x64'. + assert target_arch in ('x86', 'x64') + sdk_dir = os.environ.get('WindowsSDKDir') + if self.sdk_based and sdk_dir: + return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')), + '/' + target_arch] + else: + # We don't use VC/vcvarsall.bat for x86 because vcvarsall calls + # vcvars32, which it can only find if VS??COMNTOOLS is set, which it + # isn't always. + if target_arch == 'x86': + if self.short_name >= '2013' and self.short_name[-1] != 'e' and ( + os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or + os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'): + # VS2013 and later, non-Express have a x64-x86 cross that we want + # to prefer. + return [os.path.normpath( + os.path.join(self.path, 'VC/vcvarsall.bat')), 'amd64_x86'] + # Otherwise, the standard x86 compiler. + return [os.path.normpath( + os.path.join(self.path, 'Common7/Tools/vsvars32.bat'))] else: - # Otherwise, the standard x86 compiler. We don't use VC/vcvarsall.bat - # for x86 because vcvarsall calls vcvars32, which it can only find if - # VS??COMNTOOLS is set, which isn't guaranteed. - return [JoinPath(self.path, 'Common7', 'Tools', 'vsvars32.bat')] - elif target_arch == 'x64': - arg = 'x86_amd64' - # Use the 64-on-64 compiler if we're not using an express edition and - # we're running on a 64bit OS. - if self.short_name[-1] != 'e' and is_host_arch_x64: - arg = 'amd64' - return [vcvarsall, arg] - - def SetupScript(self, target_arch): - script_data = self._SetupScriptInternal(target_arch) - script_path = script_data[0] - if not os.path.exists(script_path): - raise Exception('%s is missing - make sure VC++ tools are installed.' % - script_path) - return script_data + assert target_arch == 'x64' + arg = 'x86_amd64' + # Use the 64-on-64 compiler if we're not using an express + # edition and we're running on a 64bit OS. + if self.short_name[-1] != 'e' and ( + os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or + os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'): + arg = 'amd64' + return [os.path.normpath( + os.path.join(self.path, 'VC/vcvarsall.bat')), arg] def _RegistryQueryBase(sysdir, key, value): @@ -163,6 +134,8 @@ def _RegistryQueryBase(sysdir, key, value): # Obtain the stdout from reg.exe, reading to the end so p.returncode is valid # Note that the error text may be in [1] in some cases text = p.communicate()[0] + if PY3: + text = text.decode('utf-8') # Check return code from reg.exe; officially 0==success and 1==error if p.returncode: return None @@ -208,11 +181,11 @@ def _RegistryGetValueUsingWinReg(key, value): ImportError if _winreg is unavailable. """ try: - # Python 2 - from _winreg import HKEY_LOCAL_MACHINE, OpenKey, QueryValueEx + # Python 2 + from _winreg import HKEY_LOCAL_MACHINE, OpenKey, QueryValueEx except ImportError: - # Python 3 - from winreg import HKEY_LOCAL_MACHINE, OpenKey, QueryValueEx + # Python 3 + from winreg import HKEY_LOCAL_MACHINE, OpenKey, QueryValueEx try: root, subkey = key.split('\\', 1) @@ -263,26 +236,6 @@ def _CreateVersion(name, path, sdk_based=False): if path: path = os.path.normpath(path) versions = { - '2019': VisualStudioVersion('2019', - 'Visual Studio 2019', - solution_version='12.00', - project_version='16.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v142', - compatible_sdks=['v8.1', 'v10.0']), - '2017': VisualStudioVersion('2017', - 'Visual Studio 2017', - solution_version='12.00', - project_version='15.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v141', - compatible_sdks=['v8.1', 'v10.0']), '2015': VisualStudioVersion('2015', 'Visual Studio 2015', solution_version='12.00', @@ -385,6 +338,8 @@ def _ConvertToCygpath(path): if sys.platform == 'cygwin': p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE) path = p.communicate()[0].strip() + if PY3: + path = path.decode('utf-8') return path @@ -395,6 +350,7 @@ def _DetectVisualStudioVersions(versions_to_check, force_express): A list of visual studio versions installed in descending order of usage preference. Base this on the registry and a quick check if devenv.exe exists. + Only versions 8-10 are considered. Possibilities are: 2005(e) - Visual Studio 2005 (8) 2008(e) - Visual Studio 2008 (9) @@ -402,8 +358,6 @@ def _DetectVisualStudioVersions(versions_to_check, force_express): 2012(e) - Visual Studio 2012 (11) 2013(e) - Visual Studio 2013 (12) 2015 - Visual Studio 2015 (14) - 2017 - Visual Studio 2017 (15) - 2019 - Visual Studio 2019 (16) Where (e) is e for express editions of MSVS and blank otherwise. """ version_to_year = { @@ -413,8 +367,6 @@ def _DetectVisualStudioVersions(versions_to_check, force_express): '11.0': '2012', '12.0': '2013', '14.0': '2015', - '15.0': '2017', - '16.0': '2019', } versions = [] for version in versions_to_check: @@ -445,18 +397,13 @@ def _DetectVisualStudioVersions(versions_to_check, force_express): # The old method above does not work when only SDK is installed. keys = [r'HKLM\Software\Microsoft\VisualStudio\SxS\VC7', - r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7', - r'HKLM\Software\Microsoft\VisualStudio\SxS\VS7', - r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VS7'] + r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7'] for index in range(len(keys)): path = _RegistryGetValue(keys[index], version) if not path: continue path = _ConvertToCygpath(path) - if version == '15.0': - if os.path.exists(path): - versions.append(_CreateVersion('2017', path)) - elif version != '14.0': # There is no Express edition for 2015. + if version != '14.0': # There is no Express edition for 2015. versions.append(_CreateVersion(version_to_year[version] + 'e', os.path.join(path, '..'), sdk_based=True)) @@ -475,7 +422,7 @@ def SelectVisualStudioVersion(version='auto', allow_fallback=True): if version == 'auto': version = os.environ.get('GYP_MSVS_VERSION', 'auto') version_map = { - 'auto': ('16.0', '15.0', '14.0', '12.0', '10.0', '9.0', '8.0', '11.0'), + 'auto': ('14.0', '12.0', '10.0', '9.0', '8.0', '11.0'), '2005': ('8.0',), '2005e': ('8.0',), '2008': ('9.0',), @@ -487,8 +434,6 @@ def SelectVisualStudioVersion(version='auto', allow_fallback=True): '2013': ('12.0',), '2013e': ('12.0',), '2015': ('14.0',), - '2017': ('15.0',), - '2019': ('16.0',), } override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH') if override_path: diff --git a/tools/gyp/pylib/gyp/common.py b/tools/gyp/pylib/gyp/common.py index 351800ee25e23e..d866e81d40b0a4 100644 --- a/tools/gyp/pylib/gyp/common.py +++ b/tools/gyp/pylib/gyp/common.py @@ -8,12 +8,15 @@ import re import tempfile import sys +import subprocess try: from collections.abc import MutableSet except ImportError: from collections import MutableSet +PY3 = bytes != str + # A minimal memoizing decorator. It'll blow up if the args aren't immutable, # among other "problems". @@ -341,11 +344,16 @@ def WriteOnDiff(filename): class Writer(object): """Wrapper around file which only covers the target if it differs.""" def __init__(self): + # On Cygwin remove the "dir" argument because `C:` prefixed paths are treated as relative, + # consequently ending up with current dir "/cygdrive/c/..." being prefixed to those, which was + # obviously a non-existent path, for example: "/cygdrive/c//C:\". + # See https://docs.python.org/2/library/tempfile.html#tempfile.mkstemp for more details + base_temp_dir = "" if IsCygwin() else os.path.dirname(filename) # Pick temporary file. tmp_fd, self.tmp_path = tempfile.mkstemp( suffix='.tmp', prefix=os.path.split(filename)[1] + '.gyp.', - dir=os.path.split(filename)[0]) + dir=base_temp_dir) try: self.tmp_file = os.fdopen(tmp_fd, 'wb') except Exception: @@ -428,19 +436,21 @@ def GetFlavor(params): return 'solaris' if sys.platform.startswith('freebsd'): return 'freebsd' - if sys.platform.startswith('dragonfly'): - return 'freebsd' if sys.platform.startswith('openbsd'): return 'openbsd' if sys.platform.startswith('netbsd'): return 'netbsd' if sys.platform.startswith('aix'): return 'aix' + if sys.platform.startswith('zos'): + return 'zos' + if sys.platform.startswith('os390'): + return 'zos' return 'linux' -def CopyTool(flavor, out_path, generator_flags={}): +def CopyTool(flavor, out_path): """Finds (flock|mac|win)_tool.gyp in the gyp directory and copies it to |out_path|.""" # aix and solaris just need flock emulation. mac and win use more complicated @@ -460,18 +470,11 @@ def CopyTool(flavor, out_path, generator_flags={}): with open(source_path) as source_file: source = source_file.readlines() - # Set custom header flags. - header = '# Generated by gyp. Do not edit.\n' - mac_toolchain_dir = generator_flags.get('mac_toolchain_dir', None) - if flavor == 'mac' and mac_toolchain_dir: - header += "import os;\nos.environ['DEVELOPER_DIR']='%s'\n" \ - % mac_toolchain_dir - # Add header and write it out. tool_path = os.path.join(out_path, 'gyp-%s-tool' % prefix) with open(tool_path, 'w') as tool_file: tool_file.write( - ''.join([source[0], header] + source[1:])) + ''.join([source[0], '# Generated by gyp. Do not edit.\n'] + source[1:])) # Make file executable. os.chmod(tool_path, 0o755) @@ -620,3 +623,16 @@ def CrossCompileRequested(): os.environ.get('AR_target') or os.environ.get('CC_target') or os.environ.get('CXX_target')) + +def IsCygwin(): + try: + out = subprocess.Popen("uname", + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout, stderr = out.communicate() + if PY3: + stdout = stdout.decode("utf-8") + return "CYGWIN" in str(stdout) + except Exception: + return False + diff --git a/tools/gyp/pylib/gyp/easy_xml.py b/tools/gyp/pylib/gyp/easy_xml.py index 86d0ba6c0c57d4..1ddd9091756a26 100644 --- a/tools/gyp/pylib/gyp/easy_xml.py +++ b/tools/gyp/pylib/gyp/easy_xml.py @@ -119,7 +119,7 @@ def WriteXmlIfChanged(content, path, encoding='utf-8', pretty=False, xml_string = xml_string.replace('\n', '\r\n') default_encoding = locale.getdefaultlocale()[1] - if default_encoding and default_encoding.upper() != encoding.upper(): + if default_encoding.upper() != encoding.upper(): xml_string = xml_string.encode(encoding) # Get the old content diff --git a/tools/gyp/pylib/gyp/easy_xml_test.py b/tools/gyp/pylib/gyp/easy_xml_test.py index 664b538a58db60..2a80b8a4564aa7 100755 --- a/tools/gyp/pylib/gyp/easy_xml_test.py +++ b/tools/gyp/pylib/gyp/easy_xml_test.py @@ -8,11 +8,10 @@ import gyp.easy_xml as easy_xml import unittest - try: - from StringIO import StringIO # Python 2 + from cStringIO import StringIO except ImportError: - from io import StringIO # Python 3 + from io import StringIO class TestSequenceFunctions(unittest.TestCase): diff --git a/tools/gyp/pylib/gyp/generator/cmake.py b/tools/gyp/pylib/gyp/generator/cmake.py index 149268711b8b9b..5601a6657e3d03 100644 --- a/tools/gyp/pylib/gyp/generator/cmake.py +++ b/tools/gyp/pylib/gyp/generator/cmake.py @@ -36,7 +36,6 @@ import string import subprocess import gyp.common -import gyp.xcode_emulation generator_default_variables = { 'EXECUTABLE_PREFIX': '', @@ -240,7 +239,10 @@ def StringToCMakeTargetName(a): Invalid for make: ':' Invalid for unknown reasons but cause failures: '.' """ - return a.translate(string.maketrans(' /():."', '_______')) + try: + return a.translate(str.maketrans(' /():."', '_______')) + except AttributeError: + return a.translate(string.maketrans(' /():."', '_______')) def WriteActions(target_name, actions, extra_sources, extra_deps, @@ -575,7 +577,7 @@ class CMakeNamer(object): """Converts Gyp target names into CMake target names. CMake requires that target names be globally unique. One way to ensure - this is to fully qualify the names of the targets. Unfortunatly, this + this is to fully qualify the names of the targets. Unfortunately, this ends up with all targets looking like "chrome_chrome_gyp_chrome" instead of just "chrome". If this generator were only interested in building, it would be possible to fully qualify all target names, then create @@ -611,8 +613,8 @@ def CreateCMakeTargetName(self, qualified_target): def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, - options, generator_flags, all_qualified_targets, flavor, - output): + options, generator_flags, all_qualified_targets, output): + # The make generator does this always. # TODO: It would be nice to be able to tell CMake all dependencies. circular_libs = generator_flags.get('circular', True) @@ -636,10 +638,6 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, spec = target_dicts.get(qualified_target, {}) config = spec.get('configurations', {}).get(config_to_use, {}) - xcode_settings = None - if flavor == 'mac': - xcode_settings = gyp.xcode_emulation.XcodeSettings(spec) - target_name = spec.get('target_name', '') target_type = spec.get('type', '') target_toolset = spec.get('toolset') @@ -647,7 +645,7 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, cmake_target_type = cmake_target_type_from_gyp_target_type.get(target_type) if cmake_target_type is None: print('Target %s has unknown target type %s, skipping.' % - ( target_name, target_type)) + ( target_name, target_type )) return SetVariable(output, 'TARGET', target_name) @@ -871,7 +869,7 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, elif target_type != 'executable': print('ERROR: What output file should be generated?', - 'type', target_type, 'target', target_name) + 'type', target_type, 'target', target_name) product_prefix = spec.get('product_prefix', default_product_prefix) product_name = spec.get('product_name', default_product_name) @@ -911,10 +909,10 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, defines = config.get('defines') if defines is not None: SetTargetProperty(output, - cmake_target_name, - 'COMPILE_DEFINITIONS', - defines, - ';') + cmake_target_name, + 'COMPILE_DEFINITIONS', + defines, + ';') # Compile Flags - http://www.cmake.org/Bug/view.php?id=6493 # CMake currently does not have target C and CXX flags. @@ -934,13 +932,6 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, cflags = config.get('cflags', []) cflags_c = config.get('cflags_c', []) cflags_cxx = config.get('cflags_cc', []) - if xcode_settings: - cflags = xcode_settings.GetCflags(config_to_use) - cflags_c = xcode_settings.GetCflagsC(config_to_use) - cflags_cxx = xcode_settings.GetCflagsCC(config_to_use) - #cflags_objc = xcode_settings.GetCflagsObjC(config_to_use) - #cflags_objcc = xcode_settings.GetCflagsObjCC(config_to_use) - if (not cflags_c or not c_sources) and (not cflags_cxx or not cxx_sources): SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', cflags, ' ') @@ -979,13 +970,6 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, if ldflags is not None: SetTargetProperty(output, cmake_target_name, 'LINK_FLAGS', ldflags, ' ') - # XCode settings - xcode_settings = config.get('xcode_settings', {}) - for xcode_setting, xcode_value in xcode_settings.viewitems(): - SetTargetProperty(output, cmake_target_name, - "XCODE_ATTRIBUTE_%s" % xcode_setting, xcode_value, - '' if isinstance(xcode_value, str) else ' ') - # Note on Dependencies and Libraries: # CMake wants to handle link order, resolving the link line up front. # Gyp does not retain or enforce specifying enough information to do so. @@ -1050,7 +1034,7 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, output.write(cmake_target_name) output.write('\n') if static_deps: - write_group = circular_libs and len(static_deps) > 1 and flavor != 'mac' + write_group = circular_libs and len(static_deps) > 1 if write_group: output.write('-Wl,--start-group\n') for dep in gyp.common.uniquer(static_deps): @@ -1066,9 +1050,9 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, output.write('\n') if external_libs: for lib in gyp.common.uniquer(external_libs): - output.write(' "') - output.write(RemovePrefix(lib, "$(SDKROOT)")) - output.write('"\n') + output.write(' ') + output.write(lib) + output.write('\n') output.write(')\n') @@ -1080,7 +1064,6 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, config_to_use): options = params['options'] generator_flags = params['generator_flags'] - flavor = gyp.common.GetFlavor(params) # generator_dir: relative path from pwd to where make puts build files. # Makes migrating from make to cmake easier, cmake doesn't put anything here. @@ -1163,9 +1146,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, # Force ninja to use rsp files. Otherwise link and ar lines can get too long, # resulting in 'Argument list too long' errors. - # However, rsp files don't work correctly on Mac. - if flavor != 'mac': - output.write('set(CMAKE_NINJA_FORCE_RESPONSE_FILE 1)\n') + output.write('set(CMAKE_NINJA_FORCE_RESPONSE_FILE 1)\n') output.write('\n') namer = CMakeNamer(target_list) @@ -1180,13 +1161,8 @@ def GenerateOutputForConfig(target_list, target_dicts, data, all_qualified_targets.add(qualified_target) for qualified_target in target_list: - if flavor == 'mac': - gyp_file, _, _ = gyp.common.ParseQualifiedTarget(qualified_target) - spec = target_dicts[qualified_target] - gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[gyp_file], spec) - WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, - options, generator_flags, all_qualified_targets, flavor, output) + options, generator_flags, all_qualified_targets, output) output.close() diff --git a/tools/gyp/pylib/gyp/generator/compile_commands_json.py b/tools/gyp/pylib/gyp/generator/compile_commands_json.py index 575db63c4e1943..1b8490451f9793 100644 --- a/tools/gyp/pylib/gyp/generator/compile_commands_json.py +++ b/tools/gyp/pylib/gyp/generator/compile_commands_json.py @@ -43,7 +43,7 @@ def CalculateVariables(default_variables, params): def AddCommandsForTarget(cwd, target, params, per_config_commands): output_dir = params['generator_flags']['output_dir'] - for configuration_name, configuration in target['configurations'].iteritems(): + for configuration_name, configuration in target['configurations'].items(): builddir_name = os.path.join(output_dir, configuration_name) if IsMac(params): @@ -92,7 +92,7 @@ def resolve(filename): def GenerateOutput(target_list, target_dicts, data, params): per_config_commands = {} - for qualified_target, target in target_dicts.iteritems(): + for qualified_target, target in target_dicts.items(): build_file, target_name, toolset = ( gyp.common.ParseQualifiedTarget(qualified_target)) if IsMac(params): @@ -102,7 +102,7 @@ def GenerateOutput(target_list, target_dicts, data, params): AddCommandsForTarget(cwd, target, params, per_config_commands) output_dir = params['generator_flags']['output_dir'] - for configuration_name, commands in per_config_commands.iteritems(): + for configuration_name, commands in per_config_commands.items(): filename = os.path.join(output_dir, configuration_name, 'compile_commands.json') diff --git a/tools/gyp/pylib/gyp/generator/eclipse.py b/tools/gyp/pylib/gyp/generator/eclipse.py index 372ceec246dedb..91f187d685ad51 100644 --- a/tools/gyp/pylib/gyp/generator/eclipse.py +++ b/tools/gyp/pylib/gyp/generator/eclipse.py @@ -26,6 +26,8 @@ import shlex import xml.etree.cElementTree as ET +PY3 = bytes != str + generator_wants_static_library_dependencies_adjusted = False generator_default_variables = { @@ -97,6 +99,8 @@ def GetAllIncludeDirectories(target_list, target_dicts, proc = subprocess.Popen(args=command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output = proc.communicate()[1] + if PY3: + output = output.decode('utf-8') # Extract the list of include dirs from the output, which has this format: # ... # #include "..." search starts here: @@ -195,7 +199,7 @@ def GetAllDefines(target_list, target_dicts, data, config_name, params, """Calculate the defines for a project. Returns: - A dict that includes explict defines declared in gyp files along with all of + A dict that includes explicit defines declared in gyp files along with all of the default defines that the compiler uses. """ @@ -234,6 +238,8 @@ def GetAllDefines(target_list, target_dicts, data, config_name, params, cpp_proc = subprocess.Popen(args=command, cwd='.', stdin=subprocess.PIPE, stdout=subprocess.PIPE) cpp_output = cpp_proc.communicate()[0] + if PY3: + cpp_output = cpp_output.decode('utf-8') cpp_lines = cpp_output.split('\n') for cpp_line in cpp_lines: if not cpp_line.strip(): diff --git a/tools/gyp/pylib/gyp/generator/make.py b/tools/gyp/pylib/gyp/generator/make.py index 91a119c5a57694..196053679492f2 100644 --- a/tools/gyp/pylib/gyp/generator/make.py +++ b/tools/gyp/pylib/gyp/generator/make.py @@ -12,7 +12,7 @@ # all are sourced by the top-level Makefile. This means that all # variables in .mk-files clobber one another. Be careful to use := # where appropriate for immediate evaluation, and similarly to watch -# that you're not relying on a variable value to last beween different +# that you're not relying on a variable value to last between different # .mk files. # # TODOs: @@ -149,7 +149,7 @@ def CalculateGeneratorInputInfo(params): # special "figure out circular dependencies" flags around the entire # input list during linking. quiet_cmd_link = LINK($(TOOLSET)) $@ -cmd_link = $(LINK.$(TOOLSET)) -o $@ $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,--start-group $(LD_INPUTS) $(LIBS) -Wl,--end-group +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) $(LIBS) -Wl,--end-group # We support two kinds of shared objects (.so): # 1) shared_library, which is just bundling together many dependent libraries @@ -168,10 +168,10 @@ def CalculateGeneratorInputInfo(params): # - Set SONAME to the library filename so our binaries don't reference # the local, absolute paths used on the link command-line. quiet_cmd_solink = SOLINK($(TOOLSET)) $@ -cmd_solink = $(LINK.$(TOOLSET)) -o $@ -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module = $(LINK.$(TOOLSET)) -o $@ -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) """ LINK_COMMANDS_MAC = """\ @@ -234,6 +234,25 @@ def CalculateGeneratorInputInfo(params): """ +LINK_COMMANDS_OS390 = """\ +quiet_cmd_alink = AR($(TOOLSET)) $@ +cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) + +quiet_cmd_alink_thin = AR($(TOOLSET)) $@ +cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) + +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) + +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) -Wl,DLL + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) -Wl,DLL + +""" + + # Header of toplevel Makefile. # This should go into the build tree, but it's easier to keep it here for now. SHARED_HEADER = ("""\ @@ -317,7 +336,7 @@ def CalculateGeneratorInputInfo(params): # We write to a dep file on the side first and then rename at the end # so we can't end up with a broken dep file. depfile = $(depsdir)/$(call replace_spaces,$@).d -DEPFLAGS = -MMD -MF $(depfile).raw +DEPFLAGS = %(makedep_args)s -MF $(depfile).raw # We have to fixup the deps output in a few ways. # (1) the file output should mention the proper .o file. @@ -362,17 +381,17 @@ def CalculateGeneratorInputInfo(params): # - quiet_cmd_foo is the brief-output summary of the command. quiet_cmd_cc = CC($(TOOLSET)) $@ -cmd_cc = $(CC.$(TOOLSET)) -o $@ $< $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c +cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< quiet_cmd_cxx = CXX($(TOOLSET)) $@ -cmd_cxx = $(CXX.$(TOOLSET)) -o $@ $< $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c +cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< %(extra_commands)s quiet_cmd_touch = TOUCH $@ cmd_touch = touch $@ quiet_cmd_copy = COPY $@ # send stderr to /dev/null to ignore messages when linking directories. -cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp %(copy_archive_args)s "$<" "$@") +cmd_copy = rm -rf "$@" && cp %(copy_archive_args)s "$<" "$@" %(link_commands)s """ @@ -630,6 +649,9 @@ def Sourceify(path): def QuoteSpaces(s, quote=r'\ '): return s.replace(' ', quote) +def SourceifyAndQuoteSpaces(path): + """Convert a path to its source directory form and quote spaces.""" + return QuoteSpaces(Sourceify(path)) # TODO: Avoid code duplication with _ValidateSourcesForMSVSProject in msvs.py. def _ValidateSourcesForOSX(spec, all_sources): @@ -657,9 +679,8 @@ def _ValidateSourcesForOSX(spec, all_sources): error += ' %s: %s\n' % (basename, ' '.join(files)) if error: - print('static library %s has several files with the same basename:\n' % - spec['target_name'] + error + 'libtool on OS X will generate' + - ' warnings for them.') + print(('static library %s has several files with the same basename:\n' % spec['target_name']) + + error + 'libtool on OS X will generate' + ' warnings for them.') raise GypError('Duplicate basenames in sources section, see list above') @@ -929,7 +950,7 @@ def WriteActions(self, actions, extra_sources, extra_outputs, '%s%s' % (name, cd_action, command)) self.WriteLn() - outputs = [self.Absolutify(o) for o in outputs] + outputs = [self.Absolutify(output) for output in outputs] # The makefile rules are all relative to the top dir, but the gyp actions # are defined relative to their containing dir. This replaces the obj # variable for the action rule with an absolute version so that the output @@ -1019,7 +1040,7 @@ def WriteRules(self, rules, extra_sources, extra_outputs, outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs] inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs] - outputs = [self.Absolutify(o) for o in outputs] + outputs = [self.Absolutify(output) for output in outputs] all_outputs += outputs # Only write the 'obj' and 'builddir' rules for the "primary" output # (:1); it's superfluous for the "extra outputs", and this avoids @@ -1362,7 +1383,7 @@ def ComputeOutputBasename(self, spec): target = '%s.stamp' % target elif self.type != 'executable': print("ERROR: What output file should be generated?", - "type", self.type, "target", target) + "type", self.type, "target", target) target_prefix = spec.get('product_prefix', target_prefix) target = spec.get('product_name', target) @@ -1755,8 +1776,8 @@ def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, # - The multi-output rule will have an do-nothing recipe. # Hash the target name to avoid generating overlong filenames. - cmddigest = hashlib.sha1((command or self.target).encode("utf-8")).hexdigest() - intermediate = "%s.intermediate" % (cmddigest) + cmddigest = hashlib.sha1((command or self.target).encode('utf-8')).hexdigest() + intermediate = "%s.intermediate" % cmddigest self.WriteLn('%s: %s' % (' '.join(outputs), intermediate)) self.WriteLn('\t%s' % '@:') self.WriteLn('%s: %s' % ('.INTERMEDIATE', intermediate)) @@ -1930,11 +1951,13 @@ def _InstallableTargetInstallPath(self): """Returns the location of the final output for an installable target.""" # Xcode puts shared_library results into PRODUCT_DIR, and some gyp files # rely on this. Emulate this behavior for mac. - if (self.type == 'shared_library' and - (self.flavor != 'mac' or self.toolset != 'target')): - # Install all shared libs into a common directory (per toolset) for - # convenient access with LD_LIBRARY_PATH. - return '$(builddir)/lib.%s/%s' % (self.toolset, self.alias) + + # XXX(TooTallNate): disabling this code since we don't want this behavior... + #if (self.type == 'shared_library' and + # (self.flavor != 'mac' or self.toolset != 'target')): + # # Install all shared libs into a common directory (per toolset) for + # # convenient access with LD_LIBRARY_PATH. + # return '$(builddir)/lib.%s/%s' % (self.toolset, self.alias) return '$(builddir)/' + self.alias @@ -1956,7 +1979,7 @@ def WriteAutoRegenerationRule(params, root_makefile, makefile_name, "%(makefile_name)s: %(deps)s\n" "\t$(call do_cmd,regen_makefile)\n\n" % { 'makefile_name': makefile_name, - 'deps': ' '.join(Sourceify(bf) for bf in build_files), + 'deps': ' '.join(SourceifyAndQuoteSpaces(bf) for bf in build_files), 'cmd': gyp.common.EncodePOSIXShellList( [gyp_binary, '-fmake'] + gyp.RegenerateFlags(options) + @@ -2024,6 +2047,7 @@ def CalculateMakefilePath(build_file, base_name): flock_command= 'flock' copy_archive_arguments = '-af' + makedep_arguments = '-MMD' header_params = { 'default_target': default_target, 'builddir': builddir_name, @@ -2034,6 +2058,15 @@ def CalculateMakefilePath(build_file, base_name): 'extra_commands': '', 'srcdir': srcdir, 'copy_archive_args': copy_archive_arguments, + 'makedep_args': makedep_arguments, + 'CC.target': GetEnvironFallback(('CC_target', 'CC'), '$(CC)'), + 'AR.target': GetEnvironFallback(('AR_target', 'AR'), '$(AR)'), + 'CXX.target': GetEnvironFallback(('CXX_target', 'CXX'), '$(CXX)'), + 'LINK.target': GetEnvironFallback(('LINK_target', 'LINK'), '$(LINK)'), + 'CC.host': GetEnvironFallback(('CC_host', 'CC'), 'gcc'), + 'AR.host': GetEnvironFallback(('AR_host', 'AR'), 'ar'), + 'CXX.host': GetEnvironFallback(('CXX_host', 'CXX'), 'g++'), + 'LINK.host': GetEnvironFallback(('LINK_host', 'LINK'), '$(CXX.host)'), } if flavor == 'mac': flock_command = './gyp-mac-tool flock' @@ -2047,6 +2080,18 @@ def CalculateMakefilePath(build_file, base_name): header_params.update({ 'link_commands': LINK_COMMANDS_ANDROID, }) + elif flavor == 'zos': + copy_archive_arguments = '-fPR' + makedep_arguments = '-qmakedep=gcc' + header_params.update({ + 'copy_archive_args': copy_archive_arguments, + 'makedep_args': makedep_arguments, + 'link_commands': LINK_COMMANDS_OS390, + 'CC.target': GetEnvironFallback(('CC_target', 'CC'), 'njsc'), + 'CXX.target': GetEnvironFallback(('CXX_target', 'CXX'), 'njsc++'), + 'CC.host': GetEnvironFallback(('CC_host', 'CC'), 'njsc'), + 'CXX.host': GetEnvironFallback(('CXX_host', 'CXX'), 'njsc++'), + }) elif flavor == 'solaris': header_params.update({ 'flock': './gyp-flock-tool flock', @@ -2071,17 +2116,6 @@ def CalculateMakefilePath(build_file, base_name): 'flock_index': 2, }) - header_params.update({ - 'CC.target': GetEnvironFallback(('CC_target', 'CC'), '$(CC)'), - 'AR.target': GetEnvironFallback(('AR_target', 'AR'), '$(AR)'), - 'CXX.target': GetEnvironFallback(('CXX_target', 'CXX'), '$(CXX)'), - 'LINK.target': GetEnvironFallback(('LINK_target', 'LINK'), '$(LINK)'), - 'CC.host': GetEnvironFallback(('CC_host', 'CC'), 'gcc'), - 'AR.host': GetEnvironFallback(('AR_host', 'AR'), 'ar'), - 'CXX.host': GetEnvironFallback(('CXX_host', 'CXX'), 'g++'), - 'LINK.host': GetEnvironFallback(('LINK_host', 'LINK'), '$(CXX.host)'), - }) - build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) make_global_settings_array = data[build_file].get('make_global_settings', []) wrappers = {} diff --git a/tools/gyp/pylib/gyp/generator/msvs.py b/tools/gyp/pylib/gyp/generator/msvs.py index 1aed4ca8aa7e00..8dbe0dc05b86b6 100644 --- a/tools/gyp/pylib/gyp/generator/msvs.py +++ b/tools/gyp/pylib/gyp/generator/msvs.py @@ -12,6 +12,8 @@ import subprocess import sys +from collections import OrderedDict + import gyp.common import gyp.easy_xml as easy_xml import gyp.generator.ninja as ninja_generator @@ -25,15 +27,7 @@ from gyp.common import GypError from gyp.common import OrderedSet -# TODO: Remove once bots are on 2.7, http://crbug.com/241769 -def _import_OrderedDict(): - import collections - try: - return collections.OrderedDict - except AttributeError: - import gyp.ordered_dict - return gyp.ordered_dict.OrderedDict -OrderedDict = _import_OrderedDict() +PY3 = bytes != str # Regular expression for validating Visual Studio GUIDs. If the GUID @@ -48,8 +42,6 @@ def _import_OrderedDict(): generator_default_variables = { - 'DRIVER_PREFIX': '', - 'DRIVER_SUFFIX': '.sys', 'EXECUTABLE_PREFIX': '', 'EXECUTABLE_SUFFIX': '.exe', 'STATIC_LIB_PREFIX': '', @@ -90,12 +82,12 @@ def _import_OrderedDict(): 'msvs_enable_winrt', 'msvs_requires_importlibrary', 'msvs_enable_winphone', + 'msvs_enable_marmasm', 'msvs_application_type_revision', 'msvs_target_platform_version', 'msvs_target_platform_minversion', ] -generator_filelist_paths = None # List of precompiled header related keys. precomp_keys = [ @@ -126,6 +118,8 @@ def _GetDomainAndUserName(): call = subprocess.Popen(['net', 'config', 'Workstation'], stdout=subprocess.PIPE) config = call.communicate()[0] + if PY3: + config = config.decode('utf-8') username_re = re.compile(r'^User name\s+(\S+)', re.MULTILINE) username_match = username_re.search(config) if username_match: @@ -167,7 +161,7 @@ def _FixPath(path): Returns: The path with all slashes made into backslashes. """ - if fixpath_prefix and path and not os.path.isabs(path) and not path[0] == '$': + if fixpath_prefix and path and not os.path.isabs(path) and not path[0] == '$' and not _IsWindowsAbsPath(path): path = os.path.join(fixpath_prefix, path) path = path.replace('/', '\\') path = _NormalizedSource(path) @@ -176,6 +170,16 @@ def _FixPath(path): return path +def _IsWindowsAbsPath(path): + r""" + On Cygwin systems Python needs a little help determining if a path is an absolute Windows path or not, so that + it does not treat those as relative, which results in bad paths like: + + '..\C:\\some_source_code_file.cc' + """ + return path.startswith('c:') or path.startswith('C:') + + def _FixPaths(paths): """Fix each of the paths of the list.""" return [_FixPath(i) for i in paths] @@ -261,8 +265,6 @@ def _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset=False): if not tools.get(tool_name): tools[tool_name] = dict() tool = tools[tool_name] - if 'CompileAsWinRT' == setting: - return if tool.get(setting): if only_if_unset: return if type(tool[setting]) == list and type(value) == list: @@ -276,10 +278,6 @@ def _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset=False): tool[setting] = value -def _ConfigTargetVersion(config_data): - return config_data.get('msvs_target_version', 'Windows7') - - def _ConfigPlatform(config_data): return config_data.get('msvs_configuration_platform', 'Win32') @@ -296,29 +294,20 @@ def _ConfigFullName(config_name, config_data): return '%s|%s' % (_ConfigBaseName(config_name, platform_name), platform_name) -def _ConfigWindowsTargetPlatformVersion(config_data, version): - config_ver = config_data.get('msvs_windows_sdk_version') - vers = [config_ver] if config_ver else version.compatible_sdks - for ver in vers: - for key in [ - r'HKLM\Software\Microsoft\Microsoft SDKs\Windows\%s', - r'HKLM\Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows\%s']: - sdk_dir = MSVSVersion._RegistryGetValue(key % ver, 'InstallationFolder') - if not sdk_dir: - continue - version = MSVSVersion._RegistryGetValue(key % ver, 'ProductVersion') or '' - # Find a matching entry in sdk_dir\include. - expected_sdk_dir=r'%s\include' % sdk_dir - names = sorted([x for x in (os.listdir(expected_sdk_dir) - if os.path.isdir(expected_sdk_dir) - else [] - ) - if x.startswith(version)], reverse=True) - if names: - return names[0] - else: - print('Warning: No include files found for detected ' - 'Windows SDK version %s' % (version), file=sys.stdout) +def _ConfigWindowsTargetPlatformVersion(config_data): + ver = config_data.get('msvs_windows_target_platform_version') + if not ver or re.match(r'^\d+', ver): + return ver + for key in [r'HKLM\Software\Microsoft\Microsoft SDKs\Windows\%s', + r'HKLM\Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows\%s']: + sdkdir = MSVSVersion._RegistryGetValue(key % ver, 'InstallationFolder') + if not sdkdir: + continue + version = MSVSVersion._RegistryGetValue(key % ver, 'ProductVersion') or '' + # find a matching entry in sdkdir\include + names = sorted([x for x in os.listdir(r'%s\include' % sdkdir) \ + if x.startswith(version)], reverse = True) + return names[0] def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, @@ -775,8 +764,8 @@ def _Replace(match): # the VCProj but cause the same problem on the final command-line. Moving # the item to the end of the list does works, but that's only possible if # there's only one such item. Let's just warn the user. - print('Warning: MSVS may misinterpret the odd number of ' - 'quotes in ' + s, file=sys.stderr) + print('Warning: MSVS may misinterpret the odd number of ' + + 'quotes in ' + s, file=sys.stderr) return s @@ -937,8 +926,6 @@ def _GetMsbuildToolsetOfProject(proj_path, spec, version): toolset = default_config.get('msbuild_toolset') if not toolset and version.DefaultToolset(): toolset = version.DefaultToolset() - if spec['type'] == 'windows_driver': - toolset = 'WindowsKernelModeDriver10.0' return toolset @@ -996,8 +983,8 @@ def _ValidateSourcesForMSVSProject(spec, version): error += ' %s: %s\n' % (basename, ' '.join(files)) if error: - print('static library %s has several files with the same basename:\n' % - spec['target_name'] + error + 'MSVC08 cannot handle that.') + print('static library %s has several files with the same basename:\n' % spec['target_name'] + + error + 'MSVC08 cannot handle that.') raise GypError('Duplicate basenames in sources section, see list above') @@ -1122,7 +1109,6 @@ def _GetMSVSConfigurationType(spec, build_file): 'shared_library': '2', # .dll 'loadable_module': '2', # .dll 'static_library': '4', # .lib - 'windows_driver': '5', # .sys 'none': '10', # Utility type }[spec['type']] except KeyError: @@ -1307,7 +1293,6 @@ def _GetOutputFilePathAndTool(spec, msbuild): 'executable': ('VCLinkerTool', 'Link', '$(OutDir)', '.exe'), 'shared_library': ('VCLinkerTool', 'Link', '$(OutDir)', '.dll'), 'loadable_module': ('VCLinkerTool', 'Link', '$(OutDir)', '.dll'), - 'windows_driver': ('VCLinkerTool', 'Link', '$(OutDir)', '.sys'), 'static_library': ('VCLibrarianTool', 'Lib', '$(OutDir)lib\\', '.lib'), } output_file_props = output_file_map.get(spec['type']) @@ -1370,8 +1355,7 @@ def _GetDisabledWarnings(config): def _GetModuleDefinition(spec): def_file = '' - if spec['type'] in ['shared_library', 'loadable_module', 'executable', - 'windows_driver']: + if spec['type'] in ['shared_library', 'loadable_module', 'executable']: def_files = [s for s in spec.get('sources', []) if s.endswith('.def')] if len(def_files) == 1: def_file = _FixPath(def_files[0]) @@ -1727,17 +1711,14 @@ def _GetCopies(spec): src_bare = src[:-1] base_dir = posixpath.split(src_bare)[0] outer_dir = posixpath.split(src_bare)[1] - fixed_dst = _FixPath(dst) - full_dst = '"%s\\%s\\"' % (fixed_dst, outer_dir) - cmd = 'mkdir %s 2>nul & cd "%s" && xcopy /e /f /y "%s" %s' % ( - full_dst, _FixPath(base_dir), outer_dir, full_dst) + cmd = 'cd "%s" && xcopy /e /f /y "%s" "%s\\%s\\"' % ( + _FixPath(base_dir), outer_dir, _FixPath(dst), outer_dir) copies.append(([src], ['dummy_copies', dst], cmd, - 'Copying %s to %s' % (src, fixed_dst))) + 'Copying %s to %s' % (src, dst))) else: - fix_dst = _FixPath(cpy['destination']) cmd = 'mkdir "%s" 2>nul & set ERRORLEVEL=0 & copy /Y "%s" "%s"' % ( - fix_dst, _FixPath(src), _FixPath(dst)) - copies.append(([src], [dst], cmd, 'Copying %s to %s' % (src, fix_dst))) + _FixPath(cpy['destination']), _FixPath(src), _FixPath(dst)) + copies.append(([src], [dst], cmd, 'Copying %s to %s' % (src, dst))) return copies @@ -1913,6 +1894,8 @@ def _InitNinjaFlavor(params, target_list, target_dicts): configuration = '$(Configuration)' if params.get('target_arch') == 'x64': configuration += '_x64' + if params.get('target_arch') == 'arm64': + configuration += '_arm64' spec['msvs_external_builder_out_dir'] = os.path.join( gyp.common.RelativePath(params['options'].toplevel_dir, gyp_dir), ninja_generator.ComputeOutputDir(params), @@ -1981,19 +1964,6 @@ def PerformBuild(data, configurations, params): rtn = subprocess.check_call(arguments) -def CalculateGeneratorInputInfo(params): - if params.get('flavor') == 'ninja': - toplevel = params['options'].toplevel_dir - qualified_out_dir = os.path.normpath(os.path.join( - toplevel, ninja_generator.ComputeOutputDir(params), - 'gypfiles-msvs-ninja')) - - global generator_filelist_paths - generator_filelist_paths = { - 'toplevel': toplevel, - 'qualified_out_dir': qualified_out_dir, - } - def GenerateOutput(target_list, target_dicts, data, params): """Generate .sln and .vcproj files. @@ -2159,11 +2129,10 @@ def _MapFileToMsBuildSourceType(source, rule_dependencies, A pair of (group this file should be part of, the label of element) """ _, ext = os.path.splitext(source) - ext = ext.lower() if ext in extension_to_rule_name: group = 'rule' element = extension_to_rule_name[ext] - elif ext in ['.cc', '.cpp', '.c', '.cxx']: + elif ext in ['.cc', '.cpp', '.c', '.cxx', '.mm']: group = 'compile' element = 'ClCompile' elif ext in ['.h', '.hxx']: @@ -2172,12 +2141,12 @@ def _MapFileToMsBuildSourceType(source, rule_dependencies, elif ext == '.rc': group = 'resource' element = 'ResourceCompile' - elif ext in ['.s', '.asm']: + elif ext == '.asm': group = 'masm' element = 'MASM' for platform in platforms: if platform.lower() in ['arm', 'arm64']: - element = 'MARMASM' + element = 'MARMASM' elif ext == '.idl': group = 'midl' element = 'Midl' @@ -2686,7 +2655,7 @@ def _GetMSBuildProjectConfigurations(configurations): return [group] -def _GetMSBuildGlobalProperties(spec, version, guid, gyp_file_name): +def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name): namespace = os.path.splitext(gyp_file_name)[0] properties = [ ['PropertyGroup', {'Label': 'Globals'}, @@ -2701,18 +2670,6 @@ def _GetMSBuildGlobalProperties(spec, version, guid, gyp_file_name): os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64': properties[0].append(['PreferredToolArchitecture', 'x64']) - if spec.get('msvs_target_platform_version'): - target_platform_version = spec.get('msvs_target_platform_version') - properties[0].append(['WindowsTargetPlatformVersion', - target_platform_version]) - if spec.get('msvs_target_platform_minversion'): - target_platform_minversion = spec.get('msvs_target_platform_minversion') - properties[0].append(['WindowsTargetPlatformMinVersion', - target_platform_minversion]) - else: - properties[0].append(['WindowsTargetPlatformMinVersion', - target_platform_version]) - if spec.get('msvs_enable_winrt'): properties[0].append(['DefaultLanguage', 'en-US']) properties[0].append(['AppContainerApplication', 'true']) @@ -2721,45 +2678,49 @@ def _GetMSBuildGlobalProperties(spec, version, guid, gyp_file_name): properties[0].append(['ApplicationTypeRevision', app_type_revision]) else: properties[0].append(['ApplicationTypeRevision', '8.1']) + + if spec.get('msvs_target_platform_version'): + target_platform_version = spec.get('msvs_target_platform_version') + properties[0].append(['WindowsTargetPlatformVersion', + target_platform_version]) + if spec.get('msvs_target_platform_minversion'): + target_platform_minversion = spec.get('msvs_target_platform_minversion') + properties[0].append(['WindowsTargetPlatformMinVersion', + target_platform_minversion]) + else: + properties[0].append(['WindowsTargetPlatformMinVersion', + target_platform_version]) if spec.get('msvs_enable_winphone'): properties[0].append(['ApplicationType', 'Windows Phone']) else: properties[0].append(['ApplicationType', 'Windows Store']) platform_name = None - msvs_windows_sdk_version = None + msvs_windows_target_platform_version = None for configuration in spec['configurations'].values(): platform_name = platform_name or _ConfigPlatform(configuration) - msvs_windows_sdk_version = (msvs_windows_sdk_version or - _ConfigWindowsTargetPlatformVersion(configuration, version)) - if platform_name and msvs_windows_sdk_version: + msvs_windows_target_platform_version = \ + msvs_windows_target_platform_version or \ + _ConfigWindowsTargetPlatformVersion(configuration) + if platform_name and msvs_windows_target_platform_version: break - if msvs_windows_sdk_version: - properties[0].append(['WindowsTargetPlatformVersion', - str(msvs_windows_sdk_version)]) - elif version.compatible_sdks: - raise GypError('%s requires any SDK of %s version, but none were found' % - (version.description, version.compatible_sdks)) if platform_name == 'ARM': properties[0].append(['WindowsSDKDesktopARMSupport', 'true']) + if msvs_windows_target_platform_version: + properties[0].append(['WindowsTargetPlatformVersion', \ + str(msvs_windows_target_platform_version)]) return properties - def _GetMSBuildConfigurationDetails(spec, build_file): properties = {} for name, settings in spec['configurations'].items(): msbuild_attributes = _GetMSBuildAttributes(spec, settings, build_file) condition = _GetConfigurationCondition(name, settings) character_set = msbuild_attributes.get('CharacterSet') - config_type = msbuild_attributes.get('ConfigurationType') _AddConditionalProperty(properties, condition, 'ConfigurationType', - config_type) - if config_type == 'Driver': - _AddConditionalProperty(properties, condition, 'DriverType', 'WDM') - _AddConditionalProperty(properties, condition, 'TargetVersion', - _ConfigTargetVersion(settings)) + msbuild_attributes['ConfigurationType']) if character_set: if 'msvs_enable_winrt' not in spec : _AddConditionalProperty(properties, condition, 'CharacterSet', @@ -2858,7 +2819,6 @@ def _ConvertMSVSConfigurationType(config_type): '1': 'Application', '2': 'DynamicLibrary', '4': 'StaticLibrary', - '5': 'Driver', '10': 'Utility' }[config_type] return config_type @@ -2901,7 +2861,6 @@ def _GetMSBuildAttributes(spec, config, build_file): 'executable': 'Link', 'shared_library': 'Link', 'loadable_module': 'Link', - 'windows_driver': 'Link', 'static_library': 'Lib', } msbuild_tool = msbuild_tool_map.get(spec['type']) @@ -3086,7 +3045,7 @@ def _FinalizeMSBuildSettings(spec, configuration): value = configuration.get(ignored_setting) if value: print('Warning: The automatic conversion to MSBuild does not handle ' - '%s. Ignoring setting of %s' % (ignored_setting, str(value))) + '%s. Ignoring setting of %s' % (ignored_setting, str(value))) defines = [_EscapeCppDefineForMSBuild(d) for d in defines] disabled_warnings = _GetDisabledWarnings(configuration) @@ -3106,7 +3065,7 @@ def _FinalizeMSBuildSettings(spec, configuration): _ToolAppend(msbuild_settings, 'ResourceCompile', 'AdditionalIncludeDirectories', resource_include_dirs) # Add in libraries, note that even for empty libraries, we want this - # set, to prevent inheriting default libraries from the enviroment. + # set, to prevent inheriting default libraries from the environment. _ToolSetOrAppend(msbuild_settings, 'Link', 'AdditionalDependencies', libraries) _ToolAppend(msbuild_settings, 'Link', 'AdditionalLibraryDirectories', @@ -3401,8 +3360,7 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): }] content += _GetMSBuildProjectConfigurations(configurations) - content += _GetMSBuildGlobalProperties(spec, version, project.guid, - project_file_name) + content += _GetMSBuildGlobalProperties(spec, project.guid, project_file_name) content += import_default_section content += _GetMSBuildConfigurationDetails(spec, project.build_file) if spec.get('msvs_enable_winphone'): @@ -3411,7 +3369,8 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): content += _GetMSBuildLocalProperties(project.msbuild_toolset) content += import_cpp_props_section content += import_masm_props_section - content += import_marmasm_props_section + if spec.get('msvs_enable_marmasm'): + content += import_marmasm_props_section content += _GetMSBuildExtensions(props_files_of_rules) content += _GetMSBuildPropertySheets(configurations) content += macro_section @@ -3424,7 +3383,8 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): content += _GetMSBuildProjectReferences(project) content += import_cpp_targets_section content += import_masm_targets_section - content += import_marmasm_targets_section + if spec.get('msvs_enable_marmasm'): + content += import_marmasm_targets_section content += _GetMSBuildExtensionTargets(targets_files_of_rules) if spec.get('msvs_external_builder'): diff --git a/tools/gyp/pylib/gyp/generator/msvs_test.py b/tools/gyp/pylib/gyp/generator/msvs_test.py index 1b0cdd17201d5b..daf4f411bc481f 100755 --- a/tools/gyp/pylib/gyp/generator/msvs_test.py +++ b/tools/gyp/pylib/gyp/generator/msvs_test.py @@ -7,11 +7,10 @@ import gyp.generator.msvs as msvs import unittest - try: - from StringIO import StringIO # Python 2 + from cStringIO import StringIO except ImportError: - from io import StringIO # Python 3 + from io import StringIO class TestSequenceFunctions(unittest.TestCase): diff --git a/tools/gyp/pylib/gyp/generator/ninja.py b/tools/gyp/pylib/gyp/generator/ninja.py index 75743e770d16f9..33cc253aba67b5 100644 --- a/tools/gyp/pylib/gyp/generator/ninja.py +++ b/tools/gyp/pylib/gyp/generator/ninja.py @@ -1,9 +1,8 @@ +from __future__ import print_function # Copyright (c) 2013 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. -from __future__ import print_function - import collections import copy import hashlib @@ -153,9 +152,6 @@ def __init__(self, type): # because dependents only link against the lib (not both the lib and the # dll) we keep track of the import library here. self.import_lib = None - # Track if this target contains any C++ files, to decide if gcc or g++ - # should be used for linking. - self.uses_cpp = False def Linkable(self): """Return true if this is a target that can be linked against.""" @@ -355,7 +351,7 @@ def WriteCollapsedDependencies(self, name, targets, order_only=None): Uses a stamp file if necessary.""" - assert targets == [item for item in targets if item], targets + assert targets == filter(None, targets), targets if len(targets) == 0: assert not order_only return None @@ -383,17 +379,14 @@ def WriteSpec(self, spec, config_name, generator_flags): self.target = Target(spec['type']) self.is_standalone_static_library = bool( spec.get('standalone_static_library', 0)) - - self.target_rpath = generator_flags.get('target_rpath', r'\$$ORIGIN/lib/') + # Track if this target contains any C++ files, to decide if gcc or g++ + # should be used for linking. + self.uses_cpp = False self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec) self.xcode_settings = self.msvs_settings = None if self.flavor == 'mac': self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec) - mac_toolchain_dir = generator_flags.get('mac_toolchain_dir', None) - if mac_toolchain_dir: - self.xcode_settings.mac_toolchain_dir = mac_toolchain_dir - if self.flavor == 'win': self.msvs_settings = gyp.msvs_emulation.MsvsSettings(spec, generator_flags) @@ -430,10 +423,8 @@ def WriteSpec(self, spec, config_name, generator_flags): target = self.target_outputs[dep] actions_depends.append(target.PreActionInput(self.flavor)) compile_depends.append(target.PreCompileInput()) - if target.uses_cpp: - self.target.uses_cpp = True - actions_depends = [item for item in actions_depends if item] - compile_depends = [item for item in compile_depends if item] + actions_depends = filter(None, actions_depends) + compile_depends = filter(None, compile_depends) actions_depends = self.WriteCollapsedDependencies('actions_depends', actions_depends) compile_depends = self.WriteCollapsedDependencies('compile_depends', @@ -457,12 +448,7 @@ def WriteSpec(self, spec, config_name, generator_flags): # Write out the compilation steps, if any. link_deps = [] - try: - sources = extra_sources + spec.get('sources', []) - except TypeError: - print('extra_sources: ', str(extra_sources)) - print('spec.get("sources"): ', str(spec.get('sources'))) - raise + sources = extra_sources + spec.get('sources', []) if sources: if self.flavor == 'mac' and len(self.archs) > 1: # Write subninja file containing compile and link commands scoped to @@ -490,7 +476,7 @@ def WriteSpec(self, spec, config_name, generator_flags): if self.flavor != 'mac' or len(self.archs) == 1: link_deps += [self.GypPathToNinja(o) for o in obj_outputs] else: - print("Warning: Actions/rules writing object files don't work with " + print("Warning: Actions/rules writing object files don't work with " \ "multiarch targets, dropping. (target %s)" % spec['target_name']) elif self.flavor == 'mac' and len(self.archs) > 1: link_deps = collections.defaultdict(list) @@ -577,9 +563,6 @@ def WriteActionsRulesCopies(self, spec, extra_sources, prebuild, if 'sources' in spec and self.flavor == 'win': outputs += self.WriteWinIdlFiles(spec, prebuild) - if self.xcode_settings and self.xcode_settings.IsIosFramework(): - self.WriteiOSFrameworkHeaders(spec, outputs, prebuild) - stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs) if self.is_mac_bundle: @@ -677,7 +660,6 @@ def WriteRules(self, rules, extra_sources, prebuild, for var in special_locals: if '${%s}' % var in argument: needed_variables.add(var) - needed_variables = sorted(needed_variables) def cygwin_munge(path): # pylint: disable=cell-var-from-loop @@ -744,14 +726,13 @@ def cygwin_munge(path): elif var == 'name': extra_bindings.append(('name', cygwin_munge(basename))) else: - assert var == None, repr(var) + assert var is None, repr(var) outputs = [self.GypPathToNinja(o, env) for o in outputs] if self.flavor == 'win': # WriteNewNinjaRule uses unique_name for creating an rsp file on win. extra_bindings.append(('unique_name', hashlib.md5(outputs[0]).hexdigest())) - self.ninja.build(outputs, rule_name, self.GypPathToNinja(source), implicit=inputs, order_only=prebuild, @@ -763,11 +744,7 @@ def cygwin_munge(path): def WriteCopies(self, copies, prebuild, mac_bundle_depends): outputs = [] - if self.xcode_settings: - extra_env = self.xcode_settings.GetPerTargetSettings() - env = self.GetToolchainEnv(additional_settings=extra_env) - else: - env = self.GetToolchainEnv() + env = self.GetToolchainEnv() for copy in copies: for path in copy['files']: # Normalize the path so trailing slashes don't confuse us. @@ -789,38 +766,18 @@ def WriteCopies(self, copies, prebuild, mac_bundle_depends): return outputs - def WriteiOSFrameworkHeaders(self, spec, outputs, prebuild): - """Prebuild steps to generate hmap files and copy headers to destination.""" - framework = self.ComputeMacBundleOutput() - all_sources = spec['sources'] - copy_headers = spec['mac_framework_headers'] - output = self.GypPathToUniqueOutput('headers.hmap') - self.xcode_settings.header_map_path = output - all_headers = map(self.GypPathToNinja, - filter(lambda x:x.endswith(('.h')), all_sources)) - variables = [('framework', framework), - ('copy_headers', map(self.GypPathToNinja, copy_headers))] - outputs.extend(self.ninja.build( - output, 'compile_ios_framework_headers', all_headers, - variables=variables, order_only=prebuild)) - def WriteMacBundleResources(self, resources, bundle_depends): """Writes ninja edges for 'mac_bundle_resources'.""" xcassets = [] - - extra_env = self.xcode_settings.GetPerTargetSettings() - env = self.GetSortedXcodeEnv(additional_settings=extra_env) - env = self.ComputeExportEnvString(env) - isBinary = self.xcode_settings.IsBinaryOutputFormat(self.config_name) - for output, res in gyp.xcode_emulation.GetMacBundleResources( generator_default_variables['PRODUCT_DIR'], self.xcode_settings, map(self.GypPathToNinja, resources)): output = self.ExpandSpecial(output) if os.path.splitext(output)[-1] != '.xcassets': + isBinary = self.xcode_settings.IsBinaryOutputFormat(self.config_name) self.ninja.build(output, 'mac_tool', res, variables=[('mactool_cmd', 'copy-bundle-resource'), \ - ('env', env), ('binary', isBinary)]) + ('binary', isBinary)]) bundle_depends.append(output) else: xcassets.append(res) @@ -1039,7 +996,7 @@ def WriteSourcesForArch(self, ninja_file, config_name, config, sources, obj_ext = self.obj_ext if ext in ('cc', 'cpp', 'cxx'): command = 'cxx' - self.target.uses_cpp = True + self.uses_cpp = True elif ext == 'c' or (ext == 'S' and self.flavor != 'win'): command = 'cc' elif ext == 's' and self.flavor != 'win': # Doesn't generate .o.d files. @@ -1054,7 +1011,7 @@ def WriteSourcesForArch(self, ninja_file, config_name, config, sources, command = 'objc' elif self.flavor == 'mac' and ext == 'mm': command = 'objcxx' - self.target.uses_cpp = True + self.uses_cpp = True elif self.flavor == 'win' and ext == 'rc': command = 'rc' obj_ext = '.res' @@ -1105,16 +1062,16 @@ def WritePchTargets(self, ninja_file, pch_commands): cmd = map.get(lang) ninja_file.build(gch, cmd, input, variables=[(var_name, lang_flag)]) - def WriteLink(self, spec, config_name, config, link_deps, compile_deps): + def WriteLink(self, spec, config_name, config, link_deps): """Write out a link step. Fills out target.binary. """ if self.flavor != 'mac' or len(self.archs) == 1: return self.WriteLinkForArch( - self.ninja, spec, config_name, config, link_deps, compile_deps) + self.ninja, spec, config_name, config, link_deps) else: output = self.ComputeOutput(spec) inputs = [self.WriteLinkForArch(self.arch_subninjas[arch], spec, config_name, config, link_deps[arch], - compile_deps, arch=arch) + arch=arch) for arch in self.archs] extra_bindings = [] build_output = output @@ -1133,7 +1090,7 @@ def WriteLink(self, spec, config_name, config, link_deps, compile_deps): return output def WriteLinkForArch(self, ninja_file, spec, config_name, config, - link_deps, compile_deps, arch=None): + link_deps, arch=None): """Write out a link step. Fills out target.binary. """ command = { 'executable': 'link', @@ -1146,14 +1103,6 @@ def WriteLinkForArch(self, ninja_file, spec, config_name, config, solibs = set() order_deps = set() - if compile_deps: - # Normally, the compiles of the target already depend on compile_deps, - # but a shared_library target might have no sources and only link together - # a few static_library deps, so the link step also needs to depend - # on compile_deps to make sure actions in the shared_library target - # get run before the link. - order_deps.add(compile_deps) - if 'dependencies' in spec: # Two kinds of dependencies: # - Linkable dependencies (like a .a or a .so): add them to the link line. @@ -1190,7 +1139,7 @@ def WriteLinkForArch(self, ninja_file, spec, config_name, config, implicit_deps.add(final_output) extra_bindings = [] - if self.target.uses_cpp and self.flavor != 'win': + if self.uses_cpp and self.flavor != 'win': extra_bindings.append(('ld', '$ldxx')) output = self.ComputeOutput(spec, arch) @@ -1233,9 +1182,7 @@ def WriteLinkForArch(self, ninja_file, spec, config_name, config, rpath = 'lib/' if self.toolset != 'target': rpath += self.toolset - ldflags.append(r'-Wl,-rpath=\$$ORIGIN/%s' % rpath) - else: - ldflags.append('-Wl,-rpath=%s' % self.target_rpath) + ldflags.append(r'-Wl,-rpath=\$$ORIGIN/%s' % rpath) ldflags.append('-Wl,-rpath-link=%s' % rpath) self.WriteVariableList(ninja_file, 'ldflags', map(self.ExpandSpecial, ldflags)) @@ -1309,11 +1256,10 @@ def WriteLinkForArch(self, ninja_file, spec, config_name, config, if len(solibs): - extra_bindings.append(('solibs', - gyp.common.EncodePOSIXShellList(sorted(solibs)))) + extra_bindings.append(('solibs', gyp.common.EncodePOSIXShellList(solibs))) ninja_file.build(output, command + command_suffix, link_deps, - implicit=sorted(implicit_deps), + implicit=list(implicit_deps), order_only=list(order_deps), variables=extra_bindings) return linked_binary @@ -1366,8 +1312,7 @@ def WriteTarget(self, spec, config_name, config, link_deps, compile_deps): # needed. variables=variables) else: - self.target.binary = self.WriteLink(spec, config_name, config, link_deps, - compile_deps) + self.target.binary = self.WriteLink(spec, config_name, config, link_deps) return self.target.binary def WriteMacBundle(self, spec, mac_bundle_depends, is_empty): @@ -1380,13 +1325,9 @@ def WriteMacBundle(self, spec, mac_bundle_depends, is_empty): self.AppendPostbuildVariable(variables, spec, output, self.target.binary, is_command_start=not package_framework) if package_framework and not is_empty: - if spec['type'] == 'shared_library' and self.xcode_settings.isIOS: - self.ninja.build(output, 'package_ios_framework', mac_bundle_depends, - variables=variables) - else: - variables.append(('version', self.xcode_settings.GetFrameworkVersion())) - self.ninja.build(output, 'package_framework', mac_bundle_depends, - variables=variables) + variables.append(('version', self.xcode_settings.GetFrameworkVersion())) + self.ninja.build(output, 'package_framework', mac_bundle_depends, + variables=variables) else: self.ninja.build(output, 'stamp', mac_bundle_depends, variables=variables) @@ -1873,14 +1814,14 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, master_ninja = ninja_syntax.Writer(master_ninja_file, width=120) # Put build-time support tools in out/{config_name}. - gyp.common.CopyTool(flavor, toplevel_build, generator_flags) + gyp.common.CopyTool(flavor, toplevel_build) # Grab make settings for CC/CXX. # The rules are # - The priority from low to high is gcc/g++, the 'make_global_settings' in # gyp, the environment variable. # - If there is no 'make_global_settings' for CC.host/CXX.host or - # 'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set + # 'CC_host'/'CXX_host' environment variable, cc_host/cxx_host should be set # to cc/cxx. if flavor == 'win': ar = 'lib.exe' @@ -1899,7 +1840,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, ld_host = '$cc_host' ldxx_host = '$cxx_host' - ar_host = ar + ar_host = 'ar' cc_host = None cxx_host = None cc_host_global_setting = None @@ -1958,10 +1899,6 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, key_prefix = re.sub(r'\.HOST$', '.host', key_prefix) wrappers[key_prefix] = os.path.join(build_to_root, value) - mac_toolchain_dir = generator_flags.get('mac_toolchain_dir', None) - if mac_toolchain_dir: - wrappers['LINK'] = "export DEVELOPER_DIR='%s' &&" % mac_toolchain_dir - if flavor == 'win': configs = [target_dicts[qualified_target]['configurations'][config_name] for qualified_target in target_list] @@ -1972,7 +1909,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, configs, generator_flags) cl_paths = gyp.msvs_emulation.GenerateEnvironmentFiles( toplevel_build, generator_flags, shared_system_includes, OpenOutput) - for arch, path in sorted(cl_paths.items()): + for arch, path in cl_paths.items(): if clang_cl: # If we have selected clang-cl, use that instead. path = clang_cl @@ -2296,12 +2233,6 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, 'compile_xcassets', description='COMPILE XCASSETS $in', command='$env ./gyp-mac-tool compile-xcassets $keys $in') - master_ninja.rule( - 'compile_ios_framework_headers', - description='COMPILE HEADER MAPS AND COPY FRAMEWORK HEADERS $in', - command='$env ./gyp-mac-tool compile-ios-framework-header-map $out ' - '$framework $in && $env ./gyp-mac-tool ' - 'copy-ios-framework-headers $framework $copy_headers') master_ninja.rule( 'mac_tool', description='MACTOOL $mactool_cmd $in', @@ -2311,29 +2242,31 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, description='PACKAGE FRAMEWORK $out, POSTBUILDS', command='./gyp-mac-tool package-framework $out $version$postbuilds ' '&& touch $out') - master_ninja.rule( - 'package_ios_framework', - description='PACKAGE IOS FRAMEWORK $out, POSTBUILDS', - command='./gyp-mac-tool package-ios-framework $out $postbuilds ' - '&& touch $out') if flavor == 'win': master_ninja.rule( 'stamp', description='STAMP $out', command='%s gyp-win-tool stamp $out' % sys.executable) - master_ninja.rule( - 'copy', - description='COPY $in $out', - command='%s gyp-win-tool recursive-mirror $in $out' % sys.executable) else: master_ninja.rule( 'stamp', description='STAMP $out', command='${postbuilds}touch $out') + if flavor == 'win': + master_ninja.rule( + 'copy', + description='COPY $in $out', + command='%s gyp-win-tool recursive-mirror $in $out' % sys.executable) + elif flavor == 'zos': + master_ninja.rule( + 'copy', + description='COPY $in $out', + command='rm -rf $out && cp -fRP $in $out') + else: master_ninja.rule( 'copy', description='COPY $in $out', - command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)') + command='rm -rf $out && cp -af $in $out') master_ninja.newline() all_targets = set() @@ -2381,7 +2314,6 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, qualified_target_for_hash = gyp.common.QualifiedTarget(build_file, name, toolset) - qualified_target_for_hash = qualified_target_for_hash.encode('utf-8') hash_for_rules = hashlib.md5(qualified_target_for_hash).hexdigest() base_path = os.path.dirname(build_file) @@ -2421,7 +2353,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, # able to run actions and build libraries by their short name. master_ninja.newline() master_ninja.comment('Short names for targets.') - for short_name in sorted(target_short_names): + for short_name in target_short_names: master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in target_short_names[short_name]]) @@ -2437,7 +2369,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, if all_outputs: master_ninja.newline() - master_ninja.build('all', 'phony', sorted(all_outputs)) + master_ninja.build('all', 'phony', list(all_outputs)) master_ninja.default(generator_flags.get('default_target', 'all')) master_ninja_file.close() diff --git a/tools/gyp/pylib/gyp/generator/ninja_test.py b/tools/gyp/pylib/gyp/generator/ninja_test.py index c8adc251c97d50..5ecfbdf004d211 100644 --- a/tools/gyp/pylib/gyp/generator/ninja_test.py +++ b/tools/gyp/pylib/gyp/generator/ninja_test.py @@ -6,10 +6,9 @@ """ Unit tests for the ninja.py file. """ -import sys -import unittest - import gyp.generator.ninja as ninja +import unittest +import sys class TestPrefixesAndSuffixes(unittest.TestCase): diff --git a/tools/gyp/pylib/gyp/generator/xcode.py b/tools/gyp/pylib/gyp/generator/xcode.py index 9242324196d2d3..6317d04c703026 100644 --- a/tools/gyp/pylib/gyp/generator/xcode.py +++ b/tools/gyp/pylib/gyp/generator/xcode.py @@ -1,9 +1,8 @@ +from __future__ import print_function # 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. -from __future__ import print_function - import filecmp import gyp.common import gyp.xcodeproj_file @@ -79,7 +78,6 @@ 'mac_framework_headers', 'mac_framework_private_headers', 'mac_xctest_bundle', - 'mac_xcuitest_bundle', 'xcode_create_dependents_test_runner', ] @@ -541,7 +539,7 @@ def ExpandXcodeVariables(string, expansions): """ matches = _xcode_variable_re.findall(string) - if matches == None: + if matches is None: return string matches.reverse() @@ -694,7 +692,6 @@ def GenerateOutput(target_list, target_dicts, data, params): 'executable+bundle': 'com.apple.product-type.application', 'loadable_module+bundle': 'com.apple.product-type.bundle', 'loadable_module+xctest': 'com.apple.product-type.bundle.unit-test', - 'loadable_module+xcuitest': 'com.apple.product-type.bundle.ui-testing', 'shared_library+bundle': 'com.apple.product-type.framework', 'executable+extension+bundle': 'com.apple.product-type.app-extension', 'executable+watch+extension+bundle': @@ -711,19 +708,13 @@ def GenerateOutput(target_list, target_dicts, data, params): type = spec['type'] is_xctest = int(spec.get('mac_xctest_bundle', 0)) - is_xcuitest = int(spec.get('mac_xcuitest_bundle', 0)) is_bundle = int(spec.get('mac_bundle', 0)) or is_xctest is_app_extension = int(spec.get('ios_app_extension', 0)) is_watchkit_extension = int(spec.get('ios_watchkit_extension', 0)) is_watch_app = int(spec.get('ios_watch_app', 0)) if type != 'none': type_bundle_key = type - if is_xcuitest: - type_bundle_key += '+xcuitest' - assert type == 'loadable_module', ( - 'mac_xcuitest_bundle targets must have type loadable_module ' - '(target %s)' % target_name) - elif is_xctest: + if is_xctest: type_bundle_key += '+xctest' assert type == 'loadable_module', ( 'mac_xctest_bundle targets must have type loadable_module ' @@ -755,9 +746,6 @@ def GenerateOutput(target_list, target_dicts, data, params): assert not is_bundle, ( 'mac_bundle targets cannot have type none (target "%s")' % target_name) - assert not is_xcuitest, ( - 'mac_xcuitest_bundle targets cannot have type none (target "%s")' % - target_name) assert not is_xctest, ( 'mac_xctest_bundle targets cannot have type none (target "%s")' % target_name) @@ -1010,7 +998,7 @@ def GenerateOutput(target_list, target_dicts, data, params): actions.append(action) if len(concrete_outputs_all) > 0: - # TODO(mark): There's a possibilty for collision here. Consider + # TODO(mark): There's a possibility for collision here. Consider # target "t" rule "A_r" and target "t_A" rule "r". makefile_name = '%s.make' % re.sub( '[^a-zA-Z0-9_]', '_' , '%s_%s' % (target_name, rule['rule_name'])) diff --git a/tools/gyp/pylib/gyp/mac_tool.py b/tools/gyp/pylib/gyp/mac_tool.py index c4c4a6df130404..222befb982a9d4 100755 --- a/tools/gyp/pylib/gyp/mac_tool.py +++ b/tools/gyp/pylib/gyp/mac_tool.py @@ -19,7 +19,6 @@ import re import shutil import string -import struct import subprocess import sys import tempfile @@ -53,7 +52,6 @@ def _CommandifyName(self, name_string): def ExecCopyBundleResource(self, source, dest, convert_to_binary): """Copies a resource file to the bundle/Resources directory, performing any necessary compilation on each resource.""" - convert_to_binary = convert_to_binary == 'True' extension = os.path.splitext(source)[1].lower() if os.path.isdir(source): # Copy tree. @@ -67,16 +65,11 @@ def ExecCopyBundleResource(self, source, dest, convert_to_binary): return self._CopyXIBFile(source, dest) elif extension == '.storyboard': return self._CopyXIBFile(source, dest) - elif extension == '.strings' and not convert_to_binary: - self._CopyStringsFile(source, dest) + elif extension == '.strings': + self._CopyStringsFile(source, dest, convert_to_binary) else: - if os.path.exists(dest): - os.unlink(dest) shutil.copy(source, dest) - if convert_to_binary and extension in ('.plist', '.strings'): - self._ConvertToBinary(dest) - def _CopyXIBFile(self, source, dest): """Compiles a XIB file with ibtool into a binary plist in the bundle.""" @@ -87,49 +80,27 @@ def _CopyXIBFile(self, source, dest): if os.path.relpath(dest): dest = os.path.join(base, dest) - args = ['xcrun', 'ibtool', '--errors', '--warnings', '--notices'] - - if os.environ['XCODE_VERSION_ACTUAL'] > '0700': - args.extend(['--auto-activate-custom-fonts']) - if 'IPHONEOS_DEPLOYMENT_TARGET' in os.environ: - args.extend([ - '--target-device', 'iphone', '--target-device', 'ipad', - '--minimum-deployment-target', - os.environ['IPHONEOS_DEPLOYMENT_TARGET'], - ]) - else: - args.extend([ - '--target-device', 'mac', - '--minimum-deployment-target', - os.environ['MACOSX_DEPLOYMENT_TARGET'], - ]) - - args.extend(['--output-format', 'human-readable-text', '--compile', dest, - source]) - + args = ['xcrun', 'ibtool', '--errors', '--warnings', '--notices', + '--output-format', 'human-readable-text', '--compile', dest, source] ibtool_section_re = re.compile(r'/\*.*\*/') ibtool_re = re.compile(r'.*note:.*is clipping its content') - try: - stdout = subprocess.check_output(args) - except subprocess.CalledProcessError as e: - print(e.output) - raise + ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE) current_section_header = None - for line in stdout.splitlines(): + for line in ibtoolout.stdout: if ibtool_section_re.match(line): current_section_header = line elif not ibtool_re.match(line): if current_section_header: - print(current_section_header) + sys.stdout.write(current_section_header) current_section_header = None - print(line) - return 0 + sys.stdout.write(line) + return ibtoolout.returncode def _ConvertToBinary(self, dest): subprocess.check_call([ 'xcrun', 'plutil', '-convert', 'binary1', '-o', dest, dest]) - def _CopyStringsFile(self, source, dest): + def _CopyStringsFile(self, source, dest, convert_to_binary): """Copies a .strings file using iconv to reconvert the input into UTF-16.""" input_code = self._DetectInputEncoding(source) or "UTF-8" @@ -139,25 +110,32 @@ def _CopyStringsFile(self, source, dest): # semicolon in dictionary. # on invalid files. Do the same kind of validation. import CoreFoundation - with open(source, 'rb') as in_file: - s = in_file.read() + s = open(source, 'rb').read() d = CoreFoundation.CFDataCreate(None, s, len(s)) _, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None) if error: return - with open(dest, 'wb') as fp: - fp.write(s.decode(input_code).encode('UTF-16')) + fp = open(dest, 'wb') + fp.write(s.decode(input_code).encode('UTF-16')) + fp.close() + + if convert_to_binary == 'True': + self._ConvertToBinary(dest) def _DetectInputEncoding(self, file_name): """Reads the first few bytes from file_name and tries to guess the text encoding. Returns None as a guess if it can't detect it.""" - with open(file_name, 'rb') as fp: - try: - header = fp.read(3) - except Exception: - return None - if header.startswith(("\xFE\xFF", "\xFF\xFE")): + fp = open(file_name, 'rb') + try: + header = fp.read(3) + except Exception: + fp.close() + return None + fp.close() + if header.startswith("\xFE\xFF"): + return "UTF-16" + elif header.startswith("\xFF\xFE"): return "UTF-16" elif header.startswith("\xEF\xBB\xBF"): return "UTF-8" @@ -167,8 +145,9 @@ def _DetectInputEncoding(self, file_name): def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys): """Copies the |source| Info.plist to the destination directory |dest|.""" # Read the source Info.plist into memory. - with open(source, 'r') as fd: - lines = fd.read() + fd = open(source, 'r') + lines = fd.read() + fd.close() # Insert synthesized key/value pairs (e.g. BuildMachineOSBuild). plist = plistlib.readPlistFromString(lines) @@ -178,7 +157,7 @@ def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys): # Go through all the environment variables and replace them as variables in # the file. - IDENT_RE = re.compile(r'[_/\s]') + IDENT_RE = re.compile(r'[/\s]') for key in os.environ: if key.startswith('_'): continue @@ -201,16 +180,17 @@ def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys): lines = string.replace(lines, evar, evalue) # Remove any keys with values that haven't been replaced. - lines = lines.splitlines() + lines = lines.split('\n') for i in range(len(lines)): if lines[i].strip().startswith("${"): lines[i] = None lines[i - 1] = None - lines = '\n'.join(line for line in lines if line is not None) + lines = '\n'.join(filter(lambda x: x is not None, lines)) # Write out the file with variables replaced. - with open(dest, 'w') as fd: - fd.write(lines) + fd = open(dest, 'w') + fd.write(lines) + fd.close() # Now write out PkgInfo file now that the Info.plist file has been # "compiled". @@ -238,8 +218,9 @@ def _WritePkgInfo(self, info_plist): signature_code = '?' * 4 dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo') - with open(dest, 'w') as fp: - fp.write('%s%s' % (package_type, signature_code)) + fp = open(dest, 'w') + fp.write('%s%s' % (package_type, signature_code)) + fp.close() def ExecFlock(self, lockfile, *cmd_list): """Emulates the most basic behavior of Linux's flock(1).""" @@ -251,8 +232,7 @@ def ExecFlock(self, lockfile, *cmd_list): def ExecFilterLibtool(self, *cmd_list): """Calls libtool and filters out '/path/to/libtool: file: foo.o has no symbols'.""" - libtool_re = re.compile(r'^.*libtool: (?:for architecture: \S* )?' - r'file: .* has no symbols$') + libtool_re = re.compile(r'^.*libtool: file: .* has no symbols$') libtool_re5 = re.compile( r'^.*libtool: warning for library: ' + r'.* the table of contents is empty ' + @@ -279,22 +259,6 @@ def ExecFilterLibtool(self, *cmd_list): break return libtoolout.returncode - 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') - if not os.path.exists(module_path): - os.mkdir(module_path) - module_template = 'framework module %s {\n' \ - ' umbrella header "%s.h"\n' \ - '\n' \ - ' export *\n' \ - ' module * { export * }\n' \ - '}\n' % (binary, binary) - - with open(os.path.join(module_path, 'module.modulemap'), "w") as module_file: - module_file.write(module_template) - def ExecPackageFramework(self, framework, version): """Takes a path to Something.framework and the Current version of that and sets up all the symlinks.""" @@ -331,23 +295,6 @@ def _Relink(self, dest, link): os.remove(link) os.symlink(dest, link) - def ExecCompileIosFrameworkHeaderMap(self, out, framework, *all_headers): - framework_name = os.path.basename(framework).split('.')[0] - all_headers = [os.path.abspath(header) for header in all_headers] - filelist = {} - for header in all_headers: - filename = os.path.basename(header) - filelist[filename] = header - filelist[os.path.join(framework_name, filename)] = header - WriteHmap(out, filelist) - - def ExecCopyIosFrameworkHeaders(self, framework, *copy_headers): - header_path = os.path.join(framework, 'Headers') - if not os.path.exists(header_path): - os.makedirs(header_path) - for header in copy_headers: - shutil.copy(header, os.path.join(header_path, os.path.basename(header))) - def ExecCompileXcassets(self, keys, *inputs): """Compiles multiple .xcassets files into a single .car file. @@ -408,28 +355,49 @@ def ExecMergeInfoPlist(self, output, *inputs): self._MergePlist(merged_plist, plist) plistlib.writePlist(merged_plist, output) - def ExecCodeSignBundle(self, key, entitlements, provisioning, path, preserve): + def ExecCodeSignBundle(self, key, resource_rules, entitlements, provisioning): """Code sign a bundle. This function tries to code sign an iOS bundle, following the same algorithm as Xcode: - 1. pick the provisioning profile that best match the bundle identifier, + 1. copy ResourceRules.plist from the user or the SDK into the bundle, + 2. pick the provisioning profile that best match the bundle identifier, and copy it into the bundle as embedded.mobileprovision, - 2. copy Entitlements.plist from user or SDK next to the bundle, - 3. code sign the bundle. + 3. copy Entitlements.plist from user or SDK next to the bundle, + 4. code sign the bundle. """ + resource_rules_path = self._InstallResourceRules(resource_rules) substitutions, overrides = self._InstallProvisioningProfile( provisioning, self._GetCFBundleIdentifier()) entitlements_path = self._InstallEntitlements( entitlements, substitutions, overrides) + subprocess.check_call([ + 'codesign', '--force', '--sign', key, '--resource-rules', + resource_rules_path, '--entitlements', entitlements_path, + os.path.join( + os.environ['TARGET_BUILD_DIR'], + os.environ['FULL_PRODUCT_NAME'])]) - args = ['codesign', '--force', '--sign', key] - if preserve == 'True': - args.extend(['--deep', '--preserve-metadata=identifier,entitlements']) - else: - args.extend(['--entitlements', entitlements_path]) - args.extend(['--timestamp=none', path]) - subprocess.check_call(args) + def _InstallResourceRules(self, resource_rules): + """Installs ResourceRules.plist from user or SDK into the bundle. + + Args: + resource_rules: string, optional, path to the ResourceRules.plist file + to use, default to "${SDKROOT}/ResourceRules.plist" + + Returns: + Path to the copy of ResourceRules.plist into the bundle. + """ + source_path = resource_rules + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['CONTENTS_FOLDER_PATH'], + 'ResourceRules.plist') + if not source_path: + source_path = os.path.join( + os.environ['SDKROOT'], 'ResourceRules.plist') + shutil.copy2(source_path, target_path) + return target_path def _InstallProvisioningProfile(self, profile, bundle_identifier): """Installs embedded.mobileprovision into the bundle. @@ -478,8 +446,7 @@ def _FindProvisioningProfile(self, profile, bundle_identifier): profiles_dir = os.path.join( os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles') if not os.path.isdir(profiles_dir): - print('cannot find mobile provisioning for %s' % bundle_identifier, - file=sys.stderr) + print('cannot find mobile provisioning for %s' % (bundle_identifier), file=sys.stderr) sys.exit(1) provisioning_profiles = None if profile: @@ -500,8 +467,7 @@ def _FindProvisioningProfile(self, profile, bundle_identifier): valid_provisioning_profiles[app_id_pattern] = ( profile_path, profile_data, team_identifier) if not valid_provisioning_profiles: - print('cannot find mobile provisioning for %s' % bundle_identifier, - file=sys.stderr) + print('cannot find mobile provisioning for %s' % (bundle_identifier), file=sys.stderr) sys.exit(1) # If the user has multiple provisioning profiles installed that can be # used for ${bundle_identifier}, pick the most specific one (ie. the @@ -644,71 +610,5 @@ def _ExpandVariables(self, data, substitutions): return {k: self._ExpandVariables(data[k], substitutions) for k in data} return data -def NextGreaterPowerOf2(x): - return 2**(x).bit_length() - -def WriteHmap(output_name, filelist): - """Generates a header map based on |filelist|. - - Per Mark Mentovai: - A header map is structured essentially as a hash table, keyed by names used - in #includes, and providing pathnames to the actual files. - - The implementation below and the comment above comes from inspecting: - http://www.opensource.apple.com/source/distcc/distcc-2503/distcc_dist/include_server/headermap.py?txt - while also looking at the implementation in clang in: - https://llvm.org/svn/llvm-project/cfe/trunk/lib/Lex/HeaderMap.cpp - """ - magic = 1751998832 - version = 1 - _reserved = 0 - count = len(filelist) - capacity = NextGreaterPowerOf2(count) - strings_offset = 24 + (12 * capacity) - max_value_length = max(len(value) for value in filelist.values()) - - out = open(output_name, "wb") - out.write(struct.pack(' 0 or arg.count('/') > 1: - arg = os.path.normpath(arg) - # For a literal quote, CommandLineToArgvW requires 2n+1 backslashes # preceding it, and results in n backslashes + the quote. So we substitute # in 2* what we match, +1 more, plus the quote. @@ -130,7 +127,10 @@ def _FindDirectXInstallation(): # Setup params to pass to and attempt to launch reg.exe. cmd = ['reg.exe', 'query', r'HKLM\Software\Microsoft\DirectX', '/s'] p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - for line in p.communicate()[0].splitlines(): + stdout = p.communicate()[0] + if PY3: + stdout = stdout.decode('utf-8') + for line in stdout.splitlines(): if 'InstallPath' in line: dxsdk_dir = line.split(' ')[3] + "\\" @@ -241,7 +241,11 @@ def GetExtension(self): def GetVSMacroEnv(self, base_to_build=None, config=None): """Get a dict of variables mapping internal VS macro names to their gyp equivalents.""" - target_platform = 'Win32' if self.GetArch(config) == 'x86' else 'x64' + target_arch = self.GetArch(config) + if target_arch == 'x86': + target_platform = 'Win32' + else: + target_platform = target_arch target_name = self.spec.get('product_prefix', '') + \ self.spec.get('product_name', self.spec['target_name']) target_dir = base_to_build + '\\' if base_to_build else '' @@ -273,8 +277,7 @@ def ConvertVSMacros(self, s, base_to_build=None, config=None): def AdjustLibraries(self, libraries): """Strip -l from library if it's specified with that.""" libs = [lib[2:] if lib.startswith('-l') else lib for lib in libraries] - return [lib + '.lib' if not lib.lower().endswith('.lib') \ - and not lib.lower().endswith('.obj') else lib for lib in libs] + return [lib + '.lib' if not lib.endswith('.lib') else lib for lib in libs] def _GetAndMunge(self, field, path, default, prefix, append, map): """Retrieve a value from |field| at |path| or return |default|. If @@ -304,17 +307,14 @@ def GetArch(self, config): if not platform: # If no specific override, use the configuration's. platform = configuration_platform # Map from platform to architecture. - return {'Win32': 'x86', 'x64': 'x64'}.get(platform, 'x86') + return {'Win32': 'x86', 'x64': 'x64', 'ARM64': 'arm64'}.get(platform, 'x86') def _TargetConfig(self, config): """Returns the target-specific configuration.""" # There's two levels of architecture/platform specification in VS. The # first level is globally for the configuration (this is what we consider # "the" config at the gyp level, which will be something like 'Debug' or - # 'Release'), VS2015 and later only use this level - if self.vs_version.short_name >= 2015: - return config - # and a second target-specific configuration, which is an + # 'Release_x64'), and a second target-specific configuration, which is an # override for the global one. |config| is remapped here to take into # account the local target-specific overrides to the global configuration. arch = self.GetArch(config) @@ -379,7 +379,7 @@ def GetCompilerPdbName(self, config, expand_special): return pdbname def GetMapFileName(self, config, expand_special): - """Gets the explicitly overriden map file name for a target or returns None + """Gets the explicitly overridden map file name for a target or returns None if it's not set.""" config = self._TargetConfig(config) map_file = self._Setting(('VCLinkerTool', 'MapFileName'), config) @@ -476,10 +476,8 @@ def GetCflags(self, config): prefix='/arch:') cflags.extend(['/FI' + f for f in self._Setting( ('VCCLCompilerTool', 'ForcedIncludeFiles'), config, default=[])]) - if self.vs_version.project_version >= 12.0: - # New flag introduced in VS2013 (project version 12.0) Forces writes to - # the program database (PDB) to be serialized through MSPDBSRV.EXE. - # https://msdn.microsoft.com/en-us/library/dn502518.aspx + if self.vs_version.short_name in ('2013', '2013e', '2015'): + # New flag required in 2013 to maintain previous PDB behavior. cflags.append('/FS') # ninja handles parallelism by itself, don't have the compiler do it too. cflags = filter(lambda x: not x.startswith('/MP'), cflags) @@ -495,9 +493,8 @@ def _GetPchFlags(self, config, extension): if self.msvs_precompiled_header[config]: source_ext = os.path.splitext(self.msvs_precompiled_source[config])[1] if _LanguageMatchesForPch(source_ext, extension): - pch = self.msvs_precompiled_header[config] - pchbase = os.path.split(pch)[1] - return ['/Yu' + pch, '/FI' + pch, '/Fp${pchprefix}.' + pchbase + '.pch'] + pch = os.path.split(self.msvs_precompiled_header[config])[1] + return ['/Yu' + pch, '/FI' + pch, '/Fp${pchprefix}.' + pch + '.pch'] return [] def GetCflagsC(self, config): @@ -539,8 +536,7 @@ def GetDefFile(self, gyp_to_build_path): """Returns the .def file from sources, if any. Otherwise returns None.""" spec = self.spec if spec['type'] in ('shared_library', 'loadable_module', 'executable'): - def_files = [s for s in spec.get('sources', []) - if s.lower().endswith('.def')] + def_files = [s for s in spec.get('sources', []) if s.endswith('.def')] if len(def_files) == 1: return gyp_to_build_path(def_files[0]) elif len(def_files) > 1: @@ -575,7 +571,10 @@ def GetLdflags(self, config, gyp_to_build_path, expand_special, 'VCLinkerTool', append=ldflags) self._GetDefFileAsLdflags(ldflags, gyp_to_build_path) ld('GenerateDebugInformation', map={'true': '/DEBUG'}) - ld('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'}, + # TODO: These 'map' values come from machineTypeOption enum, + # and does not have an official value for ARM64 in VS2017 (yet). + # It needs to verify the ARM64 value when machineTypeOption is updated. + ld('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM', '18': 'ARM64'}, prefix='/MACHINE:') ldflags.extend(self._GetAdditionalLibraryDirectories( 'VCLinkerTool', config, gyp_to_build_path)) @@ -872,7 +871,9 @@ def midl(name, default=None): ('iid', iid), ('proxy', proxy)] # TODO(scottmg): Are there configuration settings to set these flags? - target_platform = 'win32' if self.GetArch(config) == 'x86' else 'x64' + target_platform = self.GetArch(config) + if target_platform == 'x86': + target_platform = 'win32' flags = ['/char', 'signed', '/env', target_platform, '/Oicf'] return outdir, output, variables, flags @@ -900,7 +901,7 @@ def __init__( def _PchHeader(self): """Get the header that will appear in an #include line for all source files.""" - return self.settings.msvs_precompiled_header[self.config] + return os.path.split(self.settings.msvs_precompiled_header[self.config])[1] def GetObjDependencies(self, sources, objs, arch): """Given a list of sources files and the corresponding object files, @@ -973,10 +974,6 @@ def _ExtractImportantEnvironment(output_of_set): 'tmp', ) env = {} - # This occasionally happens and leads to misleading SYSTEMROOT error messages - # if not caught here. - if output_of_set.count('=') == 0: - raise Exception('Invalid output_of_set. Value is:\n%s' % output_of_set) for line in output_of_set.splitlines(): for envvar in envvars_to_save: if re.match(envvar + '=', line.lower()): @@ -1045,8 +1042,8 @@ def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, popen = subprocess.Popen( args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) variables, _ = popen.communicate() - if popen.returncode != 0: - raise Exception('"%s" failed with error %d' % (args, popen.returncode)) + if PY3: + variables = variables.decode('utf-8') env = _ExtractImportantEnvironment(variables) # Inject system includes from gyp files into INCLUDE. @@ -1066,6 +1063,8 @@ def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, 'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i')) popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE) output, _ = popen.communicate() + if PY3: + output = output.decode('utf-8') cl_paths[arch] = _ExtractCLPath(output) return cl_paths diff --git a/tools/gyp/pylib/gyp/ordered_dict.py b/tools/gyp/pylib/gyp/ordered_dict.py deleted file mode 100644 index 6fe9c1f6c7c22b..00000000000000 --- a/tools/gyp/pylib/gyp/ordered_dict.py +++ /dev/null @@ -1,289 +0,0 @@ -# Unmodified from http://code.activestate.com/recipes/576693/ -# other than to add MIT license header (as specified on page, but not in code). -# Linked from Python documentation here: -# http://docs.python.org/2/library/collections.html#collections.OrderedDict -# -# This should be deleted once Py2.7 is available on all bots, see -# http://crbug.com/241769. -# -# Copyright (c) 2009 Raymond Hettinger. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. -# Passes Python2.7's test suite and incorporates all the latest updates. - -try: - from thread import get_ident as _get_ident -except ImportError: - from dummy_thread import get_ident as _get_ident - -try: - from _abcoll import KeysView, ValuesView, ItemsView -except ImportError: - pass - - -class OrderedDict(dict): - 'Dictionary that remembers insertion order' - # An inherited dict maps keys to values. - # The inherited dict provides __getitem__, __len__, __contains__, and get. - # The remaining methods are order-aware. - # Big-O running times for all methods are the same as for regular dictionaries. - - # The internal self.__map dictionary maps keys to links in a doubly linked list. - # The circular doubly linked list starts and ends with a sentinel element. - # The sentinel element never gets deleted (this simplifies the algorithm). - # Each link is stored as a list of length three: [PREV, NEXT, KEY]. - - def __init__(self, *args, **kwds): - '''Initialize an ordered dictionary. Signature is the same as for - regular dictionaries, but keyword arguments are not recommended - because their insertion order is arbitrary. - - ''' - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - try: - self.__root - except AttributeError: - self.__root = root = [] # sentinel node - root[:] = [root, root, None] - self.__map = {} - self.__update(*args, **kwds) - - def __setitem__(self, key, value, dict_setitem=dict.__setitem__): - 'od.__setitem__(i, y) <==> od[i]=y' - # Setting a new item creates a new link which goes at the end of the linked - # list, and the inherited dictionary is updated with the new key/value pair. - if key not in self: - root = self.__root - last = root[0] - last[1] = root[0] = self.__map[key] = [last, root, key] - dict_setitem(self, key, value) - - def __delitem__(self, key, dict_delitem=dict.__delitem__): - 'od.__delitem__(y) <==> del od[y]' - # Deleting an existing item uses self.__map to find the link which is - # then removed by updating the links in the predecessor and successor nodes. - dict_delitem(self, key) - link_prev, link_next, key = self.__map.pop(key) - link_prev[1] = link_next - link_next[0] = link_prev - - def __iter__(self): - 'od.__iter__() <==> iter(od)' - root = self.__root - curr = root[1] - while curr is not root: - yield curr[2] - curr = curr[1] - - def __reversed__(self): - 'od.__reversed__() <==> reversed(od)' - root = self.__root - curr = root[0] - while curr is not root: - yield curr[2] - curr = curr[0] - - def clear(self): - 'od.clear() -> None. Remove all items from od.' - try: - for node in self.__map.itervalues(): - del node[:] - root = self.__root - root[:] = [root, root, None] - self.__map.clear() - except AttributeError: - pass - dict.clear(self) - - def popitem(self, last=True): - '''od.popitem() -> (k, v), return and remove a (key, value) pair. - Pairs are returned in LIFO order if last is true or FIFO order if false. - - ''' - if not self: - raise KeyError('dictionary is empty') - root = self.__root - if last: - link = root[0] - link_prev = link[0] - link_prev[1] = root - root[0] = link_prev - else: - link = root[1] - link_next = link[1] - root[1] = link_next - link_next[0] = root - key = link[2] - del self.__map[key] - value = dict.pop(self, key) - return key, value - - # -- the following methods do not depend on the internal structure -- - - def keys(self): - 'od.keys() -> list of keys in od' - return list(self) - - def values(self): - 'od.values() -> list of values in od' - return [self[key] for key in self] - - def items(self): - 'od.items() -> list of (key, value) pairs in od' - return [(key, self[key]) for key in self] - - def iterkeys(self): - 'od.iterkeys() -> an iterator over the keys in od' - return iter(self) - - def itervalues(self): - 'od.itervalues -> an iterator over the values in od' - for k in self: - yield self[k] - - def items(self): - 'od.items -> an iterator over the (key, value) items in od' - for k in self: - yield (k, self[k]) - - # Suppress 'OrderedDict.update: Method has no argument': - # pylint: disable=E0211 - def update(*args, **kwds): - '''od.update(E, **F) -> None. Update od from dict/iterable E and F. - - If E is a dict instance, does: for k in E: od[k] = E[k] - If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] - Or if E is an iterable of items, does: for k, v in E: od[k] = v - In either case, this is followed by: for k, v in F.items(): od[k] = v - - ''' - if len(args) > 2: - raise TypeError('update() takes at most 2 positional ' - 'arguments (%d given)' % (len(args),)) - elif not args: - raise TypeError('update() takes at least 1 argument (0 given)') - self = args[0] - # Make progressively weaker assumptions about "other" - other = () - if len(args) == 2: - other = args[1] - if isinstance(other, dict): - for key in other: - self[key] = other[key] - elif hasattr(other, 'keys'): - for key in other.keys(): - self[key] = other[key] - else: - for key, value in other: - self[key] = value - for key, value in kwds.items(): - self[key] = value - - __update = update # let subclasses override update without breaking __init__ - - __marker = object() - - def pop(self, key, default=__marker): - '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. - If key is not found, d is returned if given, otherwise KeyError is raised. - - ''' - if key in self: - result = self[key] - del self[key] - return result - if default is self.__marker: - raise KeyError(key) - return default - - def setdefault(self, key, default=None): - 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' - if key in self: - return self[key] - self[key] = default - return default - - def __repr__(self, _repr_running={}): - 'od.__repr__() <==> repr(od)' - call_key = id(self), _get_ident() - if call_key in _repr_running: - return '...' - _repr_running[call_key] = 1 - try: - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) - finally: - del _repr_running[call_key] - - def __reduce__(self): - 'Return state information for pickling' - items = [[k, self[k]] for k in self] - inst_dict = vars(self).copy() - for k in vars(OrderedDict()): - inst_dict.pop(k, None) - if inst_dict: - return (self.__class__, (items,), inst_dict) - return self.__class__, (items,) - - def copy(self): - 'od.copy() -> a shallow copy of od' - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S - and values equal to v (which defaults to None). - - ''' - d = cls() - for key in iterable: - d[key] = value - return d - - def __eq__(self, other): - '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive - while comparison to a regular mapping is order-insensitive. - - ''' - if isinstance(other, OrderedDict): - return len(self)==len(other) and self.items() == other.items() - return dict.__eq__(self, other) - - def __ne__(self, other): - return not self == other - - # -- the following methods are only used in Python 2.7 -- - - def viewkeys(self): - "od.viewkeys() -> a set-like object providing a view on od's keys" - return KeysView(self) - - def viewvalues(self): - "od.viewvalues() -> an object providing a view on od's values" - return ValuesView(self) - - def viewitems(self): - "od.viewitems() -> a set-like object providing a view on od's items" - return ItemsView(self) - diff --git a/tools/gyp/pylib/gyp/win_tool.py b/tools/gyp/pylib/gyp/win_tool.py index ab6db1c4e047fb..0a6daf203931e6 100755 --- a/tools/gyp/pylib/gyp/win_tool.py +++ b/tools/gyp/pylib/gyp/win_tool.py @@ -20,6 +20,7 @@ import sys BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +PY3 = bytes != str # A regex matching an argument corresponding to the output filename passed to # link.exe. @@ -118,20 +119,14 @@ def ExecLinkWrapper(self, arch, use_separate_mspdbsrv, *args): env = self._GetEnv(arch) if use_separate_mspdbsrv == 'True': self._UseSeparateMspdbsrv(env, args) - if sys.platform == 'win32': - args = list(args) # *args is a tuple by default, which is read-only. - args[0] = args[0].replace('/', '\\') - # https://docs.python.org/2/library/subprocess.html: - # "On Unix with shell=True [...] if args is a sequence, the first item - # specifies the command string, and any additional items will be treated as - # additional arguments to the shell itself. That is to say, Popen does the - # equivalent of: - # Popen(['/bin/sh', '-c', args[0], args[1], ...])" - # For that reason, since going through the shell doesn't seem necessary on - # non-Windows don't do that there. - link = subprocess.Popen(args, shell=sys.platform == 'win32', env=env, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + link = subprocess.Popen([args[0].replace('/', '\\')] + list(args[1:]), + shell=True, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) out, _ = link.communicate() + if PY3: + out = out.decode('utf-8') for line in out.splitlines(): if (not line.startswith(' Creating library ') and not line.startswith('Generating code') and @@ -223,6 +218,8 @@ def ExecManifestWrapper(self, arch, *args): popen = subprocess.Popen(args, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out, _ = popen.communicate() + if PY3: + out = out.decode('utf-8') for line in out.splitlines(): if line and 'manifest authoring warning 81010002' not in line: print(line) @@ -255,6 +252,8 @@ def ExecMidlWrapper(self, arch, outdir, tlb, h, dlldata, iid, proxy, idl, popen = subprocess.Popen(args, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out, _ = popen.communicate() + if PY3: + out = out.decode('utf-8') # Filter junk out of stdout, and write filtered versions. Output we want # to filter is pairs of lines that look like this: # Processing C:\Program Files (x86)\Microsoft SDKs\...\include\objidl.idl @@ -274,6 +273,8 @@ def ExecAsmWrapper(self, arch, *args): popen = subprocess.Popen(args, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out, _ = popen.communicate() + if PY3: + out = out.decode('utf-8') for line in out.splitlines(): if (not line.startswith('Copyright (C) Microsoft Corporation') and not line.startswith('Microsoft (R) Macro Assembler') and @@ -289,6 +290,8 @@ def ExecRcWrapper(self, arch, *args): popen = subprocess.Popen(args, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out, _ = popen.communicate() + if PY3: + out = out.decode('utf-8') for line in out.splitlines(): if (not line.startswith('Microsoft (R) Windows (R) Resource Compiler') and not line.startswith('Copyright (C) Microsoft Corporation') and diff --git a/tools/gyp/pylib/gyp/xcode_emulation.py b/tools/gyp/pylib/gyp/xcode_emulation.py index 905bec7be34ba8..60171649900aae 100644 --- a/tools/gyp/pylib/gyp/xcode_emulation.py +++ b/tools/gyp/pylib/gyp/xcode_emulation.py @@ -151,7 +151,6 @@ class XcodeSettings(object): # Populated lazily by _SdkPath(). Shared by all XcodeSettings, so cached # at class-level for efficiency. _sdk_path_cache = {} - _platform_path_cache = {} _sdk_root_cache = {} # Populated lazily by GetExtraPlistItems(). Shared by all XcodeSettings, so @@ -166,8 +165,6 @@ def __init__(self, spec): self.spec = spec self.isIOS = False - self.mac_toolchain_dir = None - self.header_map_path = None # Per-target 'xcode_settings' are pushed down into configs earlier by gyp. # This means self.xcode_settings[config] always contains all settings @@ -201,7 +198,7 @@ def _ConvertConditionalKeys(self, configname): new_key = key.split("[")[0] settings[new_key] = settings[key] else: - print('Warning: Conditional keys not implemented, ignoring:', + print('Warning: Conditional keys not implemented, ignoring:', \ ' '.join(conditional_keys)) del settings[key] @@ -228,19 +225,8 @@ def IsBinaryOutputFormat(self, configname): default) return format == "binary" - def IsIosFramework(self): - 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() - - def _IsXCTest(self): - return int(self.spec.get('mac_xctest_bundle', 0)) != 0 - - def _IsXCUiTest(self): - return int(self.spec.get('mac_xcuitest_bundle', 0)) != 0 + return int(self.spec.get('mac_bundle', 0)) != 0 def _IsIosAppExtension(self): return int(self.spec.get('ios_app_extension', 0)) != 0 @@ -251,6 +237,9 @@ def _IsIosWatchKitExtension(self): def _IsIosWatchApp(self): return int(self.spec.get('ios_watch_app', 0)) != 0 + def _IsXCTest(self): + return int(self.spec.get('mac_xctest_bundle', 0)) != 0 + def GetFrameworkVersion(self): """Returns the framework version of the current target. Only valid for bundles.""" @@ -316,62 +305,11 @@ def GetBundleResourceFolder(self): return self.GetBundleContentsFolderPath() return os.path.join(self.GetBundleContentsFolderPath(), 'Resources') - 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: - return self.GetBundleContentsFolderPath() - elif self.spec['type'] in ('executable', 'loadable_module'): - return os.path.join(self.GetBundleContentsFolderPath(), 'MacOS') - - def GetBundleJavaFolderPath(self): - """Returns the qualified path to the bundle's Java resource folder. - E.g. Chromium.app/Contents/Resources/Java. Only valid for bundles.""" - assert self._IsBundle() - return os.path.join(self.GetBundleResourceFolder(), 'Java') - - def GetBundleFrameworksFolderPath(self): - """Returns the qualified path to the bundle's frameworks folder. E.g, - Chromium.app/Contents/Frameworks. Only valid for bundles.""" - assert self._IsBundle() - return os.path.join(self.GetBundleContentsFolderPath(), 'Frameworks') - - def GetBundleSharedFrameworksFolderPath(self): - """Returns the qualified path to the bundle's frameworks folder. E.g, - Chromium.app/Contents/SharedFrameworks. Only valid for bundles.""" - assert self._IsBundle() - return os.path.join(self.GetBundleContentsFolderPath(), - 'SharedFrameworks') - - def GetBundleSharedSupportFolderPath(self): - """Returns the qualified path to the bundle's shared support folder. E.g, - Chromium.app/Contents/SharedSupport. Only valid for bundles.""" - assert self._IsBundle() - if self.spec['type'] == 'shared_library': - return self.GetBundleResourceFolder() - else: - return os.path.join(self.GetBundleContentsFolderPath(), - 'SharedSupport') - - def GetBundlePlugInsFolderPath(self): - """Returns the qualified path to the bundle's plugins folder. E.g, - Chromium.app/Contents/PlugIns. Only valid for bundles.""" - assert self._IsBundle() - return os.path.join(self.GetBundleContentsFolderPath(), 'PlugIns') - - def GetBundleXPCServicesFolderPath(self): - """Returns the qualified path to the bundle's XPC services folder. E.g, - Chromium.app/Contents/XPCServices. Only valid for bundles.""" - assert self._IsBundle() - return os.path.join(self.GetBundleContentsFolderPath(), 'XPCServices') - 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'): return os.path.join(self.GetBundleContentsFolderPath(), 'Info.plist') else: return os.path.join(self.GetBundleContentsFolderPath(), @@ -391,10 +329,6 @@ def GetProductType(self): assert self._IsBundle(), ('ios_watch_app flag requires mac_bundle ' '(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']) - return 'com.apple.product-type.bundle.ui-testing' if self._IsBundle(): return { 'executable': 'com.apple.product-type.application', @@ -425,8 +359,11 @@ def _GetBundleBinaryPath(self): """Returns the name of the bundle binary of by this target. E.g. Chromium.app/Contents/MacOS/Chromium. Only valid for bundles.""" assert self._IsBundle() - return os.path.join(self.GetBundleExecutableFolderPath(), \ - self.GetExecutableName()) + if self.spec['type'] in ('shared_library') or self.isIOS: + path = self.GetBundleContentsFolderPath() + elif self.spec['type'] in ('executable', 'loadable_module'): + path = os.path.join(self.GetBundleContentsFolderPath(), 'MacOS') + return os.path.join(path, self.GetExecutableName()) def _GetStandaloneExecutableSuffix(self): if 'product_extension' in self.spec: @@ -477,8 +414,8 @@ def GetExecutableName(self): return self._GetStandaloneBinaryPath() def GetExecutablePath(self): - """Returns the qualified path to the primary executable of the bundle - represented by this target. E.g. Chromium.app/Contents/MacOS/Chromium.""" + """Returns the directory name of the bundle represented by this target. E.g. + Chromium.app/Contents/MacOS/Chromium.""" if self._IsBundle(): return self._GetBundleBinaryPath() else: @@ -499,7 +436,7 @@ def _GetSdkVersionInfoItem(self, sdk, infoitem): # Since the CLT has no SDK paths anyway, returning None is the # most sensible route and should still do the right thing. try: - return GetStdoutQuiet(['xcrun', '--sdk', sdk, infoitem]) + return GetStdoutQuiet(['xcodebuild', '-version', '-sdk', sdk, infoitem]) except GypError: pass @@ -508,14 +445,6 @@ def _SdkRoot(self, configname): configname = self.configname return self.GetPerConfigSetting('SDKROOT', configname, default='') - 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') - XcodeSettings._platform_path_cache[sdk_root] = platform_path - return XcodeSettings._platform_path_cache[sdk_root] - def _SdkPath(self, configname=None): sdk_root = self._SdkRoot(configname) if sdk_root.startswith('/'): @@ -524,7 +453,7 @@ def _SdkPath(self, configname=None): def _XcodeSdkPath(self, sdk_root): if sdk_root not in XcodeSettings._sdk_path_cache: - sdk_path = self._GetSdkVersionInfoItem(sdk_root, '--show-sdk-path') + sdk_path = self._GetSdkVersionInfoItem(sdk_root, 'Path') XcodeSettings._sdk_path_cache[sdk_root] = sdk_path if sdk_root: XcodeSettings._sdk_root_cache[sdk_path] = sdk_root @@ -555,9 +484,6 @@ def GetCflags(self, configname, arch=None): if 'SDKROOT' in self._Settings() and sdk_root: cflags.append('-isysroot %s' % sdk_root) - if self.header_map_path: - cflags.append('-I%s' % self.header_map_path) - if self._Test('CLANG_WARN_CONSTANT_CONVERSION', 'YES', default='NO'): cflags.append('-Wconstant-conversion') @@ -854,7 +780,7 @@ def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None): product_dir: The directory where products such static and dynamic 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. + current gyp file to paths relative to the build directory. """ self.configname = configname ldflags = [] @@ -900,8 +826,7 @@ def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None): ldflags.append('-arch ' + archs[0]) # Xcode adds the product directory by default. - # Rewrite -L. to -L./ to work around http://www.openradar.me/25313838 - ldflags.append('-L' + (product_dir if product_dir != '.' else './')) + ldflags.append('-L' + product_dir) install_name = self.GetInstallName() if install_name and self.spec['type'] != 'loadable_module': @@ -920,9 +845,8 @@ def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None): if self._IsXCTest(): platform_root = self._XcodePlatformPath(configname) - if sdk_root and platform_root: + if platform_root: ldflags.append('-F' + platform_root + '/Developer/Library/Frameworks/') - ldflags.append('-framework XCTest') is_extension = self._IsIosAppExtension() or self._IsIosWatchKitExtension() if sdk_root and is_extension: @@ -930,14 +854,14 @@ 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. + ldflags.append('-lpkstart') xcode_version, _ = XcodeVersion() if xcode_version < '0900': - ldflags.append('-lpkstart') ldflags.append(sdk_root + '/System/Library/PrivateFrameworks/PlugInKit.framework/PlugInKit') - else: - ldflags.append('-e _NSExtensionMain') ldflags.append('-fapplication-extension') + ldflags.append('-Xlinker -rpath ' + '-Xlinker @executable_path/../../Frameworks') self._Appendf(ldflags, 'CLANG_CXX_LIBRARY', '-stdlib=%s') @@ -1002,7 +926,7 @@ def GetPerTargetSetting(self, setting, default=None): def _GetStripPostbuilds(self, configname, output_binary, quiet): """Returns a list of shell commands that contain the shell commands - neccessary to strip this target's binary. These should be run as postbuilds + necessary to strip this target's binary. These should be run as postbuilds before the actual postbuilds run.""" self.configname = configname @@ -1011,8 +935,7 @@ def _GetStripPostbuilds(self, configname, output_binary, quiet): self._Test('STRIP_INSTALLED_PRODUCT', 'YES', default='NO')): default_strip_style = 'debugging' - if ((self.spec['type'] == 'loadable_module' or self._IsIosAppExtension()) - and self._IsBundle()): + if self.spec['type'] == 'loadable_module' and self._IsBundle(): default_strip_style = 'non-global' elif self.spec['type'] == 'executable': default_strip_style = 'all' @@ -1037,7 +960,7 @@ def _GetStripPostbuilds(self, configname, output_binary, quiet): def _GetDebugInfoPostbuilds(self, configname, output, output_binary, quiet): """Returns a list of shell commands that contain the shell commands - neccessary to massage this target's debug information. These should be run + necessary to massage this target's debug information. These should be run as postbuilds before the actual postbuilds run.""" self.configname = configname @@ -1067,68 +990,27 @@ def _GetIOSPostbuilds(self, configname, output_binary): """Return a shell command to codesign the iOS output binary so it can 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()): + if not (self.isIOS and self.spec['type'] == 'executable'): return [] - postbuilds = [] - product_name = self.GetFullProductName() settings = self.xcode_settings[configname] - - # Xcode expects XCTests to be copied into the TEST_HOST dir. - if self._IsXCTest(): - source = os.path.join("${BUILT_PRODUCTS_DIR}", product_name) - test_host = os.path.dirname(settings.get('TEST_HOST')) - xctest_destination = os.path.join(test_host, 'PlugIns', product_name) - postbuilds.extend(['ditto %s %s' % (source, xctest_destination)]) - key = self._GetIOSCodeSignIdentityKey(settings) if not key: - return postbuilds + return [] # Warn for any unimplemented signing xcode keys. unimpl = ['OTHER_CODE_SIGN_FLAGS'] unimpl = set(unimpl) & set(self.xcode_settings[configname].keys()) if unimpl: - print('Warning: Some codesign keys not implemented, ignoring: %s' % - ', '.join(sorted(unimpl))) + print('Warning: Some codesign keys not implemented, ignoring: %s' % ( + ', '.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'] - for framework in frameworks: - source = os.path.join(platform_root, framework) - destination = os.path.join(frameworks_dir, os.path.basename(framework)) - postbuilds.extend(['ditto %s %s' % (source, destination)]) - - # 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) - ]) - 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) - ]) - - postbuilds.extend(['%s code-sign-bundle "%s" "%s" "%s" "%s" %s' % ( + return ['%s code-sign-bundle "%s" "%s" "%s" "%s"' % ( os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key, + settings.get('CODE_SIGN_RESOURCE_RULES_PATH', ''), settings.get('CODE_SIGN_ENTITLEMENTS', ''), - settings.get('PROVISIONING_PROFILE', ''), - os.path.join("${BUILT_PRODUCTS_DIR}", product_name), False) - ]) - return postbuilds + settings.get('PROVISIONING_PROFILE', '')) + ] def _GetIOSCodeSignIdentityKey(self, settings): identity = settings.get('CODE_SIGN_IDENTITY') @@ -1173,7 +1055,7 @@ def _AdjustLibrary(self, library, config_name=None): # "/usr/lib" libraries, is do "-L/usr/lib -lname" which is dependent on the # library order and cause collision when building Chrome. # - # Instead substitude ".tbd" to ".dylib" in the generated project when the + # Instead substitute ".tbd" to ".dylib" in the generated project when the # following conditions are both true: # - library is referenced in the gyp file as "$(SDKROOT)/**/*.dylib", # - the ".dylib" file does not exists but a ".tbd" file do. @@ -1210,37 +1092,25 @@ def GetExtraPlistItems(self, configname=None): xcode_version, xcode_build = XcodeVersion() cache['DTXcode'] = xcode_version cache['DTXcodeBuild'] = xcode_build - 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') - cache['DTSDKName'] = sdk_root + (sdk_version or '') - if xcode_version >= '0720': + cache['DTSDKName'] = sdk_root + if xcode_version >= '0430': cache['DTSDKBuild'] = self._GetSdkVersionInfoItem( - sdk_root, '--show-sdk-build-version') - elif xcode_version >= '0430': - cache['DTSDKBuild'] = sdk_version + sdk_root, 'ProductBuildVersion') else: cache['DTSDKBuild'] = cache['BuildMachineOSBuild'] if self.isIOS: - cache['MinimumOSVersion'] = self.xcode_settings[configname].get( - 'IPHONEOS_DEPLOYMENT_TARGET') - cache['DTPlatformName'] = sdk_root - cache['DTPlatformVersion'] = sdk_version - + cache['DTPlatformName'] = cache['DTSDKName'] if configname.endswith("iphoneos"): + cache['DTPlatformVersion'] = self._GetSdkVersionInfoItem( + sdk_root, 'ProductVersion') cache['CFBundleSupportedPlatforms'] = ['iPhoneOS'] - cache['DTPlatformBuild'] = cache['DTSDKBuild'] else: cache['CFBundleSupportedPlatforms'] = ['iPhoneSimulator'] - # This is weird, but Xcode sets DTPlatformBuild to an empty field - # for simulator builds. - cache['DTPlatformBuild'] = "" XcodeSettings._plist_cache[configname] = cache # Include extra plist items that are per-target, not per global @@ -1450,8 +1320,7 @@ def GetStdoutQuiet(cmdlist): """Returns the content of standard output returned by invoking |cmdlist|. Ignores the stderr. Raises |GypError| if the command return with a non-zero return code.""" - job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out = job.communicate()[0] if PY3: out = out.decode("utf-8") @@ -1476,7 +1345,7 @@ def GetStdout(cmdlist): 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 - xcode_settings dict, the local key gets precendence. + xcode_settings dict, the local key gets precedence. """ # The xcode generator special-cases global xcode_settings and does something # that amounts to merging in the global xcode_settings into each local @@ -1495,10 +1364,7 @@ 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 \ - (int(spec.get('mac_bundle', 0)) != 0 and flavor == 'mac') - + is_mac_bundle = (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")' % @@ -1522,7 +1388,7 @@ def GetMacBundleResources(product_dir, xcode_settings, resources): output = dest # The make generator doesn't support it, so forbid it everywhere - # to keep the generators more interchangable. + # to keep the generators more interchangeable. assert ' ' not in res, ( "Spaces in resource filenames not supported (%s)" % res) @@ -1564,14 +1430,14 @@ def GetMacInfoPlist(product_dir, xcode_settings, gyp_path_to_build_path): relative to the build directory. xcode_settings: The XcodeSettings of the current target. gyp_to_build_path: A function that converts paths relative to the - current gyp file to paths relative to the build direcotry. + current gyp file to paths relative to the build directory. """ info_plist = xcode_settings.GetPerTargetSetting('INFOPLIST_FILE') if not info_plist: return None, None, [], {} # The make generator doesn't support it, so forbid it everywhere - # to keep the generators more interchangable. + # to keep the generators more interchangeable. assert ' ' not in info_plist, ( "Spaces in Info.plist filenames not supported (%s)" % info_plist) @@ -1608,14 +1474,13 @@ def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, additional_settings: An optional dict with more values to add to the result. """ - if not xcode_settings: return {} # This function is considered a friend of XcodeSettings, so let it reach into # its implementation details. spec = xcode_settings.spec - # These are filled in on an as-needed basis. + # These are filled in on a as-needed basis. env = { 'BUILT_FRAMEWORKS_DIR' : built_products_dir, 'BUILT_PRODUCTS_DIR' : built_products_dir, @@ -1628,16 +1493,12 @@ def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, # written for bundles: 'TARGET_BUILD_DIR' : built_products_dir, 'TEMP_DIR' : '${TMPDIR}', - 'XCODE_VERSION_ACTUAL' : XcodeVersion()[0], } if xcode_settings.GetPerConfigSetting('SDKROOT', configuration): env['SDKROOT'] = xcode_settings._SdkPath(configuration) 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'): env['EXECUTABLE_NAME'] = xcode_settings.GetExecutableName() @@ -1648,27 +1509,10 @@ def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, env['MACH_O_TYPE'] = mach_o_type env['PRODUCT_TYPE'] = xcode_settings.GetProductType() 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() + xcode_settings.GetBundleContentsFolderPath() 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['PLUGINS_FOLDER_PATH'] = xcode_settings.GetBundlePlugInsFolderPath() - env['XPCSERVICES_FOLDER_PATH'] = \ - xcode_settings.GetBundleXPCServicesFolderPath() env['INFOPLIST_PATH'] = xcode_settings.GetBundlePlistPath() env['WRAPPER_NAME'] = xcode_settings.GetWrapperName() @@ -1800,12 +1644,11 @@ def _AddIOSDeviceConfigurations(targets): for target_dict in targets.values(): toolset = target_dict['toolset'] configs = target_dict['configurations'] - for config_name, simulator_config_dict in dict(configs).items(): - iphoneos_config_dict = copy.deepcopy(simulator_config_dict) + for config_name, config_dict in dict(configs).items(): + iphoneos_config_dict = copy.deepcopy(config_dict) configs[config_name + '-iphoneos'] = iphoneos_config_dict - configs[config_name + '-iphonesimulator'] = simulator_config_dict + configs[config_name + '-iphonesimulator'] = config_dict if toolset == 'target': - simulator_config_dict['xcode_settings']['SDKROOT'] = 'iphonesimulator' iphoneos_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' return targets diff --git a/tools/gyp/pylib/gyp/xcode_ninja.py b/tools/gyp/pylib/gyp/xcode_ninja.py index 2bc2143340229b..d70eddc90a57d1 100644 --- a/tools/gyp/pylib/gyp/xcode_ninja.py +++ b/tools/gyp/pylib/gyp/xcode_ninja.py @@ -92,16 +92,11 @@ def _TargetFromSpec(old_spec, params): new_xcode_settings['CODE_SIGNING_REQUIRED'] = "NO" new_xcode_settings['IPHONEOS_DEPLOYMENT_TARGET'] = \ old_xcode_settings['IPHONEOS_DEPLOYMENT_TARGET'] - for key in ['BUNDLE_LOADER', 'TEST_HOST']: - if key in old_xcode_settings: - new_xcode_settings[key] = old_xcode_settings[key] - ninja_target['configurations'][config] = {} ninja_target['configurations'][config]['xcode_settings'] = \ new_xcode_settings ninja_target['mac_bundle'] = old_spec.get('mac_bundle', 0) - ninja_target['mac_xctest_bundle'] = old_spec.get('mac_xctest_bundle', 0) ninja_target['ios_app_extension'] = old_spec.get('ios_app_extension', 0) ninja_target['ios_watchkit_extension'] = \ old_spec.get('ios_watchkit_extension', 0) @@ -143,10 +138,9 @@ def IsValidTargetForWrapper(target_extras, executable_target_pattern, spec): if target_extras is not None and re.search(target_extras, target_name): return True - # Otherwise just show executable targets and xc_tests. - if (int(spec.get('mac_xctest_bundle', 0)) != 0 or - (spec.get('type', '') == 'executable' and - spec.get('product_extension', '') != 'bundle')): + # Otherwise just show executable targets. + if spec.get('type', '') == 'executable' and \ + spec.get('product_extension', '') != 'bundle': # If there is a filter and the target does not match, exclude the target. if executable_target_pattern is not None: @@ -233,26 +227,13 @@ def CreateWrapper(target_list, target_dicts, data, params): # Tell Xcode to look everywhere for headers. sources_target['configurations'] = {'Default': { 'include_dirs': [ depth ] } } - # Put excluded files into the sources target so they can be opened in Xcode. - skip_excluded_files = \ - not generator_flags.get('xcode_ninja_list_excluded_files', True) - sources = [] for target, target_dict in target_dicts.items(): base = os.path.dirname(target) files = target_dict.get('sources', []) + \ target_dict.get('mac_bundle_resources', []) - - if not skip_excluded_files: - files.extend(target_dict.get('sources_excluded', []) + - target_dict.get('mac_bundle_resources_excluded', [])) - for action in target_dict.get('actions', []): files.extend(action.get('inputs', [])) - - if not skip_excluded_files: - files.extend(action.get('inputs_excluded', [])) - # Remove files starting with $. These are mostly intermediate files for the # build system. files = [ file for file in files if not file.startswith('$')] diff --git a/tools/gyp/pylib/gyp/xcodeproj_file.py b/tools/gyp/pylib/gyp/xcodeproj_file.py index 0534f51fe5cf8d..93ffca7c901561 100644 --- a/tools/gyp/pylib/gyp/xcodeproj_file.py +++ b/tools/gyp/pylib/gyp/xcodeproj_file.py @@ -220,7 +220,7 @@ class XCObject(object): an empty string ("", in the case of property_type str) or list ([], in the case of is_list True) from being set for the property. - default: Optional. If is_requried is True, default may be set + default: Optional. If is_required is True, default may be set to provide a default value for objects that do not supply their own value. If is_required is True and default is not provided, users of the class must supply their own @@ -1940,40 +1940,24 @@ class PBXCopyFilesBuildPhase(XCBuildPhase): 'name': [0, str, 0, 0], }) - # path_tree_re matches "$(DIR)/path", "$(DIR)/$(DIR2)/path" or just "$(DIR)". - # Match group 1 is "DIR", group 3 is "path" or "$(DIR2") or "$(DIR2)/path" - # or None. If group 3 is "path", group 4 will be None otherwise group 4 is - # "DIR2" and group 6 is "path". - path_tree_re = re.compile(r'^\$\((.*?)\)(/(\$\((.*?)\)(/(.*)|)|(.*)|)|)$') - - # path_tree_{first,second}_to_subfolder map names of Xcode variables to the - # associated dstSubfolderSpec property value used in a PBXCopyFilesBuildPhase - # object. - path_tree_first_to_subfolder = { - # Types that can be chosen via the Xcode UI. - 'BUILT_PRODUCTS_DIR': 16, # Products Directory - 'BUILT_FRAMEWORKS_DIR': 10, # Not an official Xcode macro. - # Existed before support for the - # names below was added. Maps to - # "Frameworks". - } - - path_tree_second_to_subfolder = { - 'WRAPPER_NAME': 1, # Wrapper - # Although Xcode's friendly name is "Executables", the destination - # is demonstrably the value of the build setting - # EXECUTABLE_FOLDER_PATH not EXECUTABLES_FOLDER_PATH. - 'EXECUTABLE_FOLDER_PATH': 6, # Executables. - 'UNLOCALIZED_RESOURCES_FOLDER_PATH': 7, # Resources - 'JAVA_FOLDER_PATH': 15, # Java Resources - 'FRAMEWORKS_FOLDER_PATH': 10, # Frameworks - 'SHARED_FRAMEWORKS_FOLDER_PATH': 11, # Shared Frameworks - 'SHARED_SUPPORT_FOLDER_PATH': 12, # Shared Support - 'PLUGINS_FOLDER_PATH': 13, # PlugIns - # For XPC Services, Xcode sets both dstPath and dstSubfolderSpec. - # Note that it re-uses the BUILT_PRODUCTS_DIR value for - # dstSubfolderSpec. dstPath is set below. - 'XPCSERVICES_FOLDER_PATH': 16, # XPC Services. + # path_tree_re matches "$(DIR)/path" or just "$(DIR)". Match group 1 is + # "DIR", match group 3 is "path" or None. + path_tree_re = re.compile('^\\$\\((.*)\\)(/(.*)|)$') + + # path_tree_to_subfolder maps names of Xcode variables to the associated + # dstSubfolderSpec property value used in a PBXCopyFilesBuildPhase object. + path_tree_to_subfolder = { + 'BUILT_FRAMEWORKS_DIR': 10, # Frameworks Directory + 'BUILT_PRODUCTS_DIR': 16, # Products Directory + # Other types that can be chosen via the Xcode UI. + # TODO(mark): Map Xcode variable names to these. + # : 1, # Wrapper + # : 6, # Executables: 6 + # : 7, # Resources + # : 15, # Java Resources + # : 11, # Shared Frameworks + # : 12, # Shared Support + # : 13, # PlugIns } def Name(self): @@ -1994,61 +1978,14 @@ def SetDestination(self, path): path_tree_match = self.path_tree_re.search(path) if path_tree_match: + # Everything else needs to be relative to an Xcode variable. path_tree = path_tree_match.group(1) - if path_tree in self.path_tree_first_to_subfolder: - subfolder = self.path_tree_first_to_subfolder[path_tree] - relative_path = path_tree_match.group(3) + relative_path = path_tree_match.group(3) + + if path_tree in self.path_tree_to_subfolder: + subfolder = self.path_tree_to_subfolder[path_tree] if relative_path is None: relative_path = '' - - if subfolder == 16 and path_tree_match.group(4) is not None: - # BUILT_PRODUCTS_DIR (16) is the first element in a path whose - # second element is possibly one of the variable names in - # path_tree_second_to_subfolder. Xcode sets the values of all these - # variables to relative paths so .gyp files must prefix them with - # BUILT_PRODUCTS_DIR, e.g. - # $(BUILT_PRODUCTS_DIR)/$(PLUGINS_FOLDER_PATH). Then - # xcode_emulation.py can export these variables with the same values - # as Xcode yet make & ninja files can determine the absolute path - # to the target. Xcode uses the dstSubfolderSpec value set here - # to determine the full path. - # - # An alternative of xcode_emulation.py setting the values to absolute - # paths when exporting these variables has been ruled out because - # then the values would be different depending on the build tool. - # - # Another alternative is to invent new names for the variables used - # to match to the subfolder indices in the second table. .gyp files - # then will not need to prepend $(BUILT_PRODUCTS_DIR) because - # xcode_emulation.py can set the values of those variables to - # the absolute paths when exporting. This is possibly the thinking - # behind BUILT_FRAMEWORKS_DIR which is used in exactly this manner. - # - # Requiring prepending BUILT_PRODUCTS_DIR has been chosen because - # this same way could be used to specify destinations in .gyp files - # that pre-date this addition to GYP. However they would only work - # with the Xcode generator. The previous version of xcode_emulation.py - # does not export these variables. Such files will get the benefit - # of the Xcode UI showing the proper destination name simply by - # regenerating the projects with this version of GYP. - path_tree = path_tree_match.group(4) - relative_path = path_tree_match.group(6) - separator = '/' - - if path_tree in self.path_tree_second_to_subfolder: - subfolder = self.path_tree_second_to_subfolder[path_tree] - if relative_path is None: - relative_path = '' - separator = '' - if path_tree == 'XPCSERVICES_FOLDER_PATH': - relative_path = '$(CONTENTS_FOLDER_PATH)/XPCServices' \ - + separator + relative_path - else: - # subfolder = 16 from above - # The second element of the path is an unrecognized variable. - # Include it and any remaining elements in relative_path. - relative_path = path_tree_match.group(3) - else: # The path starts with an unrecognized Xcode variable # name like $(SRCROOT). Xcode will still handle this @@ -2319,8 +2256,6 @@ class PBXNativeTarget(XCTarget): '', ''], 'com.apple.product-type.bundle.unit-test': ['wrapper.cfbundle', '', '.xctest'], - 'com.apple.product-type.bundle.ui-testing': ['wrapper.cfbundle', - '', '.xctest'], 'com.googlecode.gyp.xcode.bundle': ['compiled.mach-o.dylib', '', '.so'], 'com.apple.product-type.kernel-extension': ['wrapper.kext', @@ -2377,9 +2312,7 @@ def __init__(self, properties=None, id=None, parent=None, force_extension = suffix[1:] if self._properties['productType'] == \ - 'com.apple.product-type-bundle.unit.test' or \ - self._properties['productType'] == \ - 'com.apple.product-type-bundle.ui-testing': + 'com.apple.product-type-bundle.unit.test': if force_extension is None: force_extension = suffix[1:]