New CMake version results in strange command lines and warnings - cmake

I've been building a (vendor supplied) package with CMake for about a year now under Ubuntu-18.04-LTS and 20.04-LTS, but it seems that after a recent upgrade (cmake version 3.23.1) something has changed which is giving many weird anomalies. I'm wondering if any of the following look familiar and if there's an easy fix?
CMake Warning:
Ignoring extra path from command line:
"Export compile commands"
I can tell that this is because I'm getting a build.make file generated that contains
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON CACHE INTERNAL FORCE "Export compile commands"
which in turn is coming from this snippet in default.cmake:
set(CMAKE_EXPORT_COMPILE_COMMANDS ON
CACHE INTERNAL FORCE
"Export compile commands")
but what I can't figure out (being an intimidated novice CMake user) is why this recently stopped working normally and started giving these warning messages. I could ignore the warnings but I don't know for certain that other bad things aren't happening under the hood as well.
Is there something I can do (short of waiting for the vendor to release a fix, who knows when that might happen) that will get my builds working normally again?

FORCE is the last parameter of the set command.
set(CMAKE_EXPORT_COMPILE_COMMANDS ON
CACHE INTERNAL FORCE
"Export compile commands")
creates a cache variable with documentation "FORCE" and list one additional parameter "Export compile commands" which does not match the pattern of set(CACHE) usage:
set(<variable> <value>... CACHE <type> <docstring> [FORCE])
Change the snippet to
set(CMAKE_EXPORT_COMPILE_COMMANDS ON
CACHE INTERNAL
"Export compile commands" FORCE)
and the warning should be fixed. You may also remove FORCE entirely, since FORCE is implied by type INTERNAL.
set(CMAKE_EXPORT_COMPILE_COMMANDS ON
CACHE INTERNAL
"Export compile commands")

Related

CMake Error: Target contains relative path in its INTERFACE_INCLUDE_DIRECTORIES

