OS specific instructions in CMAKE: How to?
Use
if (WIN32)
# do something
endif (WIN32)
or
if (UNIX)
# do something
endif (UNIX)
or
if (MSVC)
# do something
endif (MSVC)
or similar
see CMake Useful Variables
and CMake Checking Platform
How to make CMakelists.txt to include some *.c and *.h files only for one OS?
The modern CMake solution is to use target_sources
.
# common sources
add_executable(${TARGET}
main.cpp
mainwindow.cpp
mainwindow.h
mainwindow.ui
)
# Stuff only for WIN32
if (WIN32)
target_sources(${TARGET}
PRIVATE test.c
PUBLIC test.h
)
endif()
This should make your CMakeLists.txt
files easier to maintain than wrangling variables.
How to construct CMake files to be OS generic but specific too?
Use code like this in your CMakeLists.txt:
if(UNIX AND NOT APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
elseif(WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_LEAN_AND_MEAN")
endif()
Notes:
- Append your options to ${CMAKE_CXX_FLAGS} so that user-specified settings are also included.
- You cannot use list(APPEND ...) with compiler flags because it uses semicolons to separate parameters (this is why the code above uses set(...) with quotes)
- APPLE is also UNIX, so we need NOT APPLE when we actually mean Linux
Platform detection in CMake
Here is a simple solution.
macro(get_WIN32_WINNT version)
if (WIN32 AND CMAKE_SYSTEM_VERSION)
set(ver ${CMAKE_SYSTEM_VERSION})
string(REPLACE "." "" ver ${ver})
string(REGEX REPLACE "([0-9])" "0\\1" ver ${ver})
set(${version} "0x${ver}")
endif()
endmacro()
get_WIN32_WINNT(ver)
add_definitions(-D_WIN32_WINNT=${ver})
How to specify new GCC path for CMake
Do not overwrite CMAKE_C_COMPILER
, but export CC
(and CXX
) before calling cmake:
export CC=/usr/local/bin/gcc
export CXX=/usr/local/bin/g++
cmake /path/to/your/project
make
The export only needs to be done once, the first time you configure the project, then those values will be read from the CMake cache.
UPDATE: longer explanation on why not overriding CMAKE_C(XX)_COMPILER
after Jake's comment
I recommend against overriding the CMAKE_C(XX)_COMPILER
value for two main reasons: because it won't play well with CMake's cache and because it breaks compiler checks and tooling detection.
When using the set
command, you have three options:
- without cache, to create a normal variable
- with cache, to create a cached variable
- force cache, to always force the cache value when configuring
Let's see what happens for the three possible calls to set
:
Without cache
set(CMAKE_C_COMPILER /usr/bin/clang)
set(CMAKE_CXX_COMPILER /usr/bin/clang++)
When doing this, you create a "normal" variable CMAKE_C(XX)_COMPILER
that hides the cache variable of the same name. That means your compiler is now hard-coded in your build script and you cannot give it a custom value. This will be a problem if you have multiple build environments with different compilers. You could just update your script each time you want to use a different compiler, but that removes the value of using CMake in the first place.
Ok, then, let's update the cache...
With cache
set(CMAKE_C_COMPILER /usr/bin/clang CACHE PATH "")
set(CMAKE_CXX_COMPILER /usr/bin/clang++ CACHE PATH "")
This version will just "not work". The CMAKE_C(XX)_COMPILER
variable is already in the cache, so it won't get updated unless you force it.
Ah... let's use the force, then...
Force cache
set(CMAKE_C_COMPILER /usr/bin/clang CACHE PATH "" FORCE)
set(CMAKE_CXX_COMPILER /usr/bin/clang++ CACHE PATH "" FORCE)
This is almost the same as the "normal" variable version, the only difference is your value will be set in the cache, so users can see it. But any change will be overwritten by the set
command.
Breaking compiler checks and tooling
Early in the configuration process, CMake performs checks on the compiler: Does it work? Is it able to produce executables? etc. It also uses the compiler to detect related tools, like ar
and ranlib
. When you override the compiler value in a script, it's "too late", all checks and detections are already done.
For instance, on my machine with gcc as default compiler, when using the set
command to /usr/bin/clang
, ar
is set to /usr/bin/gcc-ar-7
. When using an export before running CMake it is set to /usr/lib/llvm-3.8/bin/llvm-ar
.
How to detect if 64 bit MSVC with cmake?
There are several ways - also used by CMake itself - that will check for "not 64Bit":
if(NOT "${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)")
...
endif()
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
...
endif()
if(NOT CMAKE_CL_64)
...
endif()
References
CMAKE_GENERATOR
CMAKE_SIZEOF_VOID_P
CMAKE_CL_64
Related Topics
Precise Thread Sleep Needed. Max 1Ms Error
Should I Worry About the Alignment During Pointer Casting
Random Number C++ in Some Range
Error: Invalid Operands of Types 'Const Char [35]' and 'Const Char [2]' to Binary 'Operator+'
Error Enabling Openmp - "Ld: Library Not Found for -Lgomp" and Clang Errors
What's the Meaning of * and & When Applied to Variable Names
Inherit Interfaces Which Share a Method Name
Is There a Range Class in C++11 for Use with Range Based for Loops
Why Should I Use the "Using" Keyword to Access My Base Class Method
C++ Exception:Throwing Std::String
Type Erasing Type Erasure, 'Any' Questions
Simple Way to Unzip a .Zip File Using Zlib