I want to check default cmake build mode.
when i do this:
message(${CMAKE_BUILD_TYPE})
it comes out:
CMake Error at CMakeLists.txt:9 (message):
message called with incorrect number of arguments
seems not existed environment variable ${CMAKE_BUILD_TYPE}.
I also read some blogs, which said, i can:
cmake -L . | grep CMAKE_BUILD_TYPE
to check, but i got:
CMAKE_BUILD_TYPE:STRING=
So, how to check my cmake default build mode?
I want to use release mode, but seems
cmake ..
and
cmake .. -DCMAKE_BUILD_TYPE=Release
make no difference in the messages.
Could you help on this?
The default is that CMAKE_BUILD_TYPE is undefined, which equates to a toolchain-specific implicit default.
Personally I add something like...
if ( NOT CMAKE_BUILD_TYPE )
message( "Build Type not set, defaulting to Debug..." )
set( CMAKE_BUILD_TYPE Debug )
endif()
...both to make the default explicit, and to default to Debug, as you usually build that much more often than the Release configuration.
Related
Consider the following CMakeLists.txt file:
project(MyProject)
cmake_minimum_required(VERSION 3.16)
add_executable(MyApp main.cpp)
message(${CMAKE_CXX_FLAGS})
Now, running this:
$ cmake --DCMAKE_BUILD_TYPE=Debug <path_to_directory>
I get an error that the CMAKE_CXX_FLAGS is not set. (more accurately - message is called with wrong number of arguments).
I try to understand what exactly the CMAKE_BUILD_TYPE is causing by default - i.e. how it translates to compiler options/flags.
After building the project, I can clearly see that when running with CMAKE_BUILD_TYPE set to Release, the file is smaller (around a third) than when running with it set to Debug, so clearly it has some effect.
First of all, you must always call cmake_minimum_required before any other commands.
cmake_minimum_required(VERSION 3.16)
project(MyProject)
add_executable(MyApp main.cpp)
message(STATUS "CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}")
Now, to answer your question...
Why is CMAKE_CXX_FLAGS empty?
Because it is intended to be set on the command line by a user of your build. This is the place where you would inject flags that apply to all C++ compiler invocations, regardless of configuration.
I try to understand what exactly the CMAKE_BUILD_TYPE is causing by default - i.e. how it translates to compiler options/flags.
On a multi configuration generator, like Visual Studio or Xcode, it does nothing. On a single configuration generator (like Makefiles or Ninja), the variable sets the active config. That means that all the variables listed in the documentation with <CONFIG> in the name get ${CMAKE_BUILD_TYPE} substituted in for <CONFIG> and used alongside their non-<CONFIG> variants.
There are four configurations that CMake provides:
Debug -- don't optimize and ensure debug symbols are enabled. On GCC this is -g.
Release -- full optimization, disable assert(). On GCC this is -O3 -DNDEBUG.
MinSizeRel -- release mode, but optimize for size. On GCC this is -Os -DNDEBUG.
RelWithDebInfo -- release mode, but optimize less to facilitate debugging. Include debug symbols. On GCC this is -O2 -g -DNDEBUG.
I am trying to do something like
cmake -DCMAKE_CONFIGURATION_TYPES="Debug;RelWithDebInfo" ...
I wanted to check if I did not have any mistakes in type names so I tried something nonsensical hoping cmake will error out and confirm that my configuration types are correct.
cmake -DCMAKE_CONFIGURATION_TYPES="Debug;Relalaland" ...
But cmake just creates the configuration types I specify...
Is there a way to tell cmake to not accept unfamiliar CONFIGURATION_TYPES?
Is there a way to tell cmake to not accept unfamiliar CONFIGURATION_TYPES?
Don't. A user might want to define a custom configuration type externally, which is perfectly possible to do in a toolchain file or at the command line. One use for this might be for sanitizer builds. In general, you should avoid restricting what your users can do with your build. Only hard requirements go in your CMakeLists.txt and denying a custom build type doesn't qualify.
All that said, here's how you can do this:
set(known_types Debug Release RelWithDebInfo MinSizeRel)
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if (is_multi_config)
foreach (config IN LISTS CMAKE_CONFIGURATION_TYPES)
if (NOT config IN_LIST known_types)
message(FATAL_ERROR "Build type '${config}' invalid. Expected one of: ${known_types}")
endif ()
endforeach ()
elseif (NOT CMAKE_BUILD_TYPE IN_LIST known_types)
message(FATAL_ERROR "Build type '${CMAKE_BUILD_TYPE}' invalid. Expected one of: ${known_types}")
endif ()
This works for both single and multi config generators.
So just check them.
set(allowed_types Debug Release RelWithDebInfo MinSizeRel)
foreach(i IN LISTS CMAKE_CONFIGURATION_TYPES)
if(NOT i IN_LIST allowed_types)
message(FATAL_ERROR "${i} is not valie configuration type")
endif()
endforeach()
I want to set compiler path (for example:icc) automatically in cmake, so my program can compile at any computer as long as it have installed icc, and we do not need to care about where the icc is installed.
At First, I using the follow command to set compiler. Everything is OK.
set(Intel_C_COMPILER "/opt/intel/compilers_and_libraries_2019.0.117/linux/bin/intel64/icc")
set(Intel_CXX_COMPILER "/opt/intel/compilers_and_libraries_2019.0.117/linux/bin/intel64/icpc")
set(CMAKE_C_COMPILER ${Intel_C_COMPILER} )
set(CMAKE_CXX_COMPILER ${Intel_CXX_COMPILER})
project(MyProject)
....
Then, I want to set compiler path automatically, I know that the follow command can find compiler path
which icc
So I write the follow command try to set compiler automatically by cmake.
execute_process(COMMAND which icc OUTPUT_VARIABLE Intel_C_COMPILER)
execute_process(COMMAND which icpc OUTPUT_VARIABLE Intel_CXX_COMPILER)
message(Intel_CXX_COMPILER: ${Intel_C_COMPILER})
message(Intel_CXX_COMPILER: ${Intel_CXX_COMPILER})
set(CMAKE_C_COMPILER ${Intel_C_COMPILER} )
set(CMAKE_CXX_COMPILER ${Intel_CXX_COMPILER})
project(MyProject)
....
At these case, something strange happens, cmake shows that:
Intel_CXX_COMPILER:/opt/intel/compilers_and_libraries_2019.0.117/linux/bin/intel64/icpc
-- The C compiler identification is unknown
-- The CXX compiler identification is unknown
CMake Error at CMakeLists.txt:27 (project): The CMAKE_C_COMPILER:
/opt/intel/compilers_and_libraries_2019.0.117/linux/bin/intel64/icc
is not a full path to an existing compiler tool.
Tell CMake where to find the compiler by setting either the
environment variable "CC" or the CMake cache entry CMAKE_C_COMPILER
to the full path to the compiler, or to the compiler name if it is
in the PATH.
CMake Error at CMakeLists.txt:27 (project): The CMAKE_CXX_COMPILER:
/opt/intel/compilers_and_libraries_2019.0.117/linux/bin/intel64/icpc
is not a full path to an existing compiler tool.
Tell CMake where to find the compiler by setting either the
environment variable "CXX" or the CMake cache entry
CMAKE_CXX_COMPILER to the full path to the compiler, or to the
compiler name if it is in the PATH.
-- Configuring incomplete, errors occurred!
CMake said that the path is not a full path to an existing compiler, but as shown in the message, it is just where the compiler located!
I know there are other techniques that we can set compiler, for example export some environment variables to help cmake find the path, but I want to know why my method dose not work?
Is there any better way can handle this problem?
Thanks in advance.
Variables Intel_C_COMPILER and Intel_CXX_COMPILER have trailing newline. Way for removing that newline are described in that question and its answers: How to strip trailing whitespace in CMake variable?
E.g., you may run execute_process with OUTPUT_STRIP_TRAILING_WHITESPACE option, so it will behave similar to the shell's backtick operator (`which icc`).
Detailed description
Most of shell utilities output single- (or even multi-) line information with trailing newline. And utility which is not an exception. With trailing newline an output looks nice when one run these utilities in the terminal.
But when run such utility in the script and grab its output programmatically, one need to care about such newline.
Generally speaking, it is not possible to set the variables CMAKE_C_COMPILER and CMAKE_CXX_COMPILER from within a project.
Since the compiler detection happens with the project() call, the compiler has to be set early on while configuring the project.
I suggest you try the following:
export CC=/opt/intel/compilers_and_libraries_2019.0.117/linux/bin/intel64/icc
export CXX=/opt/intel/compilers_and_libraries_2019.0.117/linux/bin/intel64/icpc
cd /path/to/build
cmake /path/to/src
or you could also pass the variables CMAKE_C_COMPILER and CMAKE_CXX_COMPILER:
export CC=/opt/intel/compilers_and_libraries_2019.0.117/linux/bin/intel64/icc
export CXX=/opt/intel/compilers_and_libraries_2019.0.117/linux/bin/intel64/icpc
cd /path/to/build
cmake \
-DCMAKE_C_COMPILER:FILEPATH=/opt/intel/compilers_and_libraries_2019.0.117/linux/bin/intel64/icc \
-DCMAKE_CXX_COMPILER:FILEPATH=/opt/intel/compilers_and_libraries_2019.0.117/linux/bin/intel64/icpc \
/path/to/src
Important: When trying these commands, make sure to configure the project in an empty build directory.
I'm having trouble setting a configuration variable via the command line. I can't determine it from the system, so I expect the user to specify:
cmake -DCMAKE_TOOLCHAIN_FILE=../android.toolchain -DANDROID_ABI:STRING="arm64" ..
Inside my android.toolchain, I have the following:
message(STATUS "Android ABI: ${ANDROID_ABI}")
if( "${ANDROID_ABI}" STREQUAL "" )
message(FATAL_ERROR "Please specifiy ABI at cmake call -DANDROID_ABI:STRING=armeabi or -DANDROID_ABI:STRING=arm64")
endif()
No matter what, it fails at this line EVEN THOUGH it prints out the correct arm64:
-- Android ABI: arm64
CMake Error at yaml-cpp/android.toolchain:45 (message):
Please specifiy ABI at cmake call -DANDROID_ABI:STRING=armeabi or -DANDROID_ABI:STRING=arm64
Could anyone direct me to what I'm doing wrong?
I think this has to do with:
-D adds a cache variable instead of a normal variable
This is in a toolchain file... it seems to ignore cache variables
Any thoughts or suggestions?
I don't pretend to fully understand what's going on behind the scenes, but here's a workaround that works for me:
# Problem: CMake runs toolchain files multiple times, but can't read cache variables on some runs.
# Workaround: On first run (in which cache variables are always accessible), set an intermediary environment variable.
if (FOO)
# Environment variables are always preserved.
set(ENV{_FOO} "${FOO}")
else ()
set(FOO "$ENV{_FOO}")
endif ()
CMake 3.6 introduces variable CMAKE_TRY_COMPILE_PLATFORM_VARIABLES which contains a list of variables, automatically passed from the main project to the project, created with try_compile.
A toolchain may add its variables to that list, so they could be extracted in a subproject:
message(STATUS "Android ABI: ${ANDROID_ABI}")
if( "${ANDROID_ABI}" STREQUAL "" )
message(FATAL_ERROR "Please specifiy ABI at cmake call -DANDROID_ABI:STRING=armeabi or -DANDROID_ABI:STRING=arm64")
endif()
# propagate the variable into "inner" subprojects.
list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES "ANDROID_ABI")
Caveats:
This approach affects only to source flow of try_compile command. It won't work when try_compile is used for create fully-fledged CMake project with signature
try_compile(<resultVar> <bindir> <srcdir> <projectName> ...)
(Approach with setting environment variable, as described in the #sorbet answer, works perfectly in this case.)
This approach won't work for a subproject, created with ExternalProject_Add.
(Approach with setting environment variable fails in that case too.)
I'm having trouble setting a configuration variable via the command line. I can't determine it from the system, so I expect the user to specify:
cmake -DCMAKE_TOOLCHAIN_FILE=../android.toolchain -DANDROID_ABI:STRING="arm64" ..
Inside my android.toolchain, I have the following:
message(STATUS "Android ABI: ${ANDROID_ABI}")
if( "${ANDROID_ABI}" STREQUAL "" )
message(FATAL_ERROR "Please specifiy ABI at cmake call -DANDROID_ABI:STRING=armeabi or -DANDROID_ABI:STRING=arm64")
endif()
No matter what, it fails at this line EVEN THOUGH it prints out the correct arm64:
-- Android ABI: arm64
CMake Error at yaml-cpp/android.toolchain:45 (message):
Please specifiy ABI at cmake call -DANDROID_ABI:STRING=armeabi or -DANDROID_ABI:STRING=arm64
Could anyone direct me to what I'm doing wrong?
I think this has to do with:
-D adds a cache variable instead of a normal variable
This is in a toolchain file... it seems to ignore cache variables
Any thoughts or suggestions?
I don't pretend to fully understand what's going on behind the scenes, but here's a workaround that works for me:
# Problem: CMake runs toolchain files multiple times, but can't read cache variables on some runs.
# Workaround: On first run (in which cache variables are always accessible), set an intermediary environment variable.
if (FOO)
# Environment variables are always preserved.
set(ENV{_FOO} "${FOO}")
else ()
set(FOO "$ENV{_FOO}")
endif ()
CMake 3.6 introduces variable CMAKE_TRY_COMPILE_PLATFORM_VARIABLES which contains a list of variables, automatically passed from the main project to the project, created with try_compile.
A toolchain may add its variables to that list, so they could be extracted in a subproject:
message(STATUS "Android ABI: ${ANDROID_ABI}")
if( "${ANDROID_ABI}" STREQUAL "" )
message(FATAL_ERROR "Please specifiy ABI at cmake call -DANDROID_ABI:STRING=armeabi or -DANDROID_ABI:STRING=arm64")
endif()
# propagate the variable into "inner" subprojects.
list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES "ANDROID_ABI")
Caveats:
This approach affects only to source flow of try_compile command. It won't work when try_compile is used for create fully-fledged CMake project with signature
try_compile(<resultVar> <bindir> <srcdir> <projectName> ...)
(Approach with setting environment variable, as described in the #sorbet answer, works perfectly in this case.)
This approach won't work for a subproject, created with ExternalProject_Add.
(Approach with setting environment variable fails in that case too.)