Unable to compile and link simple C++ program with

2020-02-28 15:10发布

问题:

With Visual Studio 2015 I am no longer able to compile and link a simple C++ program using the command line tools.

Consider main.cpp:

#include <stdlib.h>
int main() { return 0; }

In previous releases (for example Visual Studio 2012) I was able to compile and link main.cpp easily:

C:\Users\bkircher\src\test>cl main.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe
main.obj

And done.

With Visual Studio 2015 however, I no longer have proper CRT include and library paths set:

C:\Users\bkircher\src\test>cl main.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23026 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
main.cpp(1): fatal error C1083: Cannot open include file: 'stdlib.h': No such file or directory

I understand that Microsoft distributes the C runtime as a new Windows operating system component, the Universal CRT.

As described in Introducing the Universal CRT, I should use following MSBuild properties to find the appropriate paths

$(UniversalCRT_IncludePath)
$(UniversalCRT_LibraryPath_x64)

Despite that, how do I get proper library and include paths for build systems other than devenv or MSBuild?

For the sake of it:

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC>set include
INCLUDE=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ATLMFC\INCLUDE;C:\Program Files (x86)\Windows Kits\10\include\wdf\ucrt;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6\include\um;C:\Program Files (x86)\Windows Kits\10\include\wdf\shared;C:\Program Files (x86)\Windows Kits\10\include\wdf\um;C:\Program Files (x86)\Windows Kits\10\include\wdf\winrt;

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC>set lib
LIB=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\LIB\amd64;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ATLMFC\LIB\amd64;C:\Program Files (x86)\Windows Kits\10\lib\wdf\ucrt\x64;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6\lib\um\x64;C:\Program Files (x86)\Windows Kits\10\lib\wdf\um\x64;
LIBPATH=C:\Windows\Microsoft.NET\Framework64\v4.0.30319;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\LIB\amd64;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ATLMFC\LIB\amd64;C:\Program Files (x86)\Windows Kits\10\UnionMetadata;C:\Program Files (x86)\Windows Kits\10\References;C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\1.0.0.0;C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.FoundationContract\1.0.0.0;C:\Program Files (x86)\Windows Kits\10\References\indows.Networking.Connectivity.WwanContract\1.0.0.0;C:\Program Files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs\Microsoft.VCLibs\14.0\References\CommonConfiguration\neutral;

回答1:

Including the contents of the environment variables was a good idea. Based on the paths appearing there, it seems that you have the Windows Driver Kit installed and you're encountering this issue reported on Connect.

According to the description of the issue, the wdf directory created by the WDK confuses the batch file that tries to determine the latest SDK versions available. For example, instead of

C:\Program Files (x86)\Windows Kits\10\include\wdf\ucrt

in the INCLUDE variable, you should have something like

C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt

The "carpet-bombing" solution: uninstall the WDK, make sure the wdf directories are gone, and things should return to normal.


If that's not an option, here's a "surgical" solution: you need to edit

"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\vcvarsqueryregistry.bat"

(back it up first, of course)

1. Look for the following two labels:

:GetWindowsSdkDirHelper32
:GetWindowsSdkDirHelper64

Under each of them, you'll find the following line:

@REM Get windows 10 sdk version number
@if not "%WindowsSdkDir%"=="" @FOR /F "delims=" %%i IN ('dir "%WindowsSdkDir%include\" /b /ad-h /on') DO @set WindowsSDKVersion=%%i\

Change it to:

@REM Get windows 10 sdk version number
@if not "%WindowsSdkDir%"=="" @FOR /F "delims=" %%i IN ('dir "%WindowsSdkDir%include\" /b /ad-h /on') DO (
   @if not "%%i"=="wdf" (
      @set WindowsSDKVersion=%%i\
   )
)

2. Look for the following two labels:

:GetUniversalCRTSdkDirHelper32
:GetUniversalCRTSdkDirHelper64

Under each of them, change the following line:

@FOR /F "delims=" %%i IN ('dir "%UniversalCRTSdkDir%include\" /b /ad-h /on') DO @SET UCRTVersion=%%i

to:

@FOR /F "delims=" %%i IN ('dir "%UniversalCRTSdkDir%include\" /b /ad-h /on') DO (
   @if not "%%i"=="wdf" (
      @SET UCRTVersion=%%i
   )
)

That's it. Let me know if it helped.

Keep in mind that this will skip the wdf directories altogether. If the WDK command prompt setup scripts happen to use the same vcvarsqueryregistry.bat batch file (I doubt it, but...), then they won't work correctly anymore; a bit more hacking will be needed in this case to select the proper batch file for each build environment.