I mean to compile example Advancing_front_surface_reconstruction from the CGAL package under Win10 + PortableApps Msys2.
For the library itself I use a precompiled package ($ pacman -Qs cgal gives local/mingw-w64-x86_64-cgal 4.14-1).
I used to be able to do that in my previous PC, see details below.
After transferring everything to a new PC (simply copying, it is PortableApps), I made a system update in Msys2 (required for other reasons).
I proceed as usual: mkdir build, cd build, ccmake ... Selecting Release mode, and verbosity ON, upon pressing g to generate files I got
CMake Error in CMakeLists.txt:
Imported target "CGAL::CGAL" includes non-existent path
"C:/building/msys64/mingw64/include"
in its INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:
* The path was deleted, renamed, or moved to another location.
* An install or uninstall procedure did not complete successfully.
* The installation package was faulty and references files it does not
provide.
Upon pressing e to exit the error message, the ccmake gui was exited and there were no files generated.
After googling a bit, this suggested creating the missing dirs, which seems merely a workaround (I did not try adapting this).
I created those dirs, and then I got
CMake Error in CMakeLists.txt:
Target "CGAL::CGAL" contains relative path in its
INTERFACE_INCLUDE_DIRECTORIES:
"C:/building/msys64/mingw64/include"
How can I fix this?
I found no suitable answers around.
Possibly related links, but which I found no way of relating to a suitable solution:
https://gitlab.kitware.com/cmake/cmake/commit/634bb33f3aa3b7f2181a896c025976b52171524a
https://cmake.org/cmake/help/v3.12/manual/cmake-buildsystem.7.html
NOTE:
The same happened with other examples.
EDIT:
I do not know what changed, but now upon pressing e to exit the error message (see above) all generated files are present, including the Makefile.
So I can proceed as described below in Previous state of affairs.
This happens either with or without the missing dirs (the error message changes, but I can generate my executables).
AFAICT, the only related change is that
I have just installed packages
, mingw-w64-x86_64-eigen3 (3.3.7-1)
, mingw-w64-x86_64-suitesparse (5.4.0-1)
, mingw-w64-x86_64-lapack (3.8.0-5)
, but I would not think this should matter.
Previous state of affairs
To compile and link CGAL examples, in my previous PC, some tweaking was needed.
Compilation went fine, but linking required a couple of tweaks.
An example command line produced for linking reads
/mingw64/bin/c++.exe -O3 -DNDEBUG -Wl,--enable-auto-import CMakeFiles/reconstruction_structured.dir/reconstruction_structured.cpp.o -o reconstruction_structured.exe -Wl,--out-implib,libreconstruction_structured.dll.a -Wl,--major-image-version,0,--minor-image-version,0 /mingw64/lib/lib/libmpfr.a /mingw64/lib/lib/libgmp.dll.a /mingw64/lib/lib/libCGAL.dll.a -lC:/building/msys64/mingw64/lib/libgmp.dll.a -lC:/building/msys64/mingw64/lib/libmpfr.a
The two types of required fixes are
Replacing /mingw64/lib/lib/ with /mingw64/lib/ in every (link.txt;build.make) file.
Replacing flag -lC:/building/msys64/mingw64/lib/libgmp.dll.a with -lgmp in every link.txt file. Similarly for -lmpfr.
Run this command to find all the places in the CGAL CMake files where the erroneous directory C:/building/ is mentioned:
grep -r '/building/' /mingw64/lib/cmake/CGAL
For each instance, either delete it or replace it with something more appropriate.
(Note: I haven't tried this myself.)
This erroneous directory is a general issue with MSYS2 which I attempted to fix at one point.

CMAKE_SYSROOT in CMakeTestCCompiler

I have a project which builds for PPC, the Toolchain is working correctly, i can build when the sysroot is installed under /opt/poky/1.5. Now i tried to move that Installation to the Project Directory (it is not a part of the Repository there, it is just installed there so it is not reliant on that fix path, so that everyone can check out the project and build it wothout setting up the sysroot under that fixed folder).
To achieve this I set CMAKE_SYSROOT to "${PROJECT_SOURCE_DIR}/poky" where the poky will be installed upon execution of a custom build script (the project also needs to build a secure image, so it is way simpler to use a build script instead of anything else, also this is convenient for jenkins).
Since the CMAKE_SYSROOT is build from the PROJECT_SOURCE_DIR which is different for the CMakeTestCCompiler Project, the cmake call fails teloling me that the CCompiler is broken of course. So I want to know, how I am supposed to get the CMakeTestCCompiler Project to compile with the same CMAKE_SYSROOT variable, without altering the CMakeTestCCompiler Project itself (of course).
Somehow I cannot find an answer anywhere, it seems that noone ever had this issue (which frankly i cannot understand, this should be a common setup in my opinion). (Or maybe i am just too much of a noob when it comes to CMAKE, which i will gladly admit)
I am not interested in solutions like: "JUST INSTALL IT IN A FIX PATH" or such... please, I need the setup like this, I have reasons for that.
THX for reading/trying/answering/helping
Have a nice day
EDIT1:
In CMakeLists.txt (top level CMakeFile so it should be used by any build):
`SET(CMAKE_SYSROOT "${PROJECT_SOURCE_DIR}/poky/sysroots")`
In ToolchainCMake (the one given to the cmake as CMAKE_TOOLCHAIN_FILE):
`SET(CMAKE_SYSTEM_NAME Linux)`
`SET(CMAKE_SYSTEM_VERSION 1)`
`SET(CMAKE_SYSROOT "${PROJECT_SOURCE_DIR}/poky/sysroots")`
`SET(COMPILER_ROOT ${PROJECT_SOURCE_DIR}/poky/sysroots/i686-pokysdk-linux/usr/bin/powerpc-poky-linux-gnuspe)`
`SET(CMAKE_C_COMPILER ${COMPILER_ROOT}/powerpc-poky-linux-gnuspe-gcc)`
`SET(CMAKE_CXX_COMPILER ${COMPILER_ROOT}/powerpc-poky-linux-gnuspe-g++)`
`MESSAGE("CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")`
`MESSAGE("CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}")`
`MESSAGE("COMPILER_ROOT: ${COMPILER_ROOT}")`
`SET(CMAKE_FIND_ROOT_PATH ${SYS_ROOT}/ppce500v2-poky-linux-gnuspe)`
`SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)`
`SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)`
`SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)`
EDIT2:
I used the
`set(CMAKE_C_COMPILER_WORKS 1 CACHE INTERNAL "")`
`set(CMAKE_CXX_COMPILER_WORKS 1 CACHE INTERNAL "")`
settings to simulate the CMakeTestCCompiler build succeeding and realized that I am facing some additional problems: It seem that the packages are looked up on the system instead of the CMAKE_SYSROOT folder. Even tried the
`SET(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})`
to try to force the search in there, but without luck. In the CMakeError.log I can see, that the compiler itself was configured with the prefix option that points to /opt/poky/1.5, the path that i want to "overwrite", now I am not sure if the compiler could even deal with an alternate path.
I felt the need to add these information, they not really add to the problem at hand.
ERRORS:
I also found some errors in the above cmake:
`SET(CMAKE_SYSROOT "${PROJECT_SOURCE_DIR}/poky/sysroots")`
must be
`SET(CMAKE_SYSROOT "${PROJECT_SOURCE_DIR}/poky/sysroots/ppce500v2-poky-linux-gnuspe")`
instead and therefor the
`SET(CMAKE_FIND_ROOT_PATH ${SYS_ROOT}/ppce500v2-poky-linux-gnuspe)`
changes to
`SET(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})`
EDIT: Whole answer changed.
My first suspicion was that the problem is that value of ${PROJECT_SOURCE_DIR} is not known in CMAKE_TOOLCHAIN_FILE as it is processed before CMakeLists.txt. But this isn't true.
I had similar problem (CMake 2.8.12.2), everything worked OK, when I passed cross compiler by CC environment variable with --sysroot option, i.e. CMake was invoked as follows:
CC="arm-linux-gnueabi-gcc --sysroot=/path/to/sysroot" cmake /path/to/sources
When I switched to using toolchain file, CMake started to report that C compiler doesn't work.
To workaround this problem, I use CMakeForceCompiler package. Parts toolchain file (along with comments) I think are relevant:
include(CMakeForceCompiler)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
# Force compiler - only option that actually works
cmake_force_c_compiler (${TOOLCHAIN_PATH}/bin/arm-linux-gnueabi-gcc GNU)
cmake_force_cxx_compiler(${TOOLCHAIN_PATH}/bin/arm-linux-gnueabi-g++ GNU)
# NOTE: CMAKE_SYSROOT doesn't work as expected
add_definitions("--sysroot=${TOOLCHAIN_SYSROOT}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --sysroot=${TOOLCHAIN_SYSROOT}" CACHE INTERNAL "" FORCE)
Note, that TOOLCHAIN_PATH and TOOLCHAIN_SYSROOT are my local variables set before.

Cmake apparently ignoring CMAKE_BUILD_TYPE?

So I'm using CMake for a project.
It consists of a set of shared libraries linked to one executable. All are generated in the project (there are no external targets). Each sub project lives in its own directory, with its own cmakelists file.
So I make an out-of-source build, taking care to set CMAKE_BUILD_TYPE to Debug, and run cmake, and then make. I use GNU make 3.81, GCC 4.8.1, binutils 2.23.2 and CMake 3.2.3 on a Windows box using MSYS/MINGW.
The problem is that, when I load this executable in gdb (version 7.6), place a breakpoint on a function from one of the shared libraries, and then try to single step, gdb skips the whole function saying it has no line number information.
According to my understanding, line number information is a part of the debugging information, so I expected this to be generated during the compiling process (as per the CMAKE_BUILD_TYPE) which it didn't, so I would like to know how I can get CMake to generate this line number information properly (that is, without manually adding compiler-specific options in the cmake files, although I would take that if it's the only solution).
I've tried setting CMAKE_BUILD_TYPE from the command line (when invoking the cmake utility), inside the cmakelists, and even by modifying the CMakeCache.txt, and restarting the build from an empty directory with no success. I then made sure that CMAKE_BUILD_TYPE was effectively set to Debug by using the MESSAGE command to print it's value, and it was correctly set to Debug. So then I executed 'make VERBOSE=1' to see if the correct compiler option was added, and found it correctly used the "-g" option (although I would have expected -ggdb, but more on this later). The cmake documentation and Google did not bring me any answers.
My hypothesis is that the -g option only generates basic debugging information (such as the mappings between functions and their memory addresses, and how to access their arguments) whereas -ggdb would generate more in-detail debugging information in a gdb-specific format, including said line number informations), but a troubling fact is that, when running the executable in gdb, functions defined inside the executable do have line number information, only the shared libraries don't, hence my confusion.

