diff --git a/gyp/MSVS/MSVSSettings.py b/gyp/MSVS/MSVSSettings.py index 36d03878..db61bb08 100644 --- a/gyp/MSVS/MSVSSettings.py +++ b/gyp/MSVS/MSVSSettings.py @@ -979,7 +979,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/gyp/MSVS/MSVSVersion.py b/gyp/MSVS/MSVSVersion.py index ecc50c8e..be6b34bf 100644 --- a/gyp/MSVS/MSVSVersion.py +++ b/gyp/MSVS/MSVSVersion.py @@ -6,7 +6,6 @@ import os import glob -from typing import Dict from gyp.MSVS.MSVSUtil import TryQueryRegistryValue msvs_version_map = { @@ -130,7 +129,7 @@ def SetupScript(self, target_arch): return script_data -MSVS_VERSIONS = { # type: Dict[str, VisualStudioVersion] +MSVS_VERSIONS = { '2019': VisualStudioVersion( short_name='2019', diff --git a/gyp/generator/msvs.py b/gyp/generator/msvs.py index 32f6e01b..f29a8706 100644 --- a/gyp/generator/msvs.py +++ b/gyp/generator/msvs.py @@ -1825,6 +1825,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), @@ -2563,7 +2565,7 @@ def _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules): def _GetConfigurationAndPlatform(name, settings): configuration = name.rsplit('_', 1)[0] - platform = settings.get('msvs_configuration_platform', 'Win32') + platform = settings.get('msvs_configuration_platform', 'x64') return configuration, platform diff --git a/gyp/msvs_emulation.py b/gyp/msvs_emulation.py index 11918174..da88b1e2 100644 --- a/gyp/msvs_emulation.py +++ b/gyp/msvs_emulation.py @@ -200,7 +200,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 '' target_ext = '.' + self.GetExtension() @@ -276,7 +280,7 @@ 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.""" @@ -475,7 +479,10 @@ def GetLibFlags(self, config, gyp_to_build_path): lib = self._GetWrapper(self, self.msvs_settings[config], 'VCLibrarianTool', append=libflags) libflags.extend(self._GetAdditionalLibraryDirectories('VCLibrarianTool', config, gyp_to_build_path)) lib('LinkTimeCodeGeneration', map={'true': '/LTCG'}) - lib('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'}, prefix='/MACHINE:') + # 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. + lib('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM', '18': 'ARM64'}, prefix='/MACHINE:') lib('AdditionalOptions') return libflags @@ -514,7 +521,10 @@ def GetLdflags(self, config, gyp_to_build_path, expand_special, manifest_base_na ld = self._GetWrapper(self, self.msvs_settings[config], 'VCLinkerTool', append=ldflags) self._GetDefFileAsLdflags(ldflags, gyp_to_build_path) ld('GenerateDebugInformation', map={'true': '/DEBUG'}) - ld('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'}, prefix='/MACHINE:') + # 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)) ld('DelayLoadDLLs', prefix='/DELAYLOAD:') ld('TreatLinkerWarningAsErrors', prefix='/WX', map={'true': '', 'false': ':NO'}) @@ -764,7 +774,9 @@ def midl(name, default=None): output = [header, dlldata, iid, proxy] variables = [('tlb', tlb), ('h', header), ('dlldata', dlldata), ('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 diff --git a/test/configurations/arm64/configurations.c b/test/configurations/arm64/configurations.c new file mode 100644 index 00000000..e1afaf18 --- /dev/null +++ b/test/configurations/arm64/configurations.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("Hello ARM64\n"); + return 0; +} diff --git a/test/configurations/arm64/configurations.gyp b/test/configurations/arm64/configurations.gyp new file mode 100644 index 00000000..aaf830dc --- /dev/null +++ b/test/configurations/arm64/configurations.gyp @@ -0,0 +1,22 @@ +# Copyright (c) 2009 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. + +{ + 'target_defaults': { + 'configurations': { + 'Debug': { + 'msvs_configuration_platform': 'ARM64', + }, + }, + }, + 'targets': [ + { + 'target_name': 'configurationsARM64', + 'type': 'executable', + 'sources': [ + 'configurations.c', + ], + }, + ], +} diff --git a/test/configurations/arm64/gyptest-arm64.py b/test/configurations/arm64/gyptest-arm64.py new file mode 100644 index 00000000..ec3e1b11 --- /dev/null +++ b/test/configurations/arm64/gyptest-arm64.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies build of an executable for ARM64 configurations. +""" + +import TestGyp + +import sys + +formats = ['msvs'] +if sys.platform == 'win32': + formats += ['ninja'] +test = TestGyp.TestGyp(formats=formats) + +test.run_gyp('configurations.gyp') +test.set_configuration('Debug|ARM64') +test.build('configurations.gyp', test.ALL) + +output = test.run_dumpbin('/headers', test.built_file_path('configurations%s.exe' % 'ARM64')) +if 'AA64 machine (ARM64)' not in output: + test.fail_test() +test.pass_test() diff --git a/test/win/gyptest-midl-rules.py b/test/win/gyptest-midl-rules.py index 591a5073..1ba3bcf6 100644 --- a/test/win/gyptest-midl-rules.py +++ b/test/win/gyptest-midl-rules.py @@ -17,7 +17,7 @@ CHDIR = 'idl-rules' test.run_gyp('basic-idl.gyp', chdir=CHDIR) - for platform in ['Win32', 'x64']: + for platform in ['Win32', 'x64', 'ARM64']: test.set_configuration('Debug|%s' % platform) test.build('basic-idl.gyp', test.ALL, chdir=CHDIR) @@ -25,4 +25,4 @@ if test.format == 'ninja' and 'Processing' in test.stdout(): test.fail_test() - test.pass_test() + test.pass_test() diff --git a/test/win/idl-rules/basic-idl.gyp b/test/win/idl-rules/basic-idl.gyp index b74622ad..bfca47aa 100644 --- a/test/win/idl-rules/basic-idl.gyp +++ b/test/win/idl-rules/basic-idl.gyp @@ -15,6 +15,10 @@ 'inherit_from': ['Debug'], 'msvs_configuration_platform': 'x64', }, + 'Debug_ARM64': { + 'inherit_from': ['Debug'], + 'msvs_configuration_platform': 'ARM64', + }, }, }, 'targets': [ diff --git a/testlib/TestGyp.py b/testlib/TestGyp.py index 7254135a..97877208 100644 --- a/testlib/TestGyp.py +++ b/testlib/TestGyp.py @@ -429,6 +429,12 @@ def configuration_dirname(self): else: return 'Default' + def configuration_platform(self): + if self.configuration and '|' in self.configuration: + return self.configuration.split('|')[1] + else: + return '' + def configuration_buildname(self): if self.configuration: return self.configuration @@ -802,7 +808,10 @@ def FindVisualStudioInstallation(): '-requires', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', ] vswhere_json = subprocess.check_output(args1) - top_vs_info = json.loads(vswhere_json)[0] + vswhere_infos = json.loads(vswhere_json) + if len(vswhere_infos) == 0: + raise IOError("vswhere did not find any MSVS instances.") + top_vs_info = vswhere_infos[0] if top_vs_info: inst_path = top_vs_info['installationPath'] args2 = ['cmd.exe', '/d', '/c', @@ -972,8 +981,6 @@ def build(self, gyp_file, target=None, rebuild=False, clean=False, **kw): from the specified gyp_file. """ if '15.0' in self.build_tool or 'Current' in self.build_tool: - configuration = '/p:Configuration=' + ( - self.configuration or self.configuration_buildname()) build = '/t' if target not in (None, self.ALL, self.DEFAULT): build += ':' + target @@ -984,10 +991,13 @@ def build(self, gyp_file, target=None, rebuild=False, clean=False, **kw): elif ':' not in build: build += ':Build' arguments = kw.get('arguments', [])[:] - arguments.extend([gyp_file.replace('.gyp', '.sln'), - build, configuration]) + configuration_arg = '/p:Configuration=%s' % self.configuration_dirname() + arguments.extend([gyp_file.replace('.gyp', '.sln'), build, configuration_arg]) + platform = self.configuration_platform() + if platform: + arguments.append('/p:Platform=%s' % platform) else: - configuration = self.configuration_buildname() + configuration_arg = self.configuration_buildname() if clean: build = '/Clean' elif rebuild: @@ -995,8 +1005,7 @@ def build(self, gyp_file, target=None, rebuild=False, clean=False, **kw): else: build = '/Build' arguments = kw.get('arguments', [])[:] - arguments.extend([gyp_file.replace('.gyp', '.sln'), - build, configuration]) + arguments.extend([gyp_file.replace('.gyp', '.sln'), build, configuration_arg]) # Note: the Visual Studio generator doesn't add an explicit 'all' # target, so we just treat it the same as the default. if target not in (None, self.ALL, self.DEFAULT):