[CMake] Using C++11 features and Cmake 3.1
Andrew Maclean
andrew.amaclean at gmail.com
Mon Jan 19 16:11:20 EST 2015
This is a bit long but it should help those using C++11 features in CMake
3.1.
This is an extract from my CMakeLists.txt file that uses C++11 in a
cross-platform manner. It also lists the available C++11 features and shows
you how to set up defines that can be used in your code.
The ancillary files that reside in a subdirectory called CMake:
CMakeOptions.cmake - sets global options.
DetermineCompilerFlags.cmake - self explanatory.
SetCompilerFeatures.cmake - this is important as CMake3.1 doesn't know
about C++11 features in XCode (CLang) and MSVC. So it checks for
appropriate versions in the case of MSVC and sets the cxx flags for CLang.
Here is a cut down version of the top-level CMakeLists.txt file:
################################
#-----------------------------------------------------------------------------
# Don't build anything unless the version of CMake is high enough.
# Note: The cmake_minimum_required command also sets the policy version.
# This will request NEW behavior for all policies introduced in the
# corresponding version of CMake or earlier.
# Policies introduced in later versions are marked as not set in
# order to produce proper warning messages.
cmake_minimum_required(VERSION 3.1)
#-----------------------------------------------------------------------------
# Set policies as needed.
foreach(p
# This is just a placeholder for CMPs that may appear in newer versions.
# CMP???? # CMake 3.1+
)
if(POLICY ${p})
cmake_policy(SET ${p} NEW)
endif()
endforeach()
#-----------------------------------------------------------------------------
project ( XXX )
#-----------------------------------------------------------------------------
# We will enforce an out of source build.
STRING(COMPARE EQUAL "${${PROJECT_NAME}_SOURCE_DIR}"
"${${PROJECT_NAME}_BINARY_DIR}" INSOURCE)
if(INSOURCE)
MESSAGE(FATAL_ERROR "${PROJECT_NAME} requires an out of source build.
Please create a separate binary directory and run CMake there.")
endif(INSOURCE)
#-----------------------------------------------------------------------------
# Directory where the CMakeFiles are
set ( CMAKE_FILE_DIR
${PROJECT_SOURCE_DIR}/CMake
)
#-----------------------------------------------------------------------------
# Any global options
include(${CMAKE_FILE_DIR}/CMakeOptions.cmake)
#-----------------------------------------------------------------------------
# What are the CMake known C++ features?
get_property(cxx_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
message(STATUS "This CMake version supports these C++ features:")
foreach(i ${cxx_features})
message(STATUS "${i}")
endforeach()
message(STATUS "Compiler ID/Version: ${CMAKE_CXX_COMPILER_ID}
${CMAKE_CXX_COMPILER_VERSION}")
#-----------------------------------------------------------------------------
# We need these features.
set(needed_features
cxx_auto_type
cxx_lambdas
cxx_range_for
)
#-----------------------------------------------------------------------------
# We may need to define flags based on the needed features.
foreach(i ${needed_features})
string(TOUPPER ${i} s)
add_definitions("-D${s}")
endforeach()
#-----------------------------------------------------------------------------
# Set the compiler warning level and other compiler settings.
include(${CMAKE_FILE_DIR}/DetermineCompilerFlags.cmake)
include(${CMAKE_FILE_DIR}/SetCompilerFeatures.cmake)
#-----------------------------------------------------------------------------
# Get the version info.
# Versioning
#-----------------------------------------------------------------------------
#
set( TARGET_BASE_NAME "${PROJECT_NAME}" )
set( LIB_NAME "${TARGET_BASE_NAME}Lib" )
set( EXE_NAME "${TARGET_BASE_NAME}" )
#-----------------------------------------------------------------------------
# We need these C++11 features.
set(needed_features
cxx_lambdas
cxx_auto_type)
#-----------------------------------------------------------------------------
# We may need to define flags based on the needed features.
foreach(i ${needed_features})
string(TOUPPER ${i} s)
add_definitions("-D${s}")
endforeach()
#-----------------------------------------------------------------------------
# Paths to directories
include_directories(
# ...
)
add_subdirectory(${???}) # For the library called e.g. yy.
add_subdirectory(${???}) # For the executable called e.g. MyExecutable.
################################
Then in the subdirectories, do this in the case of a library (note the use
of SetCompilerFeatures),
################################
#-----------------------------------------------------------------------------
# The name of the library.
#
set(KIT yy)
set(LIB_NAME ${LIB_PREFIX}${KIT})
#-----------------------------------------------------------------------------
# The directory in which the source files are.
set(${KIT}_DIR ${CMAKE_CURRENT_SOURCE_DIR})
#-----------------------------------------------------------------------------
set(${KIT}_Srcs
...
)
set(${KIT}_Incs
...
)
add_library( ${LIB_NAME} ${${KIT}_Srcs} ${${KIT}_Incs} )
SetCompilerFeatures(${LIB_NAME})
################################
Do this for the executable:
################################
set(KIT ${EG}MyExecutable)
# Source files
set( Srcs
...
)
# Include files
set( Incs
)
add_executable( ${KIT} ${Srcs} ${Incs} )
SetCompilerFeatures(${KIT})
target_link_libraries( ${KIT}
yy
)
install(TARGETS ${KIT}
BUNDLE DESTINATION . COMPONENT Runtime
RUNTIME DESTINATION bin COMPONENT Runtime
# LIBRARY DESTINATION lib
# ARCHIVE DESTINATION lib
)
################################
I hope this helps.
Andrew
--
___________________________________________
Andrew J. P. Maclean
___________________________________________
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake/attachments/20150120/e7f708a9/attachment-0001.html>
-------------- next part --------------
option(BUILD_TESTING
"Build the tests."
OFF)
option(BUILD_EXAMPLES
"Build the examples."
OFF)
-------------- next part --------------
# Modified from: vtkDetermineCompilerFlags.cmake
# A GCC compiler.
IF(CMAKE_COMPILER_IS_GNUCXX)
SET(CMAKE_CXX_FLAGS "-Wall -Wextra")
SET(CMAKE_C_FLAGS "-Wall -Wextra")
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
IF(MSVC)
# Use the highest warning level for visual c++ compiler.
SET(CMAKE_CXX_WARNING_LEVEL 4)
IF(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
STRING(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
ELSE(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
ENDIF(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
ENDIF(MSVC)
# Disable deprecation warnings for standard C and STL functions in VS2005
# and later
IF(MSVC_VERSION EQUAL 1400 OR MSVC_VERSION GREATER 1400 OR MSVC10)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS)
ADD_DEFINITIONS(-D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS)
ENDIF(MSVC_VERSION EQUAL 1400 OR MSVC_VERSION GREATER 1400 OR MSVC10)
# Enable /MP flag for Visual Studio 2008 and greater
IF(MSVC_VERSION GREATER 1400)
SET(CMAKE_CXX_MP_FLAG OFF CACHE BOOL "Build with /MP flag enabled")
SET(PROCESSOR_COUNT "$ENV{NUMBER_OF_PROCESSORS}")
SET(CMAKE_CXX_MP_NUM_PROCESSORS CACHE ${PROCESSOR_COUNT} "The maximum number of processes for the /MP flag")
IF (CMAKE_CXX_MP_FLAG)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP${CMAKE_CXX_MP_NUM_PROCESSORS}")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP${CMAKE_CXX_MP_NUM_PROCESSORS}")
ENDIF (CMAKE_CXX_MP_FLAG)
ENDIF(MSVC_VERSION GREATER 1400)
-------------- next part --------------
function(SetCompilerFeatures TGT_NAME)
#----------------------------------------------------------
# Set C++11 compatibility.
#----------------------------------------------------------
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if(NOT(TGT_NAME STREQUAL ""))
target_compile_features(${TGT_NAME} PUBLIC ${needed_features})
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# Pick a MSVC version that supports what you need.
if (MSVC_VERSION LESS "1800")
message(FATAL_ERROR "No suitable compiler exists.")
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++")
else()
message(FATAL_ERROR "No suitable compiler exists.")
endif()
endfunction()
More information about the CMake
mailing list