When I try to run a CMake generated makefile to compile my program, I get the error that
range based for loops are not supported in C++ 98 mode.
I tried adding add_definitions(-std=c++0x) to my CMakeLists.txt, but it did not help.
I tried this too:
if(CMAKE_COMPILER_IS_GNUCXX)
add_definitions(-std=gnu++0x)
endif()
When I do g++ --version, I get:
g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
I have also tried SET(CMAKE_CXX_FLAGS "-std=c++0x"), which also does not work.
I do not understand how I can activate C++ 11 features using CMake.
CMake 3.1 introduced the CMAKE_CXX_STANDARD variable that you can use. If you know that you will always have CMake 3.1 or later available, you can just write this in your top-level CMakeLists.txt file, or put it right before any new target is defined:
set (CMAKE_CXX_STANDARD 11)
If you need to support older versions of CMake (quite unlikely these days), here is a macro I came up with that you can use:
macro(use_cxx11)
if (CMAKE_VERSION VERSION_LESS "3.1")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
endif ()
else ()
set (CMAKE_CXX_STANDARD 11)
endif ()
endmacro(use_cxx11)
The macro only supports GCC right now, but it should be straight-forward to expand it to other compilers.
Then you could write use_cxx11() at the top of any CMakeLists.txt file that defines a target that uses C++11.
CMake issue #15943 for clang users targeting macOS
If you are using CMake and clang to target macOS there is a bug that can cause the CMAKE_CXX_STANDARD feature to simply not work (not add any compiler flags). Make sure that you do one of the following things:
Use cmake_minimum_required to require CMake 3.0 or later, or
Set policy CMP0025 to NEW with the following code at the top of your CMakeLists.txt file before the project command:
# Fix behavior of CMAKE_CXX_STANDARD when targeting macOS.
if (POLICY CMP0025)
cmake_policy(SET CMP0025 NEW)
endif ()
The CMake command target_compile_features() is used to specify the required C++ feature cxx_range_for. CMake will then induce the C++ standard to be used.
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project(foobar CXX)
add_executable(foobar main.cc)
target_compile_features(foobar PRIVATE cxx_range_for)
There is no need to use add_definitions(-std=c++11) or to modify the CMake variable CMAKE_CXX_FLAGS, because CMake will make sure the C++ compiler is invoked with the appropriate command line flags.
Maybe your C++ program uses other C++ features than cxx_range_for. The CMake global property CMAKE_CXX_KNOWN_FEATURES lists the C++ features you can choose from.
Instead of using target_compile_features() you can also specify the C++ standard explicitly by setting the CMake properties
CXX_STANDARD
and
CXX_STANDARD_REQUIRED for your CMake target.
See also my more detailed answer.
I am using
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
But if you want to play with C++11, g++ 4.6.1 is pretty old.
Try to get a newer g++ version.
The easiest way to set the Cxx standard is:
set_property(TARGET tgt PROPERTY CXX_STANDARD 11)
See the CMake documentation for more details.
On modern CMake (>= 3.1) the best way to set global requirements is:
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
It translates to "I want C++11 for all targets, it's not optional, I don’t want to use any GNU or Microsoft extensions."
As of C++17, this still is IMHO the best way.
Source: Enabling C++11 And Later In CMake
As it turns out, SET(CMAKE_CXX_FLAGS "-std=c++0x") does activate many C++11 features. The reason it did not work was that the statement looked like this:
set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")
Following this approach, somehow the -std=c++0x flag was overwritten and it did not work. Setting the flags one by one or using a list method is working.
list( APPEND CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")
For CMake 3.8 and newer you can use
target_compile_features(target PUBLIC cxx_std_11)
If you want the generation step to fail if the toolchain cannot adhere to this standard, you can make this required.
set_target_properties(target PROPERTIES CXX_STANDARD_REQUIRED ON)
If you want strict adherence to standard C++ i.e. avoid C++ extensions offered by your compiler (like GCC's -std=gnu++17), additionally set
set_target_properties(target PROPERTIES CXX_EXTENSIONS OFF)
This is documented in detail at An Introduction to Modern CMake -> Adding Features -> C++11 and Beyond. It also offers advice on how to achieve this on older versions of CMake if you're constrained to those.
The easiest way:
add_compile_options(-std=c++11)
This is another way of enabling C++11 support,
ADD_DEFINITIONS(
-std=c++11 # Or -std=c++0x
# Other flags
)
I have encountered instances where only this method works and other methods fail. Maybe it has something to do with the latest version of CMake.
Modern cmake offers simpler ways to configure compilers to use a specific version of C++. The only thing anyone needs to do is set the relevant target properties. Among the properties supported by cmake, the ones that are used to determine how to configure compilers to support a specific version of C++ are the following:
CXX_STANDARD sets the C++ standard whose features are requested to build the target. Set this as 11 to target C++11.
CXX_EXTENSIONS, a boolean specifying whether compiler specific extensions are requested. Setting this as Off disables support for any compiler-specific extension.
To demonstrate, here is a minimal working example of a CMakeLists.txt.
cmake_minimum_required(VERSION 3.1)
project(testproject LANGUAGES CXX )
set(testproject_SOURCES
main.c++
)
add_executable(testproject ${testproject_SOURCES})
set_target_properties(testproject
PROPERTIES
CXX_STANDARD 11
CXX_EXTENSIONS off
)
In case you want to always activate the latest C++ standard, here's my extension of David Grayson's answer, in light of the recent (CMake 3.8 and CMake 3.11) additions of values of 17 and 20 for CMAKE_CXX_STANDARD):
IF (CMAKE_VERSION VERSION_LESS "3.8")
SET(CMAKE_CXX_STANDARD 14)
ELSEIF (CMAKE_VERSION VERSION_LESS "3.11")
SET(CMAKE_CXX_STANDARD 17)
ELSE()
SET(CMAKE_CXX_STANDARD 20)
ENDIF()
# Typically, you'll also want to turn off compiler-specific extensions:
SET(CMAKE_CXX_EXTENSIONS OFF)
(Use that code in the place of set (CMAKE_CXX_STANDARD 11) in the linked answer.)
What works for me is to set the following line in your CMakeLists.txt:
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
Setting this command activates the C++11 features for the compiler and after executing the cmake .. command, you should be able to use range based for loops in your code and compile it without any errors.
I think just these two lines are enough.
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
The modern way is to specify the minimum required standard to C++11 with:
target_compile_features(foo PUBLIC cxx_std_11)
This way:
CMake can honor default C++ standard of the compiler if it's greater than C++11
You can clearly specify whether C++ standard is required at build time, consume time, or both. This is nice for libraries.
Public compile features are propagated to downstream targets, so it comes for free in those targets even if they don't directly use this feature.
Users can externally set another C++ standard (more recent basically), with CMAKE_CXX_STANDARD, either from command line or CMake presets. If you hardcode CMAKE_CXX_STANDARD in a CMakeLists, nobody can override the C++ standard without editing your CMakeLists, which is not very pleasant.
It requires CMake >= 3.8
You can use the following. This automatically modifies the feature based on your environment.
target_compile_features(your_target INTERFACE cxx_std_20)
For example,
on Gnu/Linux the following adds -std=gnu++20
on Windows with Clang/Ninja it becomes -std=c++20
on Windows with MSVC it becomes /std=c++20
So you support as many as environments possible.
In case you stumble on that same error using cmake as i did.
You need to set
set (CMAKE_CXX_STANDARD 11)
to activate threading because it is only supported from c++11 ++
hope that helps
OS X and Homebrew LLVM related:
Don't forget to call cmake_minimum_required(VERSION 3.3) and project() after it!
Or CMake will insert project() implicitly before line 1, causing trouble with Clang version detection and possibly other sorts of troubles. Here is a related issue.
This question already has answers here:
How to add "-l" (ell) compiler flag in CMake
(2 answers)
Closed 2 years ago.
In trying to link restbed with CMake I get the usual undefined function error. However, trying the exact same code linked with g++ test.cpp -o test -lrestbed works fine.
Furthermore, when I first implemented the CMakeLists.txt it also worked fine and as I added to the project it started facing issues. Now even a single restbed function is not defined.
My restbed includes are located at /usr/local/include and the shared objects to link at /usr/local/lib. Pretty standard locations.
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(vcar-server)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -lrestbed")
file(GLOB CXX_EXEC "src/*.cpp")
add_subdirectory(vcar-embedded)
add_executable(vcar-server ${CXX_EXEC})
target_link_libraries(vcar-server vcar)
Do not use CMAKE_CXX_FLAGS, or rather use it as a "last resort" when configuring the build system as a user. Prefer to use object model in place of global variables. The modern cmake way would most probably be something along:
cmake_minimum_required(VERSION 3.11)
project(vcar-server)
add_subdirectory(vcar-embedded)
find_package(Threads REQUIRED)
add_executable(vcar-server ${cxx_exec})
target_link_libraries(vcar-server PUBLIC vcar restbed Threads::Threads)
set_target_properties(vcar-server PUBLIC CXX_STANDARD 20)
So I've been trying to learn CMake and use it with C++. I'd like to have a go at creating a portable game engine which uses Direct3D 12 on Windows.
Currently, I have the following CMakeLists.txt for my project:
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(PsychoEngineCore)
set(SRCS_CXX ${CMAKE_CURRENT_LIST_DIR})
include(${CMAKE_CURRENT_SOURCE_DIR}/src/dir_src.cmake)
set(LIB_TYPE "STATIC" CACHE STRING "Static or Dynamic Linking")
if(${CMAKE_CXX_COMPILER_ID} STREQUAL GNU OR
${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
set(warnings "-Wall -Wextra -Werror")
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
set(warnings "/W4 /WX /EHsc")
endif()
if(NOT CONFIGURED_ONCE)
set(CMAKE_CXX_FLAGS "${warnings}"
CACHE STRING "Flags used by the compiler during all build types." FORCE)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Do we want static libraries?
# When STATIC_LINKING is TRUE, then cmake looks for binaries ending in ".a".
# THIS IS FOR LINUX ONLY!
if(LIB_TYPE EQUAL STATIC)
if (UNIX AND NOT APPLE)
set(CMAKE_FIND_LIBRARY_SUFFIXES(".a"))
endif(UNIX AND NOT APPLE)
set(CMAKE_EXE_LINKER_FLAGS "-static")
set_target_properties(surface PROPERTIES LINK_SEARCH_END_STATIC 1)
endif(LIB_TYPE EQUAL STATIC)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include(GenerateExportHeader)
add_library(${PROJECT_NAME} ${LIB_TYPE} ${SRCS_CXX})
GENERATE_EXPORT_HEADER(
${PROJECT_NAME}
EXPORT_MACRO_NAME PE_API
EXPORT_FILE_NAME ${CMAKE_CURRENT_SOURCE_DIR}/include/Engine/API/${PROJECT_NAME}Export.hpp
DEPRECATED_MACRO_NAME PE_API_DEP
STATIC_DEFINE PE_STATIC
)
Currently I have my d3d12.lib file in the following location:
C:\Program Files (x86)\Windows Kits\10\Libs\10.0.16299.0\um\x64
Is there a way to keep the path dynamic and preferably "update" if a newer version is available on said system?
Thanks!
Turning my comment into an answer
Generally speaking, just add a
target_link_libraries((${PROJECT_NAME} d3d12.lib)
The Windows SDK (where the Direct3D SDK is now part of) is in the standard search paths e.g. of the linker for libraries. So it's found automatically by the MSVC compiler and linker.
And I don't think that upgrading to a newer (yet unknown) API version automatically is a good idea. You're writing your program for a specific API version.
Working Example
Here is a minimal working example (Tested VS2017 15.5.5, CMake 3.9.0):
cmake_minimum_required(VERSION 3.0)
project(Direct3DExample)
find_package(Git REQUIRED)
set(_path "${CMAKE_BINARY_DIR}/DirectX-Graphics-Samples/Samples/Desktop/D3D12HelloWorld/src/HelloTriangle")
if (NOT EXISTS "${_path}")
execute_process(
COMMAND "${GIT_EXECUTABLE}" clone https://github.com/Microsoft/DirectX-Graphics-Samples.git
)
endif()
file(GLOB _files "${_path}/*")
list(APPEND _shader ${_files})
list(FILTER _files EXCLUDE REGEX "\\.vcxproj|\\.hlsl")
list(FILTER _shader INCLUDE REGEX "\\.hlsl")
get_filename_component(_name "${_path}" NAME)
add_executable(${_name} WIN32 ${_files})
target_compile_definitions(${_name} PRIVATE "UNICODE" "_UNICODE")
target_link_libraries(${_name} PRIVATE "d3d12.lib" "dxgi.lib" "d3dcompiler.lib")
add_custom_command(
TARGET ${_name}
POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy ${_shader} $<TARGET_FILE_DIR:${_name}>
)
If you need more (compilers/linkers that are not finding the Windows SDK automatically), you may want to look the following find_package() config code:
https://github.com/Microsoft/DirectXShaderCompiler/blob/master/cmake/modules/FindD3D12.cmake
I want to pass linker flags to all sub-projects (sub-directory CMakeList) in my project.
Before switching to new cmake 3.3, I was using the following code (cmake 3.2) which was working well, adding flags for both compilation and linking :
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -stdlibc++")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -stdlibc++")
With cmake 3.3 this no longer works and set the flags only for compilation step. I updated the CMakeList to use a more "modern" cmake syntax :
set(MY_DEBUG_OPTIONS -g -stdlib=libstdc++ -Wfatal-errors)
set(MY_RELEASE_OPTIONS -O3 -stdlib=libstdc++ -Wfatal-errors)
add_compile_options(
"$<$<CONFIG:DEBUG>:${MY_DEBUG_OPTIONS}>"
"$<$<CONFIG:RELEASE>:${MY_RELEASE_OPTIONS}>")
This set compilation flags for all sub-projects, is there a similar way of doing this for linker flags ? I know one can add linker flags on a target basis with target_link_librariescommand but can't find anything else.
I tried using CMAKE_SHARED_LINKER_FLAGS (and corresponding var for exe, module,..) variable with no success.
Update :
It turns out that this has nothing to do with cmake version, things work correctly with CMAKE_CXX_FLAGS_XXXvariables, except on first make command. If one run make a second time (with a modification in CmakeList), flags are presents.
I think I found a solution while testing with a simple CMakeList : if flags are declared after the project command it just work as expected. I don't know if it's a requirement from cmake itself or just a weird behavior.
cmake_minimum_required (VERSION 3.2)
set(PROJECT Test_Project)
# Not working (on first run)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -stdlib=libstdc++ -Wfatal-errors")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -stdlib=libstdc++ -Wfatal-errors")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -stdlib=libstdc++ -Wfatal-errors")
project(${PROJECT})
# Declare here instead...
add_executable(Test test.cpp)
MESSAGE( STATUS "Config flags : " ${CMAKE_CXX_FLAGS_RELEASE})
Using :
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release .
Your problems are/were not related to a specific CMake version.
It's the same for all linker/compiler flag variables in CMake. Because those variables are cached variables and set with the project()/enable_language() command (details see here), you either have to
prefill the cache with set(... CACHE ...) before the project() command
generally use the set(... CACHE ... FORCE) to force/overwrite
move the set() after the project() command to hide or append to the cached variables
Here is an example for CMAKE_EXE_LINKER_FLAGS showing all three variants:
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
# 1. prefill
#set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=output.map" CACHE INTERNAL "")
project(Test_Project CXX)
# 2. force
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=output.map" CACHE INTERNAL "" FORCE)
# 3. hide
#set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=output.map")
# 3. or append
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=output.map")
# TODO: Remove, this is just for testing
file(WRITE "foo.cpp" "int main() {}")
add_executable(${PROJECT_NAME} foo.cpp)
Whatever the values of those variables are at the end of your any given CMakeLists.txt file will be applied to all corresponding targets in the same CMakeLists.txt file as defaults (see CMAKE - setting compile flags for libraries and What's the CMake syntax to set and use variables?).
The first variant has the disadvantage that it's really only the initial value. The second and third variant would most likely need an if (CMAKE_COMPILER_IS_GNUCXX) around it, so I prefer the second variant with moving those settings to its own initial-cache file:
MyGNUSettings.cmake
set(CMAKE_CXX_FLAGS "-stdlib=libstdc++ -Wfatal-errors" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "-g" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE INTERNAL "" FORCE)
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=output.map" CACHE INTERNAL "" FORCE)
Using e.g.
cmake -G "Unix Makefiles" -C MyGNUSettings.cmake -DCMAKE_BUILD_TYPE=Release .
And yes - for the global and per compiler settings - I prefer the global cached variables over the add_compile_options() command. I think add_compile_options() haven't replaced the global variables, it was mainly introduced to prevent people putting compiler options in add_definitions() commands.
I just started to learn CMake and thought I would have understood the basic process of first writing the CMakeLists.txt, then configuring to generate the CMakeCache.txtand at the end generating the Makefiles.
However, when I try to apply it to the following CMakeLists.txt, I'm not getting the expected results and I'm not sure what is going wrong. Part of the CMakeLists.txt looks like this:
# compiler flags
if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fpermissive -Wall -Wformat-security")
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-local-typedefs")
endif()
endif()
Since I'm using gcc/g++ 4.7.3, the compiler flags from the first if-statement should be set. But if I configure this with CMake-Gui, there are no compiler flags pre-defined whatsoever. The same happens when I out-comment the if-statements and just keep the set(CMAKE_CXX_FLAGS ...).
When searching the CMakeCache.txt for any -std=c++11 flags, I don't get any results, too.
Why does this happen? What's the point of specifying compiler flags inside the CMakeLists.txt when they aren't used? Or am I getting something completely wrong and they are used, but then I don't know why and how I could check.
When generating the actual (Eclipse CDT) project with make and importing it to Eclipse, I'm getting error messages that C++11 features can't be resolved, the __cplusplus macro contains the value 199711 so the -std=c++11 flag is obviously not used.
The flags you specified in the CMakeLists.txt file are probably correctly used by the compiler. You can't see them directly in CMakeCache.txt but:
You can see command lines by running make VERBOSE=1 instead of standard make
Also, you can set CMAKE_VERBOSE_MAKEFILE to 1 to enable printing of commands (this can be found by checking "Advanced" in CMake GUI)
As #Angew said, if you really want to see the updated flags in the CMake GUI, set your variables with CACHE FORCE
As an example, i use this kind of configuration in a project for some month, and never had problem:
if(MSVC) # MSVC compiler (Win32 only)
# Display more warnings
set(CMAKE_CXX_FLAGS "/W3")
elseif(UNIX OR CMAKE_COMPILER_IS_GNUCXX) # Clang OR Gcc (Linux, Mac OS or Win32 with MingW)
# Enable C++11 and displays all warnings
set(CMAKE_CXX_FLAGS "-Wall -std=c++11")
if(APPLE) # Clang / Mac OS only
# Required on OSX to compile c++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -mmacosx-version-min=10.7")
endif(APPLE)
endif()
Update:
Starting with CMake 3.0, you can replace set(CMAKE_CXX_FLAGS "...") by add_compile_options(-std=c++11)
CMake 3.1 introduced a new syntax to configure the compiler with specific C++ version:
set(CMAKE_CXX_STANDARD 11)
You can first, set the variable to a value only if it is not in cache already. The last parameter is the description which we don't need since we'll override it anyway.
set(VARIABLE "Hello World!" CACHE STRING "")
Then force the value into cache using its existing value from the line above. Since that is cached, users can still change the variable and it won't be set back every time.
set(VARIABLE ${VARIABLE} CACHE STRING "Description." FORCE)
This is a bit hacky in CMake as you can see, but it works reliably.