Compiling C++17 using CLion, CMake and the VS2017 compiler - c++

When creating a new CLion project and selecting the C++17 language standard the C++17 code will not compile.
The initial CMakeLists.txt file is as follows:
cmake_minimum_required(VERSION 3.8)
project(optional2)
set(CMAKE_CXX_STANDARD 17)
set(SOURCE_FILES main.cpp)
add_executable(optional2 ${SOURCE_FILES})
To compile the C++17 code I had to add the following line to the CMakeLists.txt file:
add_compile_options(/std:c++latest)
Is this the correct way (and/or only way?) to add this compile option in CMAKE / CLion?
The C++ compiler in use is the vs2017 cl.exe with nmake.exe on a Windows 10 workstation running CLion 2017.2.

The CMAKE_CXX_STANDARD variable is used to initialize the CXX_STANDARD property.
From the property documentation:
For compilers that have no notion of a standard level, such as MSVC,
this has no effect.
For Visual Studio 2017 with plain CMake, the canonical way for C++17 (the default is C++14) is:
target_compile_options(optional2 PRIVATE /std:c++latest)

Related

Using boost::thread with CMake in MS Visual Studio 2017 results in two compiler errors

I want to use boost::thread in my project and I use CMake as a build tool. However, even a very simple setup results in two compiler errors:
main.cpp
#include <boost/thread.hpp>
int main()
{
boost::thread t;
return 0;
}
CMakeLists.txt
cmake_minimum_required (VERSION 2.6)
project (ThreadTest)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.58.0 COMPONENTS random thread)
set(SOURCE_DIR src)
set(SOURCE_FILES
${SOURCE_DIR}/main.cpp
)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(test ${SOURCE_FILES})
target_link_libraries(test ${Boost_LIBRARIES})
endif()
I'm using Boost 1.68.0 which CMake can find and is able to build proper Visual Studio project files.
I tried using boost::random, and it worked.
However, compiling the above program results in two error messages:
E2512: Argument for a feature-test-macro has to be a simple identifier (pointing out to an error in boost file error_code.hpp)
LINK1104: File 'libboost_thread-vc141-mt-x64-1_68.lib' cannot be opened
This is the line in error_code.hpp which throws the error
I looked for the file 'libboost_thread-vc141-mt-x64-1_68.lib' in my boost installation but only found 'boost_1_68_0\lib64-msvc-14.0\boost_thread-vc140-mt-gd-x64-1_68.lib'
The linker settings contain the correct files:
So, my two questions:
Why is there a compilation error in error_code.hpp, which is part of the boost::system module and what can I do about it?
Why does VS want to link the file libboost_thread-vc141-mt-x64-1_68.lib, instead of the correct and available libboost_thread-vc140-mt-x64-1_68.lib?
I get the same error message in Visual Studio 2017 version 15.9 and Boost 1.69.0; I think that the trouble arises from this VS version introducing some version of __has_cpp_attribute which the boost authors expected only to be present in clang.
I had to change boost\system\detail\config.hpp line 50
from
#if defined(__has_cpp_attribute)
to
#if defined(__clang__) && defined(__has_cpp_attribute)
as the remaining preprocessor define is only relevant to clang anyways.
Changing boost headers is quite messy, but I didn't find a clean solution yet :(.
I was hoping /Zc had some switch to deactive this new "feature" (feature testing macro)
1) If you use
set(Boost_USE_STATIC_LIBS OFF)
and dont give a version number for boost
find_package(Boost COMPONENTS random thread)
since you are using 1.68 and not 1.58, right? It should work. I can reproduce your error messages with your settings and it works using the mentioned settings.
2) The boost CMake package file searches for a boost version depending on your selected compiler, I guess the default for vs 2017 is 14.1. See also here.
To solve this problem, download and install the proper prebuilt binaries.
Thank you for your hints!
The following steps resolved the problem:
1) I installed boost for MSVC 14.1 (prebuild binaries)
2) I added the following to the CMakeLists.txt:
add_definitions(-DBOOST_ALL_NO_LIB)

How to strictly target C++98 in CLion

For some reason I cannot configure CLion to only use C++98 for my project
I keep getting clang-tidy for c++11 instead of c++98 (How do I set it to C++98)
I do not get any red lines or compiler errors when I use syntax for C++ versions greater than C++98 (How do I enable strict enforcement of C++98)
When I set the IDE to C++98 I do not want the IDE to let me use any standard greater than C++98 (How do I do this?)
Does anyone know how to enforce this standard in CLion? My guess is to configure the cmake file to C++98. Not sure if I'm doing it right though...
My CMakeLists.txt is shown below
cmake_minimum_required(VERSION 3.10)
project(myProject)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c98")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++98")
set(CMAKE_CXX_STANDARD 98)
add_executable(myProject main.cpp Myclass.cpp Myclass.h)
add_definitions(-std=c++98)
p.s I do not have the option to work in any other version than C++98 and lower due to hardware constraints.
I have had similar problem and setting standard for a target worked, it would be something like
set_property(TARGET myProject PROPERTY CXX_STANDARD 98)
for you

Enabling support for C++17 in CMake for Visual Studio

