How to view the exact command cmake_automoc is running? - c++

I have an issue with automoc in that moc fails with Parse error at "BOOST_JOIN". I tried the "least evil" hack outlined here, but to no avail (speficially, I added set(CMAKE_AUTOMOC_MOC_OPTIONS "-DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED") to my CMakeLists.txt). Further, when I try to moc the offending file myself, it seems to work.
I'd like to know the exact command CMake is running so I can continue debugging this. If I do ninja -v, however (equivalent of make VERBOSE=1), I get something like:
cd projdir && cmake -E cmake_automoc projdir/CMakeFiles/proj_automoc.dir/ Debug
If I run that myself, sure enough I get the same Parse error at "BOOST_JOIN" message, but I still don't know how CMake is calling moc.
cmake --debug-output -E cmake_automoc ... throws a usage error.

Once you have done the cmake configure step and generated the build scripts (eithe VS solution files or Unix makefiles), you can use cmake with the build option as described in the manual cmake(1). If you are using Makefiles, then you can use:
make VERBOSE=1
For Visual Studio, see
Is there an option to produce more 'verbose' compiling? for details.

Related

How to get cmake-generated Makefile to echo compiler command-lines? [duplicate]

This question already has answers here:
Using CMake with GNU Make: How can I see the exact commands?
(8 answers)
Closed 8 months ago.
On Linux I can build a C++ project with cmake like:
$ mkdir build
$ cd build
$ cmake ../myproject
$ make
[ ] Building CXX object ...
Is there a way to pass an option to cmake or make so that it will print the full command-lines (and all the options) it is passing to the C++ compiler to compile each object file?
(I tried:
$ make V=1
but it doesn't seem to work. I guess the cmake-generated Makefile doesn't work with that option?)
As per this link There are three options (+1 extra found in the answer of HolyBlackCat):
1
If you can / want to modify the CMakeLists.txt, you can just add
set(CMAKE_VERBOSE_MAKEFILE ON)
This has to be done in every CMakeLists.txt file in your project though, so it might be a bit cumbersome, if you want to enable it for the entire project.
2
To write the verbose changes directly to the makefile, you can run the cmake command which generates the make file with an additional flag:
cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON ./path
And, you guessed it, to disable it, you need to run it again:
cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=OFF ./path
3
Finally, if you build your project by calling make and do not use the cmake --build ./path or cmake --build ./path --target target commands, you can pass it as an option to make directly:
make VERBOSE=1;
Although I would not recommend it, because they whole point of cmake is to not have to use make anymore (although it's still called behind the scenes).
Use either make VERBOSE=1, or cmake --build <path> --verbose which automatically invokes the right command for the generator you used.

Can someone expand what is meant by 'configure' and 'build' with CMake files

I am downloading this code from GitHub (subdivision-regression), and am getting stuck following the instructions:
To build doosabin_regression:
Run CMake with an out of source build.
Set COMMON_CPP_INCLUDE_DIR to the full path to rstebbing/common/cpp.
Set DOOSABIN_INCLUDE_DIR to the full path to rstebbing/subdivision/cpp/doosabin/include.
Set Ceres_DIR to the directory containing CeresConfig.cmake.
Set GFLAGS_INCLUDE_DIR, GFLAGS_LIBRARY and RAPID_JSON_INCLUDE_DIR. (Add -std=c++11 to CMAKE_CXX_FLAGS if compiling with gcc.)
Configure.
Build.
I have edited the CMakeLists.txt file to put the correct paths in. I then created a new directory called subdivision-regression-bin and ran:
cmake ../subdivision-regression/src
It completes this and displays:
-- Configuring done
-- Generating done
-- Build files have been written to: /home/hert5584/RStebbing/subdivision-regression-bin
However, when I try and run the example code, it cannot find the files listed in CMakeLists.txt (I know they are the right paths as otherwise CMake does not run).
I have tried running:
sudo make install
But get the following error:
make: *** No rule to make target 'install'. Stop.
Any ideas why this isn't working? Have the above steps Configured and Built the files?
The ordered CMake idiom to understand is:
The Configure step
The Generate step (This is often subsumed in the Configure step, and not mentioned explicitly, as in this case.)
The Build step (in which you actually compile/link your code into libraries/executables)
Take a look at this resource for information about the configure and generate stages.
You didn't appear to perform the steps to set CMake cache variables. For these you have to use CMake command line options (-D specifically). So run CMake as something like this instead to set all six variables:
cmake -DCOMMON_CPP_INCLUDE_DIR=/rstebbing/common/cp -DDOOSABIN_INCLUDE_DIR=...[More CMake Cache variables]... ../subdivision-regression/src
For building, try just running make without sudo or install:
make

How to add preprocessor definitions on CMake's command line? [duplicate]

I try to set a preprocessor macro in the command line of CMake. I've tried:
set generator="Visual Studio 8 2005"
set params=-D MY_MACRO=1
cmake.exe -G %generator% %params% ..\some_project
but it's neither defined when I compile nor can I find the name MY_MACRO in the files generated by CMake at all, except for CMakeCache.txt where it's present in the form:
MY_MACRO:UNINITIALIZED=1
How can I do it?
A good alternative would be to define a cmake option:
OPTION(DEFINE_MACRO "Option description" ON) # Enabled by default
Followed by a condition:
IF(DEFINE_MACRO)
ADD_DEFINITIONS(-DMACRO)
ENDIF(DEFINE_MACRO)
Then you can turn that option ON/OFF via command line with cmake using the -D flag. Example:
cmake -DDEFINE_MACRO=OFF ..
To make sure the compiler is receiving the definition right, you can call make in verbose mode and check for the macro being defined or not:
make VERBOSE=1
This is a good solution also because make will recompile your code when any of cmake options changes.
Try this: -D CMAKE_CXX_FLAGS=/DMY_MACRO=1
The motivation behind the question was to batch build 3rd party libraries, which is why I wanted to avoid modifying CMakeLists. So years later, even though I don't need that anymore, I figured out that it's easily achievable by means external to CMake:
Invoke CMake as usual, no special flags.
Then:
With MSVC: The compiler reads the CL environment variable to get extra command line arguments. So
set CL=/DMY_MACRO=1 %CL%
then invoke MSBuild to do its job.
With Makefiles: The generated makefiles use the CFLAGS and CXX_FLAGS variables as makefiles are expected to do. So the build can be started by
make CXX_FLAGS=-DMY_MACRO=1
or by setting the corresponding environment variables.
Unless you have a good reason not to, you should use ADD_DEFINITIONS(<name>=<value>[, ...]).
Just add the following line to your CMakeLists.txt:
ADD_DEFINITIONS("MY_MACRO=1")
CMake will take care of the syntax of the switches (be it -D<name>=<value>, or /D<name>=<value>).

Can I manually use CMake's cpp file dependency-scanner in my cmake code?

I am trying to add a custom target with CMake that executes one command for each given .cpp file. The command should only be re-executed when the source file itself or one of the included source files changes. AFAIK to achieve this I need a list of all the included files and add them to the DEPENDS option of the add_custom_command() calls that belong to my custom target.
So is there a built-in way to get that list of included files?
I know about the IMPLICIT_DEPENDS option of the add_custom_command() function but it only works for Makefile generators. I would like to make this work for all generators.
Thank you for your time
Edit:
As requested I will post some cmake code to show what I want to achieve.
I want to add a custom target, that runs clang-tidy on all the given .cpp files. When incrementally building the custom target the clang-tidy commands should be re-run whenever a .cpp file or one of its directly or indirectly included header files is changed. Just like re-runs of the compiler are handled.
# ----------------------------------------------------------------------------------------
# mainTargetName The name of the target that shall be analyzed
# files A list of all the main targets .cpp files
#
function( addStaticAnalysisTarget mainTargetName files )
set(targetName runStaticAnalysis_${mainTargetName})
set(command "clang-tidy-4.0 -checks=* -p ${CMAKE_BINARY_DIR}")
foreach( file ${files} )
get_filename_component( baseName ${file} NAME_WE)
set(stampFile ${CMAKE_CURRENT_BINARY_DIR}/analyze_${baseName}.stamp )
set(fullFile ${CMAKE_CURRENT_SOURCE_DIR}/${file})
set(commandWithFile "${command} ${fullFile}")
separate_arguments_for_platform( commandList ${commandWithFile})
add_custom_command(
OUTPUT ${stampFile}
DEPENDS "${fullFile}"
IMPLICIT_DEPENDS CXX "${fullFile}"
COMMAND ${commandList}
COMMAND cmake -E touch "${stampFile}" # without creating a file as a touch-stone the command will always be re-run.
WORKING_DIRECTORY ${CPPCODEBASE_ROOT_DIR}
COMMENT "${commandWithFile}"
VERBATIM
)
list(APPEND stampFiles ${stampFile})
endforeach()
set_source_files_properties(${stampFiles} PROPERTIES GENERATED TRUE) # make the stamp files known to cmake as generated files.
add_custom_target(
${targetName}
DEPENDS ${stampFiles}
)
endfunction()
The problem with that is, that it does not seem to work. When I change included files clang-tidy is not re-run for the affected files.
I used the "Unix Makefile" generator for this example so it should work at least with make. Any hints why it doesn't?
My hopes where that I could achieve the desired behavior for all generators by somehow getting the file-dependencies at cmake time and then adding them to the ''''DEPENDS'''' list. But the dependency scanning must be done each time the command is run, so it can not be done at cmake time. This means that the scanning must be implemented by cmake which it currently is not.
A guy with similar problems:
https://gitlab.kitware.com/cmake/cmake/issues/16830
Edit 2:
I think the problem that the IMPLICIT_DEPENDS option was not working was because I did not use correct filenames. I changed that in the code snipped, but I have not yet tested if it works in the project.
I think the answer to my question is ...
No, you can not use cmakes dependency scanner in the cmake code.
That makes sense, because this problem can not be solved at cmake time, because the dependencies of a .cpp file may change without cmake being re-run.
The problem must be solved within cmake itself at make time. This is done when using the IMPLICIT_DEPENDS option.
Also, I tried to solve a Problem that I did not really have, because at this point I can only run clang-tidy on linux anyways. However, clang-tidy may become available on windows as well and then I may have the problem again.
To sum the comments up:
Tambre stated that CMake is not a compiler and therefore can not do that.
I think this is wrong. According to this article, CMake can parse cpp include dependencies because make has no such dependency searcher itself. That was news to me, but I mostly live on Windows so I am not that familiar with make. It could also be possible that in the meantime make was extended to do its own dependency searching. Also this explains why the IMPLICIT_DEPENDS option is only available for make.
Florian pointed out that it is not necessary to create an own custom target for running clang-tidy. Instead, one can use the CXX_CLANG_TIDY target property to run clang-tidy for each file after compiling it. This means however, that static-analysis can not be separated from the build which could lead to inacceptable buildtimes.
There is the cmake -E cmake_depends command line, that could be used to retrieve dependencies at cmake time. But as stated above, I erroneously thought that I needed the dependencies at cmake time, while I needed them at runtime.
The IMPLICIT_DEPENDS options did not work because I had an error in my cmake code.

How to Use CCache with CMake?

I would like to do the following: If CCache is present in PATH, use "ccache g++" for compilation, else use g++. I tried writing a small my-cmake script containing
CC="ccache gcc" CXX="ccache g++" cmake $*
but it does not seem to work (running make still does not use ccache; I checked this using CMAKE_VERBOSE_MAKEFILE on).
Update:
As per this link I tried changing my script to
cmake -D CMAKE_CXX_COMPILER="ccache" -D CMAKE_CXX_COMPILER_ARG1="g++" -D CMAKE_C_COMPILER="ccache" -D CMAKE_C_COMPILER_ARG1="gcc" $*
but cmake bails out complaining that a test failed on using the compiler ccache (which can be expected).
As of CMAKE 3.4 you can do:
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
It is now possible to specify ccache as a launcher for compile commands and link commands (since cmake 2.8.0). That works for Makefile and Ninja generator. To do this, just set the following properties :
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) # Less useful to do it for linking, see edit2
endif(CCACHE_FOUND)
It is also possible to set these properties only for specific directories or targets.
For Ninja, this is possible since version 3.4.
For XCode, Craig Scott gives a workaround in his answer.
Edit : Thanks to uprego and Lekensteyn's comment, I edited the answer to check if ccache is available before using it as launcher and for which generators is it possible to use a compile launcher.
Edit2: #Emilio Cobos recommended to avoid doing that for the linking part as ccache doesn't improve linking speed and can mess with other types of cache like sccache
I personally have /usr/lib/ccache in my $PATH. This directory contains loads of symlinks for every possible name the compiler could be called from (like gcc and gcc-4.3), all pointing to ccache.
And I didn't even create the symlinks. That directory comes pre-filled when I install ccache on Debian.
From CMake 3.1, it is possible to use ccache with the Xcode generator and Ninja is supported from CMake 3.4 onwards. Ninja will honour RULE_LAUNCH_COMPILE just like the Unix Makefiles generator (so #Babcool's answer gets you there for Ninja too), but getting ccache working for the Xcode generator takes a little more work. The following article explains the method in detail, focussing on a general implementation which works for all three CMake generators and making no assumptions about setting up ccache symlinks or the underlying compiler used (it still lets CMake decide the compiler):
https://crascit.com/2016/04/09/using-ccache-with-cmake/
The general gist of the article is as follows. The start of your CMakeLists.txt file should be set up something like this:
cmake_minimum_required(VERSION 2.8)
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
# Support Unix Makefiles and Ninja
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
endif()
project(SomeProject)
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
if(RULE_LAUNCH_COMPILE AND CMAKE_GENERATOR STREQUAL "Xcode")
# Set up wrapper scripts
configure_file(launch-c.in launch-c)
configure_file(launch-cxx.in launch-cxx)
execute_process(COMMAND chmod a+rx
"${CMAKE_BINARY_DIR}/launch-c"
"${CMAKE_BINARY_DIR}/launch-cxx")
# Set Xcode project attributes to route compilation through our scripts
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
endif()
The two script template files launch-c.in and launch-cxx.in look like this (they should be in the same directory as the CMakeLists.txt file):
launch-c.in:
#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_C_COMPILER}" "$#"
launch-cxx.in:
#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_CXX_COMPILER}" "$#"
The above uses RULE_LAUNCH_COMPILE alone for Unix Makefiles and Ninja, but for the Xcode generator it relies on help from CMake's CMAKE_XCODE_ATTRIBUTE_... variables support. The setting of the CC and CXX user-defined Xcode attributes to control the compiler command and LD and LDPLUSPLUS for the linker command is not, as far as I can tell, a documented feature of Xcode projects, but it does seem to work. If anyone can confirm it is officially supported by Apple, I'll update the linked article and this answer accordingly.
I didn't like to set a symlink from g++ to ccache. And CXX="ccache g++" didn't work for me as some cmake test case wanted to have just the compiler program without attributes.
So I used a small bash script instead:
#!/bin/bash
ccache g++ "$#"
and saved it as an executable in /usr/bin/ccache-g++.
Then C configured cmake to use /usr/bin/ccache-g++ as C++ compiler.
This way it passes the cmake test cases and I feel more comfortable than having symlinks that I might forget about in 2 or 3 weeks and then maybe wonder if something doesn't work...
I verified the following works (source: this link):
CC="gcc" CXX="g++" cmake -D CMAKE_CXX_COMPILER="ccache" -D CMAKE_CXX_COMPILER_ARG1="g++" -D CMAKE_C_COMPILER="ccache" -D CMAKE_C_COMPILER_ARG1="gcc" $*
Update: I later realized that even this does not work. Strangely it works every alternate time (the other times cmake complains).
Let me add one important item that was not mentioned here before.
While bootstrapping a minimalistic build system from the ubuntu:18.04 docker image, I've found that order of installation makes a difference.
In my case ccache worked fine when calling gcc, but failed to catch invocations of the same compiler by the other names: cc and c++.
To fully install ccache, you need to make sure all compilers are installed first, or add a call to update-ccache symlinks to be safe.
sudo /usr/sbin/update-ccache-symlinks
export PATH="/usr/lib/ccache/:$PATH"```
... and then (due to updated symlinks) also calls to cc and c++ get caught!
In my opinion the best way is to symlink gcc,g++ to ccache, but if you would like to use within cmake, try this:
export CC="ccache gcc" CXX="ccache g++" cmake ...
Here are 2 methods I think are clean/robust, and also don't pollute your CMake code.
1.) Set environment variables
This method is nice since you don't have to individually set it up for each CMake project. The con is you may not want ccache for each CMake project.
# Requires CMake 3.17 (https://cmake.org/cmake/help/latest/envvar/CMAKE_LANG_COMPILER_LAUNCHER.html)
export CMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/ccache
export CMAKE_C_COMPILER_LAUNCHER=/usr/bin/ccache
2.) Pass in cache variables during project configuration
Con a bit annoying to do for each project. This can be negated by your IDE though.
# Requires CMake 3.4
$ cmake ... -D CMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/ccache \
-D CMAKE_C_COMPILER_LAUNCHER=/usr/bin/ccache
NOTE: It isn't really necessary to specify the full path.
If ccache is in your path you can just specify ccache instead.
export CMAKE_CXX_COMPILER_LAUNCHER=ccache
export CMAKE_C_COMPILER_LAUNCHER=ccache
It is extending #Nicolas answer.
Add following line to your cmake file:
list(PREPEND CMAKE_PROGRAM_PATH /usr/lib/ccache)
Or add it as argument to cmake configuration step:
cmake -DCMAKE_PROGRAM_PATH=/usr/lib/ccache