The Good (C++11/14), the Bad (CMAKE_CXX_FLAGS) and the Ugly (cmake)
I have tried to find an updated answer with the best practices when dealing with ROS and C++11/14, but everything is messy or out of date...
0 - Setting the C++ standard directly [DEPRECATED]
I know that the quicker way to enable C++11/14 is to add in the CMakeLists.txt
one of the following macros
cmake_minimum_required(VERSION 2.8.3 FATAL_ERROR)
...
set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_CXX_FLAGS "-std=c++14")
even with all the possible checks (see the many answers on SO or this one).
Nonetheless it is written everywhere - apparently not enough though - NOT to set CMAKE_CXX_FLAGS
(e.g. catkin docs).
So I have searched a bit more to find some updated guidelines for cmake and C++11/14 like the followings: [1], [2], [3], [4]. It comes out that since cmake v3.1/3.2
there are two main methods which overcome the CMAKE_CXX_FLAGS
manual setup.
1 - Setting the C++ standard directly
The standard C++11/14 can be specified directly and the *_REQUIRED
protects the building from potential compiler errors if the standard is not supported.
cmake_minimum_required(VERSION 3.2.0 FATAL_ERROR)
...
set_property(TARGET target1 target2 ... PROPERTY CXX_STANDARD 11) # 98, 11 or 14
set_property(TARGET target1 target2 ... PROPERTY CXX_STANDARD_REQUIRED ON)
Otherwise the CMAKE_*
variables specify the properties for all the targets in the CMakeLists.txt
([8], [9]).
2 - Setting the C++ standard based on features
If a finer tuning or a higher control is required, the right C++ standard can be set from the features which are really used in the code. This is surely more accurate, but it requires time to be properly set (lots of features) and can be fragile if not supported correctly over time.
cmake_minimum_required(VERSION 3.2.0 FATAL_ERROR)
...
target_compile_features(myTarget
PUBLIC
cxx_variadic_templates
cxx_nullptr
...
PRIVATE
cxx_lambdas
...
)
Note
In every docs regarding ROS you always find cmake_minimum_required(VERSION 2.8.3)
which is fine to guarantee that our code could be compiled even with older cmake version, and everybody seems happy.
The current version of cmake shipped with Ubuntu 16.04 and ROS Kinetic (both LTS, and hoping the new standard for at least a couple of years) is the 3.5.1
. The drawback of allowing such an old cmake compatibility is the unkown behaviour in not tested old systems (which is the case of almost every small project). Indeed another best practice for cmake usage is to set the minimum required version to the lower testable one.
The question is: what is ROS waiting for to increase the minimum requirements to at least cmake v3.2
and to improve docs with updated best practices?
re: what are we waiting for: the EOL of Trusty, which is still 2.5 years away (see wiki/Distributions)? (note: this is a question, not a statement)
Also: IIRC, CMake 2.8.3 should support setting target-specific properties via
SET_TARGET_PROPERTIES
andCOMPILE_FLAGS
. Doesn't that circumvent the problem you are implicitly describing (setting C++ standard for the entire workspace)?Other 2.5 years of backward compatibility of cmake 2.8.3? I could understand this for Indigo and Jade, but at least Kinetic should try to use up-to-date standards in my opinion.
I think you could use the
COMPILE_FLAGS
, but I was wondering about best practices, not workaround. If I get the point from the overall references, you should never manually set compiler flags in theCMakeLists.txt
.Indigo and Kinetic are the two LTS releases right now. From a maintenance point of view, it makes sense to standardise on a single build infra. I'm not the OSRF, but I can imagine moving to CMake 3+ has not been high on the agenda. ROS2 has migrated to C++11/CMake 3.5+ though.
Perhaps this is more a discussion thing, not so much a question. Not sure, but perhaps the discourse.ros.org site might be more suited for that.
Merely trying to be pragmatic. Using
set_target_properties(..)
withCOMPILE_FLAGS
would allow you to do what you want, right now, in Indigo, even with ancient CMake.Btw, Kinetic has standardised on CMake 3.0.2, see REP-3 - Platforms by Distribution - Kinetic Kame.