title: How to properly set target OS version when building a library on Windows using Visual C++ compiler
body: <p>I'm building a cross-platform library using Visual C++ 2013 compiler with C++11 features on Windows platform specifically, using CMake (NMake generator) for build system. I'm using Windows 7.</p>
  
  <p>My library uses some of functions/enum values/structure members available only in Windows 8/7.</p>
  
  <p>I want to be able to build the library for Windows XP, Windows Vista, Windows 7 and Windows 8/8.1 OS versions and x86, x64 and arm architectures, i.e. not a single build that just targets Windows XP and works everywhere, but many different builds targeting specific OS'es, since newer OS versions have more of useful features my library could provide.</p>
  
  <p>My questions are:</p>
  
  <ol>
  <li><p>How do I tell the compiler to target a specific OS version (i.e. XP, Vista, 7, 8, 8.1, etc)?</p></li>
  <li><p>How do I tell the compiler to target a specific architecture (i.e. x86, x64, arm, etc)?</p></li>
  <li><p>What happens if I use functions/enum values/structure members available only in Windows 8/7 but build my library targeting Windows XP? Would compiler warn me that such things don't exist on Windows XP? Or would it actually compile but fail to run on the Windows XP system?</p></li>
  <li><p>How do I make it so the when I compile for Windows XP, my code skips over things that are not present in Windows XP (Windows 7/8 functions and such)?</p></li>
  <li><p>Does it matter which Windows SDK version I use when targeting different OS versions? I seem to have installed 8.1, 8.0 and 7.1 Windows SDKs. Is it fine if I always use the latest SDK version even when targeting Windows XP?</p></li>
  </ol>
  
  <p>Here are some answers I found, which I'm not sure are correct or complete:</p>
  
  <ol>
  <li><p>I just need to set <code>_WIN32_WINNT</code> and <code>WINVER</code> defines to <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa383745(v=vs.85).aspx#macros_for_conditional_declarations" rel="noreferrer">appropriate values for the target system</a> and that's it, I don't need to set anything in addition to that, my application will run on the specified system (i.e. Windows XP) with just that.</p></li>
  <li><ul>
  <li>I need to use appropriate option when setting up compiler enviroment variables with "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat", i.e. "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat amd64" for 64 bit.</li>
  <li><p>I also need to specify <a href="https://msdn.microsoft.com/en-us/library/fcc1zstk.aspx" rel="noreferrer">appropriate <code>/SUBSYSTEM</code> value</a> to the linker, i.e. <code>/SUBSYSTEM:WINDOWS,5.02</code> or <code>/SUBSYSTEM:WINDOWS,6.00</code> for x64. But what is the difference between <code>5.02</code> and <code>6.00</code>? Why two values specify the same thing (64-bitness)? Same for <code>5.01</code> and <code>6.00</code>, why they both specify 32-bitness? I would emagine having a single value for 64/32 bit would be enough.</p>
  
  <ul>
  <li>Those values (<code>5.01</code>, <code>5.02</code> and <code>6.00</code>) look similar to platform values from <code>WINVER</code> from (1). Do they also set target OS, besides the architecture? But <code>WINVER=502</code> from (1) is used to target Windows Server 2003, which was released in both 64-bit and 32-bit versions according to wikipedia, but in here 5.02 stands strictly for 64-bit, which doesn't make sense...</li>
  </ul></li>
  </ul></li>
  <li><p>Compiler would fail to compile because the <code>WINVER</code> define from (1) would exclude functions and stuff not present in targeting OS (Windows header files use that define to <code>#ifdef</code> things).</p></li>
  <li><p>I should <code>#ifdef</code> things based on <code>WINVER</code> in my own code, like Windows headers do, and provide alternatives for the missing functionality when required.</p></li>
  <li><p>Don't know.</p></li>
  </ol>
  
  <p>Note that I'm not using Visual Studio IDE, so telling me to set option X in the IDE is a bit meaningless.</p>
  
  <p>I'm coming from Linux development, so Windows things are a bit new to me.</p>