11# begin basic metadata
22# minimum CMake version required for C++20 support, among other things
3- cmake_minimum_required (VERSION 3.12)
3+ cmake_minimum_required (VERSION 3.15)
4+
5+ # detect if Project is being used as a sub-project of another CMake project
6+ if (NOT DEFINED PROJECT_NAME )
7+ set (PROJECT_SUBPROJECT OFF )
8+ else ()
9+ set (PROJECT_SUBPROJECT ON )
10+ endif ()
11+
12+ project (project VERSION 0.3.0 LANGUAGES CXX)
413
514find_program (CCACHE_PROGRAM ccache)
615if (CCACHE_PROGRAM)
716 set_property (GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM} " )
817endif ()
918
10- project (proj VERSION 0.0.0 LANGUAGES CXX)
19+ # Set a default build type if none was specified
20+ set (DEFAULT_BUILD_TYPE "Debug" )
21+
22+ if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES )
23+ set (CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE} " CACHE STRING "Choose the type of build." FORCE)
24+ # Set the possible values of build type for cmake-gui
25+ set_property (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo" )
26+ endif ()
27+
28+ # set some handy custom variables to detect Release-type builds from Debug-type ones
29+ if (CMAKE_BUILD_TYPE STREQUAL "Debug" )
30+ set (PROJECT_BUILD_DEBUG ON )
31+ set (PROJECT_BUILD_RELEASE OFF )
32+ else ()
33+ set (PROJECT_BUILD_DEBUG OFF )
34+ set (PROJECT_BUILD_RELEASE ON )
35+ endif ()
36+
37+ message (STATUS "[project] Build Mode: ${CMAKE_BUILD_TYPE} " )
1138
1239# set the C++ standard to use to C++20 always
13- set (PROJ_CXX_STANDARD "20" )
14- message (STATUS "[proj ] C++ Standard set to C++${PROJ_CXX_STANDARD } " )
15- set (CMAKE_CXX_STANDARD ${PROJ_CXX_STANDARD } )
40+ set (PROJECT_CXX_STANDARD "20" )
41+ message (STATUS "[project ] C++ Standard set to C++${PROJECT_CXX_STANDARD } " )
42+ set (CMAKE_CXX_STANDARD ${PROJECT_CXX_STANDARD } )
1643set (CMAKE_CXX_STANDARD_REQUIRED ON )
1744
45+ include (CMakeDependentOption)
46+ # if building in Release mode, provide an option to explicitly enable tests if desired (always ON for other builds, OFF by default for Release builds)
47+ cmake_dependent_option(ENABLE_TESTS "Build the unit tests in release mode?" OFF PROJECT_BUILD_RELEASE ON )
48+
49+ # Premature Optimisation causes problems. Commented out code below allows detection and enabling of LTO.
50+ # It's not being used currently because it seems to cause linker errors with Clang++ on Ubuntu if the library
51+ # is compiled with LTO but the unit tests are not. This suggests LTO may force some downstream software into
52+ # using LTO also if it's enabled. The plan is to reënable LTO as an option in the future, possibly done much
53+ # more optionally (and probably not by default).
54+
55+ # include(CheckIPOSupported)
56+ # check_ipo_supported(RESULT IPO_SUPPORTED)
57+ # # If we're in Release mode, set PROJECT_USE_IPO to ON by default if it's detected as supported (user can always explicitly enable it in Release mode)
58+ # cmake_dependent_option(PROJECT_USE_IPO "Use Link-Time/Inter-Procedural Optimisation?" ${IPO_SUPPORTED} PROJECT_BUILD_RELEASE OFF)
59+ # if(PROJECT_USE_IPO)
60+ # message(STATUS "[project] Link-Time-Optimisation Enabled")
61+ # endif()
62+
1863set (
19- PROJ_VERSION_STRING
64+ PROJECT_VERSION_STRING
2065 "${PROJECT_VERSION_MAJOR} .${PROJECT_VERSION_MINOR} .${PROJECT_VERSION_PATCH} "
2166)
22- set (PROJ_ESCAPED_VERSION_STRING "\" ${PROJ_VERSION_STRING } \" " )
67+ set (PROJECT_ESCAPED_VERSION_STRING "\" ${PROJECT_VERSION_STRING } \" " )
2368# end basic metadata
2469
25- # pass in version of project as preprocessor definitions
26- add_definitions (-DPROJ_VERSION_MAJOR=${PROJECT_VERSION_MAJOR} )
27- add_definitions (-DPROJ_VERSION_MINOR=${PROJECT_VERSION_MINOR} )
28- add_definitions (-DPROJ_VERSION_PATCH=${PROJECT_VERSION_PATCH} )
29- add_definitions (-DPROJ_VERSION_STRING=${PROJ_ESCAPED_VERSION_STRING} )
70+ # This is a special target which only exists to capture compilation options
71+ # used for project and its tests. This is to avoid setting global compiler
72+ # options which would be inherited by dependencies as well, which is bad
73+ # because project uses strict compiler warning options which not all other
74+ # projects can build successfully with.
75+ # Any target linked with this one will inherit the compiler options used for
76+ # project.
77+ add_library (project-compiler-options INTERFACE )
3078
3179# used for enabling additional compiler options if supported
3280include (CheckCXXCompilerFlag)
3381
3482function (enable_cxx_compiler_flag_if_supported flag)
35- message (STATUS "[proj] Checking if compiler supports warning flag '${flag} '" )
36- string (FIND "${CMAKE_CXX_FLAGS} " "${flag} " flag_already_set)
37- if (flag_already_set EQUAL -1)
38- check_cxx_compiler_flag("${flag} " flag_supported)
39- if (flag_supported)
40- message (STATUS "[proj] Enabling warning flag '${flag} '" )
41- set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag} " PARENT_SCOPE)
42- endif ()
83+ message (STATUS "[project] Checking if compiler supports warning flag '${flag} '" )
84+ check_cxx_compiler_flag("${flag} " flag_supported)
85+ if (flag_supported)
86+ message (STATUS "[project] Enabling warning flag '${flag} '" )
87+ target_compile_options (project-compiler-options INTERFACE "${flag} " )
4388 endif ()
44- unset (flag_already_set CACHE )
4589 unset (flag_supported CACHE )
4690endfunction ()
4791
48- # enable extra flags (warnings) if we're not in release mode
49- if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "" )
50- message (STATUS "[proj] Warnings Enabled" )
51- if (MSVC ) # MSVC supports different warning options to GCC/Clang
52- add_compile_options (/WX /W3) # treat all warnings as errors, set warning level 3
53- else () # GCC/Clang warning option
54- # NOTE: GCC and Clang support most of the same options, but neither supports all
55- # of the others'. By only enabling them if supported, we get graceful failure
56- # when trying to enable unsupported flags
57- # e.g. at the time of writing, GCC does not support -Wdocumentation
58- #
59- # enable all warnings about 'questionable constructs'
60- enable_cxx_compiler_flag_if_supported("-Wall" )
61- # issue 'pedantic' warnings for strict ISO compliance
62- enable_cxx_compiler_flag_if_supported("-pedantic" )
63- # enable 'extra' strict warnings
64- enable_cxx_compiler_flag_if_supported("-Wextra" )
65- # enable sign conversion warnings
66- enable_cxx_compiler_flag_if_supported("-Wsign-conversion" )
67- # enable warnings about mistakes in Doxygen documentation
68- enable_cxx_compiler_flag_if_supported("-Wdocumentation" )
69- # convert all warnings into errors
92+ # enable a large amount of extra warnings, regardless of build mode
93+ if (MSVC ) # MSVC supports different warning options to GCC/Clang
94+ # add_compile_options(/W4) # set warning level 4
95+ enable_cxx_compiler_flag_if_supported("/W4" )
96+ # if in debug mode, enable converting all warnings to errors too
97+ if (PROJECT_BUILD_DEBUG)
98+ # add_compile_options(/WX)
99+ enable_cxx_compiler_flag_if_supported("/WX" )
100+ endif ()
101+ else () # GCC/Clang warning option
102+ # NOTE: GCC and Clang support most of the same options, but neither supports all
103+ # of the others'. By only enabling them if supported, we get graceful failure
104+ # when trying to enable unsupported flags
105+ # e.g. at the time of writing, GCC does not support -Wdocumentation
106+ #
107+ # enable all warnings about 'questionable constructs'
108+ enable_cxx_compiler_flag_if_supported("-Wall" )
109+ # issue 'pedantic' warnings for strict ISO compliance
110+ enable_cxx_compiler_flag_if_supported("-pedantic" )
111+ # enable 'extra' strict warnings
112+ enable_cxx_compiler_flag_if_supported("-Wextra" )
113+ # enable sign conversion warnings
114+ enable_cxx_compiler_flag_if_supported("-Wsign-conversion" )
115+ # enable warnings about mistakes in Doxygen documentation
116+ enable_cxx_compiler_flag_if_supported("-Wdocumentation" )
117+ # if in debug mode, enable converting all warnings to errors too
118+ if (PROJECT_BUILD_DEBUG)
70119 enable_cxx_compiler_flag_if_supported("-Werror" )
71120 # exclude the following kinds of warnings from being converted into errors
72121 # unknown-pragma is useful to have as a warning but not as an error, if you have
@@ -76,86 +125,21 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "")
76125 enable_cxx_compiler_flag_if_supported("-Wno-error=unused-function" )
77126 enable_cxx_compiler_flag_if_supported("-Wno-error=unused-variable" )
78127 enable_cxx_compiler_flag_if_supported("-Wno-error=unused-parameter" )
128+ enable_cxx_compiler_flag_if_supported("-Wno-error=unused-private-field" )
79129 endif ()
80130endif ()
81131
82-
83132# add custom dependencies directory
84- set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR} /cmake/Modules/" )
85-
86- # begin dependencies
87-
88- # ...Add additional dependencies here...
89-
90- # end dependencies
91-
92- # C++ library source files
93- file (GLOB PROJ_SOURCES "proj/*.cpp" )
94- # C++ program source file
95- set (PROJ_CLI_SOURCE "main.cpp" )
96- # C++ source files for unit tests
97- file (GLOB TEST_SOURCES "tests/*.cpp" )
98- # Header files
99- set (PROJ_HEADERS "proj/proj.hpp" )
100-
101- # if project is a library
102- add_library (proj ${PROJ_SOURCES} )
103- # set up version for library objects
104- set_target_properties (
105- proj PROPERTIES VERSION ${PROJ_VERSION_STRING}
106- SOVERSION ${PROJECT_VERSION_MAJOR}
107- )
108- # link proj with C math library if we're on Linux
109- if (UNIX AND NOT APPLE )
110- target_link_libraries (proj m)
133+ set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR} /cmake/Modules/" )
134+
135+ # a better way to load dependencies
136+ include (CPM)
137+
138+ # library
139+ add_subdirectory (project)
140+ # unit tests --only enable if requested AND we're not building as a sub-project
141+ if (ENABLE_TESTS AND NOT PROJECT_SUBPROJECT)
142+ message (STATUS "[project] Unit Tests Enabled" )
143+ add_subdirectory (tests)
144+ enable_testing ()
111145endif ()
112-
113- # the proj executable --this is the command-line program
114- add_executable (proj-cli ${PROJ_CLI_SOURCE} )
115- # link the program with the library
116- target_link_libraries (proj-cli proj)
117- # set output name property so it will be called proj despite target name being different
118- set_target_properties (proj-cli PROPERTIES OUTPUT_NAME proj)
119-
120- # build unit tests
121- add_executable (unit_tests ${TEST_SOURCES} )
122- target_link_libraries (unit_tests proj)
123- enable_testing ()
124-
125- # auto-discover and add Catch2 tests from unit tests program
126- include (CTest)
127- include (Catch)
128-
129- catch_discover_tests(unit_tests)
130-
131- install (
132- TARGETS proj
133- ARCHIVE DESTINATION lib
134- LIBRARY DESTINATION lib
135- )
136- install (
137- TARGETS proj-cli
138- RUNTIME DESTINATION bin
139- )
140-
141- # Generate rough (nearest major) version-dependent header installation folder
142- set (
143- PROJ_ROUGH_HEADER_DESTINATION
144- "proj-${PROJECT_VERSION_MAJOR} "
145- )
146- # Generate precise (major and minor) version-dependent header installation folder
147- set (
148- PROJ_PRECISE_HEADER_DESTINATION
149- "proj-${PROJECT_VERSION_MAJOR} .${PROJECT_VERSION_MINOR} "
150- )
151-
152- # Install main library header files, both to rough and precise install locations
153- install (
154- FILES ${PROJ_HEADERS}
155- DESTINATION "include/${PROJ_ROUGH_HEADER_DESTINATION} "
156- )
157-
158- install (
159- FILES ${PROJ_HEADERS}
160- DESTINATION "include/${PROJ_PRECISE_HEADER_DESTINATION} "
161- )
0 commit comments