4

I'm trying to compile MPIR (Windows-friendly version of GMP). I have Visual Studio 2017 installed, so it should work, but I get this error message:

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Microsoft.Cpp.WindowsSDK.targets(46,5): error MSB8036: The Windows SDK version 8.1 was not found. Install the required version of Windows SDK or change the SDK version in the project property pages or by right-clicking the solution and selecting "Retarget solution". [C:\mpir\msvc\vs17\lib_mpir_gc\lib_mpir_gc.vcxproj]

I specifically need to get to a point where it can compile on any machine, not just this one, so installing that exact SDK version on this machine wouldn't solve the problem. I need to change something to get it to build with Visual Studio 2017.

Looking in C:\mpir\msvc\vs17\lib_mpir_gc\lib_mpir_gc.vcxproj, I find the line:

<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>

Which looks promising, but deleting it has no effect whatsoever; the error message remains unchanged.

What can I change to eliminate this error?

To summarize my reason for believing this should be possible:

If you write a C++ program, say in the simplest scenario, in a single file called foo.cpp, and compile it with the commandline compiler cl foo.cpp it will automatically compile and link with whatever SDK version is used by the current Visual Studio install to generate foo.exe that will (unless you used some very specialized API only available in later Windows versions) run on any Windows from at least Vista on.

And that's exactly the same cl.exe that gets called by msbuild. So I'm not asking for new functionality. Rather, the above error message is being generated because something went out of its way to break the default 'it just works' scenario and add the lock to a particular SDK version. I'm asking how to remove the lock and get back to the default scenario where it just works with whatever SDK version Visual Studio came with.

rwallace
  • 31,405
  • 40
  • 123
  • 242
  • Error message already lists available options. – user7860670 Apr 23 '19 at 07:19
  • @VTT Error message suggests locking to a different SDK version. I'm asking how to remove the lock entirely and fix it so it builds with any Visual Studio 2017 install. – rwallace Apr 23 '19 at 07:36
  • 1
    Then you are basically asking how to eliminate platform targeting which is essential part of VS projects. – user7860670 Apr 23 '19 at 07:41
  • 1
    @VTT Eliminate, yes. Essential, that makes no sense whatsoever. The different SDK versions are compatible with each other. A well-written C++ program, unless it is doing something extremely specialized that needs a feature only available in the latest version of Windows, should be able to build with any SDK released in the last decade or so. – rwallace Apr 23 '19 at 07:45
  • 1
    Unfortunately things don't work this way. For example in order to use `GetFileVersionInfoSizeExW` function that has been around since Windows Vista one needs to link to version.dll or to api-ms-win-core-version-l1-1-0.dll, or to api-ms-win-core-version-l1-1-1.dll, depending on target SDK. A lot of stuff is getting moved around or reworked (DirectX SDK is the most notorious example). – user7860670 Apr 23 '19 at 08:14
  • @VTT Then how do people manage to write C++ programs that successfully run on several different versions of Windows? – rwallace Apr 23 '19 at 08:16
  • 1
    Well, that's a different kind of question. Typically people just target Windows version corresponding to the oldest supported system. If they need to utilize some newer features on newer systems without breaking compatibility with older ones then project needs to be split or that newer stuff needs to be invoked through manually loading appropriate dlls (this is not a big problem when it is something COM based). – user7860670 Apr 23 '19 at 08:26
  • 2
    @rwallace: By targeting Windows 7 or 8 SDK's. Windows 10 is backwards compatible. It still has that `version.dll` from Vista. Windows understands that programs using that old DLL are built with an older SDK. – MSalters Apr 23 '19 at 08:26
  • "it just works" approach in reality does not necessary work. When building from command line SDK targeting is performed based on environment. I think VS Installer sets up things to target the latest installed SDK by default. So if you are building on WIndows 10 with fresh SDK program using GetFileVersionInfoSizeExW and linking Mincore.lib won't run on older versions of windows. – user7860670 Apr 23 '19 at 09:01
  • 1
    AFAIK to set a custom target SDK for the CLI you need to use `vcvarsall.bat` with some custom options. – Acorn Apr 23 '19 at 09:08

2 Answers2

6

As the comments state, this is unavoidable.

If you build with the Windows 8.1 SDK, you get a version that runs on Windows 8.1 or higher. If you build with the Windows 10 SDK, you can restrict its functionality to Windows 8, or you can pick a Windows 10 build (e.g. 1607). Of course, if you pick a new SDK to use new Windows 10 functionality, you can't run it on Windows 8.1 which misses that functionality.

