5

Is it possible to print the complete *CFLAGS and *CXX_FLAGS of a CMake project (of all targets?)?

I tried looking in CMakeCache.txt after configuring and building the project, but all the *C*FLAGS* related variables are almost empty, and anyway do not contain my project settings, such as -D and -I flags specific to my dependencies.

Why I want to do this? In order to create a configuration file for the clang-complete vim plugin: https://vim.sourceforge.io/scripts/script.php?script_id=3302

fferri
  • 18,285
  • 5
  • 46
  • 95
  • Can please give more details on what you have already tried and why it didn't fit you needs? If I just [google for it](https://www.google.de/search?q=cmake+clang_complete) I see several how-to tutorials. – Florian Sep 19 '17 at 18:31
  • @Florian I tried using the cc_args.py script as documented [here](https://stackoverflow.com/questions/15001421/cmake-and-clang-complete) but it does not work (does not create any .clang_complete in the build directory) – fferri Sep 20 '17 at 06:53
  • @fferri, did you use '~' (instead of "$HOME") in your command as was incorrectly suggested by an answer there? – xaizek Sep 20 '17 at 22:02
  • no, I used `CXX="$HOME/.vim/bin/cc_args.py clang++" cmake` – fferri Sep 21 '17 at 12:28

3 Answers3

10

You can also get cmake to produce a json file of all commands to be run with:

-DCMAKE_EXPORT_COMPILE_COMMANDS=ON

In context:

mkdir -p release
cd release
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja .. && ninja

This will give you a file in release called compile_commands.json which has a record of your commands. This is similar to Stewart's answer except that it puts the log in a file for you automatically. Another advantage is that this file is used clang-tidy which I have found to be incredibly useful.

Bowie Owens
  • 2,798
  • 23
  • 20
9

I recommend printing properties of the respective targets, instead of printing "global" variables. The values of CMAKE_xxx_FLAGS are attached to the target when the target is defined, and may be altered afterwards.

This is a useful helper function I am using in my projects, inspired by https://stackoverflow.com/a/34292622/5751151:

function(print_target_properties tgt)
    if(NOT TARGET ${tgt})
        message("There is no target named '${tgt}'")
        return()
    endif()

    # this list of properties can be extended as needed
    set(CMAKE_PROPERTY_LIST SOURCE_DIR BINARY_DIR COMPILE_DEFINITIONS
             COMPILE_OPTIONS INCLUDE_DIRECTORIES LINK_LIBRARIES)

    message("Configuration for target ${tgt}")

    foreach (prop ${CMAKE_PROPERTY_LIST})
        get_property(propval TARGET ${tgt} PROPERTY ${prop} SET)
        if (propval)
            get_target_property(propval ${tgt} ${prop})
            message (STATUS "${prop} = ${propval}")
        endif()
    endforeach(prop)

endfunction(print_target_properties)
Kaldonia
  • 106
  • 3
6

Can you use message? Here is a sample from a useful script from cmake.

# the compiler flags for compiling C sources 
MESSAGE( STATUS "CMAKE_C_FLAGS: " ${CMAKE_C_FLAGS} )

# the compiler flags for compiling C++ sources 
MESSAGE( STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS} )

Otherwise, I will often compile with a verbose mode. Since I use Ninja as my generator, it looks like this:

cmake .. -GNinja
ninja -v

The output to console contains the full compilation command which in my case looks something like this:

[1/2] C:\msys64\mingw32\bin\c++.exe -D<Defines> -I<Includes> -isystem C:/msys64/mingw32/include -g -MD -MT <object>.obj -MF <object>.obj.d -o <object>.obj -c <object>.cpp
[2/2] C:\msys64\mingw32\bin\c++.exe -g  <object1>.obj <object2>.obj <objectN>.obj -o <Application>.exe -Wl,--major-image-version,0,--minor-image-version,0 <library1>.dll.a <library2>.dll.a -l<systemlib1> -l<systemlib2>

You can also try setting set( CMAKE_VERBOSE_MAKEFILE on ) in your CMakeLists.txt or cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON at the command line to try it from cmake without using your generator. You can check out that variable here.

Stewart
  • 4,356
  • 2
  • 27
  • 59
  • I've done the `message()` thing in the past and if you use make as your build system you can supply `VERBOSE=1` to get the full command-lines to the compiler and linker. The lines are pretty long, so I like to use my [breakln perl script](http://user.xmission.com/~legalize/blog/breakln.txt) to squish & fold the output. – legalize Sep 20 '17 at 20:03