How do I see the invocations caused by running cmake-generated makefiles? - cmake

How do I see the g++ invocations caused by running make? I am generating my makefile using cmake, so it is quite large.
Using verbose=1, cmake is still hiding the g++ invocations:
[ 0%] Building CXX object ui/CMakeFiles/ui.dir/mainwindow.cc.o
In file included from /Users/neil/nn/src/ui/mainwindow.h:6,
from /Users/neil/nn/src/ui/mainwindow.cc:9:
/Users/neil/nn/src/./core/globals.h:8:26: error: glog/logging.h: No such file or directory
I want to see if it's passing the right include directors to g++ because it's not finding glog/logging.h

Try:
make VERBOSE=TRUE

Peek in the CMakeFiles/ui.dir/ directory; you'll probably be interested in the flags.make file, though the non-includes portion of the g++ invocation is stored in build.make.

You can set the verbosity level with make VERBOSE="" (source).

Run CMake with -DCMAKE_VERBOSE_MAKEFILE="ON"
There is still a lot of noise though, so you may need to dump stdout & stderr to a file and grep for the name of the compiler...

From the shell prompt:
VERBOSE=1 make
(that is, run make with VERBOSE environment variable set to 1).

Related

how to use clang tidy in CMake

I would like to use CMake and clang-tidy in my project, however I see that build times are quite a bit higher when I use this in all the main cmake file:
set(CMAKE_CXX_CLANG_TIDY
clang-tidy-11;
-format-style='file';
-header-filter=${CMAKE_CURRENT_SOURCE_DIR};
)
It is working well, but I don't want to have this build-time penalty every time I build the project during development. Therefore I thought I would make a separate target that builds all, but uses clang-tidy. And when I do a regular debug or release build it does not do any checking. However I don't know how to do this in Cmake. Do I make a custom target with a command "cmake --build" with a target_set_property of CMAKE_CXX_CLANG_TIDY?
This feels rather clunky, so my question is, are there other ways to do this?
however I see that build times are quite a bit higher when I use this in all the main cmake file:
You're going to have to pay for the cost of running clang-tidy sometime or another. It's essentially running the first few phases of a compiler to analyze your code and look for errors.
Setting CMAKE_CXX_CLANG_TIDY runs clang-tidy in line with your build, as you have observed.
This feels rather clunky, so my question is, are there other ways to do this?
Yes. When using the Ninja or Makefile generators, you may set -DCMAKE_EXPORT_COMPILE_COMMANDS=ON at the command line. That will create a file called compile_commands.json in your build folder that the standalone clang-tidy can read.
In sum, at the command line, you would manually run:
$ cmake -G Ninja -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
$ clang-tidy-11 -format-style=file -header-filter=. -p build
The -p flag tells clang-tidy in which directory to find your compile_commands.json.

How do I get a verbose output for CMake?

