11cmake_minimum_required (VERSION 3.20 )
22project (reflect
3- VERSION 0.2.0
3+ VERSION 0.2.1
44 DESCRIPTION "C++26 reflection utilities — header-only, zero dependencies"
55 LANGUAGES CXX
66)
@@ -17,16 +17,21 @@ target_include_directories(reflect INTERFACE
1717# configure error ("cxx_std_26 is not known to CXX compiler").
1818target_compile_options (reflect INTERFACE -std=c++26 )
1919
20- # Detect compiler and add reflection flags
21- if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
22- # Bloomberg Clang fork
23- target_compile_options (reflect INTERFACE -freflection-latest )
24- elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" )
25- # GCC 16+ — reflection is enabled automatically with -std=c++26
26- if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "16.0" )
27- message (WARNING "GCC < 16 does not support C++26 reflection. "
28- "Build from GCC trunk or use Bloomberg Clang fork." )
29- endif ()
20+ # Compiler-specific reflection flag. Wrapped in a generator expression
21+ # so the decision is made at the *consumer's* build time, not when this
22+ # package is configured/installed. Without this, installing after
23+ # configuring with Clang would leak -freflection-latest into a
24+ # downstream GCC consumer's build via the exported INTERFACE.
25+ target_compile_options (reflect INTERFACE
26+ $<$<CXX_COMPILER_ID :Clang ,AppleClang >:-freflection -latest >
27+ )
28+
29+ # GCC 16+ enables reflection automatically with -std=c++26. This warning
30+ # fires only at our configure time and is not exported to consumers.
31+ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
32+ AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "16.0" )
33+ message (WARNING "GCC < 16 does not support C++26 reflection. "
34+ "Build from GCC trunk or use Bloomberg Clang fork." )
3035endif ()
3136
3237if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR )
@@ -39,9 +44,9 @@ endif()
3944# Listed explicitly rather than file(GLOB ...): a glob runs at configure
4045# time, so a new test_xxx.cpp added on disk wouldn't be picked up until
4146# CMake re-configures. With an explicit list, adding a test is a 20-second
42- # tax for guaranteed correctness — a missing entry here surfaces as a
43- # linker/ test-discovery failure on the next build, not a silently-skipped
44- # test .
47+ # tax for guaranteed determinism. The downside — a forgotten entry would
48+ # silently skip the test rather than failing the build — is caught by
49+ # scripts/verify-tests-listed.sh, run as a CI pre-flight step .
4550set (REFLECT_TEST_SOURCES
4651 tests/test_args.cpp
4752 tests/test_critical_issues.cpp
@@ -60,6 +65,27 @@ if (REFLECT_BUILD_TESTS AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests")
6065 target_link_libraries (${test_target} PRIVATE reflect )
6166 add_test (NAME ${test_name} COMMAND ${test_target} )
6267 endforeach ()
68+
69+ # Compile-failure tests: each source listed here MUST fail to
70+ # compile. The target is EXCLUDE_FROM_ALL (so the main build stays
71+ # green) and ctest invokes cmake --build on it expecting non-zero
72+ # exit (WILL_FAIL TRUE). A successful compile means the guard the
73+ # test exercises has regressed.
74+ set (REFLECT_COMPILE_FAIL_SOURCES
75+ tests/compile_fail_map_string_view.cpp
76+ )
77+ foreach (cf_src ${REFLECT_COMPILE_FAIL_SOURCES} )
78+ get_filename_component (cf_name ${cf_src} NAME_WE )
79+ set (cf_target reflect_${cf_name} )
80+ add_executable (${cf_target} EXCLUDE_FROM_ALL ${cf_src} )
81+ target_link_libraries (${cf_target} PRIVATE reflect )
82+ add_test (
83+ NAME ${cf_name}
84+ COMMAND ${CMAKE_COMMAND } --build ${CMAKE_BINARY_DIR }
85+ --target ${cf_target} --config $<CONFIG >
86+ )
87+ set_tests_properties (${cf_name} PROPERTIES WILL_FAIL TRUE )
88+ endforeach ()
6389endif ()
6490
6591# Examples
0 commit comments