From fba33065fc34b43c04966f8c06f9da878fd980ea Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Sun, 8 Dec 2019 20:24:04 +0300 Subject: update common.cmake * Add more logging messages. * Rename user-facing switches. * Refactor things a bit (a lot). * Lower the default C++ standard version back to 14 to support CMake 3.1 (meh, there're probably other features in use that are not supported by it). --- common.cmake | 149 +++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 104 insertions(+), 45 deletions(-) diff --git a/common.cmake b/common.cmake index 2d5e9f9..2d9f7e0 100644 --- a/common.cmake +++ b/common.cmake @@ -1,15 +1,27 @@ # Copyright (c) 2017 Egor Tensin -# It's a CMake code snippet I use in all of my CMake projects. -# It makes targets link the runtime statically by default + strips debug -# symbols in release builds. -# The latest version can be found at -# https://github.com/egor-tensin/cmake-common. # Distributed under the MIT License. -# Version: 2019-11-29T22:30:28Z +# It's a CMake code snippet I use in all of my CMake projects. +# It makes targets link the runtime statically by default, strips debug symbols +# in release builds and sets a couple of useful compilation options. + +# Add this to the top-level CMakeLists.txt (unless a higher version has already +# been specified): +# +# cmake_minimum_required(VERSION 3.1) -get_directory_property(parent_directory PARENT_DIRECTORY) -set(is_root_project $) +# Otherwise this line: +# +# if(toolset STREQUAL "MSVC") +# +# evaluates to false even when using Visual Studio (since MSVC is a predefined +# variable; it's completely bonkers). +if(NOT POLICY CMP0054) + message(FATAL_ERROR "common.cmake uses CMP0054, which is unsupported by this CMake version") +endif() +cmake_policy(SET CMP0054 NEW) + +# Toolset identification: if(CMAKE_C_COMPILER) set(toolset "${CMAKE_C_COMPILER_ID}") @@ -18,79 +30,126 @@ elseif(CMAKE_CXX_COMPILER) else() set(toolset "unknown") endif() +message(STATUS "Toolset: ${toolset}") + +if(toolset STREQUAL "GNU") + set(is_gcc ON) +elseif(toolset STREQUAL "MSVC") + set(is_msvc ON) +else() + message(WARNING "Unrecognized toolset: ${toolset}") +endif() -set(USE_STATIC_RUNTIME "${is_root_project}" CACHE BOOL "Link the runtime statically") -set(STRIP_SYMBOL_TABLE "${is_root_project}" CACHE BOOL "Strip symbol tables") -set(CXX_STANDARD "17" CACHE BOOL "Set C++ standard version") +# Compilation options almost always useful: -if(is_root_project) - if(MSVC) - add_compile_options(/MP /W4) - elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) - add_compile_options(-Wall -Wextra) +function(best_practices_msvc target) + set(compile_options /MP /W4) + set(compile_definitions WIN32_LEAN_AND_MEAN NOMINMAX) + get_target_property(target_type "${target}" TYPE) + if(target_type STREQUAL "INTERFACE_LIBRARY") + target_compile_definitions("${target}" INTERFACE ${compile_definitions}) else() - message(WARNING "Unrecognized toolset: ${toolset}") + target_compile_options("${target}" PRIVATE ${compile_options}) + target_compile_definitions("${target}" PRIVATE ${compile_definitions}) + endif() +endfunction() + +function(best_practices_gcc target) + set(compile_options -Wall -Wextra) + get_target_property(target_type "${target}" TYPE) + if(NOT target_type STREQUAL "INTERFACE_LIBRARY") + target_compile_options("${target}" PRIVATE ${compile_options}) + endif() +endfunction() + +function(best_practices target) + if(is_msvc) + best_practices_msvc("${target}") + elseif(is_gcc) + best_practices_gcc("${target}") endif() +endfunction() + +# User-defined switches: + +set(default_value ON) +get_directory_property(parent_directory PARENT_DIRECTORY) +if(parent_directory) + set(default_value OFF) endif() -set(CMAKE_CXX_STANDARD "${CXX_STANDARD}") +option(CC_BEST_PRACTICES "Apply useful compilation options" "${default_value}") +option(CC_STATIC_RUNTIME "Link the runtime statically" "${default_value}") +option(CC_STRIP_SYMBOLS "Strip debug symbols" "${default_value}") +set(CC_CXX_STANDARD "14" CACHE STRING "C++ standard version") + +message(STATUS "Best practices: ${CC_BEST_PRACTICES}") +message(STATUS "Static runtime: ${CC_STATIC_RUNTIME}") +message(STATUS "Strip symbols: ${CC_STRIP_SYMBOLS}") +message(STATUS "C++ standard: ${CC_CXX_STANDARD}") + +# C++ standard version: + +set(CMAKE_CXX_STANDARD "${CC_CXX_STANDARD}") set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -function(use_static_runtime_msvc target) +# Static runtime routines: + +function(static_runtime_msvc target) get_target_property(target_type "${target}" TYPE) - if(target_type STREQUAL INTERFACE_LIBRARY) - else() + if(NOT target_type STREQUAL "INTERFACE_LIBRARY") target_compile_options("${target}" PRIVATE $<$:/MTd> $<$>:/MT>) endif() endfunction() -function(use_static_runtime_gcc target) +function(static_runtime_gcc target) get_target_property(target_type "${target}" TYPE) - if(target_type STREQUAL EXECUTABLE) + if(target_type STREQUAL "EXECUTABLE") target_link_libraries("${target}" PRIVATE -static) endif() endfunction() -function(use_static_runtime target) - if(MSVC) - use_static_runtime_msvc("${target}") - elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) - use_static_runtime_gcc("${target}") - else() - message(WARNING "Unrecognized toolset: ${toolset}") +function(static_runtime target) + if(is_msvc) + static_runtime_msvc("${target}") + elseif(is_gcc) + static_runtime_gcc("${target}") endif() endfunction() -function(strip_symbol_table_gcc target) +# Symbol stripping routines: + +function(strip_symbols_gcc target) get_target_property(target_type "${target}" TYPE) - set(release_build $,$>) - if(target_type STREQUAL INTERFACE_LIBRARY) - else() + if(NOT target_type STREQUAL "INTERFACE_LIBRARY") + set(release_build $,$>) target_link_libraries("${target}" PRIVATE $<${release_build}:-s>) endif() endfunction() -function(strip_symbol_table target) - if(MSVC) - elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) - strip_symbol_table_gcc("${target}") - else() - message(WARNING "Unrecognized toolset: ${toolset}") +function(strip_symbols target) + if(is_gcc) + strip_symbols_gcc("${target}") endif() endfunction() +# Main macros: + function(apply_common_settings target) if(TARGET "${target}") get_target_property(target_imported "${target}" IMPORTED) - if(target_imported STREQUAL NOTFOUND OR NOT target_imported) - if(STRIP_SYMBOL_TABLE) - strip_symbol_table("${target}") + if(NOT target_imported) + if(CC_BEST_PRACTICES) + best_practices("${target}") + endif() + if(CC_STRIP_SYMBOLS) + strip_symbols("${target}") endif() - if(USE_STATIC_RUNTIME) - use_static_runtime("${target}") + if(CC_STATIC_RUNTIME) + static_runtime("${target}") endif() endif() endif() -- cgit v1.2.3