`COMPILE_DEFINITIONS` with generator expression: "$<${gcc_like}:-Werror>" "$<${msvc}:-WX>"


set(gcc_like "$<COMPILE_LANG_AND_ID:C,CXX,ARMClang,AppleClang,Clang,GNU,LCC>")

        SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/fallthrough.c"
        COMPILE_DEFINITIONS "$<${gcc_like}:-Werror>" "$<${msvc}:-WX>"
COMPILE_DEFINITIONS "$$<${gcc_like}:-Werror>" "$$<${msvc}:-WX>"

All gave this error:

win/x64/ninja.exe' '-C' 's2n-tls/cmake-build-debug/CMakeFiles/CMakeTmp' '-t' 'recompact'

  failed with:

   ninja: error: build.ninja:53: bad $-escape (literal $ must be written as $$)
    FLAGS = /DWIN32 /D_WINDOWS /W3  /MDd /Zi /Ob0 /Od /RTC1   $$<$<COMPILE...
                                                                 ^ near here

From https://cmake.org/cmake/help/latest/prop_tgt/COMPILE_DEFINITIONS.html you do support generator expressions here. What’s the right syntax?

The $<COMPILE_LANG_AND_ID:...> generator expression only takes one language and multiple compiler IDs. You’re trying to use multiple languages, so your second and later languages would get treated as compiler IDs.

But your main problem is that the try_compile() command doesn’t support generator expressions. The general rule is that if the documentation of a command or property doesn’t explicitly say it supports generator expressions, then it doesn’t support them.

@craig.scott But it does say:

Contents of COMPILE_DEFINITIONS may use “generator expressions” with the syntax $<...>. See the cmake-generator-expressions(7) manual for available expressions. See the cmake-buildsystem(7) manual for more on defining buildsystem properties.


Ok so try_compile uses different COMPILE_DEFINITIONS than that one?

The try_compile() command creates a separate sub-build to do the try-compile. You’re expecting details from the main project to be available in that sub-build, but that isn’t possible. Generator expressions are evaluated at generation time of the main project. The try_compile() command runs during the CMake configuration stage, which is before the generation stage. Thus, the try_compile() command cannot evaluation generator expressions. It may try to pass them down in their original form to the sub-build, but it won’t be expecting any because that command’s documentation doesn’t say that it supports generator expressions.

So while the COMPILE_DEFINITIONS property does support generator expressions, the try_compile() command you’re trying to thread them through via does not. And there’s no way they can be supported in this case (for the way you want to use them) because the information you’re expecting them to provide isn’t available yet at the point of the try_compile() call.

They can be handled during the try_compile project’s generation time (assuming the setup has enough context to answer them reliably; for this, it should). However, it looks like there’s some escaping woes because it does try to pass things, but ninja chokes on $ escaping. See Issue #16395.

I was thinking your generator expressions were referencing target properties when I made the above comment. But I see now you are only referring to details about the toolchain. Maybe the sub-build could resolve those if the generator expressions could survive the trip through the ninja.build file (which Ben’s last comment seems to indicate might not be possible, at least right now).