Merge commit '2ef7a8a47805c7165ae5a47b75e634ed35de59dd' as 'cmake'
This commit is contained in:
commit
69c22b1a3a
25
cmake/Jenkinsfile
vendored
Normal file
25
cmake/Jenkinsfile
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
pipeline {
|
||||||
|
agent none
|
||||||
|
|
||||||
|
options {
|
||||||
|
// Only keep the 1 most recent builds
|
||||||
|
buildDiscarder(logRotator(numToKeepStr: "1"))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
stages {
|
||||||
|
|
||||||
|
stage("Build")
|
||||||
|
{
|
||||||
|
agent {
|
||||||
|
label 'c++'
|
||||||
|
}
|
||||||
|
|
||||||
|
steps {
|
||||||
|
echo "build"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
1
cmake/Modules/CheckParent.cmake
Normal file
1
cmake/Modules/CheckParent.cmake
Normal file
@ -0,0 +1 @@
|
|||||||
|
get_directory_property(hasParent PARENT_DIRECTORY)
|
76
cmake/Modules/FindGMP.cmake
Normal file
76
cmake/Modules/FindGMP.cmake
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# Try to find the GMP library
|
||||||
|
# https://gmplib.org/
|
||||||
|
#
|
||||||
|
# This module supports requiring a minimum version, e.g. you can do
|
||||||
|
# find_package(GMP 6.0.0)
|
||||||
|
# to require version 6.0.0 to newer of GMP.
|
||||||
|
#
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# GMP_FOUND - system has GMP lib with correct version
|
||||||
|
# GMP_INCLUDES - the GMP include directory
|
||||||
|
# GMP_LIBRARIES - the GMP library
|
||||||
|
# GMP_VERSION - GMP version
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Jack Poulson, <jack.poulson@gmail.com>
|
||||||
|
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||||
|
|
||||||
|
find_path(GMP_INCLUDES NAMES gmp.h PATHS $ENV{GMPDIR} ${INCLUDE_INSTALL_DIR})
|
||||||
|
|
||||||
|
# Set GMP_FIND_VERSION to 5.1.0 if no minimum version is specified
|
||||||
|
if(NOT GMP_FIND_VERSION)
|
||||||
|
if(NOT GMP_FIND_VERSION_MAJOR)
|
||||||
|
set(GMP_FIND_VERSION_MAJOR 5)
|
||||||
|
endif()
|
||||||
|
if(NOT GMP_FIND_VERSION_MINOR)
|
||||||
|
set(GMP_FIND_VERSION_MINOR 1)
|
||||||
|
endif()
|
||||||
|
if(NOT GMP_FIND_VERSION_PATCH)
|
||||||
|
set(GMP_FIND_VERSION_PATCH 0)
|
||||||
|
endif()
|
||||||
|
set(GMP_FIND_VERSION
|
||||||
|
"${GMP_FIND_VERSION_MAJOR}.${GMP_FIND_VERSION_MINOR}.${GMP_FIND_VERSION_PATCH}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message("GMP_INCLUDES=${GMP_INCLUDES}")
|
||||||
|
if(GMP_INCLUDES)
|
||||||
|
# Since the GMP version macros may be in a file included by gmp.h of the form
|
||||||
|
# gmp-.*[_]?.*.h (e.g., gmp-x86_64.h), we search each of them.
|
||||||
|
file(GLOB GMP_HEADERS "${GMP_INCLUDES}/gmp.h" "${GMP_INCLUDES}/gmp-*.h")
|
||||||
|
foreach(gmp_header_filename ${GMP_HEADERS})
|
||||||
|
file(READ "${gmp_header_filename}" _gmp_version_header)
|
||||||
|
string(REGEX MATCH
|
||||||
|
"define[ \t]+__GNU_MP_VERSION[ \t]+([0-9]+)" _gmp_major_version_match
|
||||||
|
"${_gmp_version_header}")
|
||||||
|
if(_gmp_major_version_match)
|
||||||
|
set(GMP_MAJOR_VERSION "${CMAKE_MATCH_1}")
|
||||||
|
string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_MINOR[ \t]+([0-9]+)"
|
||||||
|
_gmp_minor_version_match "${_gmp_version_header}")
|
||||||
|
set(GMP_MINOR_VERSION "${CMAKE_MATCH_1}")
|
||||||
|
string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_PATCHLEVEL[ \t]+([0-9]+)"
|
||||||
|
_gmp_patchlevel_version_match "${_gmp_version_header}")
|
||||||
|
set(GMP_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}")
|
||||||
|
set(GMP_VERSION
|
||||||
|
${GMP_MAJOR_VERSION}.${GMP_MINOR_VERSION}.${GMP_PATCHLEVEL_VERSION})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Check whether found version exists and exceeds the minimum requirement
|
||||||
|
if(NOT GMP_VERSION)
|
||||||
|
set(GMP_VERSION_OK FALSE)
|
||||||
|
message(STATUS "GMP version was not detected")
|
||||||
|
elseif(${GMP_VERSION} VERSION_LESS ${GMP_FIND_VERSION})
|
||||||
|
set(GMP_VERSION_OK FALSE)
|
||||||
|
message(STATUS "GMP version ${GMP_VERSION} found in ${GMP_INCLUDES}, "
|
||||||
|
"but at least version ${GMP_FIND_VERSION} is required")
|
||||||
|
else()
|
||||||
|
set(GMP_VERSION_OK TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_library(GMP_LIBRARIES gmp PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(GMP DEFAULT_MSG
|
||||||
|
GMP_INCLUDES GMP_LIBRARIES GMP_VERSION_OK)
|
||||||
|
mark_as_advanced(GMP_INCLUDES GMP_LIBRARIES)
|
25
cmake/Modules/FindValgrind.cmake
Normal file
25
cmake/Modules/FindValgrind.cmake
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Find Valgrind.
|
||||||
|
#
|
||||||
|
# This module defines:
|
||||||
|
# VALGRIND_INCLUDE_DIR, where to find valgrind/memcheck.h, etc.
|
||||||
|
# VALGRIND_PROGRAM, the valgrind executable.
|
||||||
|
# VALGRIND_FOUND, If false, do not try to use valgrind.
|
||||||
|
#
|
||||||
|
# If you have valgrind installed in a non-standard place, you can define
|
||||||
|
# VALGRIND_PREFIX to tell cmake where it is.
|
||||||
|
#
|
||||||
|
# NOTE: Copied from the opencog project, where it is distributed under the
|
||||||
|
# terms of the New BSD License.
|
||||||
|
|
||||||
|
message(STATUS "Valgrind Prefix: ${VALGRIND_PREFIX}")
|
||||||
|
|
||||||
|
find_path(VALGRIND_INCLUDE_DIR valgrind/memcheck.h
|
||||||
|
/usr/include /usr/local/include ${VALGRIND_PREFIX}/include)
|
||||||
|
find_program(VALGRIND_PROGRAM NAMES valgrind PATH
|
||||||
|
/usr/bin /usr/local/bin ${VALGRIND_PREFIX}/bin)
|
||||||
|
|
||||||
|
find_package_handle_standard_args(VALGRIND DEFAULT_MSG
|
||||||
|
VALGRIND_INCLUDE_DIR
|
||||||
|
VALGRIND_PROGRAM)
|
||||||
|
|
||||||
|
mark_as_advanced(VALGRIND_INCLUDE_DIR VALGRIND_PROGRAM)
|
47
cmake/Modules/GenerateCccc.cmake
Normal file
47
cmake/Modules/GenerateCccc.cmake
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
INCLUDE(CheckParent)
|
||||||
|
# search for CCCC binary
|
||||||
|
FIND_PROGRAM(CCCC cccc )
|
||||||
|
|
||||||
|
#
|
||||||
|
# check if the GENERATE_CCCC function has already been defined
|
||||||
|
#
|
||||||
|
get_property(_GENERATE_CCCC GLOBAL PROPERTY _GENERATE_CCCC)
|
||||||
|
IF (NOT _GENERATE_CCCC)
|
||||||
|
|
||||||
|
# set that we have defined GENERATE_CCCC
|
||||||
|
set_property(GLOBAL PROPERTY _GENERATE_CCCC "YES")
|
||||||
|
|
||||||
|
|
||||||
|
FUNCTION(GENERATE_CCCC)
|
||||||
|
IF(CCCC)
|
||||||
|
CMAKE_PARSE_ARGUMENTS(ARG "" "" "TARGETS" ${ARGN})
|
||||||
|
get_property(_ccccfiles GLOBAL PROPERTY _ccccfiles)
|
||||||
|
foreach(_target ${ARG_TARGETS})
|
||||||
|
get_target_property(_sources ${_target} SOURCES)
|
||||||
|
get_target_property(_source_dir ${_target} SOURCE_DIR)
|
||||||
|
|
||||||
|
foreach(_source ${_sources})
|
||||||
|
set(_fullsource "${_source_dir}/${_source}")
|
||||||
|
list(APPEND _ccccfiles "${_fullsource}")
|
||||||
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
set_property(GLOBAL PROPERTY _ccccfiles ${_ccccfiles})
|
||||||
|
ENDIF()
|
||||||
|
ENDFUNCTION()
|
||||||
|
|
||||||
|
FUNCTION(RESET_CCCC)
|
||||||
|
set_property(GLOBAL PROPERTY _ccccfiles "")
|
||||||
|
ENDFUNCTION()
|
||||||
|
|
||||||
|
FUNCTION(GENERATE_CCCC_TARGET)
|
||||||
|
IF (NOT hasParent AND CCCC)
|
||||||
|
get_property(_targetccccfiles GLOBAL PROPERTY _ccccfiles)
|
||||||
|
|
||||||
|
ADD_CUSTOM_TARGET(cccc
|
||||||
|
COMMAND ${CCCC} --outdir=cccc ${_targetccccfiles}
|
||||||
|
COMMENT "Generating cccc result")
|
||||||
|
ENDIF()
|
||||||
|
ENDFUNCTION()
|
||||||
|
|
||||||
|
|
||||||
|
ENDIF()
|
74
cmake/Modules/GenerateCppCheck.cmake
Normal file
74
cmake/Modules/GenerateCppCheck.cmake
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
INCLUDE(CheckParent)
|
||||||
|
find_program(CPPCHECK NAMES cppcheck)
|
||||||
|
|
||||||
|
#
|
||||||
|
# check if the GENERATE_CPPCHECK function has already been defined
|
||||||
|
#
|
||||||
|
get_property(_GENERATE_CPPCHECK GLOBAL PROPERTY _GENERATE_CPPCHECK)
|
||||||
|
IF (NOT _GENERATE_CPPCHECK)
|
||||||
|
|
||||||
|
# set that we have defined GENERATE_CCCC
|
||||||
|
set_property(GLOBAL PROPERTY _GENERATE_CPPCHECK "YES")
|
||||||
|
|
||||||
|
FUNCTION(GENERATE_CPPCHECK)
|
||||||
|
IF(NOT TARGET cppcheck)
|
||||||
|
IF(CPPCHECK)
|
||||||
|
CMAKE_PARSE_ARGUMENTS(ARG "" "" "TARGETS" ${ARGN})
|
||||||
|
get_property(_cppcheckfiles GLOBAL PROPERTY _cppcheckfiles)
|
||||||
|
get_property(_cppcheckincludedirs GLOBAL PROPERTY _cppcheckincludedirs)
|
||||||
|
|
||||||
|
foreach(_target ${ARG_TARGETS})
|
||||||
|
get_target_property(_sources ${_target} SOURCES)
|
||||||
|
get_target_property(_source_dir ${_target} SOURCE_DIR)
|
||||||
|
get_target_property(_include_dir ${_target} INCLUDE_DIRECTORIES)
|
||||||
|
string(REPLACE "$<" ";" _include_dirs ${_include_dir})
|
||||||
|
|
||||||
|
foreach(_dir ${_include_dirs})
|
||||||
|
list(APPEND _cppcheckincludedirs -I${_include_dir})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
foreach(_source ${_sources})
|
||||||
|
set(_fullsource "${_source_dir}/${_source}")
|
||||||
|
list(APPEND _cppcheckfiles ${_fullsource})
|
||||||
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
set_property(GLOBAL PROPERTY _cppcheckfiles ${_cppcheckfiles})
|
||||||
|
set_property(GLOBAL PROPERTY _cppcheckincludedirs ${_cppcheckincludedirs})
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
ENDFUNCTION()
|
||||||
|
|
||||||
|
FUNCTION(RESET_CPPCHECK)
|
||||||
|
set_property(GLOBAL PROPERTY _cppcheckfiles "")
|
||||||
|
set_property(GLOBAL PROPERTY _cppcheckincludedirs "")
|
||||||
|
ENDFUNCTION()
|
||||||
|
|
||||||
|
|
||||||
|
FUNCTION(GENERATE_CPPCHECK_TARGET)
|
||||||
|
IF ( NOT hasParent AND CPPCHECK)
|
||||||
|
message("generate cppcheck target")
|
||||||
|
get_property(_targetcppcheckfiles GLOBAL PROPERTY _cppcheckfiles)
|
||||||
|
get_property(_targetcppcheckincludedirs GLOBAL PROPERTY _cppcheckincludedirs)
|
||||||
|
|
||||||
|
add_custom_target(cppcheck
|
||||||
|
COMMAND
|
||||||
|
${CPPCHECK}
|
||||||
|
--xml
|
||||||
|
--xml-version=2
|
||||||
|
--enable=all
|
||||||
|
--inconclusive
|
||||||
|
--force
|
||||||
|
--inline-suppr
|
||||||
|
${_targetcppcheckincludedirs}
|
||||||
|
${_targetcppcheckfiles}
|
||||||
|
2> cppcheck.xml
|
||||||
|
WORKING_DIRECTORY
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
COMMENT
|
||||||
|
"cppcheck: Running cppcheck on target ${_targetname}..."
|
||||||
|
VERBATIM)
|
||||||
|
|
||||||
|
ENDIF()
|
||||||
|
ENDFUNCTION()
|
||||||
|
|
||||||
|
ENDIF()
|
23
cmake/Modules/ProcessDOXYGEN.cmake
Normal file
23
cmake/Modules/ProcessDOXYGEN.cmake
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
INCLUDE(CheckParent)
|
||||||
|
|
||||||
|
IF(NOT hasParent)
|
||||||
|
find_package(Doxygen)
|
||||||
|
|
||||||
|
|
||||||
|
IF (DOXYGEN_FOUND)
|
||||||
|
# set input and output files
|
||||||
|
set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in)
|
||||||
|
set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||||
|
|
||||||
|
# request to configure the file
|
||||||
|
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
|
||||||
|
|
||||||
|
# note the option ALL which allows to build the docs together with the application
|
||||||
|
add_custom_target( doxygen
|
||||||
|
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
COMMENT "Generating API documentation with Doxygen"
|
||||||
|
VERBATIM )
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
ENDIF()
|
17
cmake/Modules/ProcessGIT.cmake
Normal file
17
cmake/Modules/ProcessGIT.cmake
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
if (GIT_FOUND)
|
||||||
|
execute_process(
|
||||||
|
COMMAND git rev-parse --abbrev-ref HEAD
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE GIT_BRANCH
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get the latest abbreviated commit hash of the working branch
|
||||||
|
execute_process(
|
||||||
|
COMMAND git log -1 --format=%h
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
|
||||||
|
endif()
|
22
cmake/Modules/add_my_test.cmake
Normal file
22
cmake/Modules/add_my_test.cmake
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
get_property(_ADD_MY_TEST GLOBAL PROPERTY _ADD_MY_TEST)
|
||||||
|
IF (NOT _ADD_MY_TEST)
|
||||||
|
|
||||||
|
# set that we have defined GENERATE_CCCC
|
||||||
|
set_property(GLOBAL PROPERTY _ADD_MY_TEST "YES")
|
||||||
|
|
||||||
|
|
||||||
|
FUNCTION(ADD_MY_TEST)
|
||||||
|
CMAKE_PARSE_ARGUMENTS(ARG "" "TEST" "SOURCES;LIBS" ${ARGN})
|
||||||
|
get_property(_mytests GLOBAL PROPERTY _mytests)
|
||||||
|
|
||||||
|
list(APPEND _mytests "${ARG_TEST}")
|
||||||
|
|
||||||
|
add_executable(${ARG_TEST} ${ARG_SOURCES})
|
||||||
|
target_link_libraries(${ARG_TEST} ${ARG_LIBS})
|
||||||
|
add_test(${ARG_TEST} ${ARG_TEST})
|
||||||
|
|
||||||
|
set_property(GLOBAL PROPERTY _mytests ${_mytests})
|
||||||
|
ENDFUNCTION()
|
||||||
|
|
||||||
|
|
||||||
|
ENDIF()
|
66
cmake/Modules/c++-standards.cmake
Normal file
66
cmake/Modules/c++-standards.cmake
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
# use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
# the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations under
|
||||||
|
# the License.
|
||||||
|
|
||||||
|
# Set the compiler standard to C++11
|
||||||
|
macro(cxx_11)
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
if(MSVC_VERSION GREATER_EQUAL "1900" AND CMAKE_VERSION LESS 3.10)
|
||||||
|
include(CheckCXXCompilerFlag)
|
||||||
|
check_cxx_compiler_flag("/std:c++11" _cpp_latest_flag_supported)
|
||||||
|
if(_cpp_latest_flag_supported)
|
||||||
|
add_compile_options("/std:c++11")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Set the compiler standard to C++14
|
||||||
|
macro(cxx_14)
|
||||||
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
if(MSVC_VERSION GREATER_EQUAL "1900" AND CMAKE_VERSION LESS 3.10)
|
||||||
|
include(CheckCXXCompilerFlag)
|
||||||
|
check_cxx_compiler_flag("/std:c++14" _cpp_latest_flag_supported)
|
||||||
|
if(_cpp_latest_flag_supported)
|
||||||
|
add_compile_options("/std:c++14")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Set the compiler standard to C++17
|
||||||
|
macro(cxx_17)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
if(MSVC_VERSION GREATER_EQUAL "1900" AND CMAKE_VERSION LESS 3.10)
|
||||||
|
include(CheckCXXCompilerFlag)
|
||||||
|
check_cxx_compiler_flag("/std:c++17" _cpp_latest_flag_supported)
|
||||||
|
if(_cpp_latest_flag_supported)
|
||||||
|
add_compile_options("/std:c++17")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Set the compiler standard to C++20
|
||||||
|
macro(cxx_20)
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
endmacro()
|
588
cmake/Modules/code-coverage.cmake
Normal file
588
cmake/Modules/code-coverage.cmake
Normal file
@ -0,0 +1,588 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
# use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
# the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations under
|
||||||
|
# the License.
|
||||||
|
|
||||||
|
# USAGE: To enable any code coverage instrumentation/targets, the single CMake
|
||||||
|
# option of `CODE_COVERAGE` needs to be set to 'ON', either by GUI, ccmake, or
|
||||||
|
# on the command line.
|
||||||
|
#
|
||||||
|
# From this point, there are two primary methods for adding instrumentation to
|
||||||
|
# targets: 1 - A blanket instrumentation by calling `add_code_coverage()`, where
|
||||||
|
# all targets in that directory and all subdirectories are automatically
|
||||||
|
# instrumented. 2 - Per-target instrumentation by calling
|
||||||
|
# `target_code_coverage(<TARGET_NAME>)`, where the target is given and thus only
|
||||||
|
# that target is instrumented. This applies to both libraries and executables.
|
||||||
|
#
|
||||||
|
# To add coverage targets, such as calling `make ccov` to generate the actual
|
||||||
|
# coverage information for perusal or consumption, call
|
||||||
|
# `target_code_coverage(<TARGET_NAME>)` on an *executable* target.
|
||||||
|
#
|
||||||
|
# Example 1: All targets instrumented
|
||||||
|
#
|
||||||
|
# In this case, the coverage information reported will will be that of the
|
||||||
|
# `theLib` library target and `theExe` executable.
|
||||||
|
#
|
||||||
|
# 1a: Via global command
|
||||||
|
#
|
||||||
|
# ~~~
|
||||||
|
# add_code_coverage() # Adds instrumentation to all targets
|
||||||
|
#
|
||||||
|
# add_library(theLib lib.cpp)
|
||||||
|
#
|
||||||
|
# add_executable(theExe main.cpp)
|
||||||
|
# target_link_libraries(theExe PRIVATE theLib)
|
||||||
|
# target_code_coverage(theExe) # As an executable target, adds the 'ccov-theExe' target (instrumentation already added via global anyways) for generating code coverage reports.
|
||||||
|
# ~~~
|
||||||
|
#
|
||||||
|
# 1b: Via target commands
|
||||||
|
#
|
||||||
|
# ~~~
|
||||||
|
# add_library(theLib lib.cpp)
|
||||||
|
# target_code_coverage(theLib) # As a library target, adds coverage instrumentation but no targets.
|
||||||
|
#
|
||||||
|
# add_executable(theExe main.cpp)
|
||||||
|
# target_link_libraries(theExe PRIVATE theLib)
|
||||||
|
# target_code_coverage(theExe) # As an executable target, adds the 'ccov-theExe' target and instrumentation for generating code coverage reports.
|
||||||
|
# ~~~
|
||||||
|
#
|
||||||
|
# Example 2: Target instrumented, but with regex pattern of files to be excluded
|
||||||
|
# from report
|
||||||
|
#
|
||||||
|
# ~~~
|
||||||
|
# add_executable(theExe main.cpp non_covered.cpp)
|
||||||
|
# target_code_coverage(theExe EXCLUDE non_covered.cpp test/*) # As an executable target, the reports will exclude the non-covered.cpp file, and any files in a test/ folder.
|
||||||
|
# ~~~
|
||||||
|
#
|
||||||
|
# Example 3: Target added to the 'ccov' and 'ccov-all' targets
|
||||||
|
#
|
||||||
|
# ~~~
|
||||||
|
# add_code_coverage_all_targets(EXCLUDE test/*) # Adds the 'ccov-all' target set and sets it to exclude all files in test/ folders.
|
||||||
|
#
|
||||||
|
# add_executable(theExe main.cpp non_covered.cpp)
|
||||||
|
# target_code_coverage(theExe AUTO ALL EXCLUDE non_covered.cpp test/*) # As an executable target, adds to the 'ccov' and ccov-all' targets, and the reports will exclude the non-covered.cpp file, and any files in a test/ folder.
|
||||||
|
# ~~~
|
||||||
|
|
||||||
|
# Options
|
||||||
|
option(
|
||||||
|
CODE_COVERAGE
|
||||||
|
"Builds targets with code coverage instrumentation. (Requires GCC or Clang)"
|
||||||
|
OFF)
|
||||||
|
|
||||||
|
# Programs
|
||||||
|
find_program(LLVM_COV_PATH NAMES llvm-cov llvm-cov-8 llvm-cov-7 llvm-cov-6)
|
||||||
|
find_program(LLVM_PROFDATA_PATH NAMES llvm-profdata llvm-profdata-8 llvm-profdata-7 llvm-profdata-6)
|
||||||
|
find_program(LCOV_PATH lcov)
|
||||||
|
find_program(GENHTML_PATH genhtml)
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
set(CMAKE_COVERAGE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/ccov)
|
||||||
|
|
||||||
|
# Common initialization/checks
|
||||||
|
if(CODE_COVERAGE AND NOT CODE_COVERAGE_ADDED)
|
||||||
|
set(CODE_COVERAGE_ADDED ON)
|
||||||
|
|
||||||
|
# Common Targets
|
||||||
|
add_custom_target(ccov-preprocessing
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-E
|
||||||
|
make_directory
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}
|
||||||
|
DEPENDS ccov-clean)
|
||||||
|
|
||||||
|
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||||
|
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||||
|
# Messages
|
||||||
|
message(STATUS "Building with llvm Code Coverage Tools")
|
||||||
|
|
||||||
|
if(NOT LLVM_COV_PATH)
|
||||||
|
message(FATAL_ERROR "llvm-cov not found! Aborting.")
|
||||||
|
else()
|
||||||
|
# Version number checking for 'EXCLUDE' compatability
|
||||||
|
execute_process(COMMAND ${LLVM_COV_PATH} --version
|
||||||
|
OUTPUT_VARIABLE LLVM_COV_VERSION_CALL_OUTPUT)
|
||||||
|
string(REGEX MATCH
|
||||||
|
"[0-9]+\\.[0-9]+\\.[0-9]+"
|
||||||
|
LLVM_COV_VERSION
|
||||||
|
${LLVM_COV_VERSION_CALL_OUTPUT})
|
||||||
|
|
||||||
|
if(LLVM_COV_VERSION VERSION_LESS "7.0.0")
|
||||||
|
message(
|
||||||
|
WARNING
|
||||||
|
"target_code_coverage()/add_code_coverage_all_targets() 'EXCLUDE' option only available on llvm-cov >= 7.0.0"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Targets
|
||||||
|
add_custom_target(ccov-clean
|
||||||
|
COMMAND rm -f
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list
|
||||||
|
COMMAND rm -f
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list)
|
||||||
|
|
||||||
|
# Used to get the shared object file list before doing the main all-processing
|
||||||
|
add_custom_target(ccov-libs
|
||||||
|
COMMAND ;
|
||||||
|
COMMENT "libs ready for coverage report.")
|
||||||
|
|
||||||
|
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
# Messages
|
||||||
|
message(STATUS "Building with lcov Code Coverage Tools")
|
||||||
|
|
||||||
|
if(CMAKE_BUILD_TYPE)
|
||||||
|
string(TOUPPER ${CMAKE_BUILD_TYPE} upper_build_type)
|
||||||
|
if(NOT ${upper_build_type} STREQUAL "DEBUG")
|
||||||
|
message(
|
||||||
|
WARNING
|
||||||
|
"Code coverage results with an optimized (non-Debug) build may be misleading"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(
|
||||||
|
WARNING
|
||||||
|
"Code coverage results with an optimized (non-Debug) build may be misleading"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(NOT LCOV_PATH)
|
||||||
|
message(FATAL_ERROR "lcov not found! Aborting...")
|
||||||
|
endif()
|
||||||
|
if(NOT GENHTML_PATH)
|
||||||
|
message(FATAL_ERROR "genhtml not found! Aborting...")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Targets
|
||||||
|
add_custom_target(ccov-clean
|
||||||
|
COMMAND ${LCOV_PATH}
|
||||||
|
--directory
|
||||||
|
${CMAKE_BINARY_DIR}
|
||||||
|
--zerocounters)
|
||||||
|
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Code coverage requires Clang or GCC. Aborting.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Adds code coverage instrumentation to a library, or instrumentation/targets
|
||||||
|
# for an executable target.
|
||||||
|
# ~~~
|
||||||
|
# EXECUTABLE ADDED TARGETS:
|
||||||
|
# GCOV/LCOV:
|
||||||
|
# ccov : Generates HTML code coverage report for every target added with 'AUTO' parameter.
|
||||||
|
# ccov-${TARGET_NAME} : Generates HTML code coverage report for the associated named target.
|
||||||
|
# ccov-all : Generates HTML code coverage report, merging every target added with 'ALL' parameter into a single detailed report.
|
||||||
|
#
|
||||||
|
# LLVM-COV:
|
||||||
|
# ccov : Generates HTML code coverage report for every target added with 'AUTO' parameter.
|
||||||
|
# ccov-report : Generates HTML code coverage report for every target added with 'AUTO' parameter.
|
||||||
|
# ccov-${TARGET_NAME} : Generates HTML code coverage report.
|
||||||
|
# ccov-report-${TARGET_NAME} : Prints to command line summary per-file coverage information.
|
||||||
|
# ccov-show-${TARGET_NAME} : Prints to command line detailed per-line coverage information.
|
||||||
|
# ccov-all : Generates HTML code coverage report, merging every target added with 'ALL' parameter into a single detailed report.
|
||||||
|
# ccov-all-report : Prints summary per-file coverage information for every target added with ALL' parameter to the command line.
|
||||||
|
#
|
||||||
|
# Required:
|
||||||
|
# TARGET_NAME - Name of the target to generate code coverage for.
|
||||||
|
# Optional:
|
||||||
|
# AUTO - Adds the target to the 'ccov' target so that it can be run in a batch with others easily. Effective on executable targets.
|
||||||
|
# ALL - Adds the target to the 'ccov-all' and 'ccov-all-report' targets, which merge several executable targets coverage data to a single report. Effective on executable targets.
|
||||||
|
# EXTERNAL - For GCC's lcov, allows the profiling of 'external' files from the processing directory
|
||||||
|
# EXCLUDE <REGEX_PATTERNS> - Excludes files of the patterns provided from coverage. **These do not copy to the 'all' targets.**
|
||||||
|
# OBJECTS <TARGETS> - For executables ONLY, if the provided targets are shared libraries, adds coverage information to the output
|
||||||
|
# ~~~
|
||||||
|
function(target_code_coverage TARGET_NAME)
|
||||||
|
# Argument parsing
|
||||||
|
set(options AUTO ALL EXTERNAL)
|
||||||
|
set(multi_value_keywords EXCLUDE OBJECTS)
|
||||||
|
cmake_parse_arguments(target_code_coverage
|
||||||
|
"${options}"
|
||||||
|
""
|
||||||
|
"${multi_value_keywords}"
|
||||||
|
${ARGN})
|
||||||
|
|
||||||
|
if(CODE_COVERAGE)
|
||||||
|
|
||||||
|
# Add code coverage instrumentation to the target's linker command
|
||||||
|
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||||
|
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||||
|
target_compile_options(
|
||||||
|
${TARGET_NAME}
|
||||||
|
PRIVATE -fprofile-instr-generate -fcoverage-mapping)
|
||||||
|
set_property(TARGET ${TARGET_NAME}
|
||||||
|
APPEND_STRING
|
||||||
|
PROPERTY LINK_FLAGS "-fprofile-instr-generate ")
|
||||||
|
set_property(TARGET ${TARGET_NAME}
|
||||||
|
APPEND_STRING
|
||||||
|
PROPERTY LINK_FLAGS "-fcoverage-mapping ")
|
||||||
|
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
target_compile_options(${TARGET_NAME}
|
||||||
|
PRIVATE -fprofile-arcs -ftest-coverage)
|
||||||
|
target_link_libraries(${TARGET_NAME} PRIVATE gcov)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Targets
|
||||||
|
get_target_property(target_type ${TARGET_NAME} TYPE)
|
||||||
|
|
||||||
|
# Add shared library to processing for 'all' targets
|
||||||
|
if(target_type STREQUAL "SHARED_LIBRARY" AND target_code_coverage_ALL)
|
||||||
|
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||||
|
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||||
|
add_custom_target(
|
||||||
|
ccov-run-${TARGET_NAME}
|
||||||
|
COMMAND echo
|
||||||
|
"-object=$<TARGET_FILE:${TARGET_NAME}>"
|
||||||
|
>>
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list
|
||||||
|
DEPENDS ccov-preprocessing ${TARGET_NAME})
|
||||||
|
|
||||||
|
if(NOT TARGET ccov-libs)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_dependencies(ccov-libs ccov-run-${TARGET_NAME})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# For executables add targets to run and produce output
|
||||||
|
if(target_type STREQUAL "EXECUTABLE")
|
||||||
|
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||||
|
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||||
|
|
||||||
|
# If there are shared objects to also work with, generate the string to add them here
|
||||||
|
foreach(SO_TARGET ${target_code_coverage_OBJECTS})
|
||||||
|
# Check to see if the target is a shared object
|
||||||
|
if(TARGET ${SO_TARGET})
|
||||||
|
get_target_property(SO_TARGET_TYPE ${SO_TARGET} TYPE)
|
||||||
|
if(${SO_TARGET_TYPE} STREQUAL "SHARED_LIBRARY")
|
||||||
|
set(SO_OBJECTS ${SO_OBJECTS} -object=$<TARGET_FILE:${SO_TARGET}>)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Run the executable, generating raw profile data
|
||||||
|
add_custom_target(
|
||||||
|
ccov-run-${TARGET_NAME}
|
||||||
|
COMMAND LLVM_PROFILE_FILE=${TARGET_NAME}.profraw
|
||||||
|
$<TARGET_FILE:${TARGET_NAME}>
|
||||||
|
COMMAND echo
|
||||||
|
"-object=$<TARGET_FILE:${TARGET_NAME}>"
|
||||||
|
>>
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list
|
||||||
|
COMMAND echo
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.profraw "
|
||||||
|
>>
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list
|
||||||
|
DEPENDS ccov-preprocessing ccov-libs ${TARGET_NAME})
|
||||||
|
|
||||||
|
# Merge the generated profile data so llvm-cov can process it
|
||||||
|
add_custom_target(ccov-processing-${TARGET_NAME}
|
||||||
|
COMMAND ${LLVM_PROFDATA_PATH}
|
||||||
|
merge
|
||||||
|
-sparse
|
||||||
|
${TARGET_NAME}.profraw
|
||||||
|
-o
|
||||||
|
${TARGET_NAME}.profdata
|
||||||
|
DEPENDS ccov-run-${TARGET_NAME})
|
||||||
|
|
||||||
|
# Ignore regex only works on LLVM >= 7
|
||||||
|
if(LLVM_COV_VERSION VERSION_GREATER_EQUAL "7.0.0")
|
||||||
|
foreach(EXCLUDE_ITEM ${target_code_coverage_EXCLUDE})
|
||||||
|
set(EXCLUDE_REGEX ${EXCLUDE_REGEX}
|
||||||
|
-ignore-filename-regex='${EXCLUDE_ITEM}')
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Print out details of the coverage information to the command line
|
||||||
|
add_custom_target(ccov-show-${TARGET_NAME}
|
||||||
|
COMMAND ${LLVM_COV_PATH}
|
||||||
|
show
|
||||||
|
$<TARGET_FILE:${TARGET_NAME}>
|
||||||
|
${SO_OBJECTS}
|
||||||
|
-instr-profile=${TARGET_NAME}.profdata
|
||||||
|
-show-line-counts-or-regions
|
||||||
|
${EXCLUDE_REGEX}
|
||||||
|
DEPENDS ccov-processing-${TARGET_NAME})
|
||||||
|
|
||||||
|
# Print out a summary of the coverage information to the command line
|
||||||
|
add_custom_target(ccov-report-${TARGET_NAME}
|
||||||
|
COMMAND ${LLVM_COV_PATH}
|
||||||
|
report
|
||||||
|
$<TARGET_FILE:${TARGET_NAME}>
|
||||||
|
${SO_OBJECTS}
|
||||||
|
-instr-profile=${TARGET_NAME}.profdata
|
||||||
|
${EXCLUDE_REGEX}
|
||||||
|
DEPENDS ccov-processing-${TARGET_NAME})
|
||||||
|
|
||||||
|
# Generates HTML output of the coverage information for perusal
|
||||||
|
add_custom_target(
|
||||||
|
ccov-${TARGET_NAME}
|
||||||
|
COMMAND ${LLVM_COV_PATH}
|
||||||
|
show
|
||||||
|
$<TARGET_FILE:${TARGET_NAME}>
|
||||||
|
${SO_OBJECTS}
|
||||||
|
-instr-profile=${TARGET_NAME}.profdata
|
||||||
|
-show-line-counts-or-regions
|
||||||
|
-output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${TARGET_NAME}
|
||||||
|
-format="html"
|
||||||
|
${EXCLUDE_REGEX}
|
||||||
|
DEPENDS ccov-processing-${TARGET_NAME})
|
||||||
|
|
||||||
|
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
set(COVERAGE_INFO
|
||||||
|
"${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${TARGET_NAME}.info")
|
||||||
|
|
||||||
|
# Run the executable, generating coverage information
|
||||||
|
add_custom_target(ccov-run-${TARGET_NAME}
|
||||||
|
COMMAND $<TARGET_FILE:${TARGET_NAME}>
|
||||||
|
DEPENDS ccov-preprocessing ${TARGET_NAME})
|
||||||
|
|
||||||
|
# Generate exclusion string for use
|
||||||
|
foreach(EXCLUDE_ITEM ${target_code_coverage_EXCLUDE})
|
||||||
|
set(EXCLUDE_REGEX
|
||||||
|
${EXCLUDE_REGEX}
|
||||||
|
--remove
|
||||||
|
${COVERAGE_INFO}
|
||||||
|
'${EXCLUDE_ITEM}')
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(EXCLUDE_REGEX)
|
||||||
|
set(EXCLUDE_COMMAND
|
||||||
|
${LCOV_PATH}
|
||||||
|
${EXCLUDE_REGEX}
|
||||||
|
--output-file
|
||||||
|
${COVERAGE_INFO})
|
||||||
|
else()
|
||||||
|
set(EXCLUDE_COMMAND ;)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT ${target_code_coverage_EXTERNAL})
|
||||||
|
set(EXTERNAL_OPTION --no-external)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Generates HTML output of the coverage information for perusal
|
||||||
|
add_custom_target(
|
||||||
|
ccov-${TARGET_NAME}
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-E
|
||||||
|
remove
|
||||||
|
${COVERAGE_INFO}
|
||||||
|
COMMAND ${LCOV_PATH}
|
||||||
|
--directory
|
||||||
|
${CMAKE_BINARY_DIR}
|
||||||
|
--zerocounters
|
||||||
|
COMMAND $<TARGET_FILE:${TARGET_NAME}>
|
||||||
|
COMMAND ${LCOV_PATH}
|
||||||
|
--directory
|
||||||
|
${CMAKE_BINARY_DIR}
|
||||||
|
--base-directory
|
||||||
|
${CMAKE_SOURCE_DIR}
|
||||||
|
--capture
|
||||||
|
${EXTERNAL_OPTION}
|
||||||
|
--output-file
|
||||||
|
${COVERAGE_INFO}
|
||||||
|
COMMAND ${EXCLUDE_COMMAND}
|
||||||
|
COMMAND ${GENHTML_PATH}
|
||||||
|
-o
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${TARGET_NAME}
|
||||||
|
${COVERAGE_INFO}
|
||||||
|
DEPENDS ccov-preprocessing ${TARGET_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ccov-${TARGET_NAME} POST_BUILD
|
||||||
|
COMMAND ;
|
||||||
|
COMMENT
|
||||||
|
"Open ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${TARGET_NAME}/index.html in your browser to view the coverage report."
|
||||||
|
)
|
||||||
|
|
||||||
|
# AUTO
|
||||||
|
if(target_code_coverage_AUTO)
|
||||||
|
if(NOT TARGET ccov)
|
||||||
|
add_custom_target(ccov)
|
||||||
|
endif()
|
||||||
|
add_dependencies(ccov ccov-${TARGET_NAME})
|
||||||
|
|
||||||
|
if(NOT CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
if(NOT TARGET ccov-report)
|
||||||
|
add_custom_target(ccov-report)
|
||||||
|
endif()
|
||||||
|
add_dependencies(ccov-report ccov-report-${TARGET_NAME})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ALL
|
||||||
|
if(target_code_coverage_ALL)
|
||||||
|
if(NOT TARGET ccov-all-processing)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_dependencies(ccov-all-processing ccov-run-${TARGET_NAME})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Adds code coverage instrumentation to all targets in the current directory and
|
||||||
|
# any subdirectories. To add coverage instrumentation to only specific targets,
|
||||||
|
# use `target_code_coverage`.
|
||||||
|
function(add_code_coverage)
|
||||||
|
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||||
|
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||||
|
add_compile_options(-fprofile-instr-generate -fcoverage-mapping)
|
||||||
|
add_link_options(-fprofile-instr-generate -fcoverage-mapping)
|
||||||
|
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
add_compile_options(-fprofile-arcs -ftest-coverage)
|
||||||
|
link_libraries(gcov)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Adds the 'ccov-all' type targets that calls all targets added via
|
||||||
|
# `target_code_coverage` with the `ALL` parameter, but merges all the coverage
|
||||||
|
# data from them into a single large report instead of the numerous smaller
|
||||||
|
# reports.
|
||||||
|
# ~~~
|
||||||
|
# Optional:
|
||||||
|
# EXCLUDE <REGEX_PATTERNS> - Excludes files of the regex patterns provided from coverage.
|
||||||
|
# ~~~
|
||||||
|
function(add_code_coverage_all_targets)
|
||||||
|
# Argument parsing
|
||||||
|
set(multi_value_keywords EXCLUDE)
|
||||||
|
cmake_parse_arguments(add_code_coverage_all_targets
|
||||||
|
""
|
||||||
|
""
|
||||||
|
"${multi_value_keywords}"
|
||||||
|
${ARGN})
|
||||||
|
|
||||||
|
if(CODE_COVERAGE)
|
||||||
|
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||||
|
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||||
|
|
||||||
|
# Merge the profile data for all of the run executables
|
||||||
|
add_custom_target(
|
||||||
|
ccov-all-processing
|
||||||
|
COMMAND ${LLVM_PROFDATA_PATH}
|
||||||
|
merge
|
||||||
|
-o
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata
|
||||||
|
-sparse
|
||||||
|
`cat
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list`)
|
||||||
|
|
||||||
|
# Regex exclude only available for LLVM >= 7
|
||||||
|
if(LLVM_COV_VERSION VERSION_GREATER_EQUAL "7.0.0")
|
||||||
|
foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE})
|
||||||
|
set(EXCLUDE_REGEX ${EXCLUDE_REGEX}
|
||||||
|
-ignore-filename-regex='${EXCLUDE_ITEM}')
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Print summary of the code coverage information to the command line
|
||||||
|
add_custom_target(
|
||||||
|
ccov-all-report
|
||||||
|
COMMAND
|
||||||
|
${LLVM_COV_PATH}
|
||||||
|
report
|
||||||
|
`cat
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list`
|
||||||
|
-instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata
|
||||||
|
${EXCLUDE_REGEX}
|
||||||
|
DEPENDS ccov-all-processing)
|
||||||
|
|
||||||
|
# Export coverage information so continuous integration tools (e.g. Jenkins) can consume it
|
||||||
|
add_custom_target(
|
||||||
|
ccov-all-export
|
||||||
|
COMMAND
|
||||||
|
${LLVM_COV_PATH}
|
||||||
|
export
|
||||||
|
`cat
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list`
|
||||||
|
-instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata
|
||||||
|
-format="text"
|
||||||
|
${EXCLUDE_REGEX} > ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/coverage.json
|
||||||
|
DEPENDS ccov-all-processing)
|
||||||
|
|
||||||
|
# Generate HTML output of all added targets for perusal
|
||||||
|
add_custom_target(
|
||||||
|
ccov-all
|
||||||
|
COMMAND
|
||||||
|
${LLVM_COV_PATH}
|
||||||
|
show
|
||||||
|
`cat
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list`
|
||||||
|
-instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata
|
||||||
|
-show-line-counts-or-regions
|
||||||
|
-output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged
|
||||||
|
-format="html"
|
||||||
|
${EXCLUDE_REGEX}
|
||||||
|
DEPENDS ccov-all-processing)
|
||||||
|
|
||||||
|
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
set(COVERAGE_INFO "${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.info")
|
||||||
|
|
||||||
|
# Nothing required for gcov
|
||||||
|
add_custom_target(ccov-all-processing COMMAND ;)
|
||||||
|
|
||||||
|
# Exclusion regex string creation
|
||||||
|
foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE})
|
||||||
|
set(EXCLUDE_REGEX
|
||||||
|
${EXCLUDE_REGEX}
|
||||||
|
--remove
|
||||||
|
${COVERAGE_INFO}
|
||||||
|
'${EXCLUDE_ITEM}')
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(EXCLUDE_REGEX)
|
||||||
|
set(EXCLUDE_COMMAND
|
||||||
|
${LCOV_PATH}
|
||||||
|
${EXCLUDE_REGEX}
|
||||||
|
--output-file
|
||||||
|
${COVERAGE_INFO})
|
||||||
|
else()
|
||||||
|
set(EXCLUDE_COMMAND ;)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Generates HTML output of all targets for perusal
|
||||||
|
add_custom_target(ccov-all
|
||||||
|
COMMAND ${LCOV_PATH}
|
||||||
|
--directory
|
||||||
|
${CMAKE_BINARY_DIR}
|
||||||
|
--capture
|
||||||
|
--output-file
|
||||||
|
${COVERAGE_INFO}
|
||||||
|
COMMAND ${EXCLUDE_COMMAND}
|
||||||
|
COMMAND ${GENHTML_PATH}
|
||||||
|
-o
|
||||||
|
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged
|
||||||
|
${COVERAGE_INFO}
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-E
|
||||||
|
remove
|
||||||
|
${COVERAGE_INFO}
|
||||||
|
DEPENDS ccov-all-processing)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ccov-all POST_BUILD
|
||||||
|
COMMAND ;
|
||||||
|
COMMENT
|
||||||
|
"Open ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged/index.html in your browser to view the coverage report."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
99
cmake/Modules/codecheck.cmake
Normal file
99
cmake/Modules/codecheck.cmake
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
#
|
||||||
|
option(CODECHECKER "Turns on codecheck processing if it is found." OFF)
|
||||||
|
option(CODECHECKER_STORE "Store results on central codechecker server" OFF)
|
||||||
|
option(CODECHECKER_RUN "Name of the codechecker run" "run-1")
|
||||||
|
option(CODECHECKER_URL "URL and product link to codechecker server" "http://localhost:8001/Default")
|
||||||
|
|
||||||
|
find_program(CODECHECKER_VENV_PATH
|
||||||
|
NAME activate
|
||||||
|
PATHS ~/Apps/codechecker/venv/bin/
|
||||||
|
~/codechecker/venv/bin/
|
||||||
|
/usr/src/codechecker/venv/bin/
|
||||||
|
)
|
||||||
|
|
||||||
|
find_program(CODECHECKER_PATH
|
||||||
|
NAME CodeChecker
|
||||||
|
PATHS ~/Apps/codechecker/build/CodeChecker/bin/
|
||||||
|
~/codechecker/build/CodeChecker/bin/
|
||||||
|
/usr/src/~/codechecker/build/CodeChecker/bin/
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND git rev-parse --abbrev-ref HEAD
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE CODECHECK_GIT_BRANCH
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (CODECHECKER_PATH AND CODECHECKER_VENV_PATH)
|
||||||
|
message(STATUS "CodeChecker found")
|
||||||
|
else()
|
||||||
|
message(STATUS "CodeChecker not found")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# export compile commands to json file to be used by atom c++ ide (clangd)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
||||||
|
set(CODECHECKER_COMPILE_COMMANDS "${CMAKE_BINARY_DIR}/compile_commands.json")
|
||||||
|
|
||||||
|
# check if a skip file exists
|
||||||
|
if(EXISTS ${CMAKE_SOURCE_DIR}/codecheck.skip)
|
||||||
|
set(CODECHECKER_SKIP "-i${CMAKE_SOURCE_DIR}/codecheck.skip")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# output directory for codecheck analysis
|
||||||
|
set(CODECHECKER_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/codechecker_results)
|
||||||
|
|
||||||
|
# html output directory
|
||||||
|
set(CODECHECKER_HTML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/codechecker_html)
|
||||||
|
|
||||||
|
# Common initialization/checks
|
||||||
|
if(CODECHECKER AND CODECHECKER_PATH AND CODECHECKER_VENV_PATH AND NOT CODECHECKER_ADDED)
|
||||||
|
set(CODECHECKER_ADDED ON)
|
||||||
|
|
||||||
|
add_custom_target(codechecker
|
||||||
|
COMMAND . ${CODECHECKER_VENV_PATH}\;
|
||||||
|
${CODECHECKER_PATH}
|
||||||
|
analyze
|
||||||
|
${CODECHECKER_SKIP}
|
||||||
|
-e sensitive
|
||||||
|
-j 4
|
||||||
|
-o ${CODECHECKER_OUTPUT_DIRECTORY}
|
||||||
|
${CODECHECKER_COMPILE_COMMANDS}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(codechecker-clean
|
||||||
|
COMMAND rm -rf ${CODECHECKER_OUTPUT_DIRECTORY}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
add_custom_target(codechecker-html
|
||||||
|
COMMAND . ${CODECHECKER_VENV_PATH}\;
|
||||||
|
${CODECHECKER_PATH}
|
||||||
|
parse
|
||||||
|
${CODECHECKER_OUTPUT_DIRECTORY}
|
||||||
|
-e html
|
||||||
|
-o ${CODECHECKER_HTML_OUTPUT_DIRECTORY}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (CODECHECKER_STORE)
|
||||||
|
add_custom_target(codechecker-store
|
||||||
|
COMMAND . ${CODECHECKER_VENV_PATH}\;
|
||||||
|
${CODECHECKER_PATH}
|
||||||
|
store
|
||||||
|
--tag ${CODECHECK_GIT_BRANCH}
|
||||||
|
-n ${CODECHECKER_RUN}
|
||||||
|
--url ${CODECHECKER_URL}
|
||||||
|
${CODECHECKER_OUTPUT_DIRECTORY}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
endif()
|
46
cmake/Modules/compiler-options.cmake
Normal file
46
cmake/Modules/compiler-options.cmake
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
# use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
# the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations under
|
||||||
|
# the License.
|
||||||
|
|
||||||
|
option(ENABLE_ALL_WARNINGS "Compile with all warnings for the major compilers."
|
||||||
|
OFF)
|
||||||
|
option(ENABLE_EFFECTIVE_CXX "Enable Effective C++ warnings." OFF)
|
||||||
|
|
||||||
|
if(ENABLE_ALL_WARNINGS)
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
# GCC
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
||||||
|
elseif("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||||
|
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||||
|
# Clang
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
||||||
|
elseif(MSVC)
|
||||||
|
# MSVC
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_EFFECTIVE_CXX)
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
# GCC
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weffc++")
|
||||||
|
elseif("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||||
|
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||||
|
# Clang
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weffc++")
|
||||||
|
endif()
|
||||||
|
endif()
|
13
cmake/Modules/defaultIncludes.cmake
Normal file
13
cmake/Modules/defaultIncludes.cmake
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
include(c++-standards)
|
||||||
|
include(compiler-options)
|
||||||
|
include(sanitizers)
|
||||||
|
include(codecheck)
|
||||||
|
include(code-coverage)
|
||||||
|
include(tools)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
include(CTest)
|
||||||
|
include(doxygen)
|
||||||
|
include(ProcessGIT)
|
||||||
|
include(CheckParent)
|
||||||
|
include(add_my_test)
|
||||||
|
include(TestBigEndian)
|
11
cmake/Modules/defaultOptions.cmake
Normal file
11
cmake/Modules/defaultOptions.cmake
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
include(defaultIncludes)
|
||||||
|
find_package(Git)
|
||||||
|
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
cxx_14()
|
||||||
|
build_docs(PROCESS_DOXYFILE DOXYFILE_PATH "docs/Doxyfile.in" )
|
||||||
|
cppcheck("--enable=warning,performance,portability,missingInclude;--template=\"[{severity}][{id}] {message} {callstack} \(On {file}:{line}\)\";--suppress=missingIncludeSystem;--suppress=*:${PROJECT_SOURCE_DIR}/libs/*;--quiet;--verbose;--force")
|
||||||
|
|
||||||
|
add_code_coverage_all_targets(EXCLUDE ${PROJECT_SOURCE_DIR}/libs/* ${PROJECT_SOURCE_DIR}/test/*)
|
||||||
|
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
|
132
cmake/Modules/doxygen.cmake
Normal file
132
cmake/Modules/doxygen.cmake
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
# use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
# the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations under
|
||||||
|
# the License.
|
||||||
|
|
||||||
|
find_package(Doxygen)
|
||||||
|
|
||||||
|
option(BUILD_DOCUMENTATION "Build API documentation using Doxygen. (make doc)"
|
||||||
|
${DOXYGEN_FOUND})
|
||||||
|
|
||||||
|
# Builds doxygen documentation with a default 'Doxyfile.in' or with a specified
|
||||||
|
# one, and can make the results installable (under the `doc` install target)
|
||||||
|
#
|
||||||
|
# This can only be used once per project, as each target generated is as
|
||||||
|
# `doc-${PROJECT_NAME}` unless TARGET_NAME is specified.
|
||||||
|
# ~~~
|
||||||
|
# Optional Arguments:
|
||||||
|
#
|
||||||
|
# ADD_TO_DOC
|
||||||
|
# If specified, adds this generated target to be a dependency of the more general
|
||||||
|
# `doc` target.
|
||||||
|
#
|
||||||
|
# INSTALLABLE
|
||||||
|
# Adds the generated documentation to the generic `install` target, under the
|
||||||
|
# `documentation` installation group.
|
||||||
|
#
|
||||||
|
# PROCESS_DOXYFILE
|
||||||
|
# If set, then will process the found Doxyfile through the CMAKE `configure_file`
|
||||||
|
# function for macro replacements before using it. (@ONLY)
|
||||||
|
#
|
||||||
|
# TARGET_NAME <str>
|
||||||
|
# The name to give the doc target. (Default: doc-${PROJECT_NAME})
|
||||||
|
#
|
||||||
|
# OUTPUT_DIR <str>
|
||||||
|
# The directory to place the generated output. (Default: ${CMAKE_CURRENT_BINARY_DIR}/doc)
|
||||||
|
#
|
||||||
|
# INSTALL_PATH <str>
|
||||||
|
# The path to install the documenttation under. (if not specified, defaults to
|
||||||
|
# 'share/${PROJECT_NAME})
|
||||||
|
#
|
||||||
|
# DOXYFILE_PATH <str>
|
||||||
|
# The given doxygen file to use/process. (Defaults to'${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile')
|
||||||
|
# ~~~
|
||||||
|
function(build_docs)
|
||||||
|
set(OPTIONS ADD_TO_DOC INSTALLABLE PROCESS_DOXYFILE)
|
||||||
|
set(SINGLE_VALUE_KEYWORDS
|
||||||
|
TARGET_NAME
|
||||||
|
INSTALL_PATH
|
||||||
|
DOXYFILE_PATH
|
||||||
|
OUTPUT_DIR)
|
||||||
|
set(MULTI_VALUE_KEYWORDS)
|
||||||
|
cmake_parse_arguments(build_docs
|
||||||
|
"${OPTIONS}"
|
||||||
|
"${SINGLE_VALUE_KEYWORDS}"
|
||||||
|
"${MULTI_VALUE_KEYWORDS}"
|
||||||
|
${ARGN})
|
||||||
|
|
||||||
|
if(BUILD_DOCUMENTATION)
|
||||||
|
if(NOT DOXYGEN_FOUND)
|
||||||
|
message(FATAL_ERROR "Doxygen is needed to build the documentation.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT build_docs_DOXYFILE_PATH)
|
||||||
|
set(DOXYFILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
|
||||||
|
elseif(EXISTS ${build_docs_DOXYFILE_PATH})
|
||||||
|
set(DOXYFILE_PATH ${build_docs_DOXYFILE_PATH})
|
||||||
|
else()
|
||||||
|
set(DOXYFILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${build_docs_DOXYFILE_PATH})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS ${DOXYFILE_PATH})
|
||||||
|
message(
|
||||||
|
SEND_ERROR
|
||||||
|
"Could not find Doxyfile to use for procesing documentation at: ${DOXYFILE_PATH}"
|
||||||
|
)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(build_docs_PROCESS_DOXYFILE)
|
||||||
|
set(DOXYFILE ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||||
|
configure_file(${DOXYFILE_PATH} ${DOXYFILE} @ONLY)
|
||||||
|
else()
|
||||||
|
set(DOXYFILE ${DOXYFILE_PATH})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(build_docs_OUTPUT_DIR)
|
||||||
|
set(OUT_DIR ${build_docs_OUTPUT_DIR})
|
||||||
|
else()
|
||||||
|
set(OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/doc)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(MAKE_DIRECTORY ${OUT_DIR})
|
||||||
|
|
||||||
|
if(build_docs_TARGET_NAME)
|
||||||
|
set(TARGET_NAME ${build_docs_TARGET_NAME})
|
||||||
|
else()
|
||||||
|
set(TARGET_NAME doc-${PROJECT_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_target(${TARGET_NAME}
|
||||||
|
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE}
|
||||||
|
WORKING_DIRECTORY ${OUT_DIR}
|
||||||
|
VERBATIM)
|
||||||
|
|
||||||
|
if(build_docs_ADD_TO_DOC)
|
||||||
|
if(NOT TARGET doc)
|
||||||
|
add_custom_target(doc)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_dependencies(doc ${TARGET_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(build_docs_INSTALLABLE)
|
||||||
|
if(NOT build_docs_INSTALL_PATH)
|
||||||
|
set(build_docs_INSTALL_PATH share/${PROJECT_NAME})
|
||||||
|
endif()
|
||||||
|
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/
|
||||||
|
COMPONENT documentation
|
||||||
|
DESTINATION ${build_docs_INSTALL_PATH})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
87
cmake/Modules/sanitizers.cmake
Normal file
87
cmake/Modules/sanitizers.cmake
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
# use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
# the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations under
|
||||||
|
# the License.
|
||||||
|
|
||||||
|
set(
|
||||||
|
USE_SANITIZER
|
||||||
|
""
|
||||||
|
CACHE
|
||||||
|
STRING
|
||||||
|
"Compile with a sanitizer. Options are: Address, Memory, MemoryWithOrigins, Undefined, Thread, Leak, 'Address;Undefined'"
|
||||||
|
)
|
||||||
|
|
||||||
|
function(append value)
|
||||||
|
foreach(variable ${ARGN})
|
||||||
|
set(${variable} "${${variable}} ${value}" PARENT_SCOPE)
|
||||||
|
endforeach(variable)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
if(USE_SANITIZER)
|
||||||
|
append("-fno-omit-frame-pointer" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
|
||||||
|
if(uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||||
|
append("-O1" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(USE_SANITIZER MATCHES "([Aa]ddress);([Uu]ndefined)"
|
||||||
|
OR USE_SANITIZER MATCHES "([Uu]ndefined);([Aa]ddress)")
|
||||||
|
message(STATUS "Building with Address, Undefined sanitizers")
|
||||||
|
append("-fsanitize=address,undefined" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||||
|
elseif("${USE_SANITIZER}" MATCHES "([Aa]ddress)")
|
||||||
|
# Optional: -fno-optimize-sibling-calls -fsanitize-address-use-after-scope
|
||||||
|
message(STATUS "Building with Address sanitizer")
|
||||||
|
append("-fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||||
|
elseif(USE_SANITIZER MATCHES "([Mm]emory([Ww]ith[Oo]rigins)?)")
|
||||||
|
# Optional: -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2
|
||||||
|
append("-fsanitize=memory" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||||
|
if(USE_SANITIZER MATCHES "([Mm]emory[Ww]ith[Oo]rigins)")
|
||||||
|
message(STATUS "Building with MemoryWithOrigins sanitizer")
|
||||||
|
append("-fsanitize-memory-track-origins" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||||
|
else()
|
||||||
|
message(STATUS "Building with Memory sanitizer")
|
||||||
|
endif()
|
||||||
|
elseif(USE_SANITIZER MATCHES "([Uu]ndefined)")
|
||||||
|
message(STATUS "Building with Undefined sanitizer")
|
||||||
|
append("-fsanitize=undefined" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||||
|
if(EXISTS "${BLACKLIST_FILE}")
|
||||||
|
append("-fsanitize-blacklist=${BLACKLIST_FILE}" CMAKE_C_FLAGS
|
||||||
|
CMAKE_CXX_FLAGS)
|
||||||
|
endif()
|
||||||
|
elseif(USE_SANITIZER MATCHES "([Tt]hread)")
|
||||||
|
message(STATUS "Building with Thread sanitizer")
|
||||||
|
append("-fsanitize=thread" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||||
|
elseif(USE_SANITIZER MATCHES "([Ll]eak)")
|
||||||
|
message(STATUS "Building with Leak sanitizer")
|
||||||
|
append("-fsanitize=leak" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||||
|
else()
|
||||||
|
message(
|
||||||
|
FATAL_ERROR "Unsupported value of USE_SANITIZER: ${USE_SANITIZER}")
|
||||||
|
endif()
|
||||||
|
elseif(MSVC)
|
||||||
|
if(USE_SANITIZER MATCHES "([Aa]ddress)")
|
||||||
|
message(STATUS "Building with Address sanitizer")
|
||||||
|
append("-fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||||
|
else()
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"This sanitizer not yet supported in the MSVC environment: ${USE_SANITIZER}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "USE_SANITIZER is not supported on this platform.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endif()
|
94
cmake/Modules/tools.cmake
Normal file
94
cmake/Modules/tools.cmake
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
# use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
# the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations under
|
||||||
|
# the License.
|
||||||
|
|
||||||
|
option(CLANG_TIDY "Turns on clang-tidy processing if it is found." OFF)
|
||||||
|
option(IWYU "Turns on include-what-you-use processing if it is found." OFF)
|
||||||
|
option(CPPCHECK "Turns on cppcheck processing if it is found." OFF)
|
||||||
|
|
||||||
|
# Adds clang-tidy checks to the compilation, with the given arguments being used
|
||||||
|
# as the options set.
|
||||||
|
macro(clang_tidy)
|
||||||
|
if(CLANG_TIDY AND CLANG_TIDY_EXE)
|
||||||
|
set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_EXE} ${ARGN})
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Adds include_what_you_use to the compilation, with the given arguments being
|
||||||
|
# used as the options set.
|
||||||
|
macro(include_what_you_use)
|
||||||
|
if(IWYU AND IWYU_EXE)
|
||||||
|
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "${IWYU_EXE};${ARGN}")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Adds cppcheck to the compilation, with the given arguments being used as the
|
||||||
|
# options set.
|
||||||
|
macro(cppcheck)
|
||||||
|
if(CPPCHECK AND CPPCHECK_EXE)
|
||||||
|
set(CMAKE_CXX_CPPCHECK "${CPPCHECK_EXE};${ARGN}")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
find_program(CLANG_TIDY_EXE NAMES clang-tidy clang-tidy-8 clang-tidy-7 clang-tidy-6)
|
||||||
|
if(CLANG_TIDY_EXE)
|
||||||
|
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
|
||||||
|
if(NOT CLANG_TIDY)
|
||||||
|
message(STATUS "clang-tidy NOT ENABLED via 'CLANG_TIDY' variable!")
|
||||||
|
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it
|
||||||
|
endif()
|
||||||
|
elseif(CLANG_TIDY)
|
||||||
|
message(SEND_ERROR "Cannot enable clang-tidy, as executable not found!")
|
||||||
|
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it
|
||||||
|
else()
|
||||||
|
message(STATUS "clang-tidy not found!")
|
||||||
|
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_program(IWYU_EXE NAMES "include-what-you-use")
|
||||||
|
if(IWYU_EXE)
|
||||||
|
message(STATUS "include-what-you-use found: ${IWYU_EXE}")
|
||||||
|
if(NOT IWYU)
|
||||||
|
message(STATUS "include-what-you-use NOT ENABLED via 'IWYU' variable!")
|
||||||
|
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "" CACHE STRING "" FORCE) # delete it
|
||||||
|
endif()
|
||||||
|
elseif(IWYU)
|
||||||
|
message(
|
||||||
|
SEND_ERROR "Cannot enable include-what-you-use, as executable not found!")
|
||||||
|
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "" CACHE STRING "" FORCE) # delete it
|
||||||
|
else()
|
||||||
|
message(STATUS "include-what-you-use not found!")
|
||||||
|
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "" CACHE STRING "" FORCE) # delete it
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_program(CPPCHECK_EXE NAMES "cppcheck")
|
||||||
|
if(CPPCHECK_EXE)
|
||||||
|
message(STATUS "cppcheck found: ${CPPCHECK_EXE}")
|
||||||
|
if(CPPCHECK)
|
||||||
|
set(
|
||||||
|
CMAKE_CXX_CPPCHECK
|
||||||
|
"${CPPCHECK_EXE};--enable=warning,performance,portability,missingInclude;--template=\"[{severity}][{id}] {message} {callstack} \(On {file}:{line}\)\";--suppress=missingIncludeSystem;--quiet;--verbose;--force"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(NOT CPPCHECK)
|
||||||
|
message(STATUS "cppcheck NOT ENABLED via 'CPPCHECK' variable!")
|
||||||
|
set(CMAKE_CXX_CPPCHECK "" CACHE STRING "" FORCE) # delete it
|
||||||
|
endif()
|
||||||
|
elseif(CPPCHECK)
|
||||||
|
message(SEND_ERROR "Cannot enable cppcheck, as executable not found!")
|
||||||
|
set(CMAKE_CXX_CPPCHECK "" CACHE STRING "" FORCE) # delete it
|
||||||
|
else()
|
||||||
|
message(STATUS "cppcheck not found!")
|
||||||
|
set(CMAKE_CXX_CPPCHECK "" CACHE STRING "" FORCE) # delete it
|
||||||
|
endif()
|
16
cmake/Toolchains/Toolchain-mingw64.cmake
Normal file
16
cmake/Toolchains/Toolchain-mingw64.cmake
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# the name of the target operating system
|
||||||
|
SET(CMAKE_SYSTEM_NAME Windows)
|
||||||
|
|
||||||
|
# which compilers to use for C and C++
|
||||||
|
SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
|
||||||
|
SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
|
||||||
|
|
||||||
|
# here is the target environment located
|
||||||
|
SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)
|
||||||
|
|
||||||
|
# adjust the default behaviour of the FIND_XXX() commands:
|
||||||
|
# search headers and libraries in the target environment, search
|
||||||
|
# programs in the host environment
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
Loading…
Reference in New Issue
Block a user