Skip to content

Commit a503518

Browse files
committed
fix(utils): prevent spdlog config from leaking to consumers
1 parent 1845e1f commit a503518

3 files changed

Lines changed: 101 additions & 11 deletions

File tree

‎CMakeLists.txt‎

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ option(VIX_STRICT "Treat warnings as errors" OFF)
6161
option(VIX_ENABLE_LTO "Enable link-time optimization (Release)" OFF)
6262
option(VIX_HEADER_ONLY "Build vix_utils as header-only INTERFACE" OFF)
6363
option(VIX_UTILS_BUILD_EXAMPLES "Build utils examples" OFF)
64+
option(VIX_UTILS_BUILD_TESTS "Build utils CMake regression tests" OFF)
6465
option(VIX_UTILS_FETCH_THIRD_PARTY "Auto-fetch spdlog and fmt if not installed" ON)
6566

6667
# --------------------------------------------------------------------
@@ -92,6 +93,56 @@ string(TIMESTAMP VIX_BUILD_DATE "%Y-%m-%d %H:%M:%S UTC" UTC)
9293
set(_VIX_SPDLOG_TARGET "")
9394
set(_VIX_FMT_TARGET "")
9495

96+
# FetchContent options are cache variables, so Vix's private spdlog setup
97+
# must not leave configuration behind for a consumer's later add_subdirectory.
98+
macro(vix_utils_push_spdlog_fetch_options)
99+
foreach(_vix_option IN ITEMS
100+
SPDLOG_FMT_EXTERNAL SPDLOG_BUILD_EXAMPLE SPDLOG_BUILD_EXAMPLES
101+
SPDLOG_BUILD_TESTS SPDLOG_BUILD_BENCH SPDLOG_INSTALL)
102+
get_property(_vix_normal_defined VARIABLE ${_vix_option} PROPERTY SET)
103+
set(_VIX_UTILS_${_vix_option}_NORMAL_DEFINED ${_vix_normal_defined})
104+
if (_vix_normal_defined)
105+
set(_VIX_UTILS_${_vix_option}_NORMAL_VALUE "${${_vix_option}}")
106+
endif()
107+
if (DEFINED CACHE{${_vix_option}})
108+
get_property(_VIX_UTILS_${_vix_option}_CACHE_VALUE CACHE ${_vix_option} PROPERTY VALUE)
109+
get_property(_VIX_UTILS_${_vix_option}_CACHE_TYPE CACHE ${_vix_option} PROPERTY TYPE)
110+
set(_VIX_UTILS_${_vix_option}_CACHE_DEFINED TRUE)
111+
else()
112+
set(_VIX_UTILS_${_vix_option}_CACHE_DEFINED FALSE)
113+
endif()
114+
endforeach()
115+
set(SPDLOG_FMT_EXTERNAL ON)
116+
set(SPDLOG_BUILD_EXAMPLE OFF)
117+
set(SPDLOG_BUILD_EXAMPLES OFF)
118+
set(SPDLOG_BUILD_TESTS OFF)
119+
set(SPDLOG_BUILD_BENCH OFF)
120+
set(SPDLOG_INSTALL OFF)
121+
set(SPDLOG_FMT_EXTERNAL ON CACHE BOOL "" FORCE)
122+
set(SPDLOG_BUILD_EXAMPLE OFF CACHE BOOL "" FORCE)
123+
set(SPDLOG_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
124+
set(SPDLOG_BUILD_TESTS OFF CACHE BOOL "" FORCE)
125+
set(SPDLOG_BUILD_BENCH OFF CACHE BOOL "" FORCE)
126+
set(SPDLOG_INSTALL OFF CACHE BOOL "" FORCE)
127+
endmacro()
128+
129+
macro(vix_utils_pop_spdlog_fetch_options)
130+
foreach(_vix_option IN ITEMS
131+
SPDLOG_FMT_EXTERNAL SPDLOG_BUILD_EXAMPLE SPDLOG_BUILD_EXAMPLES
132+
SPDLOG_BUILD_TESTS SPDLOG_BUILD_BENCH SPDLOG_INSTALL)
133+
if (_VIX_UTILS_${_vix_option}_NORMAL_DEFINED)
134+
set(${_vix_option} "${_VIX_UTILS_${_vix_option}_NORMAL_VALUE}")
135+
else()
136+
unset(${_vix_option})
137+
endif()
138+
if (_VIX_UTILS_${_vix_option}_CACHE_DEFINED)
139+
set(${_vix_option} "${_VIX_UTILS_${_vix_option}_CACHE_VALUE}" CACHE ${_VIX_UTILS_${_vix_option}_CACHE_TYPE} "" FORCE)
140+
else()
141+
unset(${_vix_option} CACHE)
142+
endif()
143+
endforeach()
144+
endmacro()
145+
95146
# -------------------------
96147
# spdlog
97148
# -------------------------
@@ -177,17 +228,13 @@ if ((NOT _VIX_FMT_TARGET OR NOT _VIX_SPDLOG_TARGET) AND VIX_UTILS_FETCH_THIRD_PA
177228

178229
if (NOT _VIX_SPDLOG_TARGET)
179230
message(STATUS "[utils] Fetching spdlog via FetchContent")
180-
set(SPDLOG_FMT_EXTERNAL ON CACHE BOOL "" FORCE)
181-
set(SPDLOG_BUILD_EXAMPLE OFF CACHE BOOL "" FORCE)
182-
set(SPDLOG_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
183-
set(SPDLOG_BUILD_TESTS OFF CACHE BOOL "" FORCE)
184-
set(SPDLOG_BUILD_BENCH OFF CACHE BOOL "" FORCE)
185-
set(SPDLOG_INSTALL OFF CACHE BOOL "" FORCE)
231+
vix_utils_push_spdlog_fetch_options()
186232
FetchContent_Declare(vix_spdlog
187233
GIT_REPOSITORY https://github.com/gabime/spdlog.git
188234
GIT_TAG v1.14.1
189235
)
190236
FetchContent_MakeAvailable(vix_spdlog)
237+
vix_utils_pop_spdlog_fetch_options()
191238

192239
if (TARGET spdlog::spdlog_header_only)
193240
set(_VIX_SPDLOG_TARGET spdlog::spdlog_header_only)
@@ -246,15 +293,12 @@ if (VIX_HEADER_ONLY)
246293
target_compile_definitions(vix_utils INTERFACE
247294
VIX_GIT_HASH="${VIX_GIT_HASH}"
248295
VIX_BUILD_DATE="${VIX_BUILD_DATE}"
249-
SPDLOG_FMT_EXTERNAL=1
250296
)
251297

252298
target_compile_features(vix_utils INTERFACE cxx_std_20)
253299

254300
target_link_libraries(vix_utils INTERFACE
255-
$<BUILD_INTERFACE:${_VIX_SPDLOG_TARGET}>
256301
$<BUILD_INTERFACE:${_VIX_FMT_TARGET}>
257-
$<INSTALL_INTERFACE:${_VIX_SPDLOG_INSTALL_TARGET}>
258302
$<INSTALL_INTERFACE:${_VIX_FMT_INSTALL_TARGET}>
259303
)
260304

@@ -287,17 +331,21 @@ else()
287331
target_compile_definitions(vix_utils PUBLIC
288332
VIX_GIT_HASH="${VIX_GIT_HASH}"
289333
VIX_BUILD_DATE="${VIX_BUILD_DATE}"
334+
)
335+
336+
target_compile_definitions(vix_utils PRIVATE
290337
SPDLOG_FMT_EXTERNAL=1
291338
)
292339

293340
target_compile_features(vix_utils PUBLIC cxx_std_20)
294341

295342
target_link_libraries(vix_utils
296343
PUBLIC
297-
$<BUILD_INTERFACE:${_VIX_SPDLOG_TARGET}>
298344
$<BUILD_INTERFACE:${_VIX_FMT_TARGET}>
299-
$<INSTALL_INTERFACE:${_VIX_SPDLOG_INSTALL_TARGET}>
300345
$<INSTALL_INTERFACE:${_VIX_FMT_INSTALL_TARGET}>
346+
PRIVATE
347+
$<BUILD_INTERFACE:${_VIX_SPDLOG_TARGET}>
348+
$<INSTALL_INTERFACE:${_VIX_SPDLOG_INSTALL_TARGET}>
301349
)
302350

303351
if (WIN32)
@@ -453,6 +501,11 @@ if (VIX_UTILS_BUILD_EXAMPLES AND NOT VIX_HEADER_ONLY)
453501
)
454502
endif()
455503

504+
if (VIX_UTILS_BUILD_TESTS)
505+
include(CTest)
506+
add_subdirectory(tests)
507+
endif()
508+
456509
# --------------------------------------------------------------------
457510
# Summary
458511
# --------------------------------------------------------------------

‎tests/CMakeLists.txt‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
include(CTest)
2+
enable_testing()
3+
4+
get_target_property(_vix_utils_interface_definitions vix_utils INTERFACE_COMPILE_DEFINITIONS)
5+
foreach(_vix_definition IN LISTS _vix_utils_interface_definitions)
6+
if (_vix_definition MATCHES "^SPDLOG_FMT_EXTERNAL(=|$)")
7+
message(FATAL_ERROR
8+
"vix_utils exports SPDLOG_FMT_EXTERNAL to consumers: ${_vix_definition}")
9+
endif()
10+
endforeach()
11+
12+
# Model a consumer which uses an independent bundled-fmt spdlog. It gets the
13+
# spdlog include path but deliberately not spdlog's target usage requirements;
14+
# vix::utils must therefore not inject SPDLOG_FMT_EXTERNAL into this compile.
15+
get_target_property(_vix_spdlog_includes ${_VIX_SPDLOG_TARGET} INTERFACE_INCLUDE_DIRECTORIES)
16+
add_executable(vix_utils_spdlog_interface_regression
17+
spdlog_interface_regression.cpp
18+
)
19+
target_compile_features(vix_utils_spdlog_interface_regression PRIVATE cxx_std_20)
20+
target_include_directories(vix_utils_spdlog_interface_regression PRIVATE ${_vix_spdlog_includes})
21+
target_link_libraries(vix_utils_spdlog_interface_regression PRIVATE vix::utils)
22+
23+
add_test(
24+
NAME vix_utils_spdlog_interface_regression
25+
COMMAND vix_utils_spdlog_interface_regression
26+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <spdlog/spdlog.h>
2+
3+
#ifdef SPDLOG_FMT_EXTERNAL
4+
#error "vix::utils leaked SPDLOG_FMT_EXTERNAL into an independent consumer"
5+
#endif
6+
7+
int main()
8+
{
9+
spdlog::info("vix utils interface regression");
10+
return 0;
11+
}

0 commit comments

Comments
 (0)