Compile a single file under CMake project? - c++

I'm developing a C++ project which is going to be enclosed on a bigger one.
I've seen that on the bigger project (is a Qt application and it's being generated from qmake) I am able to compile a single file from the linux command line, just entering the relative path to the specific file as an argument to make.
On the other hand, I'm using CMake for my own project. When I modify some code for a compilation unit and I have to modify its header file, I have to wait a long time to compile its dependencies and then its own source file. But there are some situations in which I would prefer to check whether the source code in the *.cc file is compilable without errors.
Is there a way to generate a Makefile from CMake the way qmake does this? Switching to qmake is not an option anymore.

You do not have to add extra custom targets to your CMake scripts, as the Makefiles generated by CMake already contain .o targets for each .cc file. E.g. if you have a source file called mySourceFile.cc, there will be a Makefile in your build directory that defines a target called <Some Path>/mySourceFile.cc.o. If you cd into your build directory, you can use grep or ack-grep to locate the Makefile that defines this target, then cd into that Makefile's directory and build it.
E.g. suppose the command ack-grep mySourceFile.cc.o prints something like:
foo/bar/Makefile
119:x/y/z/mySourceFile.o: x/y/z/mySourceFile.cc.o
123:x/y/z/mySourceFile.cc.o:
124: # recipe for building target
Then you can build mySourceFile.cc.o by doing:
cd foo/bar && make x/y/z/mySourceFile.cc.o

CMake doesn't have a generic built-in way of doing this (it's an open issue), but if you're using the Ninja generator, you can can use a special Ninja syntax for building just the direct outputs of a given source file. For example, to compile just foo.o you would use:
ninja /path/to/foo.cpp^

Not out-of-the box. CMake does not expose those "internal" makefile rules in the main makefile.
You can do this only if you consider what kind of file structure CMake uses internally. You can e.g. for compiling a single .obj files using CMake generated makefiles call
make -f CMakeFiles/myProg.dir/build.make CMakeFiles/myProg.dir/main.cc.obj
when you have something like
cmake_minimum_required(VERSION 3.1)
project(myProg CXX)
file(WRITE "main.cc" "int main()\n{\nreturn 0;\n}")
add_executable(myProg main.cc)

To build src/foo.cpp alone:
cmake --build . --target src/foo.cpp.o

No, CMake does not offer built-in support to compile single files.
You have to add a target for each object file, maybe by a function iterating over all files of a directory.

Others have suggested ways to find the target name (ending in .cpp.o) from the .cpp filename, but if you already know the name of a target that will trigger compilation of the .cpp file and you're using ninja this suggestion should be easier.
First build the target:
ninja TriggersCppCompilationLib
Assuming your file was changed or was not yet built, ninja will print the full target name. When you see the name come up, hit enter so it is not overwritten. Then simply copy the name from the terminal (e.g. using tmux copy mode).

Related

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.

clion run cmake on each build

I am not sure if its possible to do this with clion, I was testing out the program and enjoy using it to write c code because the ctags and etags support is really nice.
I am copying some files over from the cmake source tree to the bin location on each build. While using clion if I update some of the files that I am copying the results aren't updated within clion.
If I instead go back to the terminal and just run the typical cmake steps
cmake ../ && make && bin/./program
that copies the updated files and I am able to see my results.
This is the CMake command that I am using in my build.
FILE(COPY ${CMAKE_CURRENT_SOURCE_DIR}/resources/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/bin/resources/)
I might be able to restructure the cmake command to make it copy every time or it might just be a clion issue. I am unsure and would like to be able to take care of this all from within clion, instead of going back to the terminal to run the cmake command for updates to take effect.
If you want CMake to make some action whenever some file is changed, you should create a rule using add_custom_command and pass file via DEPENDS argument. Note, that only file-level dependencies are supported by CMake, for make dependency on directory you need to list all files in it.
# Collect list of files within directory.
FILES(GLOB files_list RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/resources/
"${CMAKE_CURRENT_SOURCE_DIR}/resources/*")
# This will contain full paths to files in binary directory.
set(binary_files_list)
foreach(file ${files_list})
set(source_file ${CMAKE_CURRENT_SOURCE_DIR}/resources/${file})
set(binary_file ${CMAKE_CURRENT_BINARY_DIR}/bin/resources/${file})
add_custom_command(OUTPUT ${binary_file}
COMMAND cmake -E ${source_file} ${binary_file}
DEPENDS ${source_file})
list(APPEND binary_files_list ${binary_file})
endforeach()
add_custom_target(resources DEPENDS ${binary_files_list})
Note, that in case of adding/removing files you should to run cmake explicitely. That's why hardcoded files list is preferred to GLOBing.

How to print/show included directories in CMakeList