But if you don't pick a Windows SDK, then what Windows version would you be building for? Which <windows.h> would you be using?

[edit] As for portable C++ programs, they obviously don't include <windows.h>, and they don't link directly against the Windows API's. Instead, these take a dependency on Microsoft's implementation of the C++ Standard Library (aka MSVCRT)

[edit2] I just counted, My Visual Studio 2017 install (15.7.5) has 12 SDK different options. True, some are for ARM, but that's just a variation on the basic premise: the SDK you choose affects the machines on which you can run the resulting application.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • The version that came with Visual Studio, whatever that may be. This is how it works when you use the command line compiler, so something in the toolchain is going out of its way to break that – added explanation to question text. – rwallace Apr 23 '19 at 08:37
  • @rwallace: There's longer no such a thing as **the** version that came with with VS2017/19. – MSalters Apr 23 '19 at 08:40
  • Here's a simple test you can run: write a 'hello world' program in C++, then `cl hello.cpp`. It works. And it doesn't require you to guess an SDK version. It successfully finds one. – rwallace Apr 23 '19 at 08:42
  • Okay, now try it again with a slightly more complex program that includes `` and makes some Windows API calls. `cl hello_win.cpp`. Still works. – rwallace Apr 23 '19 at 08:44
  • @rwallace: And then give it to someone with a clean Windows 8 install, no VC++ redistributable installed yet. It doesn't work anymore. – MSalters Apr 23 '19 at 08:45
  • It does if you link statically with MSVCRT. – rwallace Apr 23 '19 at 08:48
  • @rwallace: Well, you were specifically talking default settings, such as `cl hello_win.cpp`. That seemed to be the whole point. – MSalters Apr 23 '19 at 08:59
  • Even if you target the latest Windows 10 SDK, if you set the proper `#define`s properly, it should still run on Windows 7 SP1 and higher AFAIK, because the Win10 SDK supports them. The C++ libraries would still require the redistributable AFAIK, though. – Acorn Apr 23 '19 at 08:59
  • @Acorn: That might be the case right now, but Windows 7 SP1 is out of official support so that setting could disappear from the SDK. Then again, Visual Studio was supporting XP long after Microsoft as a whole was. – MSalters Apr 23 '19 at 09:02
  • @MSalters Of course, it was an example of the latest SDK -- later ones will bump the minimum version. What I don't know is if one creates a program without using anything from the C++ runtime, it would still be guaranteed to work under Win7 without the C++ redistributable. AFAIU they are 2 independent axes (SDK and C++ redist), but I am not sure. – Acorn Apr 23 '19 at 09:03
  • @Acorn: How are you going to write a program without using the C++ runtime? Don't forget, `int main(int argc, char** argv)` is not the actual entry point used by Windows, as C++ needs to initialize global objects. The CRT handles this by providing the actual entry point for the OS. – MSalters Apr 23 '19 at 09:38
  • 1
    @MSalters I am well aware of that, but you should be able to link programs that don't depend on the runtime. Of course, you may not be able to use some C++ features like global ctor/dtors, exceptions, RTTI, etc. I say "should" because I never tried with MSVC in particular, but it is indeed possible with other compilers. For MSVC, `/NODEFAULTLIB`s may do the trick. In the worst case, one could also use their C mode via `/TC` and avoid C++ entirely, which should prove easier to make a standalone executable. – Acorn Apr 23 '19 at 15:13
  • @Acorn: I have actually built a small executable with the `/NODEFAULTLIB`, but I did so by linking against an alternative slimmed runtime. Your assumption that you _should_ be able to link against no runtime at all is unfounded. That presumes that the OS provides all the necessary support for C++ (or C, in case of `/TC`), and that's simply not justified. – MSalters Apr 25 '19 at 14:15
  • @MSalters Windows supports binaries that only depend on `kernel32.dll`, so yes, it is very much justified thinking that the main compiler of the platform should support creating standalone executables somehow (like others do). And no, it does not presume anything about "*OS provides support for C++*" -- that does not even make sense. There is nothing the OS has to "provide" to support a particular language. – Acorn Apr 26 '19 at 12:46
3

VS2019 supports targeting projects to the latest installed Windows SDK version by selecting appropriate item. This may or may not produce desired results, however will definitely eliminate the need for manual project retargeting.

enter image description here

user7860670
  • 35,849
  • 4
  • 58
  • 84