1

In my CMakeLists.txt there is:

set(CMAKE_CXX_STANDARD 20)
# ...
add_library(mytarget)
# ...
target_compile_options(mytarget PRIVATE
    /Zc:char8_t-  # Disables C++20 conforming char8_t type support.
                  # https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1423r3.html
                  # https://stackoverflow.com/questions/59325910/whats-the-msvc-equivalent-for-fno-char8-t
)

It produces different command lines if I use Visual or Ninja generators. With Visual generator:

cl.exe [...] /std:c++20 [...] /Zc:char8_t-

With Ninja generator:

cl.exe [...] /Zc:char8_t- [...] -std:c++20

The order of compile flags matters here, because /std:c++20 reactivates /Zc:char8_t (note the absence of "-" here). So the build fails using Ninja.

At the time of this writing, I am using CMake 3.25.1.

Is there a way to tell CMake to put /std:c++20 before any other compile flags?

starball
  • 20,030
  • 7
  • 43
  • 238
Thibaud
  • 101
  • 7
  • 1
    Yes, sorry for the confusion, I did not write the full code between the two lines. The target is indeed defined between setting `CMAKE_CXX_STANDARD` and calling `target_compile_option`. – Thibaud May 03 '23 at 11:22

2 Answers2

2

It turns out that this was referenced as a CMake issue and fixed in recent versions of CMake.

cconsta1
  • 737
  • 1
  • 6
  • 20
Thibaud
  • 101
  • 7
2

This problem was referenced in this issue ticket in the CMake 3.26 milestone: Place language standard flags just after CMAKE__FLAGS #7931.

The 3.26 manual for compile features' section on Language Standard Flags (a newly added section) states:

In order to satisfy requirements specified by the target_compile_features() command or the [CMAKE_<LANG>_STANDARD](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_STANDARD.html) variable, CMake may pass a language standard flag to the compiler, such as -std=c++11`.

For Visual Studio Generators, CMake cannot precisely control the placement of the language standard flag on the compiler command line. For Ninja Generators, Makefile Generators, and Xcode, CMake places the language standard flag just after the language-wide flags from CMAKE_<LANG>_FLAGS and CMAKE_<LANG>_FLAGS_<CONFIG>.

Changed in version 3.26: The language standard flag is placed before flags specified by other abstractions such as the target_compile_options() command. Prior to CMake 3.26, the language standard flag was placed after them.

So if you need this behaviour, make sure you and everyone else building your project all have CMake 3.26 or later installed.

If you can't do that for some reason, one way to work around the issue would be to switch to using target_compile_options/add_compile_options to specify your language standard flags (you'd need to wrap in conditional blocks or generator expressions if you need to support multiple compilers), which is not ideal, and I wouldn't recommend it. You could also append to CMAKE_CXX_FLAGS, which gets added before those added by target_compile_options/add_compile_options.

starball
  • 20,030
  • 7
  • 43
  • 238