ned Productions Consulting


Technology musings by Niall Douglas
ned Productions Consulting
(an expert advice and services company based in Ireland)


Wednesday 4th January 2017 8.48pm

Link shared: https://github.com/ned14/boost-lite/blob/master/cmake/BoostLiteSetupProject.cmake#L9

Nailed this cunning piece of cmake hackery today, so I thought I would share it. It solves the problem of cmake annoyingly not supporting out of the box per-target setting of C++ exceptions on/off, C++ RTTI on/off and whether to use the static or dynamic C++ runtime. It also, very usefully, stops the warning MSVC makes about overriding the C++ exceptions enable that cmake enforces in the core compile flags on MSVC, this is amazingly useful when you turn on error on warnings and your C++ has exceptions disabled.

To use, do something like this:

set_target_properties(outcome_hl-unittests_noexcept PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
POSITION_INDEPENDENT_CODE ON
CXX_EXCEPTIONS OFF
CXX_RTTI OFF
CXX_STANDARD 14
)

Here's the hackup setup which creates the new properties. It's also linked to at github for your convenience.

# On MSVC very annoyingly cmake puts /EHsc and /MD(d) into the global flags which means you
# get a warning when you try to disable exceptions or use the static CRT. I hate to use this
# globally imposed solution, but we are going to hack the global flags to use properties to
# determine whether they are on or off
#
# Create custom properties called CXX_EXCEPTIONS, CXX_RTTI and CXX_STATIC_RUNTIME
# These get placed at global, directory and target scopes
foreach(scope GLOBAL DIRECTORY TARGET)
define_property(${scope} PROPERTY "CXX_EXCEPTIONS" INHERITED
BRIEF_DOCS "Enable C++ exceptions, defaults to ON at global scope"
FULL_DOCS "Not choosing ON nor OFF with exact capitalisation will lead to misoperation!"
)
define_property(${scope} PROPERTY "CXX_RTTI" INHERITED
BRIEF_DOCS "Enable C++ runtime type information, defaults to ON at global scope"
FULL_DOCS "Not choosing ON nor OFF with exact capitalisation will lead to misoperation!"
)
define_property(${scope} PROPERTY "CXX_STATIC_RUNTIME" INHERITED
BRIEF_DOCS "Enable linking against the static C++ runtime, defaults to OFF at global scope"
FULL_DOCS "Not choosing ON nor OFF with exact capitalisation will lead to misoperation!"
)
endforeach()
# Set the default for these properties at global scope. If they are not set per target or
# whatever, the next highest scope will be looked up
set_property(GLOBAL PROPERTY CXX_EXCEPTIONS ON)
set_property(GLOBAL PROPERTY CXX_RTTI ON)
set_property(GLOBAL PROPERTY CXX_STATIC_RUNTIME OFF)
if(MSVC)
# Purge unconditional use of /MDd, /MD and /EHsc.
foreach(flag
CMAKE_C_FLAGS CMAKE_CXX_FLAGS
CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO
)
string(REPLACE "/MDd" "" ${flag} "${${flag}}")
string(REPLACE "/MD" "" ${flag} "${${flag}}")
string(REPLACE "/EHsc" "" ${flag} "${${flag}}")
string(REPLACE "/GR" "" ${flag} "${${flag}}")
endforeach()
# Restore those same, but now selected by the properties
add_compile_options(
$<$<STREQUAL:$<TARGET_PROPERTY:CXX_EXCEPTIONS>,ON>:/EHsc>
$<$<STREQUAL:$<TARGET_PROPERTY:CXX_RTTI>,OFF>:/GR->
$<$<STREQUAL:$<TARGET_PROPERTY:CXX_STATIC_RUNTIME>,OFF>:$<$<CONFIG:Debug>:/MDd>$<$<NOT:$<CONFIG:Debug>>:/MD>>
$<$<STREQUAL:$<TARGET_PROPERTY:CXX_STATIC_RUNTIME>,ON>:$<$<CONFIG:Debug>:/MTd>$<$<NOT:$<CONFIG:Debug>>:/MT>>
)
else()
add_compile_options(
$<$<STREQUAL:$<TARGET_PROPERTY:CXX_EXCEPTIONS>,OFF>:-fno-exceptions>
$<$<STREQUAL:$<TARGET_PROPERTY:CXX_RTTI>,OFF>:-fno-rtti>
# $<$<STREQUAL:$<TARGET_PROPERTY:CXX_STATIC_RUNTIME>,ON>:-static>
)
endif()