├── README.md ├── LICENSE └── tnt └── project.cmake /README.md: -------------------------------------------------------------------------------- 1 | # cmake 2 | 3 | cmake contains a collection of useful CMake modules that can be easily integrated into any CMake 4 | project. 5 | 6 | ## Usage 7 | 8 | Using these modules is very straightforward. Simply add this repository to your project in a git 9 | submodule and then directly include the modules from within the CMakeLists.txt file. 10 | 11 | git submodule add https://gitlab.com/tnt-coders/cpp/cmake/cmake.git 12 | 13 | Then add the modules to the `CMAKE_MODULE_PATH` 14 | 15 | **CMakeLists.txt** 16 | 17 | # Include the required modules 18 | list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") 19 | include(tnt/project) 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /tnt/project.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | include(CMakePackageConfigHelpers) 4 | include(GNUInstallDirs) 5 | 6 | function(tnt_project__set_version_from_git) 7 | 8 | # This function requires the Git package to function 9 | find_package(Git REQUIRED) 10 | 11 | # Use "git describe" to get version information from Git 12 | execute_process( 13 | COMMAND ${GIT_EXECUTABLE} describe --dirty --long --match=v* --tags 14 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 15 | RESULT_VARIABLE git_result 16 | OUTPUT_VARIABLE git_output OUTPUT_STRIP_TRAILING_WHITESPACE 17 | ERROR_VARIABLE git_error ERROR_STRIP_TRAILING_WHITESPACE) 18 | 19 | # If the result is not "0" an error has occurred 20 | if (git_result) 21 | message(FATAL_ERROR ${git_error}) 22 | endif () 23 | 24 | # Parse the version string returned by Git 25 | # Format is "v..--[-dirty]" 26 | if (git_output MATCHES "^v([0-9]+)[.]([0-9]+)[.]([0-9]+)-([0-9]+)") 27 | set(version_major ${CMAKE_MATCH_1}) 28 | set(version_minor ${CMAKE_MATCH_2}) 29 | set(version_patch ${CMAKE_MATCH_3}) 30 | set(version_tweak ${CMAKE_MATCH_4}) 31 | 32 | string(APPEND version "${version_major}.${version_minor}.${version_patch}") 33 | else () 34 | message(FATAL_ERROR "Git returned an invalid version: ${git_output}") 35 | endif () 36 | 37 | # The version is considered dirty if there are uncommitted local changes 38 | if (git_output MATCHES "-dirty$") 39 | set(version_is_dirty TRUE) 40 | else () 41 | set(version_is_dirty FALSE) 42 | endif () 43 | 44 | # Use "git log" to get the current commit hash from Git 45 | execute_process( 46 | COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:%H 47 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 48 | RESULT_VARIABLE git_result 49 | OUTPUT_VARIABLE git_output OUTPUT_STRIP_TRAILING_WHITESPACE 50 | ERROR_VARIABLE git_error ERROR_STRIP_TRAILING_WHITESPACE) 51 | 52 | # If the result is not "0" an error has occurred 53 | if (git_result) 54 | message(FATAL_ERROR ${git_error}) 55 | endif () 56 | 57 | set(version_git_hash ${git_output}) 58 | 59 | # Set global CMake variables containing project version information 60 | set(PROJECT_VERSION ${version} PARENT_SCOPE) 61 | set(PROJECT_VERSION_MAJOR ${version_major} PARENT_SCOPE) 62 | set(PROJECT_VERSION_MINOR ${version_minor} PARENT_SCOPE) 63 | set(PROJECT_VERSION_PATCH ${version_patch} PARENT_SCOPE) 64 | set(PROJECT_VERSION_TWEAK ${version_tweak} PARENT_SCOPE) 65 | set(PROJECT_VERSION_IS_DIRTY ${version_is_dirty} PARENT_SCOPE) 66 | set(PROJECT_VERSION_HASH ${version_git_hash} PARENT_SCOPE) 67 | 68 | set(${PROJECT_NAME}_VERSION ${version} PARENT_SCOPE) 69 | set(${PROJECT_NAME}_VERSION_MAJOR ${version_major} PARENT_SCOPE) 70 | set(${PROJECT_NAME}_VERSION_MINOR ${version_minor} PARENT_SCOPE) 71 | set(${PROJECT_NAME}_VERSION_PATCH ${version_patch} PARENT_SCOPE) 72 | set(${PROJECT_NAME}_VERSION_TWEAK ${version_tweak} PARENT_SCOPE) 73 | set(${PROJECT_NAME}_VERSION_IS_DIRTY ${version_is_dirty} PARENT_SCOPE) 74 | set(${PROJECT_NAME}_VERSION_HASH ${version_git_hash} PARENT_SCOPE) 75 | endfunction() 76 | 77 | function(tnt_project__set_namespace args_NAMESPACE) 78 | set(PROJECT_NAMESPACE ${args_NAMESPACE} PARENT_SCOPE) 79 | set(${PROJECT_NAME}_NAMESPACE ${args_NAMESPACE} PARENT_SCOPE) 80 | endfunction() 81 | 82 | function(tnt_project__add_executable) 83 | set(options) 84 | set(one_value_args TARGET) 85 | set(multi_value_args SOURCES) 86 | cmake_parse_arguments(args "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN}) 87 | 88 | # Create the executable 89 | add_executable(${args_TARGET} ${args_SOURCES}) 90 | 91 | # Initialize default include directories 92 | set(private_include_dir "${PROJECT_SOURCE_DIR}/include/${args_TARGET}") 93 | 94 | # Handle namespace considerations 95 | if (PROJECT_NAMESPACE) 96 | set(private_include_dir "${PROJECT_SOURCE_DIR}/include/${PROJECT_NAMESPACE}/${args_TARGET}") 97 | endif () 98 | 99 | # Set default include directories 100 | target_include_directories(${args_TARGET} 101 | PRIVATE 102 | ${PROJECT_SOURCE_DIR}/include 103 | ${private_include_dir} 104 | ${PROJECT_SOURCE_DIR}/src) 105 | endfunction() 106 | 107 | function(tnt_project__add_library) 108 | set(options INTERFACE) 109 | set(one_value_args TARGET) 110 | set(multi_value_args SOURCES) 111 | cmake_parse_arguments(args "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN}) 112 | 113 | # Create the library 114 | if (${args_INTERFACE}) 115 | add_library(${args_TARGET} INTERFACE ${args_UNPARSED_ARGUMENTS}) 116 | else () 117 | add_library(${args_TARGET} ${args_SOURCES} ${args_UNPARSED_ARGUMENTS}) 118 | 119 | # Handle RPATH considerations for shared libraries 120 | # See "Deep CMake for Library Authors" https://www.youtube.com/watch?v=m0DwB4OvDXk 121 | set_target_properties(${args_TARGET} PROPERTIES BUILD_RPATH_USE_ORIGIN TRUE) 122 | endif () 123 | 124 | # Initialize default include directories 125 | set(private_include_dir "${PROJECT_SOURCE_DIR}/include/${args_TARGET}") 126 | 127 | # Handle namespace considerations 128 | if (PROJECT_NAMESPACE) 129 | add_library(${PROJECT_NAMESPACE}::${args_TARGET} ALIAS ${args_TARGET}) 130 | set(private_include_dir "${PROJECT_SOURCE_DIR}/include/${PROJECT_NAMESPACE}/${args_TARGET}") 131 | endif () 132 | 133 | # Set default include directories 134 | if (${args_INTERFACE}) 135 | target_include_directories(${args_TARGET} 136 | INTERFACE 137 | $ 138 | $) 139 | else () 140 | target_include_directories(${args_TARGET} 141 | PUBLIC 142 | $ 143 | $ 144 | PRIVATE 145 | $ 146 | $) 147 | endif () 148 | endfunction() 149 | 150 | function(tnt_project__install) 151 | set(options) 152 | set(one_value_args) 153 | set(multi_value_args TARGETS) 154 | cmake_parse_arguments(args "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN}) 155 | 156 | # Validate input arguments 157 | if (NOT args_TARGETS) 158 | message(FATAL_ERROR "Missing required input argument 'TARGETS'.") 159 | endif () 160 | 161 | # Set the install destination and namespace 162 | set(install_destination "lib/cmake/${PROJECT_NAME}") 163 | if (PROJECT_NAMESPACE) 164 | set(install_namespace "${PROJECT_NAMESPACE}::") 165 | endif () 166 | 167 | # Create an export package of the targets 168 | # Use GNUInstallDirs and COMPONENTS 169 | # See "Deep CMake for Library Authors" https://www.youtube.com/watch?v=m0DwB4OvDXk 170 | # TODO: Investigate why using "COMPONENTS" broke usage of the package 171 | install( 172 | TARGETS ${args_TARGETS} 173 | EXPORT ${PROJECT_NAME}-targets 174 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 175 | #COMPONENT ${PROJECT_NAME}_Development 176 | INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 177 | #COMPONENT ${PROJECT_NAME}_Development 178 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 179 | #COMPONENT ${PROJECT_NAME}_Runtime 180 | #NAMELINK_COMPONENT ${PROJECT_NAME}_Development 181 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 182 | #COMPONENT ${PROJECT_NAME}_Runtime) 183 | 184 | # Install the export package 185 | install( 186 | EXPORT ${PROJECT_NAME}-targets 187 | FILE ${PROJECT_NAME}-targets.cmake 188 | NAMESPACE ${install_namespace} 189 | DESTINATION ${install_destination}) 190 | 191 | # Generate a package configuration file 192 | file( 193 | WRITE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake.in 194 | "@PACKAGE_INIT@\n" 195 | "include(\${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}-targets.cmake)") 196 | configure_package_config_file( 197 | ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake.in 198 | ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake 199 | INSTALL_DESTINATION ${install_destination}) 200 | 201 | # Gather files to be installed 202 | list(APPEND install_files ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake) 203 | 204 | # If the package has a version specified, generate a package version file 205 | if (PROJECT_VERSION) 206 | write_basic_package_version_file(${PROJECT_NAME}-config-version.cmake 207 | VERSION ${PROJECT_VERSION} 208 | COMPATIBILITY SameMajorVersion) 209 | 210 | list(APPEND install_files ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake) 211 | endif () 212 | 213 | # Install config files for the project 214 | install( 215 | FILES ${install_files} 216 | DESTINATION ${install_destination}) 217 | 218 | # Install public header files for the project 219 | install( 220 | DIRECTORY ${PROJECT_SOURCE_DIR}/include/ 221 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 222 | FILES_MATCHING PATTERN "*.h*") 223 | endfunction() 224 | --------------------------------------------------------------------------------