Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

buildsystem: fix support for cmake older than 3.8 #1428

Closed
wants to merge 1 commit into from
Closed

buildsystem: fix support for cmake older than 3.8 #1428

wants to merge 1 commit into from

Conversation

yann-morin-1998
Copy link
Contributor

In e8b6b7a, we relaxed the cmake version check down to 3.1, the first
version to expose target_compile_features().

However, an error while testing that change improperly concluded that
the change was OK. While target_compile_features() was indeed intriduced
in cmake 3.1, the actual feature we use it to test, cxx_std_11, was
really introduced only with cmake-3.8, which explained the actual
version that was requested before e8b6b7a.

As Patrick noted, however, we can still convince cmake-3.1 to test
for C++11, by testing for an actual feature introduced in C++11, like
testing for cxx_range_for, which will instruct cmake to set the
appropriate C++11 options for the current compiler, which for gcc would
be adding -std=gnu++11.

Reported-by: Patrick Boettcher patrick.boettcher@posteo.de
Signed-off-by: "Yann E. MORIN" yann.morin.1998@free.fr

In e8b6b7a, we relaxed the cmake version check down to 3.1, the first
version to expose target_compile_features().

However, an error while testing that change improperly concluded that
the change was OK. While target_compile_features() was indeed intriduced
in cmake 3.1, the actual feature we use it to test, cxx_std_11, was
really introduced only with cmake-3.8, which explained the actual
version that was requested before e8b6b7a.

As Patrick noted, however, we can still convince cmake-3.1 to test
for C++11, by testing for an actual feature introduced in C++11, like
testing for cxx_range_for, which will instruct cmake to set the
appropriate C++11 options for the current compiler, which for gcc would
be adding -std=gnu++11.

Reported-by: Patrick Boettcher <patrick.boettcher@posteo.de>
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
@yann-morin-1998
Copy link
Contributor Author

@pboettch Could you please give your opinion on this? Thanks! ;-)

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 70f8af1 on yann-morin-1998:yem/fix-cxx11-old-cmake into e5753b1 on nlohmann:develop.

@nlohmann
Copy link
Owner

I'd also like to know whether @pboettch is fine with the change. I am just concerned about the different semantics:

  • In 3.4.x we had -std=c++11 as explicit flag for C++11.
  • Then we moved to cxx_std_11 which is the same, but compiler-agnostics. It was only ugly, because it required CMake 3.8.
  • Now we only check whether ranged for loops are supported. I am aware that this is a C++11 feature, but there were compilers supporting this, but only a subset of C++11. These compiler should be excluded by the compiler version check in the library, though.

We could switch to

if (${CMAKE_VERSION} VERSION_LESS "3.8.0") 
    target_compile_features(catch_main PUBLIC cxx_range_for)
else()
    target_compile_features(catch_main PUBLIC cxx_std_11)
endif()

to use cxx_range_for only where cxx_std_11 is not available. Do you think this is nitpicky?

@nlohmann nlohmann added the state: please discuss please discuss the issue or vote for your favorite option label Jan 14, 2019
@pboettch
Copy link
Contributor

In the meantime I had a problem with another project with cxx_range_for vs. cxx_std_11.

The conclusion there was to force CMake 3.8 and leave cxx_std_11. Because we wanted to force C++11.

cxx_range_for requires the compiler to at least activate C++11; with gcc-7 it will be C++14 and gcc-8 even C++17 (I believe) whereas cxx_std_11 forces C++11 even on compilers defaulting to later C++-versions.

In addition setting cxx_std_11 as PUBLIC on a library will make all dependents inherit the forced flag.

Hmm. Maybe for this library using cxx_range_for as a "at least C++11 is needed" is the best option.

There is also the property CXX_STANDARD_11 and CXX_STANDARD_REQUIRED, but target-properties are not transitive and they don't solve the 'C++11 or later'-idea.

set_property(TARGET <tgt> PROPERTY CXX_STANDARD 11)
set_property(TARGET <tgt> PROPERTY CXX_STANDARD_REQUIRED ON)

@yann-morin-1998
Copy link
Contributor Author

@pboettch @nlohmann Sorry guys, but this is straddling into C++ and cmake
topics I am definitely neither accustomed to nor aware of, and is getting far
from my initial goal of making it work on older cmake.

If it were me, I would just revert my previous change to at least restore the
previous, working situation. Then, if people are still motivated by supporting
older cmake versions, a better solution can be devised; then.

@nlohmann
Copy link
Owner

I agree - we should revert to the status quo, requiring 3.8.0 and using cxx_std_11. @yann-morin-1998 can you make a PR, pleae?

@yann-morin-1998
Copy link
Contributor Author

@nlohmann Sure, I'll send it in a moment.

@yann-morin-1998 yann-morin-1998 deleted the yem/fix-cxx11-old-cmake branch January 15, 2019 21:32
@iwanders
Copy link
Contributor

I would really like to be able to use a cmake version that's less recent. Some of us are still on Ubuntu 16.04, which ships with CMake 3.5.1. Using this library on Xenial requires modifying the CMakeLists just to change that feature requirement on the target.

I've filed #1441, which has the if statement approach @nlohmann suggested, please consider merging that workaround to support older versions of cmake.

@iwanders
Copy link
Contributor

Closed #1441 because of the point raised by @pboettch that the if statement will cause different behaviour depending on the CMake version, which is undesirable.

I presume in this case that we weren't setting cxx_std_11 to force C++11 was used even by compilers that support C++14 and C++17. Because if we explicitly don't want C++14 or C++17 the following point isn't worth raising:

Hmm. Maybe for this library using cxx_range_for as a "at least C++11 is needed" is the best option.

Instead of picking cxx_range_for, why not use cxx_auto_type? That is supported by CMake 3.1 and both range based for and auto were introduced with C++11. While that technically doesn't ensure all the features this library requires are provided by the compiler, it may strike a balance between the CMake version requirement and the way we select the C++ version?

@pboettch
Copy link
Contributor

As I said in your PR. There is no difference for CMake whether you put cxx_range_for or cxx_auto_type.

@iwanders
Copy link
Contributor

Oh, now I see what you mean. You are right, cxx_range_for is supported by CMake 3.1 just like cxx_auto_type >_<. My bad, sorry about that.

If deemed acceptable I'd be happy to file a PR that does:

cmake_minimum_required(VERSION 3.1)
#...
target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_range_for)

@nlohmann
Copy link
Owner

Fixed with #1441.

@nlohmann nlohmann added solution: proposed fix a fix for the issue has been proposed and waits for confirmation release item: ⚡ improvement and removed state: please discuss please discuss the issue or vote for your favorite option labels Mar 10, 2019
@nlohmann nlohmann added this to the Release 3.6.0 milestone Mar 10, 2019
@nlohmann nlohmann self-assigned this Mar 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release item: ⚡ improvement solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants