Friday, October 29, 2021

[SOLVED] Get full C++ compiler command line

Issue

In CMake, the flags for the C++ compiler can be influenced in various ways: setting CMAKE_CXX_FLAGS manually, using add_definitions(), forcing a certain C++ standard, and so forth.

In order to compile a target in the same project with different rules (a precompiled header, in my case), I need to reproduce the exact command that is used to compile files added by a command like add_executable() in this directory.

Reading CMAKE_CXX_FLAGS only returns the value set to it explicitly, CMAKE_CXX_FLAGS_DEBUG and siblings only list default Debug/Release options. There is a special functions to retrieve the flags from add_definitions() and add_compiler_options(), but none seem to be able to return the final command line.

How can I get all flags passed to the compiler into a CMake variable?


Solution

To answer my own question: It seems like the only way of getting all compiler flags is to reconstruct them from the various sources. The code I'm working with now is the following (for GCC):

macro (GET_COMPILER_FLAGS TARGET VAR)
    if (CMAKE_COMPILER_IS_GNUCXX)
        set(COMPILER_FLAGS "")

        # Get flags form add_definitions, re-escape quotes
        get_target_property(TARGET_DEFS ${TARGET} COMPILE_DEFINITIONS)
        get_directory_property(DIRECTORY_DEFS COMPILE_DEFINITIONS)
        foreach (DEF ${TARGET_DEFS} ${DIRECTORY_DEFS})
            if (DEF)
                string(REPLACE "\"" "\\\"" DEF "${DEF}")
                list(APPEND COMPILER_FLAGS "-D${DEF}")
            endif ()
        endforeach ()

        # Get flags form include_directories()
        get_target_property(TARGET_INCLUDEDIRS ${TARGET} INCLUDE_DIRECTORIES)
        foreach (DIR ${TARGET_INCLUDEDIRS})
            if (DIR)
                list(APPEND COMPILER_FLAGS "-I${DIR}")
            endif ()
        endforeach ()

        # Get build-type specific flags
        string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE_SUFFIX)
        separate_arguments(GLOBAL_FLAGS UNIX_COMMAND
                "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BUILD_TYPE_SUFFIX}}")
        list(APPEND COMPILER_FLAGS ${GLOBAL_FLAGS})

        # Add -std= flag if appropriate
        get_target_property(STANDARD ${TARGET} CXX_STANDARD)
        if ((NOT "${STANDARD}" STREQUAL NOTFOUND) AND (NOT "${STANDARD}" STREQUAL ""))
            list(APPEND COMPILER_FLAGS "-std=gnu++${STANDARD}")
        endif ()
    endif ()
    set(${VAR} "${COMPILER_FLAGS}")
endmacro ()

This could be extended to also include options induced by add_compiler_options() and more.



Answered By - Fabian Knorr