Why emits CMake a CMP0022 warning although not using LINK_INTERFACE_LIBRARIES? - cmake

In my whole code I never use LINK_INTERFACE_LIBRARIES or something similar. All install, export and link_* command are used without.The only somewhat similar occurrence I was able to grep was in the build directory in the file lib/CMakeFiles/Export/lib/cmake/mylib-targets-noconfig.cmake:
IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "CXX"
IMPORTED_LINK_INTERFACE_LIBRARIES_NOCONFIG
Still, I get a CMP0022 warning:
CMake Warning (dev) in lib/CMakeLists.txt: Policy CMP0022 is not set:
INTERFACE_LINK_LIBRARIES defines the link interface. Run "cmake
--help-policy CMP0022" for policy details. Use the cmake_policy command to set the policy and suppress this warning.
Target "mylib" has an INTERFACE_LINK_LIBRARIES property. This should
be preferred as the source of the link interface for this library but
because CMP0022 is not set CMake is ignoring the property and using
the link implementation as the link interface instead.
INTERFACE_LINK_LIBRARIES:
This happens when I link an external library to mylib. When I use CMake 2.8.12.1 which improved the handling of CMP0022 compared to 2.8.12 the number of warnings is massively reduced and I get only one warning per external library.
What causes the warning? From the documentation I don't get it.
What should I do to get rid of this warning? Is this compatible to older versions?

CMake 2.8.12.1 was released to address this issue. Please try that version.

In the meantime there was a similar question posted to the CMake mailing list. Stephen Kelly answered there are three options. [1, 2] The one I liked most uses LINK_PRIVATE and LINK_PUBLIC. But it is only backwards compatible to CMake 2.8.9.

Try putting this block:
IF(COMMAND CMAKE_POLICY)
CMAKE_POLICY(SET ???? OLD)
CMAKE_POLICY(SET ???? OLD)
ENDIF(COMMAND CMAKE_POLICY)
WHERE ???? is the name of the offending policy
I haven't read much about this yet, but I think is because they added a mechanism to set the target properties to avoid ambiguities when dealing with different targets, in any case, if a new version of CMake warns you about some policy you can set that policy to an old behavior.
https://cmake.org/cmake/help/v3.0/policy/CMP0022.html

Related

How can I ignore all cmake dev warnings from subdirectories?