CMake - Force find_package to update cache variables

In my CMake project, I provide a default path to Boost editable by the user.
set(PATH_BOOST_DEFAULT "/softs/boost/${BOOST_VER}/${ARCH}/gcc/${GCCVER}")
set(PATH_BOOST "${PATH_BOOST_DEFAULT}" CACHE PATH "Default path to Boost")
After that, I try to find the libs with:
set(BOOST_ROOT "${PATH_BOOST}")
set(Boost_USE_MULTITHREAD ON)
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost 1.53.0 REQUIRED COMPONENTS thread system)
This works fine and a lot of cache variables like Boost_INCLUDE_DIR, Boost_LIBRARY_DIRS or Boost_THREAD_LIBRARY_DEBUG are generated.
My problem comes when I try to modify the cache variable PATH_BOOST: the cache variables generated by FindBoost.cmake aren't updated. The script FindBoost.cmake seems to be called again (it print messages about found components). I think the variables like Boost_INCLUDE_DIR are not updated because they are in cache.
Is there a way to say to CMake "if the path is modified by the user, re-find the package by forcing the cache variables"?
Also, is there a nicer way to detect a cache variable was just modified than the following ugly idea?
set(MY_VAR ${MY_VAR_DEFAULT} CACHE TYPE "")
if(NOT DEFINED MY_VAR_copy)
set(MY_VAR_copy ${MY_VAR} CACHE INTERNAL "")
mark_as_advanced(FORCE MY_VAR_copy)
endif()
if(NOT "${MY_VAR}" STREQUAL "${MY_VAR_copy}")
# my_var is modified : do something
set(MY_VAR_copy ${MY_VAR} CACHE INTERNAL "")
endif()
I think I've got the same problem as you. My setup tries to find a specific version of a package:
set (MYPACK_REQUIRED_VERSION 1.2.3)
find_package (mypack ${MYPACK_REQUIRED_VERSION} EXACT)
The package config script sets the cached variable MYPACK_LIBRARIES which then is used at a later stage. However when I change the MYPACK_REQUIRED_VERSION variable cmake still use the old MYPACK_LIBRARIES instead of trying to look for the new version.
I think I've solved the problem now by unsetting this cache variable:
set (MYPACK_REQUIRED_VERSION 1.2.3)
unset (MYPACK_LIBRARIES CACHE)
find_package (mypack ${MYPACK_REQUIRED_VERSION} EXACT)
This seems to trigger the find_package procedure again in my case. There are some finer details of the find_package procedure that I don't completely understand so this might not work in your case, but it might be worth a try.
I've got the same problem as you.My project is a cross-compiled project that develops debugging on x86 machines and deploys and runs on aarch64 machines, depending on the x86 and aarch64 versions of the same package, but cmake doesn't seem to re-search for packages when switching architectures.
I noticed that cmake's documentation mentions:
Once one of the calls succeeds the result variable will be set and stored in the cache so that no call will search again.
By default the value stored in the result variable will be the path at which the file is found.
So I find the cached value in CMakeCache.txt, value is just link packageName_DIR.
Solution is:
unset(packageName_DIR CACHE)
find_package(packageName)
if(packageName_FOUND)
#do something
endif()
then each time you reload the CMakeLists, it will re-find the package.
Or you can set a flag in cache, if the flag changed, unset packageName_DIR.
Note that if some cache variables are set in the package, you also need to add unset, You may need to look at the package's FindpackageName.cmake or CmakeCache.txt to see if there are extra cache variables. For example,
packageName_LIBRARIES contain LIB1,LIB2,LIB3, you need
unset(LIB1_LIBRARY CACHE)
unset(LIB2_LIBRARY CACHE)
unset(LIB3_LIBRARY CACHE)
unset(LIB1_INCLUDE_DIR CACHE)
unset(LIB2_INCLUDE_DIR CACHE)
unset(LIB3_INCLUDE_DIR CACHE)
If none of the above works, there's a simplest and crudest way is to delete the CMakeCache.txt file (which is usually in the cmake build root directory) and reload CMakeLists.txt.

