I have a C++ project that consists of a main program (
main.cpp), a header that defines an abstract class (
algorithm.hpp), and a subdirectory (
algorithms/) full of classes that implement the abstract class. I’ve configured CMake to build the subdirectory as an object library:
# algorithms/CMakeLists.txt add_library(algorithms_lib OBJECT algo1.cpp algo2.cpp # etc. )
In my project’s root directory, I use this object library as one of the application’s sources:
# Top-level CMakeLists.txt cmake_minimum_required(VERSION 3.1) project(MyApp CXX) add_subdirectory(algorithms) add_executable(my-app main.cpp $<TARGET_OBJECTS:algorithms_lib> )
My application is written in C++14, so I need to tell CMake to use the correct compile options for that. I don’t want to require CMake version 3.8 (since it’s not packaged in some recent Linux distros that I want to support), so I can’t use the
cxx_std_14 compile feature; instead, I’ve listed a bunch of individual language features that I use:
# Top-level CMakeLists.txt (cont.) target_compile_features(my-app PUBLIC cxx_auto_type cxx_constexpr cxx_defaulted_functions # ...14 more lines... )
The problem is, these features only apply to the top-level
my-app target, not the
algorithms_lib target, so the sources in the subdirectory don’t get compiled as C++14.
I know I could copy the whole big
target_compile_features block into
algorithms/CMakeLists.txt, but I’d rather not do that — especially since this example is simplified and I actually have nine such subdirectories, each building its own object library. That’d be a lot of duplication of boilerplate code.
Is there a way to set compile features globally for all C++ targets in the project, including subdirectories? Or would it be better to get rid of
add_subdirectory and the object library, and just list all the individual subdirectory files in the top-level
add_executable command? I’m new to CMake, so I don’t know what the “best practices” are for this sort of thing.
It sounds like you want to put the following at the top of your
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF)
These set defaults for the same-named target properties without the leading
CMAKE_. The equivalent target properties do the following:
CXX_STANDARD yy sets the desired minimum C++ standard your code wants to use.
CXX_STANDARD_REQUIRED bb says whether
CXX_STANDARD is a requirement (
YES or some other boolean equivalent) or whether it is just desirable (
NO or equivalent).
CXX_EXTENSIONS bb enables (
bb = YES) or disables (
bb = NO) compiler extensions.
You don’t need to specify individual compiler features to achieve what you’re ultimately trying to do (enable C++14 for your targets). You can find a full discussion of this whole area here.