I would like to investigate why I have this error:
$ cmake ..
-- The C compiler identification is unknown
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /cygdrive/c/Users/Ycr/Home/bin/arm-none-eabi-gcc
-- Check for working C compiler: /cygdrive/c/Users/Ycr/Home/bin/arm-none-eabi-gcc -- broken
CMake Error at /usr/share/cmake-3.6.2/Modules/CMakeTestCCompiler.cmake:61 (message):
The C compiler "/cygdrive/c/Users/Ycr/Home/bin/arm-none-eabi-gcc" is not
able to compile a simple test program.
Unfortunately after the error:
I have no idea of what CMake did. I don't have a verbose log of the command it executed.
The CMakeFiles/cmTC_e4aa4.dir was cleaned after the error, so I have no possibility to explore the issue myself.
How should I investigate such an error?
I tried to use the --debug-trycompile option. This time CMake creates a CMakeTmp folder which makes perfectly without errors. However, I still have this CMakeFiles/cmTC_e4aa4.dir that generates errors and even with the option CMake unlinks the folder.
Getting a Verbose Log
The try_compile() calls that CMake does in the beginning to test the compiler, gives a detailed error output on the console and writes it to
[your binary output directory]/CMakeFiles/CMakeError.log
I've checked the source code again and there is no CMake option that would give more a more detailed output for CMake's internal try_compile() calls.
You could just force the output to standard output by adding some variable_watch() calls to your main CMakeLists.txt before your project() call like:
variable_watch(__CMAKE_C_COMPILER_OUTPUT)
variable_watch(__CMAKE_CXX_COMPILER_OUTPUT)
Keeping the Temporary Files
To keep the temporary file of try_compile, add --debug-trycompile to the cmake command line.
But be aware that the multiple compiler tests at the beginning overwrite the artifacts of previous ones:
It may however change the results of the try-compiles as old junk from a previous try-compile may cause a different test to either pass or fail incorrectly. This option is best used for one try-compile at a time, and only when debugging.
References
How to keep generated temporary files?
CMake error at CMakeLists.txt:30 (project): No CMAKE_C_COMPILER could be found
For me, none of the log files in my output directory contained useful information from try_compile(), even when using --debug-trycompile.
I ended up using the OUTPUT_VARIABLE option to capture and then print the output like this:
try_compile(<options> OUTPUT_VARIABLE TRY_COMPILE_OUTPUT)
message(WARNING ${TRY_COMPILE_OUTPUT})

Why does `cmake --verbose=1` give verbose cmake output but `cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON` does not?

My goal was to see details about an invocation of g++ called directly by cmake from the command line. I do not care about the output of make for the purposes of this question.
According to the official FAQ and the accepted answer on a related question, I should make sure CMAKE_VERBOSE_MAKEFILE:BOOL=ON is set in my generated CMakeCache.txt, by e.g. passing the commandline flag -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON. When I did that it re-queried a bunch of properties, but gave no extra information about the invocation.
However, calling cmake with the flag --verbose=1 showed me exactly what I needed.
What are these two options doing differently? Is --verbose=1 deprecated or otherwise discouraged?
No, that's not what the accepted answer and the CMake FAQ you link say, otherwise I would be surprised.
Precisely, they don't say that you should modify CMakeCache.txt. Don't modify that file, it's not a good practice, since one can easily make mistakes.
If you instead have followed exactly what both sources say, i.e.
cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON .
make
or
cmake .
make VERBOSE=1
you would have seen a verbose output from the compilation and linking phases.
Alternatively, you should achieve the same effect if you put in your CMakeLists.txt file the following line:
set( CMAKE_VERBOSE_MAKEFILE on )
The fact that you do not see output in one of the cases might due to previously cached configurations.
I suggest you do if possible out-of-source builds so that in this case you can get rid of every CMake generated files and directories by just removing the build directory.
Then you could just recreate new configurations without interference from previously generated configurations and build files.
Of course, I might be wrong and you hit a bug, but it seems unlikely.
EDIT: That's because in the configuration phase you're not compiling, i.e. you are not using a Makefile, which is what the command line option set. It's not a verbose option for the cmake command itself at any stage (configuration, compiling, installing) of the project build. It will not show extra configuration info when you do cmake . but it should show you extra information when you run the make.
So CMAKE_VERBOSE_MAKEFILE is the wrong option to set if you want to get verbose output from CMake itself.

Why does CMake ignore exported CXX and CC environment variables?

