2

I need to get the compiler flags that will be used to compile a target programmatically in CMake. I need these flags as a string because I need to pass them to an executable in a custom command that needs to know how the parent target was compiled because it propagates those flags. I know enabling compile commands generates a JSON that shows the compile command but I need that output in CMake itself.

project(foo LANGUAGES CXX)
cmake_minimum_required(VERSION 3.22)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(bar bar.cpp)

# define COMPILE_FLAGS somehow such that it equals -std=c++17    

add_custom_target(external
    COMMAND external_exe --flags ${COMPILE_FLAGS}
)

I've looked at these previous questions:

  • Using something like this or this does print compile flags like "-Werror" but the standard flag is not printed
  • Setting the standard with set_property and then getting it returns "17". Similarly, I can get the CMAKE_CXX_STANDARD to also return "17"*
  • This is the exact problem I have but the answer doesn't help in CMake
  • These questions are also related but unhelpful: one, two, and three

Am I missing something or is there no way to get this information?

*Can I assume that getting the standard number (e.g. 17) and appending that to "-std=c++" will be portably valid? It works with g++ at least but I'm not sure about other compilers/platforms.

vitalstatistix
  • 310
  • 2
  • 8
  • Looks like a XY-problem. If your code needs knowing the C++ standard version, the macro `__cplusplus` is for this purpose. – 273K Apr 25 '22 at 23:28
  • I need the standard information for an external command-line executable so the ``__cplusplus`` macro doesn't help – vitalstatistix Apr 25 '22 at 23:31
  • 4
    "I need that output in CMake itself." - In general, it is impossible to get compile flags, created by CMake, while processing `CMakeLists.txt`. CMake computes these flags **after** the configuration process is finished. Exactly at that stage all linked libraries are known and generator expressions can be expanded. – Tsyvarev Apr 25 '22 at 23:38
  • Good to know. I don't need all the compile flags (and not any linker / flags that are being transitively inherited etc), just the standard flag. I would have assumed that information is available since I'm defining the standard up front – vitalstatistix Apr 25 '22 at 23:45
  • 1
    Do you need `--flags --std=c++${CMAKE_CXX_STANDARD}`? – 273K Apr 25 '22 at 23:48
  • @273K Yes, I need that string. The second part of my question was whether constructing it like that was portably valid across different compilers/platforms – vitalstatistix Apr 25 '22 at 23:55
  • 1
    beware that gcc [8-9] use `c++2a` then later `c++20`, cmake correctly do the job after detecting the compiler... ref: https://gcc.gnu.org/projects/cxx-status.html#cxx20 – Mizux Apr 28 '22 at 06:59

1 Answers1

3

If you just need the compiler flag for choosing the C++ standard, try this:

set(COMPILE_FLAG ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION})

Alternatively, replace "STANDARD" in the code above with "EXTENSION" if you want to allow compiler-specific extensions.

I grepped through the CMake source code, and I found that variables like CMAKE_CXX17_STANDARD_COMPILE_OPTION are defined in files that tell CMake how to use different compilers.

David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • 1
    Is this a reliable solution? I don't recall ever seeing these variables referred to in the CMake docs, which makes me think this might not be a safe thing to rely on between versions – Human-Compiler Apr 26 '22 at 00:49