add_subdirectory(gtest) include(CheckSymbolExists) set(TEST_MAIN_SRC test-main.cc gtest-extra.cc gtest-extra.h util.cc) add_library(test-main STATIC ${TEST_MAIN_SRC}) target_include_directories(test-main PUBLIC $) target_link_libraries(test-main gtest fmt) function(add_fmt_executable name) add_executable(${name} ${ARGN}) # (Wstringop-overflow) - [meta-bug] bogus/missing -Wstringop-overflow warnings # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88443 # Bogus -Wstringop-overflow warning # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100395 # [10 Regression] spurious -Wstringop-overflow writing to a trailing array plus offset # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95353 if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0) target_compile_options(${name} PRIVATE -Wno-stringop-overflow) # The linker flag is needed for LTO. target_link_libraries(${name} -Wno-stringop-overflow) endif () endfunction() # Adds a test. # Usage: add_fmt_test(name srcs...) function(add_fmt_test name) cmake_parse_arguments(ADD_FMT_TEST "HEADER_ONLY;MODULE" "" "" ${ARGN}) set(sources ${name}.cc ${ADD_FMT_TEST_UNPARSED_ARGUMENTS}) if (ADD_FMT_TEST_HEADER_ONLY) set(sources ${sources} ${TEST_MAIN_SRC} ../src/os.cc) set(libs gtest fmt-header-only) if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wno-weak-vtables) endif () elseif (ADD_FMT_TEST_MODULE) set(libs test-main test-module) set_source_files_properties(${name}.cc PROPERTIES OBJECT_DEPENDS test-module) else () set(libs test-main fmt) endif () add_fmt_executable(${name} ${sources}) target_link_libraries(${name} ${libs}) # Define if certain C++ features can be used. if (FMT_PEDANTIC) target_compile_options(${name} PRIVATE ${PEDANTIC_COMPILE_FLAGS}) endif () if (FMT_WERROR) target_compile_options(${name} PRIVATE ${WERROR_FLAG}) endif () add_test(NAME ${name} COMMAND ${name}) endfunction() if (FMT_MODULE) return () endif () add_fmt_test(args-test) add_fmt_test(base-test) add_fmt_test(assert-test) add_fmt_test(chrono-test) add_fmt_test(color-test) add_fmt_test(gtest-extra-test) add_fmt_test(format-test mock-allocator.h) if (MSVC) target_compile_options(format-test PRIVATE /bigobj) endif () if (NOT (MSVC AND BUILD_SHARED_LIBS)) add_fmt_test(format-impl-test HEADER_ONLY header-only-test.cc) endif () add_fmt_test(ostream-test) add_fmt_test(compile-test) add_fmt_test(compile-fp-test HEADER_ONLY) if (MSVC) # Without this option, MSVC returns 199711L for the __cplusplus macro. target_compile_options(compile-fp-test PRIVATE /Zc:__cplusplus) endif() add_fmt_test(printf-test) add_fmt_test(ranges-test ranges-odr-test.cc) add_fmt_test(scan-test HEADER_ONLY) check_symbol_exists(strptime "time.h" HAVE_STRPTIME) if (HAVE_STRPTIME) target_compile_definitions(scan-test PRIVATE FMT_HAVE_STRPTIME) endif () add_fmt_test(std-test) try_compile(compile_result_unused ${CMAKE_CURRENT_BINARY_DIR} SOURCES ${CMAKE_CURRENT_LIST_DIR}/detect-stdfs.cc OUTPUT_VARIABLE RAWOUTPUT) string(REGEX REPLACE ".*libfound \"([^\"]*)\".*" "\\1" STDLIBFS "${RAWOUTPUT}") if (STDLIBFS) target_link_libraries(std-test ${STDLIBFS}) endif () add_fmt_test(unicode-test HEADER_ONLY) if (MSVC) target_compile_options(unicode-test PRIVATE /utf-8) endif () add_fmt_test(xchar-test) add_fmt_test(enforce-checks-test) target_compile_definitions(enforce-checks-test PRIVATE -DFMT_ENFORCE_COMPILE_STRING) if (FMT_MODULE) # The tests need {fmt} to be compiled as traditional library # because of visibility of implementation details. # If module support is present the module tests require a # test-only module to be built from {fmt} add_library(test-module OBJECT ${CMAKE_SOURCE_DIR}/src/fmt.cc) target_compile_features(test-module PUBLIC cxx_std_11) target_include_directories(test-module PUBLIC $) enable_module(test-module) add_fmt_test(module-test MODULE test-main.cc) if (MSVC) target_compile_options(test-module PRIVATE /utf-8 /Zc:__cplusplus /Zc:externConstexpr /Zc:inline) target_compile_options(module-test PRIVATE /utf-8 /Zc:__cplusplus /Zc:externConstexpr /Zc:inline) endif () endif () if (NOT DEFINED MSVC_STATIC_RUNTIME AND MSVC) foreach (flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) if (${flag_var} MATCHES "^(/|-)(MT|MTd)") set(MSVC_STATIC_RUNTIME ON) break() endif() endforeach() endif() if (NOT MSVC_STATIC_RUNTIME) add_fmt_executable(posix-mock-test posix-mock-test.cc ../src/format.cc ${TEST_MAIN_SRC}) target_include_directories( posix-mock-test PRIVATE ${PROJECT_SOURCE_DIR}/include) target_link_libraries(posix-mock-test gtest) if (FMT_PEDANTIC) target_compile_options(posix-mock-test PRIVATE ${PEDANTIC_COMPILE_FLAGS}) endif () if (MSVC) target_compile_options(posix-mock-test PRIVATE /utf-8) endif () add_test(NAME posix-mock-test COMMAND posix-mock-test) add_fmt_test(os-test) endif () message(STATUS "FMT_PEDANTIC: ${FMT_PEDANTIC}") if (FMT_PEDANTIC) # Test that the library can be compiled with exceptions disabled. # -fno-exception is broken in icc: https://github.com/fmtlib/fmt/issues/822. if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Intel") check_cxx_compiler_flag(-fno-exceptions HAVE_FNO_EXCEPTIONS_FLAG) endif () if (HAVE_FNO_EXCEPTIONS_FLAG) add_library(noexception-test ../src/format.cc noexception-test.cc) target_include_directories( noexception-test PRIVATE ${PROJECT_SOURCE_DIR}/include) target_compile_options(noexception-test PRIVATE -fno-exceptions) target_compile_options(noexception-test PRIVATE ${PEDANTIC_COMPILE_FLAGS}) endif () # Test that the library compiles without locale. add_library(nolocale-test ../src/format.cc) target_include_directories( nolocale-test PRIVATE ${PROJECT_SOURCE_DIR}/include) target_compile_definitions( nolocale-test PRIVATE FMT_STATIC_THOUSANDS_SEPARATOR=1) endif () # These tests are disabled on Windows because they take too long. # They are disabled on GCC < 4.9 because it can not parse UDLs without # a space after `operator""` but that is an incorrect syntax for any more # modern compiler. if (FMT_PEDANTIC AND NOT WIN32 AND NOT ( CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)) # Test if incorrect API usages produce compilation error. add_test(compile-error-test ${CMAKE_CTEST_COMMAND} --build-and-test "${CMAKE_CURRENT_SOURCE_DIR}/compile-error-test" "${CMAKE_CURRENT_BINARY_DIR}/compile-error-test" --build-generator ${CMAKE_GENERATOR} --build-makeprogram ${CMAKE_MAKE_PROGRAM} --build-options "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}" "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}" "-DCXX_STANDARD_FLAG=${CXX_STANDARD_FLAG}" "-DFMT_DIR=${CMAKE_SOURCE_DIR}") # Test if the targets are found from the build directory. add_test(find-package-test ${CMAKE_CTEST_COMMAND} -C ${CMAKE_BUILD_TYPE} --build-and-test "${CMAKE_CURRENT_SOURCE_DIR}/find-package-test" "${CMAKE_CURRENT_BINARY_DIR}/find-package-test" --build-generator ${CMAKE_GENERATOR} --build-makeprogram ${CMAKE_MAKE_PROGRAM} --build-options "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}" "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}" "-DFMT_DIR=${PROJECT_BINARY_DIR}" "-DPEDANTIC_COMPILE_FLAGS=${PEDANTIC_COMPILE_FLAGS}" "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") # Test if the targets are found when add_subdirectory is used. add_test(add-subdirectory-test ${CMAKE_CTEST_COMMAND} -C ${CMAKE_BUILD_TYPE} --build-and-test "${CMAKE_CURRENT_SOURCE_DIR}/add-subdirectory-test" "${CMAKE_CURRENT_BINARY_DIR}/add-subdirectory-test" --build-generator ${CMAKE_GENERATOR} --build-makeprogram ${CMAKE_MAKE_PROGRAM} --build-options "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}" "-DPEDANTIC_COMPILE_FLAGS=${PEDANTIC_COMPILE_FLAGS}" "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") endif () # This test are disabled on Windows because it is only *NIX issue. if (FMT_PEDANTIC AND NOT WIN32) add_test(static-export-test ${CMAKE_CTEST_COMMAND} -C ${CMAKE_BUILD_TYPE} --build-and-test "${CMAKE_CURRENT_SOURCE_DIR}/static-export-test" "${CMAKE_CURRENT_BINARY_DIR}/static-export-test" --build-generator ${CMAKE_GENERATOR} --build-makeprogram ${CMAKE_MAKE_PROGRAM} --build-options "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}" "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") endif () # Activate optional CUDA tests if CUDA is found. For version selection see # https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#cpp14-language-features if (FMT_CUDA_TEST) if (${CMAKE_VERSION} VERSION_LESS 3.15) find_package(CUDA 9.0) else () include(CheckLanguage) check_language(CUDA) if (CMAKE_CUDA_COMPILER) enable_language(CUDA OPTIONAL) set(CUDA_FOUND TRUE) endif () endif () if (CUDA_FOUND) add_subdirectory(cuda-test) add_test(NAME cuda-test COMMAND fmt-in-cuda-test) endif () endif ()