cmake "make run" - cmake

I'm a little unsure of terminology in this problem domain, which is an issue when I try to search for things.
I'm using CMake for my build process. I'd like to make a Makefile target such that I can use make run to run a given process (specifically, the one I've just built with make). I realize I could just make a shell script, or just run the command by typing it out. If I was writing a Makefile myself, I'd do this like so:
run:
./path/to/binary
I don't ever write a Makefile myself, though - that's generated by cmake - and I'm not sure what to put in my CMakeLists.txt to get it to generate the desired make run target.
I've found the cmake command 'execute_process', but that doesn't seem to be what I'm after - I don't want to actually run anything during the build process.
Extra: In addition, I'd love to be able to do something like the following:
CMAKE_COMMAND_ADD_MAKEFILE_TARGET ( ${CMAKE_PROJECT_DIR}/binary )
That is, add the path/to/binary using a cmake variable, if that's possible.

You are looking for add_custom_target. For instance:
add_custom_target(run
COMMAND binary
DEPENDS binary
WORKING_DIRECTORY ${CMAKE_PROJECT_DIR}
)

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 use ExternalProject_Add to get a simple make invocation?

I need ExternalProject_Add to invoke just one command for an external project whose makefile does all the needed steps. I need to have that command be "make WITH_OPTION1=no WITH_OPTION2=no" in the directory at the top of the external project's source tree. This is one of a few dozen external projects we use. Most of them fit the model of 'configure; make; make install' but a good third don't and this is one that I thought would be easy.
If I try to have the make command invoked like this:
ExternalProject_Add(build-example
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/example"
DEPENDS ""
SOURCE_DIR "${PROJECT_TOPDIR}/External/example"
CONFIGURE_COMMAND ""
BUILD_COMMAND COMMAND make WITH_OPTION1=no WITH_OPTION2=no
INSTALL_COMMAND "")
The resulting make step is done from the wrong directory and therefore the Makefile is not found.
If I add a -C option to the make command it seems to use the right directory, but it ignores the WITH_OPTION stuff. That doesn't compile properly, because those features use things I don't want to provide, and if it did work, I still don't want those features.
If I then add quotes around the entire desired make command, it goes wrong. Apparently the command is passed to 'sh' in such a way that sh fails.
If I use a mechanism to pass the command into a 'configure-file' step and invoke that file from the BUILD_COMMAND, then CMake actually tries to use a broken CMakeLists.txt file that's in the external project, and I wonder what makes CMake think that it should do so.
I just want to invoke the makefile properly, using CMake to organize that build within the dozens of other builds that have to be done to build the complete project.

CMake build & link to library without installing to /usr/local or elsewhere

I'm trying to include an external library in a build environment that uses CMake. I'm not trying to install it on the local system (in fact I'd rather not do that, I don't want /usr/local clogged up with all kinds of libraries); I'd just like to have the resulting libxml2.a available for linking with my executable. I can build it fine with the following in CMakeLists.txt:
set (LIBXML_PATH ${MY_SOURCE_DIR}/libxml2-2.9.1)
add_custom_target (build_libxml ALL
COMMENT "Building libxml"
COMMAND ./configure --prefix=/tmp
COMMAND make
WORKING_DIRECTORY ${LIBXML_PATH}
)
But I'm still having trouble with the following:
1) Is this the right approach in the first place, for the general purpose of getting libraries built with configure and make into a CMake environment?
2) How do I get the resulting library (i.e. libxml2.a) under my build output directory?
3) How can I link to that library for my executable builds?
I tried a fiddly solution with
ADD_LIBRARY( xml2 STATIC libxml2.a )
but it seems like there must be a better way than hauling a whole library's contents into… a library.
Thanks.
You need to make it clearer to CMake what is going on here. All it can see now is that you have some custom command that it will run every time. Instead of using add_custom_target with COMMAND, I've found it better to use add_custom_command.
Something like this:
set (LIBXML_PATH ${MY_SOURCE_DIR}/libxml2-2.9.1)
add_custom_command(
OUTPUT libxml2.a
COMMENT "Building libxml"
COMMAND ./configure --prefix=/tmp
COMMAND make
WORKING_DIRECTORY ${LIBXML_PATH}
)
target_link_libraries(your-program libxml2.a)
By doing it this way, CMake can understand that your custom command's essential product is libxml2.a, and when CMake sees something depending on that, it will run the command (if the library doesn't exist already).

CMake Header Generator Updates

In CMake I currently have a simple Python script to generate a header, but if I update the script itself CMake won't re-run the script. Is there a way I can get CMake to do this?
It seems you are directly invoking your code generation script when cmake is run. While it is possible solution but it is definitely not a right way to use code generators with cmake.
I recommend you to use add_custom_command for your case:
add_custom_command(
OUTPUT generated.h
COMMAND ${PYTHON_EXECUTABLE} generator.py
DEPENDS generator.py
)
And next you can simple put your header to the list of source files passed to add_library/add_executable commands. cmake will automatically track all the dependencies and invoke your script.
Term DEPENDS generator.py informs cmake that it should regenerate header if script is changed.
With this approach file generated.h will be generated only at build time (when you run make or execute a build command in IDE). In contrast if you are running your script at cmake time (with execute_process command) then you have to rerun cmake to regenerate your file. Which is possible but you need to use some tricks to introduce a non-standard dependency.

CMake Configure File Build Rule

I'm using CMake for my build system and in the project, we will have a bunch of configuration files. Some of them will just need to be copied over, some will need to be modified per computer. I'm currently using CMake's "configure_file" command to copy/replace parts of the file. This works great, and I love how I can use any variable from CMake in the configure routine.
But if you change the original file, CMake will not pick this up and you have to rerun cmake for it to configure the directory. When I run "make", I want it to pick up that I've changed the file and rerun configure.
It will also reconfigure files always, even if the file it is overwriting is newer. I want it to act like a custom target.
I think I can do this with add_custom_command, but I don't think I can run a CMake command from add_custom_command. So is there anyway to duplicate the behaviour that configure_file does in CMake?
I recently upgraded to CMake 2.8. It seems like it automatically has the exact behavior I wanted.
I do not think this has an easy answer. I see two options:
To trigger a re-run of cmake if an input changes, you might be able to make your input file depend on CMakeLists.txt.
To run a cmake command as part of and add_custom_command, there is the variable ${CMAKE_COMMAND}, which will give you the path to the running cmake. You could, as part of the configure step, generate a fragment of CMake code (that calls configure_file) that is invoked using the -P option. Either pass substitutions on the command line using -D, or write them to the CMake fragment.