The CMake find_package() command sometimes prints a message, indication that the package has been found, and possibly the found version.
What are the condition(s) for this message being printed, other than QUIET not being used?
Note: Asking about CMake 3.22 in case it matters.
I've tested this with a few configurations and made the following observations:
The version script and the package configuration script or the find script can ignore quiet and print as much as they like; the presence of the QUIET option seems more like a suggestion than something enforced by cmake.
CMake itself seems to print the version number of unsuitable packages automatically, if no suitable package is found and
REQUIRED is specified, or
QUIET isn't specified
If a suitable version of the package is found, nothing is printed, regardless of whether REQUIRED and/or QUIET are present.
(Tested with the Windows version of CMake 3.22.1. The "basic signature" was used in all tests.)
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.
I am working on fixing some CMake files that have been made with a version newer than 3.10, but should have been coded to be compatible with 3.10.
There is a particular line:
add_compile_definitions(SOME_BOOL_VARIABLE)
that I can not figure out how to change to make it work with version 3.10. The add_definitions(SOME_BOOL_VARIABLE) command was the obvious thing that I tried, but produces errors with "no such file of directory".
From the CMake documentation, the functionality of add_definitions() and add_compile_definitions() is essentially the identical:
Adds preprocessor definitions to the compiler command line for targets in the current directory and below (whether added before or after this command is invoked).
The difference is in the syntax accepted for the command arguments. The older add_definitions() command requires the -D flag be prepended to each definition.
add_definitions(-DSOME_BOOL_VARIABLE)
The newer add_compile_definitions() command (available in CMake 3.12 and above) is cleaner, and does not require the -D flag prefix.
If you are refactoring your code, modern CMake encourages a target-centric approach. Whenever possible, you should prefer the target_compile_definitions() command to add preprocessor definitions to only those targets that require them.
target_compile_definitions(MyLibraryTarget PRIVATE SOME_BOOL_VARIABLE)
Following documentation regarding CMake package creation, it is stated that:
The find_dependency macro also sets ClimbingStats_FOUND to False if the dependency is not found, along with a diagnostic that the ClimbingStats package can not be used without the Stats package.
Yet, we are observing that this is only the case if ClimbingStats is requested from downstream without the REQUIRED argument.
Not required
find_package(ClimbingStats CONFIG)
Then we get the behaviour described above, i.e.:
Found package configuration file:
...
but it set ClimbingStats_FOUND to FALSE so the package "ClimbingStats" is considered to be NOT FOUND.
Reason given by package:
ClimbingStats could not be found because dependency Stats could not be found.
Required
If we make the ClimbingStats package required instead:
find_package(ClimbingStats CONFIG REQUIRED)
Then the error does not mention ClimbingStats at all
Could not find a package configuration file provided by "Stats" with any of
the following names:
StatsConfig.cmake
stats-config.cmake
Add the installation prefix of "Stats" to CMAKE_PREFIX_PATH or set
"Stats_DIR" to a directory containing one of the above files. If "Stats"
provides a separate development package or SDK, be sure it has been
installed.
Are we misunderstanding the documentation linked above, or is this a bug in CMake behaviour?
Is there a way to require a package and still get the descriptive error message (like in the first example) when its upstreams are not found?
Are we misunderstanding the documentation linked above, or is this a bug in CMake behavior?
Looks like a bug in CMake documentation.
The documentation for find_dependency states:
find_dependency forwards the correct parameters for QUIET and REQUIRED which were passed to the original find_package() call.
So, when outer find_package() was called with REQUIRED keyword, inner find_package() is called with that keyword too.
Exactly this behavior is observed in your case: the error message is generated by call
find_package(stats REQUIRED)
and the caller code has no chance to process its FALSE result for make the error message more descriptive.
Is there a way to require a package and still get the descriptive error message (like in the first example) when its upstreams are not found?
As far as I understand, more "native" behavior of find_dependency would be to not forward REQUIRED keyword to the inner find_package, but check the result of that find_package manually, and emit appropriate message if it is FALSE.
You may submit feature request to CMake tracker about that.
I just started using the Clion IDE. Maybe this is written somewhere but I haven't seen it in a Google search. If I put a message() call in my CMake script, where in Clion can I see the output? These message calls are the only way that I know how to debug my CMake scripts.
Use message(WARNING ...) instead of message(...). Warnings go to stderr.
Another possible workaround:
disable "cmake auto-reload" if it is enabled
after you changed something in your cmake file, don't trigger "Reload changes"
run/build your project
When clion starts a build, it realizes the cmake files are not up-to-date and reloads them, but like other build output it is displayed inside the Messages tab.
Warning and errors are displayed, but other messages are currently suppressed. However, there is a feature request concerning this issue.
As of CLion 2016.2.2,
Build #CL-162.1967.7, CLion is displaying CMake message(STATUS) output in its Messages tool window (Alt+0) during Build (Ctrl+F9) when a project is first built after changes to CMakeLists.txt. But as noted in the other answers, this output doesn't show in CLion's CMake tool window (as many would prefer).
Update: Above I wrote that CLion "is displaying message(STATUS) output." I now find that this occurs intermittently. #Michael wrote that this happens if you skip cmake reload after modifying your cmake file, but I've found CLion sometimes does not display any CMake output in its Messages tool window even under this condition. So far I haven't discovered the exact circumstances that make CLion show CMake message(STATUS) output, will report back here when/if I do.
Big Update: CLion opens 2016.3 EAP: user-defined literals, CMake output, C11 keywords completion and more. See in particular:CMake output window: a separate I think it fixes this whole problem: CLion 2016.3 EAP adds a new tab that contains CMake command output.
Of course, this is EAP, which comes with JetBrains' caveat:
It is important to distinguish EAP from traditional pre-release
software. Please note that the quality of EAP versions may at times be
way below even usual beta standards.
So use it at your own risk, but you may judge this a risk worth taking if you need the CMake debugging.
Is there a possibility to debug CMakeLists.txt files (at least listing of variables) except for the message statement?
There is no interactive debugger for CMake, however there are also the flags -Wdev, --debug-output and --trace which might help. Also remember to check the log files CMakeFiles\CMakeOutput.log and CMakeFiles\CMakeError.log which mainly collect outputs of processes called by CMake (for example while checking for presence of a type or header).
Since version 3.7, CMake now officially supports a "server mode" so integration in IDEs is likely to improve in the near future. Initial support exists both in Qt Creator and Visual Studio 2017 RC
You can try using the new CMake Script Debugger provided by the VisualGDB tool. It uses an open-source fork of CMake that supports stepping through CMakeLists.txt files, setting code/data breakpoints, evaluating/changing variables, etc.
There's a detailed step-by-step tutorial on the new debugger here
I like to use variable_watch to "debug" my CMakeLists.txt files. Just set in top of my script:
variable_watch(SOME_MY_VAR)
There are steveire's CMake Daemon Tools. I haven't used them myself, but they claim to offer possibilities for introspection that seem to be pretty close to a debugger.
Edit: They are now called CMake-server and are part of CMake 3.7.
Also, read about the env var VERBOSE: https://cmake.org/cmake/help/latest/envvar/VERBOSE.html
I used it this way:
export VERBOSE=defined
make
and got some more verbosity.
In other cases, edit CMakeLists.txt file to include the following line:
set(CMAKE_VERBOSE_MAKEFILE ON)
(Some post on this is https://bytefreaks.net/programming-2/make-building-with-cmake-verbose ).
Also, there are useful cmake options controlling debug output, see the manpage: https://cmake.org/cmake/help/latest/manual/cmake.1.html