title: How to set compiler options with CMake in Visual Studio 2017
body: <p>Visual Studio 2017 comes with full CMake integration. To learn about this combination, I was starting with this basic sample:</p>
  
  <pre><code># CMakeLists.txt
  cmake_minimum_required(VERSION 3.8)
  project(foo)
  add_executable(foo foo.cpp)
  </code></pre>
  
  <p>and</p>
  
  <pre><code>// foo.cpp
  int main() {}
  </code></pre>
  
  <p>This properly generates build scripts, and compiles and links with no issues. That was easy.</p>
  
  <p>Trying to set compiler options, on the other hand, turned out to be anything but trivial. In my case I was attempting to set the warning level to 4.</p>
  
  <p>The obvious solution</p>
  
  <pre><code>add_compile_options("/W4")
  </code></pre>
  
  <p>didn't pan out as expected. The command line passed to the compiler now contains both <code>/W4</code> (as intended) as well as <code>/W3</code> (picked up from somewhere else), producing the following warning:</p>
  
  <blockquote>
  <pre><code>cl : Command line warning D9025: overriding '/W3' with '/W4'
  </code></pre>
  </blockquote>
  
  <p>To work around this, I would need to <em>replace</em> any incompatible compiler option(s) instead of just adding one. CMake does not provide any immediate support for this, and the standard solution (as <a href="https://stackoverflow.com/q/2368811/1889329">this Q&amp;A suggests</a>) seems to be:</p>
  
  <pre><code>if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
      string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
  else()
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
  endif()
  </code></pre>
  
  <p>This, however, has two issues:</p>
  
  <ul>
  <li>It sets the global <code>CMAKE_CXX_FLAGS</code>, applying to all C++ targets. This may not be intended (not an issue for me right now).</li>
  <li>It doesn't scale. For every compiler option to add, you would have to read up on incompatible options, and manually strip those first. This will inevitably fail<sup>1</sup>.</li>
  </ul>
  
  <p>My question is two-fold:</p>
  
  <ol>
  <li>Where does the CMake integration pick up default settings from, and can this be controlled?</li>
  <li>How do you set compiler options in general? (If this is too broad a topic, I'd be happy for help on setting the warning level only.)</li>
  </ol>
  
  <p><hr/>
  <sup>1</sup> <em>Incidentally, the solution I replicated fails to account for the <code>/Wall</code> option, that is incompatible with <code>/W4</code> as well.</em></p>