I am trying to build a trivial proof of concept project using CMake, and I am rapidly getting tired of it - to the point that I think it may have been a better idea to handcraft my own damn Makefile.
I have a directory structure that looks something like this:
project:
/extproj
/src/file.cpp
/include/file1.h
My CMakeLists.txt file contains the following section, which I, having read the CMake documentation, rather naively believed, will be specifying the include directories for the project:
INCLUDE_DIRECTORIES (include/
extproj/sdk/math/linearalg/
extproj/sdk/math/nonlinearsolvers/
)
I am trying to build it using the following command
COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${ALL_SOURCES}
Where ${ALL_SOURCES} is a list variable that contains all the C++ files I need to compile. I have verified that this variable contains the correct files.
I can't however, for the life of me, work out what on earth is being passed to the compiler as the include directories.
I searched online, and so a post that recommended using get_directory_properties. I tried that and of course CMake immediately failed to generate the Makefile and complained:
Unknown CMake command "get_directory_properties".
When I create a Makefile and run make on it, the compiler barfs immediately, with the error message:
/path/to/project/src/file1.cpp:1:10: fatal error: 'file1.h' file not
found
Is there ANY WAY, I can find out what on earth is being used as the include paths being passed to my compiler?
I believe the correct way to compile the source files is using
add_executable(executableName ${SRCS}. Then the directories added using include_directories(...) get passed to the compiler automatically.
If you are using a custom command to compile you need to change your CMakeLists.txt file.
set(MY_INCLUDE_DIRS_FLAGS "-Iinclude/ -Iextproj/sdk/math/linearalg/ -Iextproj/sdk/mat/nonlinearsolvers/")
set(MY_COMPILE_COMMAND ${CMAKE_CXX_COMPILER} ${MY_INCLUDE_DIRS_FLAGS} ${CMAKE_CXX_FLAGS} ${ALL_SOURCES}

cmake: read and compile dynamically-generated list of cpp files

I have a custom tool that processes a given list of IDL files and produces a number of .cpp and .h files as output. I want to add those files to the list of things to compile in my CMakeLists, and also model the dependencies those files have on the IDL.
To keep things simple, I will state that any change to any of the IDL files should trigger a regeneration of all cpp/h.
I have a custom command that takes care of running the generator tool and listing all the IDL files as dependencies.
My issue is getting the subsequent list of cpp/h files into cmake at build-time. It is not possible to infer from the name of the IDL files what cpp files will be generated. My generator tool will, however, output the list of generated files to a text file.
So my question is: how do I instruct cmake to "read from this text file and add the contents as extra source and header files to be compiled", also bearing in mind that the said text file only exists during a certain point of the build?
CMake needs to be able to infer the names of all .cpp files participating in the build at configure time. It is not possible to add files afterwards without re-running CMake.
One possible approach would be to use a two-phase CMake build: Instead of building the generated source files directly from your main project, you create a separate CMake project for building just the generated sources.
Then in your main CMake project you add a custom target that runs after the code generation and invokes CMake to both configure and build the generated files project.
The disadvantage here is that the generated files no longer appear as part of the main project. Also some trickery is required if you don't want to rebuild the generated sources every time - custom targets are always considered out-of-date, so you might want to use a script here that only runs CMake on the subproject if the generated files changed.
This is a few years late but this works just fine:
#run whatever tool that generates the cpp files
execute_process(COMMAND "./your_tool.sh")
#read files from files.txt and make a cmake 'list' out of them
file(READ "files.txt" SOURCES)
#found this technique to build the cmake list here:
#http://public.kitware.com/pipermail/cmake/2007-May/014236.html
#maybe there is a better way...
STRING(REGEX REPLACE ";" "\\\\;" SOURCES "${SOURCES}")
STRING(REGEX REPLACE "\n" ";" SOURCES "${SOURCES}")
#at this point you have your source files inside ${SOURCES}
#build a static library...?
add_library(mylib STATIC ${SOURCES})
There is a function that build the list directly from file:
file(STRINGS <filename> <variable> [<options>...])
source: https://cmake.org/cmake/help/v3.11/command/file.html

How do I tell cmake where to output its build data?

How do I tell cmake where it should output its build data?
Let's say I have a dir with the source code called src/,
and then since cmake outputs a lot of files I would like him to put all of that in
a dir called build/.
BUT I would like him to put the generated Makefile in the project root,
so I don't have to go into the build dir to build the application.
Is this possible with cmake?
I have managed to get the cmake out put if I fun cmake in the build dir like this:
cd build/
cmake ../src/
make
./hello
But it would be nice to stay in the project root and type something like this
cmake
make
./hello
I guess that I need to put a CMakeList.txt in the project root with some magic commands telling him where he could put the object files and where he can find the source code.
Thanks
Update:
Since my question is a little bit vague.
After I have run the cmake commands this is how I would like my tree to look like:
src/CMakeLists.txt
src/hello.c
src/hello.h
build/CMakeCache.txt
build/CMakeFiles/
build/cmake_install.cmake
CMakeLists.txt
Makefile
So the question is how should the CMakeLists.txt look like in this setup.
CMakeLists.txt
src/CMakeLists.txt
But maybe that is not possible?
BUT I would like him to put the generated Makefile in the project root, so I don't have to go into the build
dir to build the application.
cmake not designed for that, as I know,
BUT you can stay in the project root and type:
make -C build
./hello
with custom build rules or set_target_properties,
you can force cmake to put result executable to
sources directory or you can use
./build/hello
Type "cd build && cmake .." you need only once,
after that make will automaticaly start cmake, if something
changed.
cmake wants you to have a fresh build directory.
Okay, i get what you want. I think, you can achieve this with some machinery in CMakeLists.txt. Of course, it's not option if you are not project developer.
In root CMakeLists.txt you can add file(WRITE ...) command, which would write Makefile into ${CMAKE_SOURCE_DIR}. This Makefile would contain these commands for every target:
<target>:
cd ${CMAKE_BUILD_DIR} && ${CMAKE_MAKE_PROGRAM} <target>
So, now you can run make from source dir and it will build your project in build dir.
Simply use
cmake .
make
in your src directory. The (.) dot on unix systems addresses the current directory. Keep in mind doing so is actually not recommended since there will be a lot of build files in your src directory you'll have to clean up afterwards or at release time.