diff --git a/.gitignore b/.gitignore index f8f99f5f839389..e022e218ef5d45 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,4 @@ icu_config.gypi # Xcode workspaces and project folders *.xcodeproj *.xcworkspace +/*.log diff --git a/BUILDING.md b/BUILDING.md index ffe6d50ccfbba0..de3d4d6bb24f60 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -37,7 +37,7 @@ Support is divided into three tiers: |--------------|--------------|----------------------------------|----------------------|------------------| | GNU/Linux | Tier 1 | kernel >= 2.6.18, glibc >= 2.5 | x86, x64, arm, arm64 | | | macOS | Tier 1 | >= 10.10 | x64 | | -| Windows | Tier 1 | >= Windows 7 or >= Windows2008R2 | x86, x64 | | +| Windows | Tier 1 | >= Windows 7 / 2008 R2 | x86, x64 | vs2015 or vs2017 | | SmartOS | Tier 2 | >= 15 < 16.4 | x86, x64 | see note1 | | FreeBSD | Tier 2 | >= 10 | x64 | | | GNU/Linux | Tier 2 | kernel >= 4.2.0, glibc >= 2.19 | ppc64be | | @@ -176,6 +176,8 @@ Prerequisites: * [Visual Studio 2015 Update 3](https://www.visualstudio.com/), all editions including the Community edition (remember to select "Common Tools for Visual C++ 2015" feature during installation). + * [Visual Studio 2017](https://www.visualstudio.com/downloads/), any edition (including the Build Tools SKU). + __Required Components:__ "MSbuild", "VC++ 2017 v141 toolset" and one of the Windows SDKs (10 or 8.1). * Basic Unix tools required for some tests, [Git for Windows](http://git-scm.com/download/win) includes Git Bash and tools which can be included in the global `PATH`. diff --git a/common.gypi b/common.gypi index 2c061a7b0583e0..6a0f5701d236d1 100644 --- a/common.gypi +++ b/common.gypi @@ -233,7 +233,7 @@ 'SuppressStartupBanner': 'true', }, }, - 'msvs_disabled_warnings': [4351, 4355, 4800], + 'msvs_disabled_warnings': [4351, 4355, 4800, 4251, 4244, 4312, 4275], 'conditions': [ ['asan == 1 and OS != "mac"', { 'cflags+': [ diff --git a/configure b/configure index 6e91cb375304d3..43230314e47551 100755 --- a/configure +++ b/configure @@ -489,6 +489,12 @@ parser.add_option('-C', dest='compile_commands_json', help=optparse.SUPPRESS_HELP) +parser.add_option('--verbose', + action='store_true', + dest='verbose', + default=False, + help='make output more verbose') + (options, args) = parser.parse_args() # Expand ~ in the install prefix now, it gets written to multiple files. @@ -1004,10 +1010,21 @@ def configure_static(o): if options.enable_asan: o['libraries'] += ['-static-libasan'] +def config_vs2017(o): + if os.environ.get('VisualStudioVersion') != '15.0': return + sdk_ver = os.environ.get('WindowsSDKVersion', '').rstrip("\\") + if not sdk_ver: + print(' Error: could not find a compatible SDK, ' + + 'make sure you have either a Windows 10 or 8.1 SDK installed') + sys.exit(1) + o['msvs_windows_target_platform_version'] = sdk_ver + o['msbuild_toolset'] = 'v141' + def write(filename, data): filename = os.path.join(root_dir, filename) - print('creating %s' % filename) + if options.verbose: + print('creating %s' % filename) f = open(filename, 'w+') f.write(data) @@ -1027,7 +1044,8 @@ def glob_to_var(dir_base, dir_sub, patch_dir): patchfile = '%s/%s/%s' % (dir_base, patch_dir, file) if os.path.isfile(patchfile): srcfile = '%s/%s' % (patch_dir, file) - print('Using version-specific floating patch %s' % patchfile) + if options.verbose: + print('Using version-specific floating patch %s' % patchfile) list.append(srcfile) break return list @@ -1054,11 +1072,14 @@ def configure_intl(o): if nodedownload.candownload(auto_downloads, "icu"): nodedownload.retrievefile(url, targetfile) else: - print('Re-using existing %s' % targetfile) + if options.verbose: + print('Re-using existing %s' % targetfile) if os.path.isfile(targetfile): - print('Checking file integrity with MD5:\r') + if options.verbose: + print('Checking file integrity with MD5:\r') gotmd5 = nodedownload.md5sum(targetfile) - print('MD5: %s %s' % (gotmd5, targetfile)) + if options.verbose: + print('MD5: %s %s' % (gotmd5, targetfile)) if (md5 == gotmd5): return targetfile else: @@ -1073,8 +1094,7 @@ def configure_intl(o): return # write an empty file to start with - write(icu_config_name, do_not_edit + - pprint.pformat(icu_config, indent=2) + '\n') + write(icu_config_name, do_not_edit + pprint.pformat(icu_config, indent=2) + '\n') # always set icu_small, node.gyp depends on it being defined. o['variables']['icu_small'] = b(False) @@ -1220,7 +1240,8 @@ def configure_intl(o): print('(Fix, or disable with "--with-intl=none" )') sys.exit(1) else: - print('* Using ICU in %s' % icu_full_path) + if options.verbose: + print('* Using ICU in %s' % icu_full_path) # Now, what version of ICU is it? We just need the "major", such as 54. # uvernum.h contains it as a #define. uvernum_h = os.path.join(icu_full_path, 'source/common/unicode/uvernum.h') @@ -1284,8 +1305,7 @@ def configure_intl(o): path = '../../%s/source/%s' % (icu_full_path, icu_src[i]) icu_config['variables'][var] = glob_to_var('tools/icu', path, 'patches/%s/source/%s' % (icu_ver_major, icu_src[i]) ) # write updated icu_config.gypi with a bunch of paths - write(icu_config_name, do_not_edit + - pprint.pformat(icu_config, indent=2) + '\n') + write(icu_config_name, do_not_edit + pprint.pformat(icu_config, indent=2) + '\n') return # end of configure_intl def configure_inspector(o): @@ -1325,6 +1345,7 @@ configure_openssl(output) configure_intl(output) configure_static(output) configure_inspector(output) +config_vs2017(output) # variables should be a root level element, # move everything else to target_defaults @@ -1337,8 +1358,7 @@ config_fips = { 'make_global_settings' : [] } if 'make_fips_settings' in output: config_fips['make_global_settings'] = output['make_fips_settings'] del output['make_fips_settings'] - write('config_fips.gypi', do_not_edit + - pprint.pformat(config_fips, indent=2) + '\n') + write('config_fips.gypi', do_not_edit + pprint.pformat(config_fips, indent=2) + '\n') # make_global_settings should be a root level element too if 'make_global_settings' in output: @@ -1354,10 +1374,10 @@ output = { if make_global_settings: output['make_global_settings'] = make_global_settings -pprint.pprint(output, indent=2) - -write('config.gypi', do_not_edit + - pprint.pformat(output, indent=2) + '\n') +config_content = pprint.pformat(output, indent=2) +if options.verbose: + print(config_content) +write('config.gypi', do_not_edit + config_content + '\n') config = { 'BUILDTYPE': 'Debug' if options.debug else 'Release', @@ -1387,6 +1407,9 @@ else: if options.compile_commands_json: gyp_args += ['-f', 'compile_commands_json'] +if options.verbose: + gyp_args += ['--verbose'] + gyp_args += args if warn.warned: diff --git a/tools/gyp_node.py b/tools/gyp_node.py index 8de046aae259f1..bbeec57ac77e4a 100755 --- a/tools/gyp_node.py +++ b/tools/gyp_node.py @@ -13,27 +13,14 @@ output_dir = os.path.join(os.path.abspath(node_root), 'out') def run_gyp(args): - rc = gyp.main(args) - if rc != 0: - print 'Error running GYP' - sys.exit(rc) - -if __name__ == '__main__': - args = sys.argv[1:] - # GYP bug. # On msvs it will crash if it gets an absolute path. # On Mac/make it will crash if it doesn't get an absolute path. - if sys.platform == 'win32': - args.append(os.path.join(node_root, 'node.gyp')) - common_fn = os.path.join(node_root, 'common.gypi') - options_fn = os.path.join(node_root, 'config.gypi') - options_fips_fn = os.path.join(node_root, 'config_fips.gypi') - else: - args.append(os.path.join(os.path.abspath(node_root), 'node.gyp')) - common_fn = os.path.join(os.path.abspath(node_root), 'common.gypi') - options_fn = os.path.join(os.path.abspath(node_root), 'config.gypi') - options_fips_fn = os.path.join(os.path.abspath(node_root), 'config_fips.gypi') + arg_path = node_root if sys.platform == 'win32' else os.path.abspath(node_root) + args.append(os.path.join(arg_path, 'node.gyp')) + common_fn = os.path.join(arg_path, 'common.gypi') + options_fn = os.path.join(arg_path, 'config.gypi') + options_fips_fn = os.path.join(arg_path, 'config_fips.gypi') if os.path.exists(common_fn): args.extend(['-I', common_fn]) @@ -58,10 +45,22 @@ def run_gyp(args): args.append('-Dlibrary=static_library') # Don't compile with -B and -fuse-ld=, we don't bundle ld.gold. Can't be - # set in common.gypi due to how deps/v8/build/toolchain.gypi uses them. + # set in common.gypi due to deps/v8/build/toolchain.gypi overwriting them. args.append('-Dlinux_use_bundled_binutils=0') args.append('-Dlinux_use_bundled_gold=0') args.append('-Dlinux_use_gold_flags=0') + if '--verbose' in args: + # TODO(refack) maybe set -D for `GYP` instead + args.remove('--verbose') + print('\nGYP args: {0}'.format(' '.join(args))) + rc = gyp.main(args) + if rc != 0: + print 'Error running GYP' + sys.exit(rc) + + +if __name__ == '__main__': + args = sys.argv[1:] gyp_args = list(args) run_gyp(gyp_args) diff --git a/tools/msvs-com-helper/GetKey.ps1 b/tools/msvs-com-helper/GetKey.ps1 new file mode 100644 index 00000000000000..4c14e35775ddac --- /dev/null +++ b/tools/msvs-com-helper/GetKey.ps1 @@ -0,0 +1,40 @@ +# Copyright 2017 - Refael Ackermann +# Distributed under MIT style license +# See accompanying file LICENSE at https://github.com/node4good/windows-autoconf +# version: 1.12.2 + +param ( + [Parameter(Mandatory=$false)] + [string[]]$filters = "IsVcCompatible", + [Parameter(Mandatory=$false)] + [string[]]$keys = "VisualCppToolsCL", + [Parameter(Mandatory=$false)] + [switch]$Information +) +$invocation = (Get-Variable MyInvocation).Value +cd (Split-Path $invocation.MyCommand.Path) +if (-NOT (Test-Path 'Registry::HKEY_CLASSES_ROOT\CLSID\{177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D}')) { Exit 1 } +Add-Type -Path GetVS2017Configuration.cs; +$insts = [VisualStudioConfiguration.ComSurrogate]::QueryEx() +if ($Information) { + $insts | % { [Console]::Error.WriteLine('Found VS2017 "' +$_['Name'] + '" installed at "' + $_['InstallationPath'] + '"') } +} +$insts | % { $_.Add('Fail', @()) } +foreach ($filter in $filters) { + if ($filter -eq "*") { continue; } + if ($filter -like "*=*") { + $parts = $filter -Split "="; + $filter = $parts[0]; + $criteria = $parts[1]; + $insts | % { if ($_.Get($filter) -ne $criteria) { $_['Fail'] += $filter } } + } else { + $insts | % { if (!($_.Get($filter))) { $_['Fail'] += $filter } } + } +} +if ($Information) { + $insts | % { if ($_['Fail'].length -ne 0) {[Console]::Error.WriteLine('"' +$_['Name'] + '" installed in "' + $_['InstallationPath'] + '" does not meet criteria "' + $_['Fail'] + '"') } } +} +$insts = $insts | where { $_['Fail'].length -eq 0 } +foreach ($key in $keys) { + if ($key -eq "*") { $insts | echo } else { $insts | % { $_.Get($key) } } +} diff --git a/tools/msvs-com-helper/GetVS2017Configuration.cs b/tools/msvs-com-helper/GetVS2017Configuration.cs new file mode 100644 index 00000000000000..91978c8d2d38de --- /dev/null +++ b/tools/msvs-com-helper/GetVS2017Configuration.cs @@ -0,0 +1,326 @@ +// Copyright 2017 - Refael Ackermann +// Distributed under MIT style license +// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf +// version: 1.11.2 + +// Usage: +// powershell -ExecutionPolicy Unrestricted -Command "&{ Add-Type -Path GetVS2017Configuration.cs; $insts = [VisualStudioConfiguration.ComSurrogate]::QueryEx(); $insts | ft }" +namespace VisualStudioConfiguration +{ + using System; + using System.Collections.Generic; + using System.Runtime.InteropServices; + using System.Text.RegularExpressions; + + [Flags] + public enum InstanceState : uint + { + None = 0, + Local = 1, + Registered = 2, + NoRebootRequired = 4, + NoErrors = 8, + Complete = 4294967295, + } + + [Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IEnumSetupInstances + { + + void Next([MarshalAs(UnmanagedType.U4), In] int celt, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt, + [MarshalAs(UnmanagedType.U4)] out int pceltFetched); + + void Skip([MarshalAs(UnmanagedType.U4), In] int celt); + + void Reset(); + + [return: MarshalAs(UnmanagedType.Interface)] + IEnumSetupInstances Clone(); + } + + [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupConfiguration + { + } + + [Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupConfiguration2 : ISetupConfiguration + { + + [return: MarshalAs(UnmanagedType.Interface)] + IEnumSetupInstances EnumInstances(); + + [return: MarshalAs(UnmanagedType.Interface)] + ISetupInstance GetInstanceForCurrentProcess(); + + [return: MarshalAs(UnmanagedType.Interface)] + ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path); + + [return: MarshalAs(UnmanagedType.Interface)] + IEnumSetupInstances EnumAllInstances(); + } + + [Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupInstance + { + } + + [Guid("89143C9A-05AF-49B0-B717-72E218A2185C")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupInstance2 : ISetupInstance + { + [return: MarshalAs(UnmanagedType.BStr)] + string GetInstanceId(); + + [return: MarshalAs(UnmanagedType.Struct)] + System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetInstallationName(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetInstallationPath(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetInstallationVersion(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid); + + [return: MarshalAs(UnmanagedType.BStr)] + string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath); + + [return: MarshalAs(UnmanagedType.U4)] + InstanceState GetState(); + + [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] + ISetupPackageReference[] GetPackages(); + + ISetupPackageReference GetProduct(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetProductPath(); + + [return: MarshalAs(UnmanagedType.VariantBool)] + bool IsLaunchable(); + + [return: MarshalAs(UnmanagedType.VariantBool)] + bool IsComplete(); + + [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] + ISetupPropertyStore GetProperties(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetEnginePath(); + } + + [Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupPackageReference + { + + [return: MarshalAs(UnmanagedType.BStr)] + string GetId(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetVersion(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetChip(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetLanguage(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetBranch(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetType(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetUniqueId(); + + [return: MarshalAs(UnmanagedType.VariantBool)] + bool GetIsExtension(); + } + + [Guid("c601c175-a3be-44bc-91f6-4568d230fc83")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupPropertyStore + { + + [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] + string[] GetNames(); + + object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName); + } + + [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] + [CoClass(typeof(SetupConfigurationClass))] + [ComImport] + public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration + { + } + + [Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")] + [ClassInterface(ClassInterfaceType.None)] + [ComImport] + public class SetupConfigurationClass + { + } + + + public class VSInstance : Dictionary + { + public object Get(string key) { + if (!this.ContainsKey(key)) return false; + return this[key]; + } + + public bool JSONBool(string key) + { + if (key == null || key == "") return true; + if (!this.ContainsKey(key)) return false; + object val = this[key]; + if (val is Boolean) return (bool)val; + if (val is String[]) return ((String[])val).Length != 0; + string sVal = (string)val; + if (sVal == null) return false; + if (sVal.Length == 0) return false; + if (sVal.Trim() == "{}") return false; + if (sVal.Trim() == "[]") return false; + if (sVal.Trim() == "0") return false; + return true; + } + } + + public static class ComSurrogate + { + public static bool Is64() + { + return (IntPtr.Size == 8); + } + + public static List QueryEx(params string[] args) + { + List insts = new List(); + ISetupConfiguration query = new SetupConfiguration(); + ISetupConfiguration2 query2 = (ISetupConfiguration2) query; + IEnumSetupInstances e = query2.EnumAllInstances(); + ISetupInstance2[] rgelt = new ISetupInstance2[1]; + int pceltFetched; + e.Next(1, rgelt, out pceltFetched); + while (pceltFetched > 0) + { + ISetupInstance2 raw = rgelt[0]; + insts.Add(ParseInstance(raw)); + e.Next(1, rgelt, out pceltFetched); + } + foreach (VSInstance inst in insts.ToArray()) + { + foreach (string key in args) { + if (!inst.JSONBool(key)) { + insts.Remove(inst); + } + } + if (Array.IndexOf(args, "Packages") == -1) { + inst.Remove("Packages"); + } + } + return insts; + } + + private static VSInstance ParseInstance(ISetupInstance2 setupInstance2) + { + VSInstance inst = new VSInstance(); + string[] prodParts = setupInstance2.GetProduct().GetId().Split('.'); + Array.Reverse(prodParts); + inst["Product"] = prodParts[0]; + inst["ID"] = setupInstance2.GetInstanceId(); + inst["Name"] = setupInstance2.GetDisplayName(0x1000); + inst["Description"] = setupInstance2.GetDescription(0x1000); + inst["InstallationName"] = setupInstance2.GetInstallationName(); + inst["Version"] = setupInstance2.GetInstallationVersion(); + inst["State"] = Enum.GetName(typeof(InstanceState), setupInstance2.GetState()); + inst["InstallationPath"] = setupInstance2.GetInstallationPath(); + inst["IsComplete"] = setupInstance2.IsComplete(); + inst["IsLaunchable"] = setupInstance2.IsLaunchable(); + inst["Common7ToolsPath"] = inst["InstallationPath"] + @"\Common7\Tools\"; + inst["CmdPath"] = inst["Common7ToolsPath"] + "VsDevCmd.bat"; + inst["VCAuxiliaryBuildPath"] = inst["InstallationPath"] + @"\VC\Auxiliary\Build\"; + inst["VCVarsAllPath"] = inst["VCAuxiliaryBuildPath"] + "vcvarsall.bat"; + + inst["Win8SDK"] = ""; + inst["SDK10Full"] = ""; + inst["VisualCppTools"] = ""; + + Regex trimmer = new Regex(@"\.\d+$"); + + List packs = new List(); + foreach (ISetupPackageReference package in setupInstance2.GetPackages()) + { + string id = package.GetId(); + + string ver = package.GetVersion(); + string detail = "{\"id\": \"" + id + "\", \"version\":\"" + ver + "\"}"; + packs.Add(" " + detail); + + if (id.Contains("Component.MSBuild")) { + inst["MSBuild"] = detail; + inst["MSBuildVerFull"] = ver; + } else if (id.Contains("Microsoft.VisualCpp.Tools.Core")) { + inst["VCTools"] = detail; + inst["VisualCppToolsFullVersion"] = ver; + string majorMinor = trimmer.Replace(trimmer.Replace(ver, ""), ""); + inst["VisualCppToolsVersionMinor"] = majorMinor; + inst["VCToolsVersionCode"] = "vc" + majorMinor.Replace(".", ""); + } else if (id.Contains("Microsoft.Windows.81SDK")) { + if (inst["Win8SDK"].ToString().CompareTo(ver) > 0) continue; + inst["Win8SDK"] = ver; + } else if (id.Contains("Win10SDK_10")) { + if (inst["SDK10Full"].ToString().CompareTo(ver) > 0) continue; + inst["SDK10Full"] = ver; + } + } + packs.Sort(); + inst["Packages"] = packs.ToArray(); + + string[] sdk10Parts = inst["SDK10Full"].ToString().Split('.'); + sdk10Parts[sdk10Parts.Length - 1] = "0"; + inst["SDK10"] = String.Join(".", sdk10Parts); + inst["SDK"] = inst["SDK10"].ToString() != "0" ? inst["SDK10"] : inst["Win8SDK"]; + if (inst.ContainsKey("MSBuildVerFull")) { + string ver = trimmer.Replace(trimmer.Replace((string)inst["MSBuildVerFull"], ""), ""); + inst["MSBuildVer"] = ver; + inst["MSBuildToolsPath"] = inst["InstallationPath"] + @"\MSBuild\" + ver + @"\Bin\"; + inst["MSBuildPath"] = inst["MSBuildToolsPath"] + "MSBuild.exe"; + } + if (inst.ContainsKey("VCTools")) { + string ver = trimmer.Replace((string)inst["VisualCppToolsFullVersion"], ""); + inst["VisualCppToolsX64"] = inst["InstallationPath"] + @"\VC\Tools\MSVC\" + ver + @"\bin\HostX64\x64\"; + inst["VisualCppToolsX64CL"] = inst["VisualCppToolsX64"] + "cl.exe"; + inst["VisualCppToolsX86"] = inst["InstallationPath"] + @"\VC\Tools\MSVC\" + ver + @"\bin\HostX86\x86\"; + inst["VisualCppToolsX86CL"] = inst["VisualCppToolsX86"] + "cl.exe"; + inst["VisualCppTools"] = Is64() ? inst["VisualCppToolsX64"] : inst["VisualCppToolsX86"]; + inst["VisualCppToolsCL"] = Is64() ? inst["VisualCppToolsX64CL"] : inst["VisualCppToolsX86CL"]; + } + inst["IsVcCompatible"] = inst.JSONBool("SDK") && inst.JSONBool("MSBuild") && inst.JSONBool("VisualCppTools"); + return inst; + } + } +} diff --git a/vcbuild.bat b/vcbuild.bat index 985b7f1fccd791..b5f23f4a97af85 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -1,4 +1,4 @@ -@echo off +@if not defined DEBUG_VCBUILD echo off cd %~dp0 @@ -15,7 +15,7 @@ if /i "%1"=="/?" goto help set config=Release set target=Build set target_arch=x64 -set target_env= +set target_env=vs2015 set noprojgen= set nobuild= set sign= @@ -42,6 +42,8 @@ set build_addons= set dll= set build_addons_napi= set test_node_inspect= +if not defined msbverbosity set "msbverbosity=/nologo /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal" +if not defined no_multi_proc set no_multi_proc= :next-arg if "%1"=="" goto args-done @@ -51,9 +53,11 @@ if /i "%1"=="clean" set target=Clean&goto arg-ok if /i "%1"=="ia32" set target_arch=x86&goto arg-ok if /i "%1"=="x86" set target_arch=x86&goto arg-ok if /i "%1"=="x64" set target_arch=x64&goto arg-ok -if /i "%1"=="vc2015" set target_env=vc2015&goto arg-ok +if /i "%1"=="vs2015" set target_env=vs2015&goto arg-ok +if /i "%1"=="vs2017" set target_env=vs2017&goto arg-ok if /i "%1"=="noprojgen" set noprojgen=1&goto arg-ok if /i "%1"=="nobuild" set nobuild=1&goto arg-ok +if /i "%1"=="noparallel" set no_multi_proc=:1&goto arg-ok if /i "%1"=="nosign" set "sign="&echo Note: vcbuild no longer signs by default. "nosign" is redundant.&goto arg-ok if /i "%1"=="sign" set sign=1&goto arg-ok if /i "%1"=="nosnapshot" set nosnapshot=1&goto arg-ok @@ -85,11 +89,12 @@ if /i "%1"=="upload" set upload=1&goto arg-ok if /i "%1"=="small-icu" set i18n_arg=%1&goto arg-ok if /i "%1"=="full-icu" set i18n_arg=%1&goto arg-ok if /i "%1"=="intl-none" set i18n_arg=%1&goto arg-ok -if /i "%1"=="without-intl" set i18n_arg=%1&goto arg-ok +if /i "%1"=="without-intl" set i18n_arg=%1&goto arg-ok if /i "%1"=="download-all" set download_arg="--download=all"&goto arg-ok if /i "%1"=="ignore-flaky" set test_args=%test_args% --flaky-tests=dontcare&goto arg-ok if /i "%1"=="enable-vtune" set enable_vtune_arg=1&goto arg-ok if /i "%1"=="dll" set dll=1&goto arg-ok +if /i "%1"=="verbose" set "msbverbosity=/clp:Verbosity=d /fl /flp:logfile=node.build.log;verbosity=d"&set verbose=1&goto arg-ok echo Error: invalid command line option `%1`. exit /b 1 @@ -100,6 +105,7 @@ shift goto next-arg :args-done +if defined DEBUG_VCBUILD echo on if defined build_release ( set config=Release @@ -114,6 +120,7 @@ if defined build_release ( set "node_exe=%config%\node.exe" if "%config%"=="Debug" set configure_flags=%configure_flags% --debug +if defined verbose set configure_flags=%configure_flags% --verbose if defined nosnapshot set configure_flags=%configure_flags% --without-snapshot if defined noetw set configure_flags=%configure_flags% --without-etw& set noetw_msi_arg=/p:NoETW=1 if defined noperfctr set configure_flags=%configure_flags% --without-perfctr& set noperfctr_msi_arg=/p:NoPerfCtr=1 @@ -142,7 +149,32 @@ if defined noprojgen if defined nobuild if not defined sign if not defined msi g @rem Set environment for msbuild +@rem Look for Visual Studio 2017 +:vs-set-2017 +if "%target_env%" NEQ "vs2017" goto vs-set-2015 +echo Looking for Visual Studio 2017 +if defined VisualStudioVersion if "%VisualStudioVersion%"=="15.0" goto found_vs2017 +set ps_call=powershell -NoProfile -ExecutionPolicy Unrestricted +set ps_args="%~dp0tools\msvs-com-helper\GetKey.ps1" IsVcCompatible InstallationPath +if defined verbose set ps_args=%ps_args% -Information +@rem this call could return multiple hits, so arbitrarily we pick the last one +for /F "tokens=*" %%A IN ('%ps_call% %ps_args%') DO set VS2017_INST_PATH=%%A +if "_%VS2017_INST_PATH%_" == "__" goto vs-set-2015 +if NOT EXIST "%VS2017_INST_PATH%" goto vs-set-2015 +@rem GYP_MSVS_VERSION=2015 is a workaround for old `GYP` +if %target_arch%==x64 SET VS_TARGET_ARCH=amd64 +set "VSVARSALL="%VS2017_INST_PATH%\VC\Auxiliary\Build\vcvarsall.bat" %VS_TARGET_ARCH%" +call %VSVARSALL% +:found_vs2017 +echo Found MSVS version %VisualStudioVersion% +set GYP_MSVS_VERSION=2015 +set PLATFORM_TOOLSET=v141 +set VS_TARGET_ARCH=x86 +goto msbuild-found + @rem Look for Visual Studio 2015 +:vs-set-2015 +if "%target_env%" NEQ "vs2015" goto msbuild-not-found echo Looking for Visual Studio 2015 if not defined VS140COMNTOOLS goto msbuild-not-found if not exist "%VS140COMNTOOLS%\..\..\vc\vcvarsall.bat" goto msbuild-not-found @@ -179,8 +211,9 @@ goto run if defined noprojgen goto msbuild @rem Generate the VS project. -echo configure %configure_flags% --dest-cpu=%target_arch% --tag=%TAG% +if defined verbose echo on python configure %configure_flags% --dest-cpu=%target_arch% --tag=%TAG% +@if not defined DEBUG_VCBUILD echo off if errorlevel 1 goto create-msvs-files-failed if not exist node.sln goto create-msvs-files-failed echo Project files generated. @@ -192,7 +225,9 @@ if defined nobuild goto sign @rem Build the sln with msbuild. set "msbplatform=Win32" if "%target_arch%"=="x64" set "msbplatform=x64" -msbuild node.sln /m /t:%target% /p:Configuration=%config% /p:Platform=%msbplatform% /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo +@echo on +msbuild node.sln /m%no_multi_proc% /t:%target% /p:Configuration=%config% /p:Platform=%msbplatform% %msbverbosity% +@if not defined DEBUG_VCBUILD echo off if errorlevel 1 goto exit if "%target%" == "Clean" goto exit @@ -289,6 +324,7 @@ if not defined SSHCONFIG ( echo SSHCONFIG is not set for upload exit /b 1 ) + if not defined STAGINGSERVER set STAGINGSERVER=node-www ssh -F %SSHCONFIG% %STAGINGSERVER% "mkdir -p nodejs/%DISTTYPEDIR%/v%FULLVERSION%/win-%target_arch%" scp -F %SSHCONFIG% Release\node.exe %STAGINGSERVER%:nodejs/%DISTTYPEDIR%/v%FULLVERSION%/win-%target_arch%/node.exe @@ -376,55 +412,63 @@ goto cpplint if not defined cpplint goto jslint echo running cpplint set cppfilelist= -setlocal enabledelayedexpansion -for /f "tokens=*" %%G in ('dir /b /s /a src\*.c src\*.cc src\*.h ^ -test\addons\*.cc test\addons\*.h test\cctest\*.cc test\cctest\*.h ^ -test\gc\binding.cc tools\icu\*.cc tools\icu\*.h') do ( - set relpath=%%G - set relpath=!relpath:*%~dp0=! - call :add-to-list !relpath! -) -( endlocal - set cppfilelist=%localcppfilelist% -) +set cpp_locs=src\*.c +set cpp_locs=%cpp_locs% src\*.cc +set cpp_locs=%cpp_locs% src\*.h +set cpp_locs=%cpp_locs% test\addons\*.cc +set cpp_locs=%cpp_locs% test\addons\*.h +set cpp_locs=%cpp_locs% test\cctest\*.cc +set cpp_locs=%cpp_locs% test\cctest\*.h +set cpp_locs=%cpp_locs% test\gc\binding.cc +set cpp_locs=%cpp_locs% tools\icu\*.cc +set cpp_locs=%cpp_locs% tools\icu\*.h +for /f "tokens=*" %%G in ('dir /b /s /a:, %cpp_locs%') do call :add-to-list %%G python tools/cpplint.py %cppfilelist% python tools/check-imports.py goto jslint :add-to-list -echo %1 | findstr /c:"src\node_root_certs.h" -if %errorlevel% equ 0 goto exit - -echo %1 | findstr /c:"src\queue.h" -if %errorlevel% equ 0 goto exit - -echo %1 | findstr /c:"src\tree.h" -if %errorlevel% equ 0 goto exit - -@rem skip subfolders under /src -echo %1 | findstr /r /c:"src\\.*\\.*" -if %errorlevel% equ 0 goto exit - -echo %1 | findstr /r /c:"test\\addons\\[0-9].*_.*\.h" -if %errorlevel% equ 0 goto exit - -echo %1 | findstr /r /c:"test\\addons\\[0-9].*_.*\.cc" -if %errorlevel% equ 0 goto exit - -set "localcppfilelist=%localcppfilelist% %1" +setlocal enabledelayedexpansion +set base_path= +set relpath=%1 +set relpath=!relpath:%~dp0=! +endlocal&set relpath=%relpath% +@rem findstr can do multiple searches, but only for regexes +set find_arg=/r +set find_arg=%find_arg% /c:"src\\node_root_certs\.h" +set find_arg=%find_arg% /c:"src\\queue\.h" +set find_arg=%find_arg% /c:"src\\tree\.h" +set find_arg=%find_arg% /c:"src\\.*\\.*" +set find_arg=%find_arg% /c:"test\\addons\\[0-9].*_.*\.h" +set find_arg=%find_arg% /c:"test\\addons\\[0-9].*_.*\.cc" +echo %relpath% | findstr %find_arg% > nul +if not errorlevel 1 exit /b +set "cppfilelist=%cppfilelist% %relpath%" +exit /b + +:find_node +if exist %config%\node set nodeexe=%config%\node&exit /b +where node > nul 2> nul +if not errorlevel 1 set nodeexe=node&exit /b +echo Could not file node.exe goto exit +exit /b :jslint if defined jslint_ci goto jslint-ci if not defined jslint goto exit if not exist tools\eslint\lib\eslint.js goto no-lint +call :find_node echo running jslint -%config%\node tools\eslint\bin\eslint.js --cache --rule "linebreak-style: 0" --rulesdir=tools\eslint-rules benchmark lib test tools +%nodeexe% tools\eslint\bin\eslint.js --cache --rule "linebreak-style: 0" --rulesdir=tools\eslint-rules benchmark lib test tools +if not errorlevel 1 echo jslint finished with no errors goto exit :jslint-ci +call :find_node echo running jslint-ci -%config%\node tools\jslint.js -J -f tap -o test-eslint.tap benchmark lib test tools +%nodeexe% tools\jslint.js -J -f tap -o test-eslint.tap benchmark lib test tools +if not errorlevel 1 echo jslint-ci finished with no errors goto exit :no-lint @@ -437,10 +481,10 @@ echo Failed to create vc project files. goto exit :help -echo vcbuild.bat [debug/release] [msi] [test-all/test-uv/test-inspector/test-internet/test-pummel/test-simple/test-message] [clean] [noprojgen] [small-icu/full-icu/without-intl] [nobuild] [sign] [x86/x64] [vc2015] [download-all] [enable-vtune] [lint/lint-ci] +echo vcbuild.bat [debug/release] [msi] [test-all/test-uv/test-inspector/test-internet/test-pummel/test-simple/test-message] [clean] [noprojgen] [small-icu/full-icu/without-intl] [nobuild] [sign] [x86/x64] [vs2015/vs2017] [download-all] [enable-vtune] [lint/lint-ci] [noparallel] [verbose] echo Examples: echo vcbuild.bat : builds release build -echo vcbuild.bat debug : builds debug build +echo vcbuild.bat debug verbose : builds debug build with verbose output and node.build.log file echo vcbuild.bat release msi : builds release build and MSI installer package echo vcbuild.bat test : builds debug build and runs tests echo vcbuild.bat build-release : builds the release distribution as used by nodejs.org