I am using a few external libraries that are included as git submodules using the add_subdirectory command. Some of them are using old versions of cmake and they're issuing warnings about policies CMP0048 and CMP0077.
Is there a way to turn off all cmake warnings for these libraries?
I've tried explicitly setting the policies to OLD before including the projects but it didn't help.
I'd prefer not to edit any files in the git submodule because then there would be extra steps when someone has to clone my project's repo and build it on their machine.
I know this is a old questions, but in case someone stumbles upon the same problem, here are my findings.
Why didn't your attempts work?
Setting the policies before the add_subdirectory() call won't work, because cmake_minimum_required() implicitly set a specific set of policies, depending on the required version, which might override the set policies. Also, setting them explicitly to OLD has no effect even if they weren't overridden, since there is no distinction between being OLD because it is the default for that version or because it was explicitly set. A warning is issued in both cases, because as the documentation of every policy states, the old behavior is deprecated by definition.
Possible Solutions
I can think of the following solutions:
Use the undocumented variable CMAKE_SUPPRESS_DEVELOPER_WARNINGS, which is also set when passing -Wno-dev on the command line (see cmake.cxx). Since you probably don't want this to have an influence on your project and disable all developer warning there as well, you should restore the original value after the add_subdirectory() call:
set(no_dev_warnings_backup "$CACHE{CMAKE_SUPPRESS_DEVELOPER_WARNINGS}")
set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS ON CACHE INTERNAL "" FORCE)
add_subdirectory(...)
set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS ${no_dev_warnings_backup} CACHE INTERNAL "" FORCE)
The variable might be undocumented and therefore not that reliable as documented variables, but I wouldn't worry too much about it. It has been around since the CMake 2.x days and is unlikely to go anywhere.
Set CMAKE_POLICY_DEFAULT_CMP<NNNN> to NEW:
set(CMAKE_POLICY_DEFAULT_CMP0048 "NEW")
set(CMAKE_POLICY_DEFAULT_CMP0077 "NEW")
add_subdirectory(...)
Note that this doesn't just disable the warnings, but alters how CMake processes the affected CMakeLists.txt files. This might break the build of your external libraries!
Use CMAKE_PROJECT__INCLUDE or one of its related variables to inject some CMake code into the build of the external libraries. The injected code could then call cmake_policy(SET CMP<NNNN> NEW) to override the policy. Note that just like the 2. solution, this could break the build!
Instead of a git submodule, you could use FetchContent which fetches the external libraries and calls add_subdirectory() one them. Since FetchContent is quite related to ExternalProject it allows to patch the retrieved sources, so you can fix/customize the build of the external libraries:
include(FetchContent)
find_package(Patch REQUIRED)
FetchContent_Declare(myextlib
GIT_REPOSITORY <url>
GIT_TAG <tag_or_hash>
PATCH_COMMAND "${Patch_EXECUTABLE}" -p1 < path/to/myextlib.patch
)
FetchContent_MakeAvailable(myextlib)
More on diffs and patches can be found here. Alternatively, you also use git apply as patch command, since you use Git anyway.
Recommendations
I would recommend either 1 or 4. Approach 4 is the most flexible, since you could improve the build in other aspects as well, if necessary, but it is also the most involved one, since whenever you bump the version of your external libraries you also need to take care of your patches and check whether they still work etc. In case you don't need that flexibility and only care about disabling warnings, approach 1 would be the most straight forward solution.

What are AUTHOR_WARNING messages in cmake?

CMake's message() directive has an AUTHOR_WARNING mode, however the documentation (v3.11.1) doesn't say anything on what the differences are between an AUTHOR_WARNING and a regular WARNING.
The documentation states these modes and their description as follows:
WARNING = CMake Warning, continue processing
AUTHOR_WARNING = CMake Warning (dev), continue processing
Author warning are meant to warn the author (developer) of a CMakeLists.txt, but not a user of it. With the CMake arguments -Wdev, -Wno-dev, and -Werror=dev you have control over how to these warnings are handled (documentation).
The idea is that users should not be scared or annoyed by warnings they cannot change anyway, because they are not supposed to modify this part (of potentially third-party) code. This includes programmers who include CMake code from others and don't want to warned about issues they cannot fix within their code.
Since CMake 3.5, the dev flags also suppress or enable deprecation warnings, following the spirit of warning only people who can fix the underlying issues.

Is it possible to alter CMAKE_MODULE_PATH from CMake commandline?

