-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
205 lines (183 loc) · 8.6 KB
/
CMakeLists.txt
File metadata and controls
205 lines (183 loc) · 8.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
cmake_minimum_required(VERSION 3.20)
project(TakumCpp LANGUAGES CXX)
# =============================================================================
# Compiler and C++ Standard Detection
# =============================================================================
# Pick a preferred C++ standard dynamically. Some toolchains / CMake
# installations do not know the cxx_std_26 feature or do not support /std:c++26.
# Probe for support and fall back to older standards when necessary.
include(CheckCXXCompilerFlag)
# Check for C++26 support - be conservative with older compilers and AppleClang
check_cxx_compiler_flag("-std=c++26" HAVE_CXX26_GNU)
check_cxx_compiler_flag("/std:c++26" HAVE_CXX26_MSVC)
# Be conservative about C++26 - limit to known working combinations
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
# Disable C++26 for AppleClang due to incomplete feature support
set(HAVE_CXX26_GNU FALSE)
message(STATUS "Disabling C++26 for AppleClang due to incomplete feature support")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "18.0")
# Disable C++26 for Clang < 18 due to standard library compatibility issues with C++26
set(HAVE_CXX26_GNU FALSE)
message(STATUS "Disabling C++26 for Clang < 18.0 due to standard library compatibility issues")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14.0")
# Disable C++26 for older GCC versions
set(HAVE_CXX26_GNU FALSE)
message(STATUS "Disabling C++26 for GCC < 14.0 due to incomplete support")
endif()
# Check for C++23 support
check_cxx_compiler_flag("-std=c++23" HAVE_CXX23_GNU)
check_cxx_compiler_flag("/std:c++23" HAVE_CXX23_MSVC)
# Check for C++20 support
check_cxx_compiler_flag("-std=c++20" HAVE_CXX20_GNU)
check_cxx_compiler_flag("/std:c++20" HAVE_CXX20_MSVC)
# Set C++ standard based on what's available
if(HAVE_CXX26_GNU OR HAVE_CXX26_MSVC)
set(CMAKE_CXX_STANDARD 26)
message(STATUS "Using C++26 standard")
elseif(HAVE_CXX23_GNU OR HAVE_CXX23_MSVC)
set(CMAKE_CXX_STANDARD 23)
message(STATUS "Using C++23 standard")
elseif(HAVE_CXX20_GNU OR HAVE_CXX20_MSVC)
set(CMAKE_CXX_STANDARD 20)
message(STATUS "Using C++20 standard")
else()
message(FATAL_ERROR "At least C++20 is required. Please use a newer compiler.")
endif()
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# =============================================================================
# Compiler-Specific Configurations
# =============================================================================
# Detect compiler type for specific configurations
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
message(STATUS "Detected MSVC compiler")
# MSVC-specific flags
add_compile_options(/W4) # Warning level 4
add_compile_options(/permissive-) # Strict standards conformance
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
message(STATUS "Detected GCC compiler version ${CMAKE_CXX_COMPILER_VERSION}")
# GCC-specific flags
add_compile_options(-Wall -Wextra -Wpedantic)
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "9.0")
message(STATUS "GCC 9+ detected: enabling enhanced constexpr support")
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
message(STATUS "Detected Clang compiler version ${CMAKE_CXX_COMPILER_VERSION}")
# Clang-specific flags
add_compile_options(-Wall -Wextra -Wpedantic)
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.0")
message(STATUS "Clang 12+ detected: full C++20/23 support available")
endif()
# Workaround: libstdc++ + clang < 18 has incomplete std::format / ranges / unicode interaction
# that triggers massive constraint failures when building googletest (uses <format> internally).
# Disable std::format usage in gtest by defining GTEST_INTERNAL_HAS_STD_FORMAT=0 when we detect
# a problematic toolchain variant (clang < 18).
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "18.0")
add_compile_definitions(GTEST_INTERNAL_HAS_STD_FORMAT=0)
# Also force-disable libstdc++ std::format machinery which triggers broken
# ranges/unicode instantiations under clang 17 + libstdc++14.
add_compile_options(-U_GLIBCXX_USE_STD_FORMAT)
add_compile_definitions(_GLIBCXX_USE_STD_FORMAT=0)
message(STATUS "Disabling std::format (gtest + libstdc++) for clang <18 to work around ranges/unicode issues")
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
message(STATUS "Detected AppleClang compiler version ${CMAKE_CXX_COMPILER_VERSION}")
# AppleClang-specific flags - more conservative with C++ standards
add_compile_options(-Wall -Wextra -Wpedantic)
message(STATUS "AppleClang detected: using conservative C++ standard support")
else()
message(WARNING "Unknown compiler: ${CMAKE_CXX_COMPILER_ID}")
endif()
# Platform-specific configurations
if(WIN32)
message(STATUS "Configuring for Windows platform")
# Windows-specific settings
elseif(APPLE)
message(STATUS "Configuring for macOS platform")
# macOS-specific settings
elseif(UNIX)
message(STATUS "Configuring for Unix/Linux platform")
# Unix/Linux-specific settings
endif()
include(FetchContent)
# ---------------------------------------------------------------------------
# Generated Φ polynomial coefficients
# ---------------------------------------------------------------------------
set(PHI_COEFF_HEADER ${CMAKE_SOURCE_DIR}/include/takum/internal/generated/phi_coeffs.h)
set(PHI_GEN_SCRIPT ${CMAKE_SOURCE_DIR}/scripts/gen_poly_coeffs.py)
find_package(Python3 COMPONENTS Interpreter QUIET)
if(Python3_Interpreter_FOUND AND EXISTS ${PHI_GEN_SCRIPT})
add_custom_command(
OUTPUT ${PHI_COEFF_HEADER}
COMMAND ${Python3_EXECUTABLE} ${PHI_GEN_SCRIPT} ${PHI_COEFF_HEADER}
DEPENDS ${PHI_GEN_SCRIPT}
COMMENT "Generating Φ polynomial coefficient header"
VERBATIM
)
add_custom_target(phi_coeffs_gen DEPENDS ${PHI_COEFF_HEADER})
else()
add_custom_target(phi_coeffs_gen
COMMAND ${CMAKE_COMMAND} -E echo "Python3 or script missing; using existing phi_coeffs.h if present"
)
endif()
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.15.2
)
FetchContent_MakeAvailable(googletest)
# Provide an INTERFACE target for header-only library usage
add_library(TakumCpp INTERFACE)
target_include_directories(TakumCpp INTERFACE ${CMAKE_SOURCE_DIR}/include)
# Use the detected standard for target features - be conservative about C++26
if(CMAKE_CXX_STANDARD EQUAL 26)
# Only use cxx_std_26 if we're sure it's supported
# For now, fall back to setting standard directly for C++26
set_target_properties(TakumCpp PROPERTIES
CXX_STANDARD 26
CXX_STANDARD_REQUIRED ON)
message(STATUS "Using C++26 with direct standard setting (avoiding cxx_std_26 feature)")
elseif(CMAKE_CXX_STANDARD EQUAL 23)
target_compile_features(TakumCpp INTERFACE cxx_std_23)
elseif(CMAKE_CXX_STANDARD EQUAL 20)
target_compile_features(TakumCpp INTERFACE cxx_std_20)
endif()
# Enable CTest
include(CTest)
enable_testing()
# ---------------------------------------------------------------------------
# Options
# ---------------------------------------------------------------------------
option(TAKUM_ENABLE_AUTOTEST_LOGS "Run tests automatically after build of 'tests' target and write log + JUnit files" ON)
# Tests (depend on generated header)
add_subdirectory(test)
add_dependencies(tests phi_coeffs_gen)
# Examples
file(GLOB EXAMPLE_SOURCES "${CMAKE_SOURCE_DIR}/examples/*.cpp")
foreach(EXAMPLE_SOURCE ${EXAMPLE_SOURCES})
get_filename_component(EXAMPLE_NAME ${EXAMPLE_SOURCE} NAME_WE)
add_executable(${EXAMPLE_NAME} ${EXAMPLE_SOURCE})
target_link_libraries(${EXAMPLE_NAME} PRIVATE TakumCpp)
add_dependencies(${EXAMPLE_NAME} phi_coeffs_gen)
if(BUILD_TESTING)
add_test(NAME ${EXAMPLE_NAME} COMMAND ${EXAMPLE_NAME})
endif()
endforeach()
# Doxygen documentation: try to find a doxygen executable either in PATH
# or at a common installation location on Windows. If not found we still
# expose a `docs` target that will show an informative error when built.
find_program(DOXYGEN_EXECUTABLE NAMES doxygen HINTS "C:/Program Files/doxygen/bin" "C:/Program Files (x86)/doxygen/bin")
if(DOXYGEN_EXECUTABLE)
add_custom_target(docs
COMMAND "${DOXYGEN_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/Doxyfile"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
COMMENT "Generating API documentation with Doxygen"
VERBATIM
)
else()
add_custom_target(docs
COMMAND ${CMAKE_COMMAND} -E echo "Doxygen executable not found. Install Doxygen or add it to PATH to build docs."
COMMENT "Doxygen not found: docs target is a no-op"
)
message(WARNING "Doxygen not found; 'docs' target will be a no-op. Install doxygen to enable documentation generation.")
endif()