Skip to content

win,build: add Visual Studio 2017 support #11867

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
win,build: add Visual Studio 2017 support
Add support for Visual Studio 2017. A C# script, compiled and
executed by PowerShell, is used to query the COM server about the
location of VS installation and installed SDK version, filtering
installations that miss the required components.
  • Loading branch information
joaocgreis committed Mar 15, 2017
commit a1d8608496157b704f96462fd7572c37689aa3d0
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -59,6 +59,7 @@ ipch/
*.VC.opendb
.vs/
.vscode/
/Set_VS*.bat

/config.mk
/config.gypi
3 changes: 3 additions & 0 deletions BUILDING.md
Original file line number Diff line number Diff line change
@@ -111,6 +111,9 @@ 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/), all editions. The
required components are "VC++ 2017 v141 toolset", "Visual Studio C++ core
features" and one of the "Windows 10 SDK".
* 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`.
269 changes: 269 additions & 0 deletions tools/Find-VS2017.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
// Copyright 2017 - Refael Ackermann
// Distributed under MIT style license
// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf

// Usage:
// powershell -ExecutionPolicy Unrestricted -Version "2.0" -Command "&{Add-Type -Path Find-VS2017.cs; [VisualStudioConfiguration.Main]::Query()}"
using System;
using System.Text;
using System.Runtime.InteropServices;

namespace VisualStudioConfiguration
{
[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 static class Main
{
public static void Query()
{
ISetupConfiguration query = new SetupConfiguration();
ISetupConfiguration2 query2 = (ISetupConfiguration2)query;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use var to prevent redundancy?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're trying to support Windows 7/2008R2 with the tools that it ships with by default, that means C# version 2. var was only introduced in version 3.

IEnumSetupInstances e = query2.EnumAllInstances();

int pceltFetched;
ISetupInstance2[] rgelt = new ISetupInstance2[1];
while (true)
{
e.Next(1, rgelt, out pceltFetched);
if (pceltFetched <= 0)
{
Console.WriteLine("No usable installation of VS2017 found");
return;
}
if (CheckInstance(rgelt[0]))
return;
}
}

private static bool CheckInstance(ISetupInstance2 setupInstance2)
{
// Visual Studio Community 2017 component directory:
// https://www.visualstudio.com/en-us/productinfo/vs2017-install-product-Community.workloads

string path = setupInstance2.GetInstallationPath();
Console.WriteLine(String.Format("Found VS2017 installation at: {0}", path));

bool hasMSBuild = false;
bool hasVCTools = false;
uint Win10SDKVer = 0;
bool hasWin8SDK = false;

foreach (ISetupPackageReference package in setupInstance2.GetPackages())
{
const string Win10SDKPrefix = "Microsoft.VisualStudio.Component.Windows10SDK.";

string id = package.GetId();
if (id == "Microsoft.VisualStudio.VC.MSBuild.Base")
hasMSBuild = true;
else if (id == "Microsoft.VisualStudio.Component.VC.Tools.x86.x64")
hasVCTools = true;
else if (id.StartsWith(Win10SDKPrefix))
Win10SDKVer = Math.Max(Win10SDKVer, UInt32.Parse(id.Substring(Win10SDKPrefix.Length)));
else if (id == "Microsoft.VisualStudio.Component.Windows81SDK")
hasWin8SDK = true;
else
continue;

Console.WriteLine(String.Format(" - Found {0}", id));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onsole.WriteLine(String.Format(" - Found {0}", id)); [](start = 17, length = 53)

unreachable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is reached when any of the if conditions above is true

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ofcourse. I misread the code.

}

if (!hasMSBuild)
Console.WriteLine(" - Missing Visual Studio C++ core features (Microsoft.VisualStudio.VC.MSBuild.Base)");
if (!hasVCTools)
Console.WriteLine(" - Missing VC++ 2017 v141 toolset (x86,x64) (Microsoft.VisualStudio.Component.VC.Tools.x86.x64)");
if ((Win10SDKVer == 0) && (!hasWin8SDK))
Console.WriteLine(" - Missing a Windows SDK (Microsoft.VisualStudio.Component.Windows10SDK.* or Microsoft.VisualStudio.Component.Windows81SDK)");

if (hasMSBuild && hasVCTools)
{
if (Win10SDKVer > 0)
{
Console.WriteLine(" - Using this installation with Windows 10 SDK");
string[] lines = { String.Format("set \"VS2017_INSTALL={0}\"", path), String.Format("set \"VS2017_SDK=10.0.{0}.0\"", Win10SDKVer) };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"set "VS2017_INSTALL={0}"" [](start = 53, length = 28)

Have a string variable for this and resuse it below as well.

System.IO.File.WriteAllLines(@"Set_VS2017.bat", lines);
return true;
}
else if (hasWin8SDK)
{
Console.WriteLine(" - Using this installation with Windows 8.1 SDK");
string[] lines = { String.Format("set \"VS2017_INSTALL={0}\"", path), "set \"VS2017_SDK=8.1\"" };
System.IO.File.WriteAllLines(@"Set_VS2017.bat", lines);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This smell bad...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be done differently?

return true;
}
}

Console.WriteLine(" - Some required components are missing, not using this installation");
return false;
}
}
}
32 changes: 31 additions & 1 deletion vcbuild.bat
Original file line number Diff line number Diff line change
@@ -50,6 +50,7 @@ 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"=="vc2017" set target_env=vc2017&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"=="nosign" set "sign="&echo Note: vcbuild no longer signs by default. "nosign" is redundant.&goto arg-ok
@@ -137,7 +138,36 @@ 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
:vc-set-2017
if defined target_env if "%target_env%" NEQ "vc2017" goto vc-set-2015
echo Looking for Visual Studio 2017
del /F /Q Set_VS2017.bat > nul 2> nul
"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy Unrestricted -Command ^
"&{Add-Type -Path .\tools\Find-VS2017.cs; [VisualStudioConfiguration.Main]::Query()}" 2> nul
if not exist Set_VS2017.bat goto vc-set-2015
call Set_VS2017.bat
if not defined VS2017_INSTALL goto vc-set-2015
if not defined VS2017_SDK goto vc-set-2015
echo Found Visual Studio 2017
if defined msi (
echo Cannot build the MSI with Visual Studio 2017 - it is not yet supported by WiX
goto vc-set-2015
)
if "%target_arch%"=="x86" set "VSARCH=-arch=x86"
if "%target_arch%"=="x64" set "VSARCH=-arch=amd64"
if "%VCVARS_VER%" NEQ "150" (
call "%VS2017_INSTALL%\Common7\Tools\VsDevCmd.bat" %VSARCH% /no_logo
set VCVARS_VER=150
)
if not defined VCINSTALLDIR goto vc-set-2015
set GYP_MSVS_VERSION=2017
set PLATFORM_TOOLSET=v141
goto msbuild-found

@rem Look for Visual Studio 2015
:vc-set-2015
if defined target_env if "%target_env%" NEQ "vc2015" goto msbuild-not-found
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks the current usage. vcbuild.bat should work with no arguments.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vcbuild.bat works with no arguments. This only takes effect if the user wants to select a specific version of VS to use.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, missed the if defined target_env

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
@@ -372,7 +402,7 @@ 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]
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/vc2017] [download-all] [enable-vtune]
echo Examples:
echo vcbuild.bat : builds release build
echo vcbuild.bat debug : builds debug build