title: How to use variables and avoid CMP0054 policy violations?
body: <p>We are catching errors during testing for CMP0054 policy violations. An example can be found online at <a href="https://ci.appveyor.com/project/noloader/cryptopp/build/1.0.367/job/yp3lip31cotc6o1e" rel="noreferrer">Build 367</a>.</p>
  
  <pre><code>cmake : CMake Warning (dev) at CMakeLists.txt:364 (if):
  At line:8 char:5
  +     cmake -G "Visual Studio 15 2017" -DCMAKE_BUILD_TYPE=$env:configur ...
  +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      + CategoryInfo          : NotSpecified: (CMake Warning (...s.txt:364 (if)::String) [], RemoteException
      + FullyQualifiedErrorId : NativeCommandError
  
    Policy CMP0054 is not set: Only interpret if() arguments as variables or
    keywords when unquoted.  Run "cmake --help-policy CMP0054" for policy
    details.  Use the cmake_policy command to set the policy and suppress this
    warning.
    Quoted variables like "MSVC" will no longer be dereferenced when the policy
    is set to NEW.  Since the policy is not set the OLD behavior will be used.
  This warning is for project developers.  Use -Wno-dev to suppress it.
  </code></pre>
  
  <p>It is due to making an if statement like so:</p>
  
  <pre><code>if ("${CRYPTOPP_AMD64}" STREQUAL "1" OR "${CRYPTOPP_I386}" STREQUAL "1")
      ...
  endif()
  </code></pre>
  
  <p>The statements above are consistent with <a href="https://stackoverflow.com/a/31044116/608639">What's the CMake syntax to set and use variables?</a>, and it was the only thing that seemed to "just work" everywhere, regardless of whether the variable was set, was empty, had a 0 value, had a 1 value or had some other value.</p>
  
  <p>We removed the quotes from the variable to satisfy the god damned policy and all hell broke loose. Now we are lucky to get through a CMake configuration without an error. We tried:</p>
  
  <pre><code>if (${CRYPTOPP_AMD64} STREQUAL "1" OR ${CRYPTOPP_I386} STREQUAL "1")
      ...
  endif()
  </code></pre>
  
  <p>And:</p>
  
  <pre><code>if (${CRYPTOPP_AMD64} STREQUAL 1 OR ${CRYPTOPP_I386} STREQUAL 1)
      ...
  endif()
  </code></pre>
  
  <p>And:</p>
  
  <pre><code>if (${CRYPTOPP_AMD64} EQUAL 1 OR ${CRYPTOPP_I386} EQUAL 1)
      ...
  endif()
  </code></pre>
  
  <p>They mostly lead to a <em>"CMake Error at CMakeLists.txt... if given arguments..."</em>. For example, here's testing on Solaris 11:</p>
  
  <pre><code>CMake Error at CMakeLists.txt:507 (if):
    if given arguments:
  
      "EQUAL" "1" "AND" "NOT" "DISABLE_SSSE3"
  
    Unknown arguments specified
  </code></pre>
  
  <p>We don't control user machines, so changing a policy and running commands like cmake_policy is out of the question for us. We don't expect users to do anything special. Users are only expected to make a directory, cd into the directory, and then run cmake. That's it.</p>
  
  <p>What is the syntax we should use for variables that works everywhere given the latest changes in CMake?</p>
  
  <p>When we say everywhere, we mean from Cmake 2.8 to Current, and a variable that might be in any state, including set, empty, 0 value, 1 value or an unexpected value.</p>
  
  <hr>
  
  <p><strong><em>EDIT</em></strong>: We are now catching bug reports for the unquoted variables on Windows machines. Yet another damn CMake bug at <a href="https://github.com/weidai11/cryptopp/issues/486" rel="noreferrer">Windows CMake failure when compiler path has a space</a>.</p>
  
  <p>CMake has been in the library for two years. It makes up 18% of the bugs in our bug reporter. It causes a disproportionate number of problems for users.</p>