├── 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 |
--------------------------------------------------------------------------------