From edf1f753449a79c8d7511605c2b6c10f0d4a8d1c Mon Sep 17 00:00:00 2001 From: Nana Sakisaka <1901813+saki7@users.noreply.github.com> Date: Thu, 12 Mar 2026 22:47:06 +0900 Subject: [PATCH] Make common CMake targets more modular --- CMakeLists.txt | 97 +++++++++++++++++------- test/CMakeLists.txt | 114 +++++++++++++---------------- test/rvariant/CMakeLists.txt | 4 +- test/unicode/string/CMakeLists.txt | 2 +- 4 files changed, 126 insertions(+), 91 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 673d6cb..6c3e824 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,10 @@ set_property(GLOBAL PROPERTY IRIS_ROOT "${IRIS_ROOT}") set(CMAKE_COLOR_DIAGNOSTICS ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) +if(NOT DEFINED CMAKE_CXX_EXTENSIONS) + set(CMAKE_CXX_EXTENSIONS OFF) +endif() + option(IRIS_REMOVE_MINSIZEREL_CONFIG "Remove rarely used MinSizeRel config" ON) if(MSVC) @@ -36,9 +40,52 @@ endif() # ----------------------------------------------------------------- # Create common base targets -# Iris-specific common target -add_library(_iris_cxx_common INTERFACE) -set_target_properties(_iris_cxx_common PROPERTIES CXX_EXTENSIONS OFF) +# ABI compatibility target +add_library(iris_cxx_abi INTERFACE) +set_target_properties(iris_cxx_abi PROPERTIES CXX_EXTENSIONS OFF) + +# In contrast to the flags defined in `iris_cxx_abi`, certain +# miscellaneous flags aren't strictly required for ABI compatibility. +# +# However, we're going to merge them into `Iris::Iris` anyway, because +# the whole point of using Iris is to simplify C++ build system and use +# common flags everywhere; enforcing best-practices is our goal. +add_library(_iris_cxx_best_practices INTERFACE) +set_target_properties(_iris_cxx_best_practices PROPERTIES CXX_EXTENSIONS OFF) + +# ASan/UBSan +add_library(iris_cxx_sanitizer INTERFACE) +set_target_properties(iris_cxx_sanitizer PROPERTIES CXX_EXTENSIONS OFF) +target_link_libraries(iris_cxx_sanitizer INTERFACE iris_cxx_abi) + +if(MSVC) + # TODO: use $<$:......> + + target_compile_options( + iris_cxx_sanitizer + INTERFACE + /wd5072 # ASan intentionally enabled on Release build + /fsanitize=address + ) + target_link_options( + iris_cxx_sanitizer + INTERFACE + /ignore:4302 # ASan intentionally enabled on Release build + /INCREMENTAL:NO # required for ASan + ) + +else() # non-MSVC + target_compile_options( + iris_cxx_sanitizer + INTERFACE + -fsanitize=undefined,address + ) + target_link_options( + iris_cxx_sanitizer + INTERFACE + -fsanitize=undefined,address + ) +endif() # ----------------------------------------------------------------- @@ -56,11 +103,11 @@ if(MSVC) "${CMAKE_CURRENT_LIST_DIR}/iris.natvis" ) - target_link_libraries(iris PUBLIC _iris_cxx_common) + target_link_libraries(iris PUBLIC iris_cxx_abi _iris_cxx_best_practices) else() add_library(iris INTERFACE) - target_link_libraries(iris INTERFACE _iris_cxx_common) + target_link_libraries(iris INTERFACE iris_cxx_abi _iris_cxx_best_practices) endif() add_library(Iris::Iris ALIAS iris) @@ -88,21 +135,21 @@ if(MSVC) set(CMAKE_CXX${IRIS_CXX_VERSION_BEFORE_LATEST}_STANDARD_COMPILE_OPTION ${CMAKE_CXX${IRIS_CXX_VERSION_BEFORE_LATEST}_STANDARD_COMPILE_OPTION} PARENT_SCOPE) set(CMAKE_CXX${IRIS_CXX_VERSION_BEFORE_LATEST}_EXTENSION_COMPILE_OPTION ${CMAKE_CXX${IRIS_CXX_VERSION_BEFORE_LATEST}_EXTENSION_COMPILE_OPTION} PARENT_SCOPE) - target_compile_options(_iris_cxx_common INTERFACE /std:c++${IRIS_CXX_VERSION_BEFORE_LATEST}preview) + target_compile_options(iris_cxx_abi INTERFACE /std:c++${IRIS_CXX_VERSION_BEFORE_LATEST}preview) else() # MSVC's CMake support does not provide the latest `cxx_std_XX` # feature until the very last stage of the implementation. Instead, # the feature number that is one version behind the latest usually # resolves to `/std:c++latest`. - target_compile_features(_iris_cxx_common INTERFACE cxx_std_${IRIS_CXX_VERSION_BEFORE_LATEST}) + target_compile_features(iris_cxx_abi INTERFACE cxx_std_${IRIS_CXX_VERSION_BEFORE_LATEST}) endif() else() # Non-MSVC if(DEFINED CMAKE_CXX_STANDARD) - target_compile_features(_iris_cxx_common INTERFACE cxx_std_${CMAKE_CXX_STANDARD}) + target_compile_features(iris_cxx_abi INTERFACE cxx_std_${CMAKE_CXX_STANDARD}) else() - target_compile_features(_iris_cxx_common INTERFACE cxx_std_${IRIS_CXX_VERSION_LATEST}) + target_compile_features(iris_cxx_abi INTERFACE cxx_std_${IRIS_CXX_VERSION_LATEST}) endif() endif() @@ -115,47 +162,45 @@ unset(IRIS_CXX_FEATURE_BEFORE_LATEST) if(WIN32) target_compile_definitions( - _iris_cxx_common + iris_cxx_abi INTERFACE NOMINMAX WIN32_LEAN_AND_MEAN ) endif() if(MSVC) - # Don't set too strict flags for testing! They must go to `iris_cxx_test`. - # ABI-dependent configurations MUST be set here. + # Some flags affect ABI-compatibility, which means they are mandatory + # for any kind of downstream applications. + target_compile_definitions( - _iris_cxx_common + iris_cxx_abi INTERFACE UNICODE _UNICODE ) target_compile_options( - _iris_cxx_common + iris_cxx_abi INTERFACE /EHsc /MP /utf-8 /Zc:__cplusplus /Zc:preprocessor /permissive- - # $<$:/fsanitize=address> # TODO ) - target_link_options( - _iris_cxx_common + + target_compile_options( + _iris_cxx_best_practices INTERFACE - # $<$:/INCREMENTAL:NO> # TODO + /W4 /analyze /analyze:external- ) + else() if(CMAKE_CXX_COMPILER_ID MATCHES Clang) target_compile_options( - _iris_cxx_common + iris_cxx_abi INTERFACE -fno-builtin-std-forward_like -Wno-c++26-extensions # workaround for warnings emitted when using pack indexing ) endif() + target_compile_options( - _iris_cxx_common - INTERFACE - # $<$:-fsanitize=undefined,address> # TODO - ) - target_link_options( - _iris_cxx_common + _iris_cxx_best_practices INTERFACE - # $<$:-fsanitize=undefined,address> # TODO + -Wall -Wextra -pedantic ) endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5347bca..dcac8a3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,63 +3,33 @@ # ----------------------------------------------------------------- # Setup the basic targets -# For internal common settings -add_library(_iris_cxx_test_common INTERFACE) -set_target_properties(_iris_cxx_test_common PROPERTIES CXX_EXTENSIONS OFF) -target_link_libraries(_iris_cxx_test_common INTERFACE _iris_cxx_common) +# For internal common settings # For Iris-specific tests add_library(iris_cxx_test INTERFACE) set_target_properties(iris_cxx_test PROPERTIES CXX_EXTENSIONS OFF) -target_link_libraries(iris_cxx_test INTERFACE _iris_cxx_test_common) +target_link_libraries(iris_cxx_test INTERFACE iris_cxx_abi) # For external libraries. Excludes strict warning, etc. add_library(iris_cxx_test_external INTERFACE) set_target_properties(iris_cxx_test_external PROPERTIES CXX_EXTENSIONS OFF) -target_link_libraries(iris_cxx_test_external INTERFACE _iris_cxx_test_common) +target_link_libraries(iris_cxx_test_external INTERFACE iris_cxx_abi) if(MSVC) - target_compile_options( - _iris_cxx_test_common - INTERFACE - /wd5072 # ASan intentionally enabled on Release build - /fsanitize=address - ) - target_link_options( - _iris_cxx_test_common - INTERFACE - /ignore:4302 # ASan intentionally enabled on Release build - /INCREMENTAL:NO # required for ASan - ) - - target_compile_options( - iris_cxx_test - INTERFACE /W4 /analyze /analyze:external- - ) - target_compile_options( iris_cxx_test_external INTERFACE /analyze- ) +endif() -else() # non-MSVC - target_compile_options( - _iris_cxx_test_common - INTERFACE - -fsanitize=undefined,address - ) - target_link_options( - _iris_cxx_test_common - INTERFACE - -fsanitize=undefined,address - ) - - target_compile_options( - iris_cxx_test - INTERFACE - -Wall -Wextra -pedantic - ) +# +# TODO: separate sanitizer and non-sanitizer versions +# +option(IRIS_TEST_USE_SANITIZER "Enable ASan/UBSan" ON) +if(${IRIS_TEST_USE_SANITIZER}) + target_link_libraries(iris_cxx_test INTERFACE iris_cxx_sanitizer) + target_link_libraries(iris_cxx_test_external INTERFACE iris_cxx_sanitizer) endif() @@ -84,11 +54,33 @@ set_target_properties(Catch2 PROPERTIES CXX_EXTENSIONS OFF) set_target_properties(Catch2 Catch2WithMain PROPERTIES FOLDER "_deps") target_compile_definitions(Catch2 PUBLIC DO_NOT_USE_WMAIN) + +if(MSVC) + target_compile_options(Catch2 PRIVATE /wd6054) +endif() + target_link_libraries(Catch2 PRIVATE iris_cxx_test_external) target_link_libraries(Catch2WithMain PRIVATE iris_cxx_test_external) target_link_libraries(iris_cxx_test INTERFACE Catch2::Catch2) + +# ----------------------------------------------------------------- +# Iris internal test targets + +add_library(_iris_internal_test INTERFACE) +target_include_directories(_iris_internal_test INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +if(MSVC) + target_sources(_iris_internal_test INTERFACE "${CMAKE_CURRENT_LIST_DIR}/cpp.hint") +endif() + +function(iris_define_internal_test test_name) + iris_define_test(${test_name} ${ARGN}) + target_link_libraries(${test_name}_test PRIVATE _iris_internal_test) +endfunction() + + # ----------------------------------------------------------------- # Common CMake utilities for testing @@ -102,9 +94,8 @@ function(_iris_define_test_impl test_name libs) message(FATAL_ERROR "IRIS_ROOT is not defined") endif() - add_executable(${test_name}_test ${ARGN}) - target_include_directories(${test_name}_test PRIVATE ${CMAKE_CURRENT_FUNCTION_LIST_DIR}) target_include_directories(${test_name}_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}) + target_link_libraries(${test_name}_test PRIVATE Iris::Iris iris_cxx_test ${libs}) set_target_properties(${test_name}_test PROPERTIES CXX_EXTENSIONS OFF) if(MSVC) @@ -114,12 +105,8 @@ function(_iris_define_test_impl test_name libs) TARGET_DIRECTORY ${test_name}_test PROPERTIES VS_SETTINGS "ExcludedFromBuild=true" ) - - target_sources(${test_name}_test PRIVATE "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/cpp.hint") endif() - target_link_libraries(${test_name}_test PRIVATE Iris::Iris iris_cxx_test ${libs}) - add_test(NAME ${test_name}_test COMMAND ${test_name}_test --colour-mode=ansi) set_tests_properties( ${test_name}_test PROPERTIES @@ -151,25 +138,28 @@ function(_iris_define_test_impl test_name libs) endif() endfunction() -function(iris_define_test test_name) - _iris_define_test_impl(${test_name} Catch2::Catch2WithMain ${ARGN}) +function(_iris_define_executable_test test_name libs) + add_executable(${test_name}_test ${ARGN}) + add_test(NAME ${test_name}_test COMMAND ${test_name}_test --colour-mode=ansi) + _iris_define_test_impl(${test_name} ${libs}) endfunction() -function(iris_define_test_no_main test_name) - _iris_define_test_impl(${test_name} "" ${ARGN}) + +# ----------------------------------------------------------------- +# Public test adder functions + +function(iris_define_test test_name) + _iris_define_executable_test(${test_name} Catch2::Catch2WithMain ${ARGN}) endfunction() -function(iris_define_tests) - foreach(test_name IN LISTS ARGV) - iris_define_test(${test_name} ${test_name}.cpp) - endforeach() +function(iris_define_test_no_main test_name) + _iris_define_executable_test(${test_name} Catch2::Catch2 ${ARGN}) endfunction() -function(iris_define_sub_tests prefix) - foreach(test_name IN LISTS ARGN) - iris_define_test(${prefix}_${test_name} ${test_name}.cpp) - set_target_properties(${prefix}_${test_name}_test PROPERTIES FOLDER "test/${prefix}") - endforeach() +function(iris_define_library_test library_type test_name srcs) + add_library(${test_name}_test ${library_type} ${srcs}) + add_test(NAME ${test_name}_test COMMAND ${ARGN}) + _iris_define_test_impl(${test_name} Catch2::Catch2) endfunction() @@ -190,10 +180,10 @@ if(PROJECT_IS_TOP_LEVEL) preprocess ) - iris_define_sub_tests(iris ${IRIS_TEST_IRIS_TESTS}) - foreach(test_name IN LISTS IRIS_TEST_IRIS_TESTS) + iris_define_internal_test(iris_${test_name} ${test_name}.cpp) iris_define_test_headers(iris_${test_name} iris_test.hpp) + set_target_properties(iris_${test_name}_test PROPERTIES FOLDER "test/iris") endforeach() add_subdirectory(unicode) diff --git a/test/rvariant/CMakeLists.txt b/test/rvariant/CMakeLists.txt index 4d7eef5..0404d61 100644 --- a/test/rvariant/CMakeLists.txt +++ b/test/rvariant/CMakeLists.txt @@ -14,8 +14,8 @@ if(IRIS_CI) list(APPEND IRIS_TEST_RVARIANT_TESTS many_alternatives_32) endif() -iris_define_sub_tests(rvariant ${IRIS_TEST_RVARIANT_TESTS}) - foreach(test_name IN LISTS IRIS_TEST_RVARIANT_TESTS) + iris_define_internal_test(rvariant_${test_name} ${test_name}.cpp) iris_define_test_headers(rvariant_${test_name} iris_rvariant_test.hpp) + set_target_properties(rvariant_${test_name}_test PROPERTIES FOLDER "test/rvariant") endforeach() diff --git a/test/unicode/string/CMakeLists.txt b/test/unicode/string/CMakeLists.txt index ebfa8d4..a7d1e48 100644 --- a/test/unicode/string/CMakeLists.txt +++ b/test/unicode/string/CMakeLists.txt @@ -7,7 +7,7 @@ set( ) foreach(test_name IN LISTS IRIS_TEST_UNICODE_STRING_TESTS) - iris_define_test(unicode_string_${test_name} ${test_name}.cpp) + iris_define_internal_test(unicode_string_${test_name} ${test_name}.cpp) set_target_properties(unicode_string_${test_name}_test PROPERTIES FOLDER "test/unicode/string") endforeach()