I am running a CMake (3.4.3) like this as explained in the CMake FAQ's:
export CC="cc_args.py $PWD/../bin/gcc"
export CXX="cc_args.py $PWD/../bin/g++"
cmake -DCMAKE_BUILD_TYPE=Debug ..
However when I print CMAKE_CXX_COMPILER and CMAKE_C_COMPILER it still points to the system's default compilers in /usr/bin. It only works when I explicitly read-in the environment variables like this:
IF (NOT $ENV{CC} STREQUAL "")
SET(CMAKE_C_COMPILER $ENV{CC})
ENDIF ()
IF (NOT $ENV{CXX} STREQUAL "")
SET(CMAKE_CXX_COMPILER $ENV{CXX})
ENDIF ()
But even then the building fails with this message:
/bin/sh: 1: /home/peterg/bin/cc_args.py /home/peterg/Code/build/../bin/g++: not found
However I am certain that all paths are correct since executing just the path between the two colons outputs this as expected:
g++: fatal error: no input files
compilation terminated.
Update:
It seems the compiling process does not like spaces in the compiler paths. I've now created two scripts (one for GCC and one for CC) which wrap the commands and propagate the arguments and that seems to work. But it still seems I am doing something fundamentally wrong because CMake would also not accept the exported CC=proxy_script_cc.sh and GCC=proxy_script_gcc.sh variables without spaces by itself.
Turning my comment into an answer
Problem
I've given you code a try and could reproduce your problem
CMake Error at [...]/cmake-3.5/Modules/CMakeDetermineCXXCompiler.cmake:56 (message):
Could not find compiler set in environment variable CXX:
cc_args.py [... PWD ...]/../bin/g++.
If I look at CMakeDetermineCXXCompiler.cmake code and at get_filename_component() documentation, it just means that it didn't find cc_args.py in "the system search path" or relative to your binary output directory.
Solution
So it does work when you give a full path or a relative path to your binary output dir with something like
export CC="../cc_args.py ../bin/gcc"
export CXX="../cc_args.py ../bin/g++"
Alternative
CMake does allow to define "launcher scripts" e.g. with CMAKE_<LANG>_COMPILER_LAUNCHER
$ cmake -DCMAKE_BUILD_TYPE=Debug
-DCMAKE_C_COMPILER_LAUNCHER=../cc_args.py
-DCMAKE_CXX_COMPILER_LAUNCHER=../cc_args.py
..
References
How to Use CCache with CMake?
Save and reprint warnings for successfully-compiled files on subsequent builds?
Pass -DCMAKE_CXX_COMPILER=<path/to/compiler> to your CMake call. That's less error prone compared to fiddling with shell variables.

CMake uses NASM for linking, which fails.

I have an assembler file I want to compile in one run. However, the following code fails:
enable_language(ASM_NASM)
set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -f bin")
add_executable(test test.s)
CMake first runs: nasm -f bin -o test.s.o test.s
And then: nasm -f bin -o test test.s.o
The last step fails as test.s.o is already a binary file.
My question is: How do I disable the first compilation step?
There seems to be a bug in nasm module for cmake. Cmake calls nasm for linking which is obviously wrong (that is why you see two calls to nasm). Hotfix is to set
set(CMAKE_ASM_NASM_LINK_EXECUTABLE "ld <FLAGS> <CMAKE_ASM_NASM_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
I hope you solved your problem, however I feel like I need to post here my solution just because that's the only mention of this problem and it doesn't seem to be solved by the only given answer.
Indeed, nasm can compile sources directly to .bin format (and that's really helpful for boot sectors). The problem is that Cmake doesn't seem to support single stage compilation and linking and it tries to link resulting .bin file, which is imposseible, so the execution fails no matter which linker we try to use.
The only solution that came to my mind was replacing add_executable(NAME SOURCE) with add_library(NAME OBJECT SOURCE). Object libraris are not linked, so the file produced will be exactly what we are looking for.
And here is the complete solution:
enable_language(ASM_NASM)
set(CMAKE_ASM_NASM_OBJECT_FORMAT bin)
add_compile_options("$<$<COMPILE_LANGUAGE:ASM_NASM>:-f bin>")
add_library(lib OBJECT core/boot/loader.asm)
The tricky part: the generated file will be hidden within cmake output dir. It sould be referenced with $<TARGET_OBJECTS:lib>.
Enjoy!