From 6ccc31a3b0f69eb1f682cf8bcd655907e135fcc8 Mon Sep 17 00:00:00 2001 From: Frederik Vannoote Date: Thu, 9 Feb 2017 14:07:33 +0100 Subject: [PATCH] First version --- AddQtTest.cmake | 18 +++ CodeCoverage.cmake | 42 +++++++ CommonConfig.cmake | 70 ++++++++++++ CompilerFlags.cmake | 193 +++++++++++++++++++++++++++++++++ Cppcheck.cmake | 11 ++ DefineProject.cmake | 38 +++++++ DeployDependentLibraries.cmake | 46 ++++++++ FindCppcheck.cmake | 20 ++++ FindGcov.cmake | 30 +++++ FindGcovr.cmake | 25 +++++ GeneratePackage.cmake | 92 ++++++++++++++++ config.cmake.in | 33 ++++++ readme.md | 22 ++++ 13 files changed, 640 insertions(+) create mode 100644 AddQtTest.cmake create mode 100644 CodeCoverage.cmake create mode 100644 CommonConfig.cmake create mode 100644 CompilerFlags.cmake create mode 100644 Cppcheck.cmake create mode 100644 DefineProject.cmake create mode 100644 DeployDependentLibraries.cmake create mode 100644 FindCppcheck.cmake create mode 100644 FindGcov.cmake create mode 100644 FindGcovr.cmake create mode 100644 GeneratePackage.cmake create mode 100644 config.cmake.in create mode 100644 readme.md diff --git a/AddQtTest.cmake b/AddQtTest.cmake new file mode 100644 index 0000000..d2fd718 --- /dev/null +++ b/AddQtTest.cmake @@ -0,0 +1,18 @@ +macro(add_qt_test TEST_NAME SRCS) + find_package(Qt5Test REQUIRED) + + add_executable(${TEST_NAME} ${SRCS}) + + add_test(NAME ${TEST_NAME} COMMAND $) + + target_link_libraries(${TEST_NAME} PUBLIC Qt5::Test) +endmacro() + +option(PRIVATE_TESTS_ENABLED "Enable private tests" OFF) +macro(add_private_qt_test TEST_NAME SRCS) + if(DEFINED PRIVATE_TESTS_ENABLED) + if(${PRIVATE_TESTS_ENABLED}) + add_qt_test(${TEST_NAME} ${SRCS}) + endif(${PRIVATE_TESTS_ENABLED}) + endif(DEFINED PRIVATE_TESTS_ENABLED) +endmacro() diff --git a/CodeCoverage.cmake b/CodeCoverage.cmake new file mode 100644 index 0000000..afdac33 --- /dev/null +++ b/CodeCoverage.cmake @@ -0,0 +1,42 @@ +# Enable Code Coverage +# +# USAGE: +# 1. Copy this file into your cmake modules path. +# +# 2. Add the following line to your CMakeLists.txt: +# INCLUDE(CodeCoverage) +# +# 3. Call the function ENABLE_CODE_COVERAGE +# This functions sets compiler flags to turn off optimization and enable coverage: +# SET(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -fprofile-arcs -ftest-coverage") +# +# 4. Build a Debug build: +# cmake -DCMAKE_BUILD_TYPE=Debug .. +# make +# make my_coverage_target +# +# Note: code coverage can only be enabled when in debug build! +# +# Requirements: gcov and gcovr + +# Check prereqs +find_package(Gcov) +find_package(Gcovr) + +function(ENABLE_CODE_COVERAGE) + if (GCOV_FOUND AND GCOVR_FOUND) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0 -fprofile-arcs -ftest-coverage") + if (CMAKE_COMPILER_IS_GNUCXX AND NOT UNIX) + link_libraries(debug gcov) + endif(WIN32 AND NOT UNIX) + if (NOT WIN32) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fPIC") + endif (NOT WIN32) + + set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG} PARENT_SCOPE) + + message(STATUS "Code Coverage Enabled") + else() + message("-- Code Coverage NOT Enabled because gcov and/or gcovr was not found.") + endif() +endfunction() diff --git a/CommonConfig.cmake b/CommonConfig.cmake new file mode 100644 index 0000000..6ae7c77 --- /dev/null +++ b/CommonConfig.cmake @@ -0,0 +1,70 @@ +cmake_minimum_required(VERSION 3.5.2 FATAL_ERROR) + +################# +# Build options # +################# + +if (NOT DEFINED BUILD_SHARED_LIBS) + option(BUILD_SHARED_LIBS "Build as shared library" ON) +endif() +# When set to OFF, the library will be built as a static library +if (${BUILD_SHARED_LIBS}) + add_definitions(-DBUILD_SHARED_LIBS) +endif() + + +# Usage of Qt libraries +# --------------------- +# Point CMake search path to Qt intallation directory +# Either supply QTDIR as -DQTDIR= to cmake or set an environment variable QTDIR pointing to the Qt installation +if ((NOT DEFINED QTDIR) AND DEFINED ENV{QTDIR}) + set(QTDIR $ENV{QTDIR}) +endif ((NOT DEFINED QTDIR) AND DEFINED ENV{QTDIR}) + +if (NOT DEFINED QTDIR) + message(FATAL_ERROR "QTDIR has not been set nor supplied as a define parameter to cmake.") +endif (NOT DEFINED QTDIR) + +if (QTDIR) + list (APPEND CMAKE_PREFIX_PATH ${QTDIR}) +endif (QTDIR) + +# Instruct CMake to run moc automatically when needed. +set(CMAKE_AUTOMOC ON) +# let CMake decide which classes need to be rcc'ed by qmake (Qt) +set(CMAKE_AUTORCC ON) +# let CMake decide which classes need to be uic'ed by qmake (Qt) +set(CMAKE_AUTOUIC ON) + + +# Usage of CMake Packages +# ----------------------- +include(CMakePackageConfigHelpers) + +# Point cmake to the packages of libraries in this tree. +list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR}/local-exports) + + +# Compiler flags +# -------------- +add_definitions(-Wall -fvisibility=hidden) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Find includes in corresponding build directories +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# Compile with @rpath option on Apple +if (APPLE) + set(CMAKE_MACOSX_RPATH 1) +endif (APPLE) + + +# Switch testing on +# ----------------- +enable_testing() +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) +include(AddQtTest) + +# Common compiler flags +include(CompilerFlags) diff --git a/CompilerFlags.cmake b/CompilerFlags.cmake new file mode 100644 index 0000000..3adaa73 --- /dev/null +++ b/CompilerFlags.cmake @@ -0,0 +1,193 @@ +# Force synchronous PDB writes for Visual Studio +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + add_compile_options("/FS") +endif() + +# Set default build type to release with debug info +IF(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) + SET(CMAKE_BUILD_TYPE RelWithDebInfo) +ENDIF(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) + +if(CMAKE_COMPILER_IS_GNUCXX) + set(COMPILER_FLAGS + "-std=c++11" + "-Wall" # turn on all warnings + "-pedantic" + "-Wextra" + "-fno-rtti" # disable runtime type information + "-fno-exceptions" + "-ffor-scope" + "-fuse-cxa-atexit" + "-fno-default-inline" + "-fvisibility=hidden" # do not export symbols by default + "-fvisibility-inlines-hidden" + "-pedantic-errors" + "-Wsign-promo" + "-Wsign-compare" + "-Wnon-virtual-dtor" + "-Wold-style-cast" + "-Woverloaded-virtual" + "-Wswitch" + "-Wswitch-default" + "-Wswitch-enum" + "-Wcast-qual" + "-Wcast-align" + "-Wuninitialized" + "-Wno-float-equal" + "-Wlogical-op" + "-Wpacked" + "-Wredundant-decls" + "-Wdisabled-optimization" + "-Wdeprecated" + "-Wempty-body" + "-Wreturn-type" + "-Wunused-variable" + "-Wno-unknown-pragmas" # suppress unknown pragma warnings + "-Wformat" + "-Wunreachable-code" + "-mfpmath=sse" # needed on Debian 32-bit to get high precision floating point operations + "-msse2" # needed on Debian 32-bit to get high precision floating point operations + + "-Weffc++" # warnings from Effective C++ book; + + "-Werror" + "-Wformat-nonliteral" # const char* argumements could not langer be passed due to this entry +# "-Winline" # gcc on Linux seems to decide frequently not to inline, and warns about it. +# # We don't need to know about it, since not inlining is not a problem. +# "-Wnull-character" # not supported by gcc +# "-Wshadow" # disable shadow warning as gcc generates + # warnings for parameters with same name + # as methods in the class. + # This option is enabled for clang builds, + # so the 'real' shadow variables will be + # caught be clang + "-Wsign-conversion" +# "-Wuseless-cast" +# "-Wzero-as-null-pointer-constant" + ) + if(WIN32) + # Fix for using LxCan sensor SDK + # Since LxNative.dll uses stdcall convention, MinGW expects @.. decoration of the exposed functions, + # which are not present in the DLL. This MinGW option tells the linker to also look for undecorated + # functions. + set(COMPILER_FLAGS "${COMPILER_FLAGS}" "-Wl,--enable-stdcall-fixup") + endif() +elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(COMPILER_FLAGS + "-stdlib=libc++" + "-std=c++11" + "-Wall" # turn on all warnings + "-Wpedantic" + "-Wextra" + "-Weffc++" # turn on warnings from Effective C++ handbook + "-fno-rtti" # disable runtime type information + "-fno-exceptions" + "-ffor-scope" + "-fuse-cxa-atexit" + "-fvisibility=hidden" # do not export symbols by default + "-fvisibility-inlines-hidden" + "-pedantic" # warn about language extensions + "-pedantic-errors" # treat language extension warnings as errors + "-Wsign-promo" + "-Wsign-compare" + "-Wnon-virtual-dtor" + "-Wold-style-cast" + "-Woverloaded-virtual" + "-Wint-to-void-pointer-cast" + "-Wswitch" + "-Wswitch-default" + "-Wswitch-enum" + "-Wcast-qual" + "-Wcast-align" + "-Wuninitialized" + "-Wno-float-equal" + "-Wshadow" + "-Wpacked" + "-Wredundant-decls" + "-Wdisabled-optimization" + "-Wdeprecated" + "-Wdeprecated-declarations" + "-Wempty-body" + "-Wbitwise-op-parentheses" + "-Wlogical-op-parentheses" + "-Wold-style-cast" + "-Wold-style-definition" + "-Wout-of-line-declaration" + "-Waddress-of-temporary" + "-Wbool-conversions" + "-Wbad-function-cast" + "-Wbind-to-temporary-copy" + "-Wdiv-by-zero" + "-Wheader-hygiene" + "-Wnull-dereference" + "-Widiomatic-parentheses" + "-Wparentheses" + "-Winitializer-overrides" + "-Wint-to-pointer-cast" + "-Wpointer-to-int-cast" + "-Wpointer-arith" + "-Wmissing-braces" + "-Wmissing-field-initializers" + "-Wnonnull" + "-Woverflow" + "-Wshorten-64-to-32" + "-Wno-used-but-marked-unused" + "-Weffc++" + "-Wreturn-type" + "-Wnull-character" + "-Wunused-variable" + "-Wselector" + "-Wno-unknown-pragmas" # suppress unknown pragma warnings + "-Wformat" + "-Wformat-nonliteral" + "-Wtautological-compare" + "-Wunreachable-code" + + "-Werror" +# "-Winline" # gcc on Linux seems to decide frequently not to inline, and warns about it. +# # We don't need to know about it, since not inlining is not a problem. + "-Wshadow" + "-Wsign-conversion" +# "-Wuseless-cast" # not supported by Clang +# "-Wzero-as-null-pointer-constant" # not supported by Clang + ) +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + # Remove /W3 since /W4 will be added (otherwise we get a warning about replacing /W3 with /W4) + string(REPLACE "/W3" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + + # Remove /EHsc since /EHsc- will be added (otherwise we get a warning about replacing /EHsc with /EHsc-) + string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + + # Remove /GR since /GR- will be added (otherwise we get a warning about replacing /GR with /GR-) + string(REPLACE "/GR" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + + set(COMPILER_FLAGS + "/W4" + "/WX" # treat all warnings as errors +# "/wdxxxx" # suppress specific warnings +# "/wd4820" # suppress warning about padding + "/wd4625" # suppress warning: + # copy constructor could not be generated because a base class + # copy constructor is inaccessible or deleted + "/wd4626" # assignment operator could not be generated because a base + # class assignment operator is inaccessible or deleted + "/wd4127" # suppress warning: conditional expression is constant + "/wd4505" # suppress warning: unreferenced function has been removed + "/wd4206" # suppress warning: translation unit is empty + "/wd4515" # suppress warning: namespace uses itself +# "/wd4512" # suppress warning: assignment operator could not be generated + # A fix is planned in Qt 5.4.2 (https://bugreports.qt.io/browse/QTBUG-7233) + # Check later with Qt >= 5.4.2 if warning suppression can be removed + "/nologo" + "/EHsc-" # disable exceptions + "/GR-" # disable RTTI + ) +endif() + +string(REPLACE ";" " " COMPILER_FLAGS_STRING "${COMPILER_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILER_FLAGS_STRING}") + +# disable compiler optimization which can cause release version to crash when using MinGW +if(WIN32 AND NOT UNIX AND CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-ipa-cp-clone") +endif() diff --git a/Cppcheck.cmake b/Cppcheck.cmake new file mode 100644 index 0000000..e041f2a --- /dev/null +++ b/Cppcheck.cmake @@ -0,0 +1,11 @@ +find_package(Cppcheck) + +if(CPPCHECK_FOUND) + file(GLOB_RECURSE CPPCHECK_FILES RELATIVE ${CMAKE_SOURCE_DIR} *.cpp *.h) + + add_custom_target(cppcheck + COMMAND ${CPPCHECK_EXECUTABLE} "--force" "--quiet" "--error-exitcode=1" ${CPPCHECK_FILES} + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + COMMENT "Running cppcheck..." + VERBATIM) +endif() diff --git a/DefineProject.cmake b/DefineProject.cmake new file mode 100644 index 0000000..e4ab894 --- /dev/null +++ b/DefineProject.cmake @@ -0,0 +1,38 @@ +##################################################### +# Start of configuration # +# Lines below should not be touched in normal cases # +##################################################### + +#======================================= +# Set some variables to be used later on +#======================================= +set(PROJECT_NAME ${PROJECT_NAME_PREFIX}${PROJECT_BASE_NAME}) +set(TARGET_NAME ${PROJECT_BASE_NAME}) +set(PROJECT_NAMESPACE ${PROJECT_NAME_PREFIX}${SO_VERSION}) +set(INSTALL_DIRECTORY_NAME ${PROJECT_NAME}/${PROJECT_NAME_PREFIX}${SO_VERSION}) +set(CMAKE_DIRECTORY_NAME ${PROJECT_NAME_PREFIX}${SO_VERSION}${PROJECT_BASE_NAME}) +set(PACKAGE_NAME ${PROJECT_NAME_PREFIX}${SO_VERSION}${PROJECT_BASE_NAME}) +set(MODULE_NAME ${PROJECT_NAME}) +#base name used for cmake config files: +#Config.cmake +#ConfigVersion.cmake +#Targets.cmake +#Targets_noconfig.cmake +set(CMAKE_CONFIG_FILE_BASE_NAME ${PROJECT_NAME_PREFIX}${SO_VERSION}${PROJECT_BASE_NAME}) + +set(LIB_INSTALL_DIR lib/${INSTALL_DIRECTORY_NAME}) +set(INCLUDE_INSTALL_DIR include/${INSTALL_DIRECTORY_NAME}) +set(BIN_INSTALL_DIR bin) +set(CMAKE_INSTALL_DIR lib/cmake/${CMAKE_DIRECTORY_NAME}) + +project(${PROJECT_NAME}) + +message(STATUS "Libraries will be installed to: ${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}") +message(STATUS "Header files will be installed to: ${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR}") +message(STATUS "Executables will be installed in: ${CMAKE_INSTALL_PREFIX}/${BIN_INSTALL_DIR}") +message(STATUS "CMake config-files will be written to: ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DIR}") +message(STATUS "${PROJECT_NAME} import target: ${PROJECT_NAMESPACE}::${TARGET_NAME}") +message(STATUS "Building ${PROJECT_NAME} ${FULL_VERSION} in ${CMAKE_BUILD_TYPE} mode") +if (PRIVATE_TESTS_ENABLED) + message(STATUS "Private tests are enabled") +endif() \ No newline at end of file diff --git a/DeployDependentLibraries.cmake b/DeployDependentLibraries.cmake new file mode 100644 index 0000000..bf6722c --- /dev/null +++ b/DeployDependentLibraries.cmake @@ -0,0 +1,46 @@ +# On a Windows platform, you need a way to reference to the libraries you need. +# Using this, those libraries are copied along the executable. +# +# Usage: +# target_link_libraries(${TARGET_NAME} PUBLIC ...) +# include(DeployDependentLibraries) # This include goes after your last link_libraries. + +if(WIN32) + # Copy dependent libraries to path of executable + get_property(libs TARGET ${TARGET_NAME} PROPERTY LINK_LIBRARIES) + foreach(lib ${libs}) + if(TARGET ${lib}) + # If this is a library, get its transitive dependencies + get_property(trans TARGET ${lib} PROPERTY INTERFACE_LINK_LIBRARIES) + foreach(tran ${trans}) + if(TARGET ${tran}) + get_property(path TARGET ${tran} PROPERTY LOCATION) + list(APPEND ${TARGET_NAME}_deplibs ${path}) + endif() + endforeach() + get_property(path TARGET ${lib} PROPERTY LOCATION) + list(APPEND ${TARGET_NAME}_deplibs ${path}) + else() + list(APPEND ${TARGET_NAME}_deplibs ${lib}) + endif() + endforeach() + + list(REMOVE_DUPLICATES ${TARGET_NAME}_deplibs) + + # Replace all entries ending on .lib to .dll + foreach(lib ${${TARGET_NAME}_deplibs}) + STRING(REGEX REPLACE "lib$" "dll" _replaced_lib ${lib}) + if (DEFINED _replaced_lib) + list(APPEND _${TARGET_NAME}_deplibs ${_replaced_lib}) + else() + list(APPEND _${TARGET_NAME}_deplibs ${lib}) + endif() + endforeach() + set(${TARGET_NAME}_deplibs ${_${TARGET_NAME}_deplibs}) + + foreach(lib ${${TARGET_NAME}_deplibs}) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${lib} ${CMAKE_CURRENT_BINARY_DIR} + VERBATIM) + endforeach() +endif() diff --git a/FindCppcheck.cmake b/FindCppcheck.cmake new file mode 100644 index 0000000..4534bf1 --- /dev/null +++ b/FindCppcheck.cmake @@ -0,0 +1,20 @@ +# Try to find cppcheck tool for Unix platforms +# +# Cache Variables: +# CPPCHECK_EXECUTABLE +# +# Non-cache variables you might use in your CMakeLists.txt: +# CPPCHECK_FOUND +# +# Requires these CMake modules: +# FindPackageHandleStandardArgs (known included with CMake >=2.6.2) + +find_program(CPPCHECK_EXECUTABLE cppcheck PATHS /usr/local/bin) + +set(CPPCHECK_FOUND FALSE CACHE INTERNAL "") + +if(CPPCHECK_EXECUTABLE) + set(CPPCHECK_FOUND TRUE CACHE INTERNAL "") +endif() + +mark_as_advanced(CPPCHECK_EXECUTABLE) diff --git a/FindGcov.cmake b/FindGcov.cmake new file mode 100644 index 0000000..cdc52a1 --- /dev/null +++ b/FindGcov.cmake @@ -0,0 +1,30 @@ +# Try to find gcov tool +# +# Cache Variables: +# GCOV_EXECUTABLE +# +# Non-cache variables you might use in your CMakeLists.txt: +# GCOV_FOUND +# +# Requires these CMake modules: +# FindPackageHandleStandardArgs (known included with CMake >=2.6.2) + +if(GCOV_EXECUTABLE AND NOT EXISTS "${GCOV_EXECUTABLE}") + set(GCOV_EXECUTABLE "notfound" CACHE PATH FORCE "") +endif() + +IF(NOT CMAKE_COMPILER_IS_GNUCXX AND NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + MESSAGE(WARNING "Compiler is not GNU gcc or Clang!") + set(GCOV_EXECUTABLE "notfound" CACHE PATH FORCE "") +ELSEIF( NOT CMAKE_BUILD_TYPE STREQUAL "Debug" ) + MESSAGE(WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" ) + set(GCOV_EXECUTABLE "notfound" CACHE PATH FORCE "") +ELSE() + find_program(GCOV_EXECUTABLE NAMES gcov) +ENDIF(NOT CMAKE_COMPILER_IS_GNUCXX AND NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( Gcov DEFAULT_MSG + GCOV_EXECUTABLE) + +mark_as_advanced(GCOV_EXECUTABLE) diff --git a/FindGcovr.cmake b/FindGcovr.cmake new file mode 100644 index 0000000..cf3b4f0 --- /dev/null +++ b/FindGcovr.cmake @@ -0,0 +1,25 @@ +# Try to find gcovr tool +# +# Cache Variables: +# GCOVR_EXECUTABLE +# +# Non-cache variables you might use in your CMakeLists.txt: +# GCOVR_FOUND +# +# Requires these CMake modules: +# FindPackageHandleStandardArgs (known included with CMake >=2.6.2) +# FindPythonInterp +# FindGcov + +if(GCOVR_EXECUTABLE AND NOT EXISTS "${GCOVR_EXECUTABLE}") + set(GCOVR_EXECUTABLE "notfound" CACHE PATH FORCE "") +endif() +find_program(GCOVR_EXECUTABLE NAMES gcovr) +find_package(PythonInterp) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( Gcovr DEFAULT_MSG + GCOVR_EXECUTABLE + PYTHONINTERP_FOUND) + +mark_as_advanced(GCOVR_EXECUTABLE) \ No newline at end of file diff --git a/GeneratePackage.cmake b/GeneratePackage.cmake new file mode 100644 index 0000000..3227279 --- /dev/null +++ b/GeneratePackage.cmake @@ -0,0 +1,92 @@ +# CMake helper to generate a cmake module package + +set(DEPENDENT_PACKAGES ${${TARGET_NAME}_DEPENDENT_PACKAGES}) +set(TARGET_INCLUDE_INSTALL_DIRS ${${TARGET_NAME}_INCLUDE_DIRS}) + +set_target_properties(${TARGET_NAME} PROPERTIES + VERSION ${FULL_VERSION} + SOVERSION ${SO_VERSION} + PUBLIC_HEADER "${${TARGET_NAME}_PUBLIC_HEADERS}" + PRIVATE_HEADER "${${TARGET_NAME}_PRIVATE_HEADERS}" +) + +################################################################ +# Create and export config packages for usage within this tree # +################################################################ + +# We configure our template. The template is described later. +configure_package_config_file( + ${CMAKE_CURRENT_LIST_DIR}/config.cmake.in + ${CMAKE_BINARY_DIR}/local-exports/${CMAKE_CONFIG_FILE_BASE_NAME}Config.cmake + INSTALL_DESTINATION ${CMAKE_BINARY_DIR} + PATH_VARS TARGET_INCLUDE_INSTALL_DIRS DEPENDENT_PACKAGES +) + +# This file is included in our template: +export(TARGETS ${TARGET_NAME} + FILE "${CMAKE_BINARY_DIR}/local-exports/${CMAKE_CONFIG_FILE_BASE_NAME}Targets.cmake" + NAMESPACE ${PROJECT_NAMESPACE}:: +) + +############################################## +# Create, export and install config packages # +############################################## + +set(TARGET_INCLUDE_INSTALL_DIRS ${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR}) + +# Create config file +configure_package_config_file( + ${CMAKE_CURRENT_LIST_DIR}/config.cmake.in + ${CMAKE_BINARY_DIR}/${CMAKE_CONFIG_FILE_BASE_NAME}Config.cmake + INSTALL_DESTINATION ${CMAKE_BINARY_DIR} + PATH_VARS TARGET_INCLUDE_INSTALL_DIRS +) + +# Create a config version file +write_basic_package_version_file( + ${CMAKE_BINARY_DIR}/${CMAKE_CONFIG_FILE_BASE_NAME}ConfigVersion.cmake + VERSION ${FULL_VERSION} + COMPATIBILITY SameMajorVersion +) + +# Create import targets +install(TARGETS ${TARGET_NAME} EXPORT ${TARGET_NAME}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/${BIN_INSTALL_DIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR} + PRIVATE_HEADER DESTINATION ${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR}/private +) + +# Export the import targets +export(EXPORT ${TARGET_NAME}Targets + FILE "${CMAKE_BINARY_DIR}/${CMAKE_CONFIG_FILE_BASE_NAME}Targets.cmake" + NAMESPACE ${PROJECT_NAMESPACE}:: +) + +# Now install the 3 config files +install(FILES ${CMAKE_BINARY_DIR}/${CMAKE_CONFIG_FILE_BASE_NAME}Config.cmake + ${CMAKE_BINARY_DIR}/${CMAKE_CONFIG_FILE_BASE_NAME}ConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_DIR} +) + +install(EXPORT ${TARGET_NAME}Targets + FILE + ${CMAKE_CONFIG_FILE_BASE_NAME}Targets.cmake + NAMESPACE + ${PROJECT_NAMESPACE}:: + DESTINATION + ${CMAKE_INSTALL_DIR} +) + +# Create and install a global module include file +# This makes it possible to include all header files of the module by using +# #include <${PROJECT_NAME}> +set(GLOBAL_HEADER_FILE ${CMAKE_BINARY_DIR}/${PROJECT_NAME}) +file(WRITE ${GLOBAL_HEADER_FILE} "//Includes all headers of ${PROJECT_NAME}\n\n") + +foreach(header ${${TARGET_NAME}_PUBLIC_HEADERS}) + file(APPEND ${GLOBAL_HEADER_FILE} "#include \"${header}\"\n") +endforeach() + +install(FILES ${GLOBAL_HEADER_FILE} DESTINATION ${INCLUDE_INSTALL_DIR}) diff --git a/config.cmake.in b/config.cmake.in new file mode 100644 index 0000000..7d9ceba --- /dev/null +++ b/config.cmake.in @@ -0,0 +1,33 @@ +# - Config file for the @MODULE_NAME@ module +# To be used as: +# find_package(@PACKAGE_NAME@) +# target_link_libraries(@PROJECT_NAMESPACE@::@PROJECT_BASE_NAME@) +# This will automatically set the correct include directories and link libraries + +#For more information regarding config files see: +#https://cmake.org/cmake/help/v3.5/module/CMakePackageConfigHelpers.html + +@PACKAGE_INIT@ + +cmake_policy(SET CMP0024 OLD) +include("${CMAKE_CURRENT_LIST_DIR}/@CMAKE_CONFIG_FILE_BASE_NAME@Targets.cmake") + +# find_package will silently look for the dependencies and set the correct +# include directories and link libraries +foreach(PACKAGE @DEPENDENT_PACKAGES@) + find_package(${PACKAGE} QUIET) +endforeach() + +foreach(PACKAGE @DEPENDENT_PACKAGES@) + check_required_components(${PACKAGE}) +endforeach() + +# @PROJECT_NAME@ requires C++11 +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include_directories(@TARGET_INCLUDE_INSTALL_DIRS@) + +if (@BUILD_SHARED_LIBS@) + add_definitions(-DBUILD_SHARED_LIBS) +endif() diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..2a2b0a6 --- /dev/null +++ b/readme.md @@ -0,0 +1,22 @@ +# Common cmake components + +This repository contains very generic cmake components which can be used across other cmake projects. + +# Including in your code. +The common cmake files need to be present when cmake is run. +There are various ways of achieving this. + +## Git submodule +You can fetch the files during your git clone using a submodule. +``` +git submodule add -b git@github.com:barco-healthcare/cmake-common.git path/to/cmake/common +``` + +# Usage + +You can include these files in your CMakeLists.txt +``` +# Include common cmake modules +list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/path/to/cmake/common) +include(CommonConfig) +```