In CMake, get all the include search paths in check_include_file_cxx - cmake

I want to check the self-sufficiency of all my headers in my C++ project managed with CMake. Using check_include_file_cxx I am partially able to do it, except that some include file are missing and false negatives are reported.
The solution in CHECK_INCLUDE_FILE_CXX does not respect 'target_include_directories' when looking for include file involves manually adding the required directories.
I would like to instead transfer all the search path used during any normal compilation in my project to CMAKE_REQUIRED_INCLUDES. Is it possible and how ?

Related

Predeclare search location for anticipated find_library()-call

I want to include an external library as a subproject into my own project and link its target(s) statically against my own lib.
The said project somewhere in its CMake calls the following find-functions:
find_library(MBEDTLS_LIBRARY mbedtls)
find_library(MBEDX509_LIBRARY mbedx509)
find_library(MBEDCRYPTO_LIBRARY mbedcrypto)
The subproject expects mbedtls to already be installed somewhere on the system, but it didn't consider the fact that I want to link statically. My approach is to now FetchContent mbedtls and provide the find_library() calls with the prebuilt static libraries.
Now I need a way provide those find_library-calls with the right search directory, of course without modifying its source code. Can I somehow set a prefix path? I know I could probably set CMAKE_PREFIX_PATH but that seems like an ugly hack and it would probably affect other find_library()-calls within the project which also exist. Is there a more "constrained" way?
Can I somehow set a prefix path?
Setting a prefix path won't help find_library to locate the library, because command find_library searches the file at configuration stage, but the library is built only on build stage.
Instead, you may write the target name to the CACHE variable, which is passed to find_library as the first argument:
When find the result variable to be already set, find_library won't search the library file.
In most cases a project uses result of find_library in the call to target_link_libraries, so having the library target in the result variable will fit to the project's expectations.
Example:
FetchContent_Declare(mbedtls ...)
FetchContent_MakeAvailable(mbedtls)
set(MBEDTLS_LIBRARY MbedTLS::mbedtls CACHE INTERNAL "mbedtls library target")
With such setup the following
find_library(MBEDTLS_LIBRARY mbedtls)
will do nothing, since the variable MBEDTLS_LIBRARY is already set.
And if the project will use this variable like
target_link_libraries(<executable> ${MBEDTLS_LIBRARY})
then it effectively gets
target_link_libraries(<executable> MbedTLS::mbedtls)
Name of the target which should be assigned to the variable could sometime be found from the project's documentation, but otherwise you need to look into the project's sources (CMakeLists.txt).
E.g. in case of mbedtls project, the library target mbedtls is created with add_library() call, and MbedTLS::mbedtls is created as ALIAS for it.

Is there a way to make cmake find_package config mode VERSION selection automatically work with complex paths or is my path structure flawed?

I want to have find_package in config mode is the user points cmake with the SDK <Project>_ROOT variable then possibly calls find_package passing in version numbers and setting the flags for version number sorting.
set(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
find_package(<Project> CONFIG)
CMake would then automatically finds the latest config.cmake file and everyone is happy.
The problem I have is the SDK folder structure:
<Project>/<Version>/<Toolset>/cmake/config.cmake
SDK/2.1.1/v140/cmake/SDKconfig.cmake
Where <Project> is the root folder. Based on the kinds of paths searched I could make it work if I reduced the path by 1 folder combining the names and added the project name as a prefix for the subdir but that feels very weird.
Other ideas I am considering is creating a dummy config as a find_package forwarder or maybe an importer in the middle of the path that re-tries a find package or imports things further down to the correct version or maybe toolset but haven't pursued that yet. It might again require that the version number or other have the project name as a prefix.
Is placing these highly specific content config files that far down the wrong approach?
If you look at the find_package search procedure you'll see that it will consider directories prefixed with the project name. Here are the Windows-compatible structures CMake will consider:
<prefix>/ (W)
<prefix>/(cmake|CMake)/ (W)
<prefix>/<name>*/ (W)
<prefix>/<name>*/(cmake|CMake)/ (W)
** <prefix>/<name>*/(lib/<arch>|lib*|share)/cmake/<name>*/ (W/U)
<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/ (W/U)
<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/ (W/U)
The fifth one down, the one I marked with **, is the most promising. Note that lib/<arch> is only searched if CMAKE_LIBRARY_ARCHITECTURE is set and * means "0 or more characters"; however, the * in lib* can only be 64, 32, or x32 (and only on Unix).
So here's one suggestion that's mostly useful if you're going to create an eventual directory structure that contains multiple project versions and multiple toolset versions:
<prefix>/<Project>-<Version>/lib/<Toolset>/cmake/<Project>/<Project>Config.cmake
Your users should then set CMAKE_LIBRARY_ARCHITECTURE to v141 or whichever (I have found it is blank by default on Windows). As long as you have a <Project>ConfigVersion.cmake file, users setting the version via find_package should get the correct one.
I tested this locally while writing the answer, but I've never deployed this myself. So I can't really tell you how great an idea this is beyond that it seems like it would technically work.

CMake: Remove header dependency

Is there any way to make CMake "forget" about a file in the dependency tree? My original problem (to avoid the XY situation) is the following: I want to timestamp the build of a set of tools which have complicated dependencies among them and to other tools. Right now, I want to use a pure timestamp, but later I might want add some info from the repository (SVN). Whatever system I end up implementing needs to have the following characteristics (my "X"):
No unnecessary rebuilding: the executables should not be rebuilt on every make if the only change would be the timestamp.
Update on any change: if any tool is going to be rebuilt or relinked, either by changes to its code or to one of its dependencies, the timestamp needs to be updated.
My current solution goes along the lines of creating a custom command+target that invokes CMake at make time (so the command calls CMake itself with -P script.cmake) to generate a timestamp.h file. The main files of my tools would include that file, and the projects would depend on the target so that it gets rebuilt first.
However, this has its drawbacks: if I do update the timestamp file on every call to make, then CMake's dependency scanner would know about that file even if I do not list it as an explicit dependency of my tools. Thus, every make would trigger at least a recompilation of the respective "main" files and the corresponding relink. With tens of tools, this means slowing down the build when I may be working on just two or three of them at once.
So, I was thinking that my solution would be to somehow make CMake forget about that file when building its dependency tree for the "main" file of each tool. I would keep the dependency on the custom target that does depend on the file, so that it would be regenerated first on each call to make. However, the build tool would not consider that file as relevant to determine whether it is necessary to actually rebuild each individual tool. Thus, tools only with other changes would be rebuilt (satisfying my first criterion), and any change that causes a rebuild of a tool would obviously use the version just generated (fulfilling the second criterion).
To my chagrin, I have not found a way to make the dependency scanner forget about this file, so my solution cannot be put to use. How would I go about doing such a thing? Is it even possible, or is it completely the wrong way to go about this? I am using CMake 3.4, and my code is currently C++, but I would like a solution that did not rely on C/C++ specifics, since I have a different project (written in Fortran) in which I would also like to have build timestamping.
I've had almost the same problem than you are. Simply solved by pushing the timestamp header file into standalone target containing only this header generator command. After that you have several choices:
1.. Exclude that project from the build by the IDE you are using. For example, for the Visual Studio you can do it by several ways:
1.1. Project->Project Dependencies...->uncheck project with that header (not always works: Error while removing project dependency in VS2010)
1.2. Build->Configuration Manager...->uncheck project with that header
2.. Create an environment variable and use the condition with that variable around the add_dependencies command in the CMakeLists.txt file.
3.. Generate 2 standalone solutions through the cmake generator with included and with excluded add_dependencies in the CMakeLists.txt file.
I've used particulary [1.2]. When i need build and debug, then i uncheck the dependecy. By default, dependecy always checked, so there is no problem to miss timestamp build for a build server.
Note:
The timestamp header will be included in all projects you want to include that header (for example, through the add_library and add_executable) and you still can observe it in the IDE under a project item menu even if a project depends on the timestamp project indirectly. This is useful if you don't want to search for the timestamp project with the header to open it from there and want to open it from any project which has included that header.
So, in case of removing the timestamp header from the add_library or add_executable you won't have that opportunity.

Can CMakeLists.txt depend on a file parsed by a function?

I am rather new to CMake, starting off for the first time with a larger project consisting of many subprojects.
For particular reasons (described below for the curious) I already have a set of include files that contain info about the source files needed for each CMake target (lib or exe) – and, for now, I prefer to (re)use these files (reason also described below)
Writing a function to parse these files and add their content as source files to the targets was a surprisingly easy task.
But – now the Problem:
Obviously I want to have each targets CMakeLists.txt depend on the particular include file, that generates the list of source files, so that changes on the include file will be detected as if it were changes to CMakeLists.txt itself, but I simply can’t find any references on how to accomplish that.
N.B.: I found AddFileDependencies but that is for adding dependencies on source files, not the CMakeLists.txt. However, CMake itself can figure out dependencies to included .cmake file somehow, so I figured, it should be possible to do somehow.
Background for the curious:
For this project (quite a number of libraries used by quite a number of executable targets, all organized as subprojects) I was using QMake (without actually using Qt itself) for setting up makefiles. Doing so I was able to use Qt Creator while still being able to generate Visual Studio Solution/Project files automagically. We’re also still in progress of evaluating different IDEs and the choice has not been made yet. But the most important reason to use a generator like QMake / CMake was not being forced to set up the VS files for all these subprojects manually.
Although I needed to trick QMake sometimes to do what I wanted to, things went quite well - even for the VS solution - except for one thing: Visual Studio messes up dependencies on Flex/Bison and other files using custom build rules. It keeps recompiling the Flex/Bison/other files saying „command line changed“ – which I gave up trying to fix.
For this reason I thougt, I’d try CMake as a generator instead, which looks very promising so far – although not having builtin precompiled header support in CMake is somewhat ridiculous these days (off topic, I know).
Since Qt Creators CMake support is by far not as good as the support for QMake projects, I firgured, using the approach of parsing the .pri files containing the source file list would enable me using QMake and CMake side by side – especially since the remaining project settings are rather less complicated than on most open source projects.
There's a nice trick which does exactly what you need. It's based on the idea I found in the git-revision module of #rpavlik see this so question
This is the overall idea:
Create a dummy timestamp file
Add a custom command which touches the timestamp whenever the input .pri file changes
include the timestamp file in your CMakeLists.txt
A possible implementation:
set(input_pri_file <path-to-the-input-pri-file>)
set(timestamp_file ${CMAKE_CURRENT_BINARY_DIR}/timestamp.cmake)
add_custom_command(
OUTPUT ${timestamp_file}
COMMAND ${CMAKE_COMMAND} -E touch ${timestamp_file}
MAIN_DEPENDENCY ${input_pri_file}
VERBATIM
COMMENT "Updating timestamp.cmake"
)
if(NOT EXISTS "${timestamp_file}")
file(WRITE ${timestamp_file} "") # create initial empty file
endif()
include(${timestamp_file})
# create the file list from input_pri_file
....
# use the file list
add_executable(main ${filelist})
Here's what happens when the .pri file changes:
the change triggers the execution of the custom command
which updates the timestamp
because the CMakeLists includes the timestamp it is dependent on it
so updating the timestamp triggers a re-configuration of the CMakeLists.txt
I use the configure_file() if I have some input that should retrigger CMake's configuration process. See e.g. How to make CMake reconfiguration depend on custom file? and configure_file()'s unit test
So in your case it would look something like:
configure_file(SomeInput.pri ${CMAKE_CURRENT_BINARY_DIR}/SomeInput.pri)
Then you use ${CMAKE_CURRENT_BINARY_DIR}/SomeInput.pri to generate the sources. Just make sure you do not add COPYONLY, because then configuration won't retrigger on changes of SomeInput.pri.
EDIT: Alternatively use - a relative new addition - the CMAKE_CONFIGURE_DEPENDS directory property.

CMake recursive include of modules

Is it possible to use the CMake INCLUDE command the same way as in C++.
In all my projects I have to make the same includes:
Example: CMakeLists.txt for "MyApplication"
INCLUDE("FindMyBase")
INCLUDE("FindMyGtk")
In this example FindMyGtk already has "FindMyBase" in it.
So why do I need to include FindMyBase in MyApplication?
Is there a way once one .cmake file has been included that it stays available for all other projects in the chain below?
Update 1: The idea is to avoid searching every time for MyBase if it was already found once.
Update 2: The objective is also to reduce the number of includes. In my example from 2 to 1, but if you have 10 includes then you can reduce them to just 2 if these 2 depend on the other 8.
It pretty much does do that. I visualise include as if you'd pasted the contents of the include file directly into the CMakeLists.txt file where you called it.
In your case, "FindMyBase" is called twice. This often doesn't matter - e.g. if the include file only defines functions or macros it's safe to include multiple times.
If the included file searches for components using CMake's collection of find_XXX functions, then these already do what you want. The result of the search is cached. On subsequent invocations, if this cached result shows that the component has already been found, no further searching is done.
If you want (or have) to avoid including the same file multiple times, you can add include guards to the top of the file in a similar way to C++ include guards:
if(FindMyBaseIncluded)
return()
endif()
set(FindMyBaseIncluded TRUE)
That way, including the file multiple times is almost cost-free.