Is there a variable I can use in cmake to make it act like it was passed the -q option? It would be nice because I have a very modular build that gets messy with cmakes output. I am using it in a c++ project.
There's no variable that I know of. However, you can add the following hack to the start of your top-level CMakeLists.txt (before the project call) to control the output somewhat:
function(message)
list(GET ARGV 0 MessageType)
if(MessageType STREQUAL FATAL_ERROR OR
MessageType STREQUAL SEND_ERROR OR
MessageType STREQUAL WARNING OR
MessageType STREQUAL AUTHOR_WARNING)
list(REMOVE_AT ARGV 0)
_message(${MessageType} "${ARGV}")
endif()
endfunction()
This overrides CMake's built-in message command and suppresses all STATUS and untyped messages, leaving the more important types to output correctly.
The output of e.g. a WARNING message will change from
CMake Warning at CMakeLists.txt:14 (message):
This is a dummy warning message.
to
CMake Warning at CMakeLists.txt:8 (_message):
This is a dummy warning message.
Call Stack (most recent call first):
CMakeLists.txt:14 (message)
Note that the actual line where the warning message was generated is listed in the call stack rather than being the first line of the output message.
Finally, this has no effect on the summary output which indicates success or failure of the configure attempt.
As of cmake 3.1, setting CMAKE_INSTALL_MESSAGE is also very useful. For example, set(CMAKE_INSTALL_MESSAGE LAZY) will skip the -- Up-to-date: messages.
For the installation part of CMake, which tends to print one line per file (a la -- Up-to-date: /some/destination/path and -- Installing: /some/destination/path), you can do
set(CMAKE_INSTALL_MESSAGE LAZY) # Don't tell us about up-to-date files.
which doesn't print for already present files (if you run install repeatedly, as you might during development), or even
set(CMAKE_INSTALL_MESSAGE NEVER) # Install silently.
This option has been present since CMake 3.1.
set(CMAKE_MESSAGE_LOG_LEVEL "WARNING")
https://cmake.org/cmake/help/latest/variable/CMAKE_MESSAGE_LOG_LEVEL.html
Related
I want to use cmake to build my project, my CMakeLists.txt is very simple:
cmake_minimum_required(VERSION 3.20)
project(YuvParallelProcess)
message("$(PROJECT_SOURCE_DIR)")
include_directories($(PROJECT_SOURCE_DIR)/inc)
link_directories($(PROJECT_SOURCE_DIR)/lib/libyuv)
add_executable(YuvParallelProcess $(PROJECT_SOURCE_DIR)/src/main.cpp)
target_link_libraries(YuvParallelProcess libyuv.a)
my project files are organized as follows:
YuvParallelProcess
build
data
inc
lib
src
CMakeLists.txt
when I run cmake .. in build directory, the shell prints:
$(PROJECT_SOURCE_DIR)
-- Configuring done
CMake Error at CMakeLists.txt:10 (add_executable):
Cannot find source file:
$(PROJECT_SOURCE_DIR)/src/main.cpp
CMake Error at CMakeLists.txt:10 (add_executable):
No SOURCES given to target: YuvParallelProcess
I don't know why the shell just prints $(PROJECT_SOURCE_DIR) other than the value of PROJECT_SOURCE_DIR
How can I print the value of PROJECT_SOURCE_DIR
By the way, I can't figure out why cmake failed to compile my project
Cmake uses curly braces for getting values of variables:
${PROJECT_SOURCE_DIR}
I suggest to dump messages like below to not skip empty messages.
message(PROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}")
Cmake failed to configure your project because it did not recognise variables in parentheses and considered $(PROJECT_SOURCE_DIR) to be a string literal as is.
There is CMakePrintHelpers Cmake module for dumping variables exactly like above.
include(CMakePrintHelpers)
cmake_print_variables(PROJECT_SOURCE_DIR)
Instead of using message, you can also use cmake_print_variables to display variables.
in this case, you must include CMakePrintHelpers
include(CMakePrintHelpers)
cmake_print_variables(PROJECT_SOURCE_DIR)
The ouput will be :
-- PROJECT_SOURCE_DIR="path/to/your/project"
With cmake_print_variables you can also display several variables, like this:
cmake_print_variables(PROJECT_SOURCE_DIR ANOTHER_VARIABLE)
The ouput will be :
-- PROJECT_SOURCE_DIR="path/to/your/project" ; ANOTHER_VARIABLE="other variable"
This question already has answers here:
Check CMake Cache Variable in Toolchain File
(2 answers)
Closed 1 year ago.
I'm writing CMake toolchain files for cross-compilation.
I've got several toolchains, that differ very slightly. I'd like to create a single file for cmake that describes all toolchains and have users to specify them from command line: cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain.cmake -DTOOLCHAIN_NAME=<name>
However, it seems that TOOLCHAIN_NAME sometimes becomes an empty string.
Here is the example of the toolchain file:
set(tools /opt/toolchains/Custom/toolchains/toolchain)
set(sdk /opt/toolchains/Custom/platforms/)
message(STATUS "toolchain_name ${TOOLCHAIN_NAME}")
if(NOT TOOLCHAIN_NAME)
message(SEND_ERROR "Please specify toolchain name in -DTOOLCHAIN_NAME parameter")
endif()
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR ARM)
# further processing
Then I call CMake:
mkdir build
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain.cmake -DTOOLCHAIN_NAME=proc-os-gnueabi-gcc_6_3
And get following output with errors:
-- toolchain name proc-os-gnueabi-gcc_6_3
-- toolchain name proc-os-gnueabi-gcc_6_3
-- The C compiler identification is GNU 6.3.1
-- The CXX compiler identification is GNU 6.3.1
-- Check for working C compiler: /opt/toolchains/.../bin/arm-os-gnueabi-gcc
CMake Error at /home/user/project/cmake/toolchain.cmake:59 (message):
Please specify toolchain name in -DTOOLCHAIN_NAME parameter
Call Stack (most recent call first):
/home/user/project/build/CMakeFiles/3.15.4/CMakeSystem.cmake:6 (include)
/home/user/project/build/CMakeFiles/CMakeTmp/CMakeLists.txt:2 (project)
CMake Error at /usr/local/share/cmake-3.15/Modules/CMakeTestCCompiler.cmake:44 (try_compile):
Failed to configure test project build system.
Call Stack (most recent call first):
CMakeLists.txt:15 (project)
-- Configuring incomplete, errors occurred!
See also "/home/user/project/build/CMakeFiles/CMakeOutput.log".
See also "/home/user/project/build/CMakeFiles/CMakeError.log".
CMakeOutput.log and CMakeError.log contain messages, saying that the compiler didn't find some libraries.
If I open generated file /home/user/project/build/CMakeFiles/3.15.4/CMakeSystem.cmake I can see the following
set(CMAKE_HOST_SYSTEM "Linux-4.2.0-27-generic")
set(CMAKE_HOST_SYSTEM_NAME "Linux")
set(CMAKE_HOST_SYSTEM_VERSION "4.2.0-27-generic")
set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64")
include("/home/user/project/cmake/toolchain.cmake")
set(CMAKE_SYSTEM "Generic")
set(CMAKE_SYSTEM_NAME "Generic")
set(CMAKE_SYSTEM_VERSION "")
set(CMAKE_SYSTEM_PROCESSOR "ARM")
set(CMAKE_CROSSCOMPILING "TRUE")
set(CMAKE_SYSTEM_LOADED 1)
According to CMake manual, its -D argument is used to specify cache entries.
I conclude from the output above that supplied toolchain file is processed by CMake at least 3 times. During first two times there were proper cache entries, and at the third run they were absent.
So, how can I avoid code duplication for toolchain files?
UPD. After reading this question I've tried several permutations of CMake command line parameters: specifying source path after toolchain but before options, specifying it after options, explicitly specifying source path and build path with -S and -B options. Nothing has helped.
I conclude from the output above that supplied toolchain file is processed by CMake at least 3 times. First two times there were proper cache entries, and at the third run they were absent.
Yes, this is very good observation. Technically, only the first toolchain invocation at the project() call is guarantee to see the CACHE entries (created with -D parameters to cmake or with set() commands prior to the project() call).
One approach for pass CACHE entries between the different toolchain invocations is storing them in the environment variables:
Example below uses MY_TOOLCHAIN_NAME environment variable as a storage for TOOLCHAIN_NAME CMake variable.
if(DEFINED ENV{MY_TOOLCHAIN_NAME})
# Environment variable is set.
if (TOOLCHAIN_NAME)
# CMake variable is set too.
# It is up to your which one to use.
# Uncomment line below for prefer environment variable to CMake one.
# set(TOOLCHAIN_NAME $ENV{MY_TOOLCHAIN_NAME})
else ()
# CMake variable is not set. Use environment one.
set(TOOLCHAIN_NAME $ENV{MY_TOOLCHAIN_NAME})
endif()
else()
# Environment variable is not set.
if (TOOLCHAIN_NAME)
# But CMake variable is set.
# Store it into the environment and use it.
set(ENV{MY_TOOLCHAIN_NAME} ${TOOLCHAIN_NAME})
else()
# Neither environment nor CMake variable is set.
message(SEND_ERROR "Please specify toolchain name in -DTOOLCHAIN_NAME parameter")
endif()
endif()
If you have several "tuning" variables, you may write a macro for all above steps and apply(call) this macro for every variable you need.
I am trying to configure the bcl2fastq program that uses CMake. I found the line that triggers this error message
file:bcl2fastq/src/cmake/cxxConfigure.cmake
############## content ####################
..... # ignoring many lines
bcl2fastq_find_header_or_die(HAVE_SYS_STAT_H sys/stat.h)
......# more lines following
error message:
-- time.h found as /usr/include/time.h
-- unistd.h found as /usr/include/unistd.h
CMake Error at cmake/macros.cmake:80 (message):
Required header sys/stat.h not found.
Call Stack (most recent call first):
cmake/cxxConfigure.cmake:41 (bcl2fastq_find_header_or_die)
cxx/CMakeLists.txt:34 (include)
On my system, the sys/stat.h is located in
/usr/include/x86_64-linux-gnu
In the past, I add a symbolic link in /usr/include to the sys/stat.h, which patched the problem. Can someone suggest a better method by modifying the CMake files?
Digging deeper, I found the macros.cmake file in the same directory as cxxConfigure.cmake contains the macro definition:
#
# Macro to find libraries, with support for static-only search
#
macro(bcl2fastq_find_header_or_die variable file)
find_file(${variable} ${file} HINTS ENV C_INCLUDE_PATH ENV CPATH ENV CPLUS_INCLUDE_PATH)
if (${variable})
message(STATUS "${file} found as ${${variable}}")
else (${variable})
message(FATAL_ERROR "Required header ${file} not found.")
endif (${variable})
endmacro(bcl2fastq_find_header_or_die)
Then I did the following:
export C_INCLUDE_PATH=/usr/include/x86_64-linux-gnu
After that, CMake seems to be happy. Not sure this is the proper way to handle this problem.
Exporting the environment variable like
export C_INCLUDE_PATH=/usr/include/x86_64-linux-gnu
is one use.
Moreover, according to the doc on the find_path command, PATHS should be used over HINTS for hard-coded guesses, which means modifying macros.cmake like this
find_file([...] PATHS /usr/include/x86_64-linux-gnu)
is more appropriate. For more flexibility, this could be combined with a PATHS ENV variable, too. The use of PATHS vs HINTS has also been asked in the CMake mailing list here, but the explanation didn't offer much more than the documentation entry.
I created a folder called sys in /usr/include.
Copied over the stat.h into that folder and ran the make command again. The bcl2fastq build completed without any issues.
Write <sys/stat.h> instead of <stat.h> in your code.
I have a cmake cross compiler toolchain file, abridged as:
set(CMAKE_SYSTEM_NAME Linux)
if( DEFINED TC_PATH )
message( STATUS " TC_PATH IS defined. ${TC_PATH}" )
else()
message( FATAL_ERROR " TC_PATH not defined." )
endif()
set(CMAKE_C_COMPILER ${TC_PATH}/usr/bin/i586-linux/i586-linux-gcc )
set(CMAKE_CXX_COMPILER ${TC_PATH}/usr/bin/i586-linux/i586-linux-g++ )
set(CMAKE_LINKER ${TC_PATH}/usr/bin/i586-linux/i586-linux-ld )
I call cmake, setting the TC_PATH as well as the toolchain file:
~/CMakeTest/output $ cmake -DTC_PATH:PATH=/opt/toolchain -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake ../
It appears cmake is invoking the toolchain file multiple times. On the first two time, the TC_PATH check succeeds, but later, after identifying the compilers, it throws an error:
-- TC_PATH IS defined. /opt/toolchain
-- TC_PATH IS defined. /opt/toolchain
-- The C compiler identification is GNU 4.9.1
-- The CXX compiler identification is GNU 4.9.1
-- Check for working C compiler: /opt/toolchain/usr/bin/i586-linux/i586-linux-gcc
CMake Error at /home/gnac/CMakeTest/toolchain.cmake:4 (message):
TC_PATH not defined.
Call Stack (most recent call first):
/home/gnac/CMakeTest/output/CMakeFiles/3.0.2/CMakeSystem.cmake:6 (include)
CMakeLists.txt:2 (project)
So, outside of setting a permanent environment variable in the shell, how I can set the TC_PATH variable via the command line so that it will be remain in context while executing the cmake generate command?
When compiling a test project, CMake does not pass variables to it by default.
There is CMAKE_TRY_COMPILE_PLATFORM_VARIABLES option for passing variables into the test project.
In order to fix your issue, this line should be put into the toolchain file:
set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES TC_PATH)
Your toolchain needs to be self-sufficient. The step that fails is a try_compile() which is not getting your cached variables.
Your toolchain file does not look like you're cross-compiling (it does not have a CMAKE_SYSTEM_NAME) so you can do one of the following (besides setting the CC and CXX environment variables as you have mentioned):
It's sufficient to give the full path to your C and/or CXX compiler (depending on which languages you enabled), CMake will detect the rest of your GNU toolchain automatically
cmake -DCMAKE_C_COMPILER:PATH=/opt/toolchain/usr/bin/i586-linux/i586-linux-gcc
-DCMAKE_CXX_COMPILER:PATH=/opt/toolchain/usr/bin/i586-linux/i586-linux-g++ ...
Add the following to your toolchain to skip the compiler tests (because not all options may be passed to it or because your compiler/linker of choice will not produce a valid executable)
set(CMAKE_C_COMPILER_WORKS 1 CACHE INTERNAL "")
set(CMAKE_CXX_COMPILER_WORKS 1 CACHE INTERNAL "")
Or just use the CMakeForceCompiler macros, but the use is "Discouraged. Avoid using this module if possible."
Use configure_file() to put the path into your toolchain file (just make sure to do it before the project() call)
Prefer find_program() if the possible paths of your toolchain are known over setting it from the outside (see e.g. here)
References
CMake FAQ: How do I use a different compiler?
how to specify new gcc path for cmake
CMake Cross Compiling
cmake: problems specifying the compiler (2)
cmake cross-compile with specific linker doesn't pass arguments to armlink
CMake: In which Order are Files parsed (Cache, Toolchain, …)?
I am sorry that I have to revive this but I'm still wondering why I need to resort to hacks like this to propagate variables to the toolchain configuration file:
...
elseif(${OS_FSFW} STREQUAL linux AND TGT_BSP)
if(NOT SOME_VARIABLE_USED_BY_TOOLCHAINFILE)
set(ENV{SOME_VARIABLE_USED_BY_TOOLCHAINFILE} "$ENV{HOME}/raspberrypi/rootfs")
else()
set(ENV{SOME_VARIABLE_USED_BY_TOOLCHAINFILE} "${SOME_VARIABLE_USED_BY_TOOLCHAINFILE}")
endif()
set(CMAKE_TOOLCHAIN_FILE
${CMAKE_CURRENT_SOURCE_DIR}/buildsystem/cmake/CrossCompileConfig.cmake
)
endif()
I mean, it works, but why is the toolchain file unable to handle variables set by the upper CMakeList properly? CMake is even able to print out variables set that way, but doing things like checking their existence does not appear to work unless they are environmental variables.
I have checked out a version of project from SVN. Below are the different kinds of errors I got while trying to CMAKE a project from SVN. Could it be that some of the files are not checked out? Please, go through the three kinds of errors and help me out with it.
==================Type 1==================================
CMake Error at CMakeLists.txt:184 (add_subdirectory):
add_subdirectory given source "google/gmock" which is not an existing
directory.
==================Type 2==================================
Subversion executable was not found.
CMake Error at CMakeLists.txt:14 (UpLinqSVN_WC_INFO):
Unknown CMake command "UpLinqSVN_WC_INFO".
Call Stack (most recent call first):
CMakeLists.txt:207 (CreateVersionInfo)
========================TYPE 3==========================================
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:
FFMPEG_AVCODEC_LIB
linked by target "UpLinq" in directory C:/Users/Krishna/Desktop/2.5/GUI
FFMPEG_AVCORE_LIB
linked by target "UpLinq" in directory C:/Users/Krishna/Desktop/2.5/GUI
FFMPEG_AVDEVICE_LIB
linked by target "UpLinq" in directory C:/Users/Krishna/Desktop/2.5/GUI
Configuring incomplete, errors occurred!
Error 1 indeed indicates that the CMakeLists.txt expected there to be a directory called google/gmock (relative to the CMakeLists.txt which is calling add_subdirectory at line 184).
Without more info, there's no way to tell if this is an error in the CMakeLists file or in the repository.
The first part of error 2 (can't find Subversion exe) looks like a custom error message. It may be looking for a ".svn" folder in the project root, and assuming that Subversion is available. Presumably it then looks for the Subversion exe and fails to find it (not in path maybe?)
The second part of error2 (unknown CMake command) is saying that at line 14 of CMakeLists.txt, there's a command called UpLinqSVN_WC_INFO being invoked. It doesn't recognise this as a valid command, which probably means that it's defined as a function or macro in another CMake file somewhere. It would need to be defined before it's invoked at line 14. It could be that the CMakeLists.txt you're executing is expected to be run as part of a larger build, which would define this function before starting on your CMakeLists.txt.
Error 3 is saying that there's a CMake target called "UpLinq" (an exe or lib) which has a dependency on ${FFMPEG_AVCODEC_LIB}. At some point, there's probably been a find_library call looking for the avcodec library which has also failed. The result of the search is held in the variable FFMPEG_AVCODEC, and it shows that ${FFMPEG_AVCODEC} has a value of FFMPEG_AVCODEC-NOTFOUND.
If you need more help than this, you'll need to put up a copy of the relevant parts of the CMakeLists files involved, and a bit more info about your environment / directory structures.