Different ways of setting CXX standard - cmake

Whenever it comes to set C++ standard in a project I generally use this way:
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED On)
But recently I came across a recommendation where they suggest to use this way:
set_property(TARGET MyApp PROPERTY CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED On)
Is there any difference between these two?

Rereading the recommendation I realized that I misunderstood the message. The thing is that we use this:
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED On)
To set a default standard for all targets. But with some targets we might want to user a different standard (a newer one for example) and then we can override it for this specific target as such:
set_property(TARGET FooLib PROPERTY CXX_STANDARD 20)
Thanks to #Tsyvarev for pointing this out.

Related

How to use EXCLUDE_FROM_ALL in CMake?

I'm trying to understand how to use EXCLUDE_FROM_ALL in CMakeList.txt. I've seen this example:
add_library(foo STATIC EXCLUDE_FROM_ALL "src/foo.cpp")
The only thing I understood from the documentation is that this property is a boolean value. But what does it do, and how do I use it in add_executable(), for example?
Thank you.

CMake: How to make dependence on package optional?

I would like MPI to be optional for using my code.
I currently have a Cmake project that includes MPI as follows in the CMakeLists.txt:
find_package(MPI REQUIRED)
My some of my .cpp and .h files have the following:
#define MPI_available true
On a system where MPI is not available, one can remove the first statement and change the second statement into #define MPI_available false. Then the code is structured such that it doesn't attempt to include ``mpi.h''. However, I would prefer CMAKE to detect the presence/absence of MPI, and set the MPI_available flag for compiling the source files accordingly.
I believe setting
find_package(MPI QUIET)
will ensure that cmake does not choke when it cannot find MPI. Is this the preferred way of getting where I want to be? If so, how to link this to the flag? If not, what should I do to make MPI optional when cmake-> making the code.
Call to find_package(someLib) sets a variable someLib_FOUND. You can use it to check whether the someLib is available, then you can set a compile definitions. Something like:
find_package(MPI)
if(NOT MPI_FOUND)
target_compile_definitions(yourTarget PUBLIC MPI_available=0)
endif()
Calling cmake's default FindMPI.cmake module through find_package(MPI) already ensures that cmake will define the variable MPI_FOUND to reflect whether mpi was found or not.
Afterwards, you can use MPI_FOUND to achieve your goal. For example, you can generate your project's config.h with calls to cmake's config_file to define macros such as MPI_available, and update your code accordingly.

how to add BEFORE to interface included directories for exported target?

I have a exported target A::A, there is a INTERFACE_INCLUDE_DIRECTORIES, A_includes.
set_target_properties(A::A PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${A_INCLUDE_DIRS}")
With old style I can add BEFORE to target_include_directories like following, to make sure the A_includes come before the system ones:
target_include_directories(
some_target
BEFORE
PRIVATE
${A_includes}
)
But I want to use the modern style with the exported target:
target_link_libraries(
some_target
PRIVATE
A::A
)
However, the modern one does not allow me to pass BEFORE. Is there any way to set the BEFORE during target exporting? Is there a way to make includes form A::A go before system one when I use it in a project?

CMake compiler independent flags

Are there any compiler independent flags that can be set? I'd like to be able to set single variable to e.g. OPTIMIZE_MOST and get -O3 on gcc and /O2 in MS C++ compiler. Is there something I can use or should flags be set for each compiler separately?
Simply spoken: No, there is no flag to directly set the optimization level independently for every compiler.
However, CMake provides so called build types. Those are independent of the compiler in use and each comes with a predefined selection of flags, one of which is the optimization flag.
Available build types are
Debug
Release
RelWithDebInfo
MinSizeRel
For a comprehensive explanation, I refer to this answer. It also provides some code that helps to identify the flags in question when included into the CMakeLists.txt file:
message("CMAKE_C_FLAGS_DEBUG is ${CMAKE_C_FLAGS_DEBUG}")
message("CMAKE_C_FLAGS_RELEASE is ${CMAKE_C_FLAGS_RELEASE}")
message("CMAKE_C_FLAGS_RELWITHDEBINFO is ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
message("CMAKE_C_FLAGS_MINSIZEREL is ${CMAKE_C_FLAGS_MINSIZEREL}")
message("CMAKE_CXX_FLAGS_DEBUG is ${CMAKE_CXX_FLAGS_DEBUG}")
message("CMAKE_CXX_FLAGS_RELEASE is ${CMAKE_CXX_FLAGS_RELEASE}")
message("CMAKE_CXX_FLAGS_RELWITHDEBINFO is ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
message("CMAKE_CXX_FLAGS_MINSIZEREL is ${CMAKE_CXX_FLAGS_MINSIZEREL}")
To a degree. For some concepts, CMake has support for specifying them in a compiler-agnostic manner, usually by setting properties on the target in question. Unfortunately, there is no one location where all such possibilities would be listed. I went through the current list of target properties and identified the following properties as "absrtacting away build-tool option syntax":
COMPILE_PDB_NAME
INCLUDE_DIRECTORIES
INSTALL_RPATH
INTERPROCEDURAL_OPTIMIZATION
LINK_DIRECTORIES
LINK_LIBRARIES
PDB_NAME
PDB_OUTPUT_DIRECTORY
(plus the properties for setting output name, path, etc.)
There is apparently nothing for handling optimisation flags other than IPO.
To the best of my knowledge, there is also no generic process for adding these — they are added to CMake as someone finds the need for them (and the time to implement them).

What are legal items in the INTERFACE_LINK_LIBRARIES property?

My expectations are, that the items in the target property INTERFACE_LINK_LIBRARIES are other targets. However when I use on Linux for the official Threads package.
find_package(Threads)
get_property(libs TARGET Threads::Threads PROPERTY INTERFACE_LINK_LIBRARIES)
libs ist set to -lpthread, which seems to be a linker flag, not a target.
Is this correct?
That property is populated by the command target_link_libraries(), and its documentation lists what can be specified:
A library target name
A full path to a library file
A plain library name
A link flag
Keywords debug, optimized, or general
Therefore, link flags are allowed here, even if discouraged by the CMake documentation.