I have a simple CMake (3.9.4) project with 3 libraries.
Basic library is an INTERFACE one (header only). It's using some features from C++17 that are present in Visual Studio (like constexpr if). Obviously I try to set a target property so that it propagated to dependent libraries.
I've tried:
target_compile_features(my_lib INTERFACE cxx_std_17)
But nothing changed.
Second attempt was:
set_target_properties(my_lib PROPERITES CXX_STANDARD 17)
But I get:
CMake Error at cpp/CMakeLists.txt:20 (set_target_properties):
INTERFACE_LIBRARY targets may only have whitelisted properties. The
property "CXX_STANDARD" is not allowed.
Finally I ended up with:
target_compile_options(bit INTERFACE /std:c++17)
which works fine. Is this a correct solution? Taking a look at all the compile features I believe there should be something better I can do. Also that forces me to wrap the above command in some kind of if(MSVC) ... endif() shenanigans.
CMake versions higher than 3.10 support MSVC C++ standard switches, but on earlier versions they have no effect.
The only portable approach, to ensuring your program is compiled with the correct C++ standard mode on Visual Studio, is to require at least CMake 3.10, set the target property CXX_STANDARD to your desired value and CXX_STANDARD_REQUIRED to ON.
Example usage:
set_property(TARGET my_target PROPERTY CXX_STANDARD 17)
set_property(TARGET my_target PROPERTY CXX_STANDARD_REQUIRED ON)
Note: Currently CXX_STANDARD documentation for CMake 3.10 incorrectly states that it has no effect on MSVC. There's an issue tracking this here.

How to enable /std:c++17 in VS2017 with CMake

I'm trying to add the /std:c++17 compiler flag to VS2017 with CMake. I'm using the "modern" cross-platform way so far:
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # -std=c++11 instead of -std=gnu++11
set(MY_CXX_COMPILE_FEATURES cxx_generic_lambdas cxx_range_for cxx_strong_enums)
add_library(mylib INTERFACE)
target_compile_features(mylib INTERFACE ${MY_CXX_COMPILE_FEATURES})
This adds /std:c++14 in VS2017 (which might be the default anyway?).
However I'm having trouble switching this to C++17 (i.e. having it add /std:c++17). If I just add it manually, I get the not-so-nice warning because both flags are present:
1>cl : Command line warning D9025: overriding '/std:c++14' with '/std:c++17'
I've tried set(CMAKE_CXX_STANDARD 17) but it has no effect, in fact the CMake documentation mentions that CMAKE_CXX_STANDARD has no effect on VS anyway.
As for adding a C++17 feature to target_compile_features, it doesn't seem like there are any yet (even in CMake-3.9.0-rc5), and even if there were, I'm specifically only using std::optional from C++17, and there's no target_compile_features flags for library features like std::optional.
So my question is, what's the best (or least ugly) way to do this with CMake? And in a way so it'll also work for gcc and clang? I'm happy to use a very recent CMake version (3.8 or 3.9). I prefer it to be "nice" and not manually looping through CXX_COMPILE_FLAGS and removing the string "/std:c++14" or some hack like that.
(Edit: It can also be the VS/std:c++latest switch - whichever is possible. Both work for the purpose.)
Turning my comment into an answer
The CMake team is working on it for VS2017 (as for July 2017, for upcoming CMake version 3.10):
CMake: MSVC standard version switches
Those flags seem to be rather new switches (as related to the date of this question):
VS 2017 15.3 preview now supports /std:c++17
So for Visual Studio you have to "manually" replace or append the compiler switches until CMake officially does support it.
Here is a code snippet that I've tested for std:c++latest (which is already supported e.g. in my CMake 3.8.0 version):
if (MSVC_VERSION GREATER_EQUAL "1900")
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("/std:c++latest" _cpp_latest_flag_supported)
if (_cpp_latest_flag_supported)
add_compile_options("/std:c++latest")
endif()
endif()
For CLang and GNU the support was merged into the main source code branch begin of 2017 and is part of CMake version 3.8 and above:
CMake: Features: Add support for C++ 17 language standard
CMake versions higher than 3.10 support MSVC C++ standard switches for MSVC versions newer than 19.0.24215. If either of the version requirements are not met, then they have no effect.
The only portable approach, to ensuring your program is compiled with the correct C++ standard mode on Visual Studio, is to require at least CMake 3.10, set the target property CXX_STANDARD to your desired value and CXX_STANDARD_REQUIRED to ON.
Example usage:
set_property(TARGET my_target PROPERTY CXX_STANDARD 17)
set_property(TARGET my_target PROPERTY CXX_STANDARD_REQUIRED ON)
You can add the following line to your CmakeLists.txt file
set(GCC_COMPILE_FLAGS "${GCC_COMPILE_FLAGS} /std:c++17)

Configure cmake to choose compiler based on environment

My current project directory looks like
myproject
/-build
/-include
/-somefile.h
/-somefile2.h
/-myproject.cpp
/-CMakeLists.txt
and current CMakeLists.txt looks like :
cmake_minimum_required (VERSION 3.1)
project (myproject)
add_executable(myproject myproject.cpp)
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/build)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(PROJECT_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
include_directories("${PROJECT_INCLUDE_DIR}")
include_directories("${PROJECT_SOURCE_DIR}")
I want to build this project in both x64Windows and x64Linux environment while keeping single cmake file. Currently I have Visual Studio 13 CE in Win and gcc in Linux. Is it possible that Cmake could intelligently choose the correct compiler depending on OS? And what changes should I make to CMakeLists for that?
I'm using normal stuff like STL and vanilla C++ ( no os dependent libraries) if that matters. Thanks
You want to add conditional code for each compiler:
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# Set the C++ and linker flags to GCC specifics here.
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# Set the C++ and linker flags to VC++ specifics here.
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# Set the C++ and linker flags to Clang specifics here.
elseif()
The right compiler is set automatically at least on linux. On windows I don't know. However you could always overwrite the selected compiler by the environment variables CC and CXX. This changes the cmake configuration. The changes will only affect new build configurations. So don't forget to delete your old one before selecting a new compiler.
Edit: The compiler must be of course in your PATH variable. Otherwise CMake will not find it correctly.