When should I rerun cmake?

After running the cmake command once to generate a build system, when, if ever, should I rerun the cmake command?
The generated build systems can detect changes in the associated CMakeLists.txt files and behave accordingly. You can see the logic for doing so in generated Makefiles. The exact rules for when this will happen successfully are mysterious to me.
When should I rerun cmake? Does the answer depend on the generator used?
This blog post (under heading: "Invoking CMake multiple times") points out the confusion over this issue and states that the answer is actually 'never', regardless of generator, but I find that surprising. Is it true?
The answer is simple:
The cmake binary of course needs to re-run each time you make changes to any build setting, but you wont need to do it by design; hence "never" is correct regarding commands you have to issue.
The build targets created by cmake automatically include checks for each file subsequently [=starting from the main CMakeLists.txt file] involved or included generating the current set of Makefiles/VS projects/whatever. When invoking make (assuming unix here) this automatically triggers a previous execution of cmake if necessary; so your generated projects include logic to invoke cmake itself! As all command-line parameters initially passed (e.g. cmake -DCMAKE_BUILD_TYPE=RELEASE .. will be stored in the CMakeCache.txt, you dont need to re-specify any of those on subsequent invocations, which is why the projects also can just run cmake and know it still does what you intended.
Some more detail:
CMake generates book-keeping files containing all files that were involved in Makefile/Project generation, see e.g. these sample contents of my <binary-dir>/CMakeFiles/Makefile.cmake file using MSYS makefiles:
# The top level Makefile was generated from the following files:
set(CMAKE_MAKEFILE_DEPENDS
"CMakeCache.txt"
"C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/CMakeCCompiler.cmake.in"
"C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/RepositoryInfo.txt.in"
"<my external project bin dir>/release/ep_tmp/IRON-cfgcmd.txt.in"
"../CMakeFindModuleWrappers/FindBLAS.cmake"
"../CMakeFindModuleWrappers/FindLAPACK.cmake"
"../CMakeLists.txt"
"../CMakeScripts/CreateLocalConfig.cmake"
"../Config/Variables.cmake"
"../Dependencies.cmake"
"CMakeFiles/3.1.0/CMakeCCompiler.cmake"
"CMakeFiles/3.1.0/CMakeRCCompiler.cmake")
Any modification to any of these files will trigger another cmake run whenever you choose to start a build of a target. I honestly dont know how fine-grained those dependencies tracking goes in CMake, i.e. if a target will just be build if any changes somewhere else wont affect the target's compilation. I wouldn't expect it as this can get messy quite quickly, and repeated CMake runs (correctly using the Cache capabilities) are very fast anyways.
The only case where you need to re-run cmake is when you change the compiler after you started a project(MyProject); but even this case is handled by newer CMake versions automatically now (with some yelling :-)).
additional comment responding to comments:
There are cases where you will need to manually re-run cmake, and that is whenever you write your configure scripts so badly that cmake cannot possibly detect files/dependencies you're creating. A typical scenario would be that your first cmake run creates files using e.g. execute_process and you would then include them using file(GLOB ..). This is BAD style and the CMake Docs for file explicitly say
Note: We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.
Btw this comment also sheds light on the above explained self-invocation by the generated build system :-)
The "proper" way to treat this kind of situations where you create source files during configure time is to use add_custom_command(OUTPUT ...), so that CMake is "aware" of a file being generated and tracks changes correctly. If for some reason you can't/won't use add_custom_command, you can still let CMake know of your file generation using the source file property GENERATED. Any source file with this flag set can be hard-coded into target source files and CMake wont complain about missing files at configure time (and expects this file to be generated some time during the (first!) cmake run.
Looking into this topic for reading the version information from a debian/changelog file (generation phase), I ran in the topic that cmake execution should be triggered as debian/changelog is modified. So I had the need to add debian/changelog to CMAKE_MAKEFILE_DEPENDS.
In my case, debian/changelog is read through execute_process. Execute_process unfortunately gives no possibility to add files processed to CMAKE_MAKEFILE_DEPENDS. But I found that running configure_file will do it. Actually I am really missing something like DEPENDENCIES in execute_process.
However, as I had the need to configure the debian/changelog file for my needs, the solution came implicitly to me.
I actually also found a hint about this in the official documentation of configure_file:
"If the input file is modified the build system will re-run CMake to re-configure the file and generate the build system again."
So using configure_file should be a safe to trigger the re-run of cmake.
From a user perspective, I would expect other commands to extend CMAKE_MAKEFILE_DEPENDS, too. E.g. execute_process (on demand) but also file(READ) (implicitly like configure_file). Perhaps there are others. Each read file is likely to influence the generation phase. As an alternative it would be nice to have a command to just extend the dependency list (hint for the cmake developers, perhaps one comes along).