I know that there is a flag to use clang-tidy with CMake:
https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_CLANG_TIDY.html
Is there a way that I can check the version of clang-tidy? I am thinking something along the line of CMAKE_MAJOR_VERSION or CMAKE_MINOR_VERSION, but includes the information for clang-tidy when integrating the work flow.
If not, what are my options to hack around it?
Related
Prepare the following (erroneous) CMakeLists.txt file:
cmake_minimum_required(VERSION 3.10)
project(foo)
add_executable(foo foo.cpp)
add_compile_definitions(BAR=123)
add_compile_definitions is new in CMake 3.12, so processing the above file in CMake 3.10 will result in an error.
CMake Error at CMakeLists.txt:4 (add_compile_definitions):
Unknown CMake command "add_compile_definitions".
However, using CMake 3.12 or later, no errors or warnings are output.
Therefore, as long as you are using CMake 3.12 or later, you will not notice the error.
(In this case, we can use add_compile_options instead of add_compile_definitions, but that is not the main issue.)
You may say, "you shouldn't write cmake_minimum_required(VERSION 3.10) because you are not using CMake 3.10, you should write the version you are actually using".
However, there may be cases where modifications are made to an existing code base.
Is there any way to realize that when you do so, you inadvertently write something that is not usable in the specified version?
For example, is there a tool like lint that can check for features that are not available in a given version?
Currently, is the only way to do this is to install the specified version of CMake?
You have to test with the minimum required version. But even if no error occurs, your test might be incomplete, because you only test these parts of the code, that you are actually running. If your setup does not provide an optional dependency or you did not set a flag, the code executed for this dependency or flag will not be tested.
Depending on your setup, it makes sense to have a continuous testing (GitLab, Jenkins, GitHub actions) that runs your CMake code with CMake in the minimum required version. Then you get early warning that someone added code that is above the required CMake version and you should revert it or increase the requirements.
It is really not a satisfying answer and in general not a satisfying situation.
usr1234567 wrote a good answer, but let me add an additional point:
I think you (and many others; you're in good company) are misunderstanding the guarantee made by cmake_minimum_required(VERSION X). Many people believe it means the following:
This project will build with version X.
That is not the case at all. What it actually promises is:
If this project builds with version X, then it will build on versions Y > X.
That is to say, it is a backwards compatibility guarantee, not a forwards compatibility guarantee. You cannot author a project with a newer version of CMake and expect it to work with older versions without testing it.
In my CMake package, there is a call to find_package. This succeeds, great! However, it turns out to be the wrong version of the package. I now want to go and delete that package. However, I have no idea where the heck it is on my system, nor where the -config.cmake file is that CMake must have found somewhere. Is there a way to get find_package to give me this information? Or at least verbosely tell me where it is searching?
I though this might be in the variable CMAKE_MODULE_PATH, however that is empty for me. So I guess it is in the default paths somewhere. But CMake searches a lot of places for packages, and I didn't find it in the usual locations that I remember.
Ah ok, I found a solution here:
https://riptutorial.com/cmake/example/21128/debug-find-package---errors
Turns out there is a special debug flag to make find_package tell you where it is searching:
cmake -D CMAKE_FIND_DEBUG_MODE=ON ..
As of CMake 3.17, the cmake command line has native support for printing the search directories for all of the CMake find_* commands. Use the --debug-find flag:
cmake --debug-find ..
All I can say about those commands right now is pkg_search_module has some odd usage, where I have to write the dependency that I would like to have two times. instead of just once like in find_package
pkg_search_module(ZLIB REQUIRED zlib)
#seriously two times zlib and once in only capital caseā½
find_package(ZLIB)
#much cleaner but for some odd reason find_package does not work all the time
pkg_search_module uses the pkg-config tool to determine the location of the requested library. This is mostly useful on systems where pkg-config is already in use, so you do not need to replicate all the information for CMake. Note that this approach has potential portability issues, since it requires pkg-config to be setup correctly on the build machine.
find_package on the other hand is CMake's very own mechanism for solving the same problem. For this to work you either need a CMake find script for the requested library (CMake already ships with a couple of those, but you can easily write your own) or alternatively a package config script provided by the requested library itself. In either case you might have to adjust your CMAKE_MODULE_PATH for CMake to be able to find the respective script.
The choice which one to use is quite simple:
Always prefer package config scripts, if provided by the library.
Use find scripts as a fallback for libraries that are not aware of CMake.
Use pkg_search_module if you want to exploit synergies with pkg-config. In particular, note that it is possible to implement a find script using pkg_search_module as one method of obtaining the required information.
I'm thinking to write a simple configure script (similar to autoconf one) which execs cmake. But before doing that I want to check if anyone knows of such an effort already. I wasn't able to find anything on google.
It should be able to support the basic autoconf configure flags (prefix, exec-prefix, bindir mostly).
Reason to do it is of course that there's a certain user expectancy to be able to do ./configure && make
Also not really an answer but too long for a comment:
After reading up about cmake / cpack, I can at least tell you this. Cmake expects to be present on the platform. Therefore CPack cannot generate the same type of ./configure scripts as autotools. The Autotools expect some shell to be present, which is essentially the same as cmake to be present. However since cmake also targets the Win environment, it cannot rely on a shell. That being said, CPack can provide source packages, which need to be installed with cmake in the usual manner.
Also this does not solve your problem, I do not recommend to write a tool for cmake. Cmake is able to use all these type of prefixes you are interested in. If the user wants to compile your program from scratch, he has to know at least the basics (e.g. setting variables) of your build system. This is also true for autotools. If you want to spare him the pain, you can provide binary .sh, .deb or .rpm packages, which can be easily built with cmake / cpack.
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.