Edit: The accepted answer actually shows that it is pretty normally possible to set CMAKE_MODULE_PATH as any other CMake variable e.g. via the -DCMAKE_MODULE_PATH path CLI parameter. It seems that in my case there is some included CMake script that calls set(CMAKE_MODULE_PATH /library_path), which erases all previous paths set to the variable. That's why I couldn't get the variable to do what I wanted it to do. I'll leave the question here in case anybody else faces this kind of situation.
I'm building a (3rd party) project that uses the Protobuf library (but this question is general). My system has a system-wide install of a newer version of Protobuf than the project is compatible with. So I've downloaded and compiled from source an older version of Protobuf.
The project uses CMake, and in its CMakeLists.txt, there is:
find_package(Protobuf REQUIRED)
Which, however, finds the (incompatible) system install. Of course, CMake doesn't know about my custom build of Protobuf. But how do I tell it?
I've created a FindProtobuf.cmake file in, say, ~/usr/share/cmake-3.0/Modules/ and want the build process to use this one for finding Protobuf. But I haven't succeeded forcing CMake to pick up this one and not the system one. I think the reason is quite obvious from the CMake docs of find_package:
The command has two modes by which it searches for packages: “Module” mode and “Config” mode. Module mode is available when the command is invoked with the above reduced signature. CMake searches for a file called Find<package>.cmake in the CMAKE_MODULE_PATH followed by the CMake installation. If the file is found, it is read and processed by CMake. ... If no module is found and the MODULE option is not given the command proceeds to Config mode.
So until I succeed to change CMAKE_MODULE_PATH, CMake will just pick up the FindProtobuf.cmake installed to the default system path and won't ever proceed to the "Config" mode where I could probably make use of CMAKE_PREFIX_PATH.
It's important for me to not edit the CMakeLists.txt since it belongs to a 3rd party project I don't maintain.
What I've tried (all without success):
calling CMAKE_MODULE_PATH=~/usr/share/cmake-3.0/Modules cmake ... (the env. variable is not "transferred" to the CMake variable with the same name)
calling cmake -DCMAKE_MODULE_PATH=~/usr/share/cmake-3.0/Modules ... (doesn't work, probably by design?)
calling Protobuf_DIR=path/to/my/protobuf cmake ... (the project doesn't support this kind of override for Protobuf)
It seems to me that, unfortunately, the only way to alter the CMAKE_MODULE_PATH used by find_package is to alter it from within CMakeLists.txt, which is exactly what I want to avoid.
Do you have any ideas/workarounds on how not to touch the CMakeLists.txt and still convince find_package to find my custom Protobuf?
For reference, the CMake part of this project is on github .
As a direct answer to your question, yes, you can set CMAKE_MODULE_PATH at the command line by running cmake -DCMAKE_MODULE_PATH=/some/path -S /path/to/src -B /path/to/build.
But that probably doesn't do what you want it to do; see below.
The Bitbucket link you supplied is dead, but here are a few suggestions that might help.
Avoid writing your own find modules, especially when the upstream supplies CMake config modules.
You can direct CMake to your custom Protobuf installation by setting one of CMAKE_PREFIX_PATH or Protobuf_ROOT (v3.12+) to the Protobuf install root.
You can tell find_package to try CONFIG mode first by setting CMAKE_FIND_PACKAGE_PREFER_CONFIG to true (v3.15+). Then set Protobuf_DIR to the directory containing ProtobufConfig.cmake.
Failing all else, you can manually set the variables documented in CMake's own FindProtobuf module, here: https://cmake.org/cmake/help/latest/module/FindProtobuf.html
All these variables can be set at the configure command line with the -D flag.
There are very few environment variables that populate CMake variables to start and I would avoid relying on them. There is an exhaustive list here: https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html. CMAKE_MODULE_PATH is not among them.

Ignore warnings in external modules when using CMake

I am using CMake GUI (no version) with CMake 3.6.1. I am using an external module with add_subdirectory that shows me some warnings that I do not like (because of the annoying pollution):
CMake Warning (dev) at D:/Sources/.../external/g3log/latest/Build.cmake:11 (IF):
Policy CMP0054 is not set: Only interpret if() arguments as variables or
keywords when unquoted. Run "cmake --help-policy CMP0054" for policy
details. Use the cmake_policy command to set the policy and suppress this
warning.
Quoted variables like "MSVC" will no longer be dereferenced when the policy
is set to NEW. Since the policy is not set the OLD behavior will be used.
Call Stack (most recent call first):
D:/Sources/.../external/g3log/latest/CMakeLists.txt:72 (INCLUDE)
This warning is for project developers. Use -Wno-dev to suppress it.
I want to hide these warnings without touching the external files. -Wno-dev would be ok if it will affect only the external module (g3log).
I tried using cmake_policy like following with no effect:
cmake_policy(PUSH)
cmake_policy(SET CMP0054 OLD)
add_subdirectory(${g3log_DIR} ${CMAKE_BINARY_DIR}/../g3log)
cmake_policy(POP)
Turning my comments into an answer
That sounds like your external module does have a project() command. This resets the policies for this sub-module and below.
To demonstrate a possible solution, lets say you have a external project as the following:
g3log/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(g3log NONE)
set(VAR1 "Hello World")
set(VAR2 "VAR1")
if ("${VAR2}" STREQUAL "${VAR1}")
message("CMP0054 old behavior")
endif()
You can now set CMAKE_POLICY_DEFAULT_CMP0054 to OLD (or even better to NEW; nobody really wanted the "OLD" behavior) to get rid of the "Policy CMP0054 is not set" warnings you will get with newer versions of CMake:
CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(PolicyOverwrite NONE)
set(CMAKE_POLICY_DEFAULT_CMP0054 NEW)
add_subdirectory(g3log)
Now you have set a default for policy CMP0054 to be used if none is explicitly given in your project or one of the external projects you are using.

How to make package built with make install available for cmake?

So, I'm trying to build an application that requires gtkglextmm on CentOS. So far, I grabbed the source (from here) for gtkglext and gtkglextmm, and (finally) figured out how to compile them and install them using ./configure then make then sudo make install. That was pretty cool to get that to work.
Now, I'm trying to build Degate with cmake and it's complaining that it can't find gtkglextmm. What do I need to do to get the gtkglextmm library I built, available for cmake?
Rephrase: Built and installed library a with make,make install. Now want to build application b that depends on a with cmake. How?
Thanks!
This is a newcomer's notes made for my team as we adopt cmake. It summarizes briefly what I thought would be somewhere in a novice's example. Although with references and suitable for novices, I am very new to the material and this example may suffer accordingly.
General info for this question is at: https://cmake.org/Wiki/CMake:How_To_Find_Libraries - in particular, find_package can be used on any of the named packages listed by the help command:
cmake --help-module-list
Note: the 'Find' is omitted (e.g., FindLibXml2 -> find_package(LibXml2) )
However, for this type of library, it is more likely that it will not be in that list, in which case you want to use find_library and find_path instead. A simple example is:
find_library(SQLITE3_LIB sqlite3) # simple because I did not need to give paths
find_path(SQLITE3_PATH sqlite3.h)
target_link_libraries( your_target_name ${SQLITE3_LIB} )
include_directories( ${SQLITE3_PATH} )
You do not need to test if these have the '-NOTFOUND' return value because cmake will exit with an error if they do:
...
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
SQLITE3_LIB
linked by target "test" in directory /home/matlab/QFDC_ROOT/api
-- Configuring incomplete, errors occurred!
Note that the all-capitalized 'SQLITE3_LIB' and 'SQLITE3_PATH' are the variable names that I chose. You choose the variable names. If you have other libraries and include directories, you can list them before and after this one and separated by spaces (I ordered them by their link order consistently for both, although I think include paths are insensitive).
Your case may not be so simple, in which case you want to use the CMake features described at find_library for providing CMake more information about where it should find that library. There are other Q&A on specifically that topic - my favorite is to produce your own FindXXX.cmake (although it is a very terse answer pointing you to an example).
In many cases, it is helpful to run make VERBOSE=1 to help you troubleshoot the process, such as cd build && cmake .. && make VERBOSE=1.
For even better diagnostics, I used DLRdave's answer to print out the INCLUDE_DIRS and I used a simple message to return the results of my variables:
message( STATUS "SQLITE3_LIB: ${SQLITE3_LIB} SQLITE3_PATH: ${SQLITE3_PATH}")
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
foreach(dir ${dirs})
message(STATUS "dir='${dir}'")
endforeach()
EDIT NOTE: this answer was effectively re-written 2016-04-08 after discovering that the previous day's implementation erred and confused find_library() and find_path().