[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