Apply cmake-format

This commit is contained in:
Victor Zverovich 2026-03-03 13:35:11 -08:00
parent eef9ff4938
commit e090e3ffad
9 changed files with 453 additions and 303 deletions

4
.cmake-format.yaml Normal file
View File

@ -0,0 +1,4 @@
format:
separate_ctrl_name_with_space: true
markup:
enable_markup: false

View File

@ -6,8 +6,8 @@ if (${CMAKE_VERSION} VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif () endif ()
# Determine if fmt is built as a subproject (using add_subdirectory) # Determine if fmt is built as a subproject (using add_subdirectory) or if it is
# or if it is the master project. # the master project.
if (NOT DEFINED FMT_MASTER_PROJECT) if (NOT DEFINED FMT_MASTER_PROJECT)
set(FMT_MASTER_PROJECT OFF) set(FMT_MASTER_PROJECT OFF)
# Checking project name is more reliable than checking source directories. # Checking project name is more reliable than checking source directories.
@ -18,29 +18,34 @@ if (NOT DEFINED FMT_MASTER_PROJECT)
endif () endif ()
# Joins arguments and places the results in ${result_var}. # Joins arguments and places the results in ${result_var}.
function(join result_var) function (join result_var)
set(result "") set(result "")
foreach (arg ${ARGN}) foreach (arg ${ARGN})
set(result "${result}${arg}") set(result "${result}${arg}")
endforeach () endforeach ()
set(${result_var} "${result}" PARENT_SCOPE) set(${result_var}
endfunction() "${result}"
PARENT_SCOPE)
endfunction ()
# Sets a cache variable with a docstring joined from multiple arguments: # Sets a cache variable with a docstring joined from multiple arguments:
# set_verbose(<variable> <value> CACHE <type> <docstring>...) # set_verbose(<variable> <value> CACHE <type> <docstring>...)
# This allows splitting a long docstring for readability. # This allows splitting a long docstring for readability.
function(set_verbose variable value _cache type) function (set_verbose variable value _cache type)
join(doc ${ARGN}) join(doc ${ARGN})
set(${variable} ${value} CACHE ${type} ${doc}) set(${variable}
endfunction() ${value}
CACHE ${type} ${doc})
endfunction ()
# Set the default CMAKE_BUILD_TYPE to Release. # Set the default CMAKE_BUILD_TYPE to Release.
# This should be done before the project command since the latter can set # This should be done before the project command since the latter can set
# CMAKE_BUILD_TYPE itself (it does so for nmake). # CMAKE_BUILD_TYPE itself (it does so for nmake).
if (FMT_MASTER_PROJECT AND NOT CMAKE_BUILD_TYPE) if (FMT_MASTER_PROJECT AND NOT CMAKE_BUILD_TYPE)
set_verbose(CMAKE_BUILD_TYPE Release CACHE STRING set_verbose(
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or " CMAKE_BUILD_TYPE Release CACHE STRING
"CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.") "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or "
"CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
endif () endif ()
project(FMT CXX) project(FMT CXX)
@ -48,16 +53,16 @@ project(FMT CXX)
# Determine support for the C++ module scanning. # Determine support for the C++ module scanning.
# Requires C++20, CMake >= 3.28 and (Ninja >= 1.11 OR Visual Studio >= 17.4). # Requires C++20, CMake >= 3.28 and (Ninja >= 1.11 OR Visual Studio >= 17.4).
set(FMT_USE_CMAKE_MODULES FALSE) set(FMT_USE_CMAKE_MODULES FALSE)
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.28 AND if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.28 AND CMAKE_CXX_STANDARD
CMAKE_CXX_STANDARD GREATER_EQUAL 20) GREATER_EQUAL 20)
if (CMAKE_GENERATOR STREQUAL "Ninja") if (CMAKE_GENERATOR STREQUAL "Ninja")
execute_process(COMMAND "${CMAKE_MAKE_PROGRAM}" "--version" execute_process(COMMAND "${CMAKE_MAKE_PROGRAM}" "--version"
OUTPUT_VARIABLE NINJA_VERSION) OUTPUT_VARIABLE NINJA_VERSION)
if (NINJA_VERSION VERSION_GREATER_EQUAL 1.11) if (NINJA_VERSION VERSION_GREATER_EQUAL 1.11)
set(FMT_USE_CMAKE_MODULES TRUE) set(FMT_USE_CMAKE_MODULES TRUE)
endif () endif ()
elseif (CMAKE_GENERATOR MATCHES "^Visual Studio" AND elseif (CMAKE_GENERATOR MATCHES "^Visual Studio" AND MSVC_VERSION
MSVC_VERSION GREATER_EQUAL 1934) GREATER_EQUAL 1934)
set(FMT_USE_CMAKE_MODULES TRUE) set(FMT_USE_CMAKE_MODULES TRUE)
endif () endif ()
endif () endif ()
@ -82,11 +87,14 @@ endif ()
include(GNUInstallDirs) # CMAKE_INSTALL_INCLUDEDIR include(GNUInstallDirs) # CMAKE_INSTALL_INCLUDEDIR
set_verbose(FMT_INC_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE STRING set_verbose(
"Installation directory for include files, a relative path that " FMT_INC_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE STRING
"will be joined with ${CMAKE_INSTALL_PREFIX} or an absolute path.") "Installation directory for include files, a relative path that "
"will be joined with ${CMAKE_INSTALL_PREFIX} or an absolute path.")
set(FMT_DEBUG_POSTFIX d CACHE STRING "Debug library postfix.") set(FMT_DEBUG_POSTFIX
d
CACHE STRING "Debug library postfix.")
# Get version from base.h. # Get version from base.h.
file(READ include/fmt/base.h base_h) file(READ include/fmt/base.h base_h)
@ -98,7 +106,7 @@ math(EXPR CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
math(EXPR CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2}) math(EXPR CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
math(EXPR CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3}) math(EXPR CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3})
join(FMT_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}. join(FMT_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.
${CPACK_PACKAGE_VERSION_PATCH}) ${CPACK_PACKAGE_VERSION_PATCH})
message(STATUS "{fmt} version: ${FMT_VERSION}") message(STATUS "{fmt} version: ${FMT_VERSION}")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
@ -115,56 +123,82 @@ include(JoinPaths)
if (FMT_MASTER_PROJECT AND NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET) if (FMT_MASTER_PROJECT AND NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET)
set_verbose(CMAKE_CXX_VISIBILITY_PRESET hidden CACHE STRING set_verbose(CMAKE_CXX_VISIBILITY_PRESET hidden CACHE STRING
"Preset for the export of private symbols.") "Preset for the export of private symbols.")
set_property(CACHE CMAKE_CXX_VISIBILITY_PRESET PROPERTY STRINGS set_property(CACHE CMAKE_CXX_VISIBILITY_PRESET PROPERTY STRINGS hidden
hidden default) default)
endif () endif ()
if (FMT_MASTER_PROJECT AND NOT DEFINED CMAKE_VISIBILITY_INLINES_HIDDEN) if (FMT_MASTER_PROJECT AND NOT DEFINED CMAKE_VISIBILITY_INLINES_HIDDEN)
set_verbose(CMAKE_VISIBILITY_INLINES_HIDDEN ON CACHE BOOL set_verbose(
"Whether to add a compile flag to hide symbols of inline " CMAKE_VISIBILITY_INLINES_HIDDEN ON CACHE BOOL
"functions.") "Whether to add a compile flag to hide symbols of inline " "functions.")
endif () endif ()
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(PEDANTIC_COMPILE_FLAGS -pedantic-errors -Wall -Wextra -pedantic set(PEDANTIC_COMPILE_FLAGS
-Wold-style-cast -Wundef -pedantic-errors
-Wredundant-decls -Wwrite-strings -Wpointer-arith -Wall
-Wcast-qual -Wformat=2 -Wmissing-include-dirs -Wextra
-pedantic
-Wold-style-cast
-Wundef
-Wredundant-decls
-Wwrite-strings
-Wpointer-arith
-Wcast-qual
-Wformat=2
-Wmissing-include-dirs
-Wcast-align -Wcast-align
-Wctor-dtor-privacy -Wdisabled-optimization -Wctor-dtor-privacy
-Winvalid-pch -Woverloaded-virtual -Wdisabled-optimization
-Wconversion -Wundef -Winvalid-pch
-Wno-ctor-dtor-privacy -Wno-format-nonliteral) -Woverloaded-virtual
-Wconversion
-Wundef
-Wno-ctor-dtor-privacy
-Wno-format-nonliteral)
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wno-dangling-else
-Wno-dangling-else -Wno-unused-local-typedefs) -Wno-unused-local-typedefs)
endif () endif ()
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wdouble-promotion set(PEDANTIC_COMPILE_FLAGS
-Wtrampolines -Wzero-as-null-pointer-constant -Wuseless-cast ${PEDANTIC_COMPILE_FLAGS}
-Wvector-operation-performance -Wsized-deallocation -Wshadow) -Wdouble-promotion
-Wtrampolines
-Wzero-as-null-pointer-constant
-Wuseless-cast
-Wvector-operation-performance
-Wsized-deallocation
-Wshadow)
endif () endif ()
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0) if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wshift-overflow=2 set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wshift-overflow=2
-Wduplicated-cond) -Wduplicated-cond)
# Workaround for GCC regression # Workaround for GCC 12-15 regression:
# [12/13/14/15 regression] New (since gcc 12) false positive null-dereference in vector.resize # a false positive null-dereference in vector.resize
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108860 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108860.
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnull-dereference) set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnull-dereference)
endif () endif ()
endif () endif ()
set(WERROR_FLAG -Werror) set(WERROR_FLAG -Werror)
endif () endif ()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -pedantic -Wconversion -Wundef set(PEDANTIC_COMPILE_FLAGS
-Wdeprecated -Wweak-vtables -Wshadow -Wall
-Wextra
-pedantic
-Wconversion
-Wundef
-Wdeprecated
-Wweak-vtables
-Wshadow
-Wno-gnu-zero-variadic-macro-arguments) -Wno-gnu-zero-variadic-macro-arguments)
check_cxx_compiler_flag(-Wzero-as-null-pointer-constant HAS_NULLPTR_WARNING) check_cxx_compiler_flag(-Wzero-as-null-pointer-constant HAS_NULLPTR_WARNING)
if (HAS_NULLPTR_WARNING) if (HAS_NULLPTR_WARNING)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS}
-Wzero-as-null-pointer-constant) -Wzero-as-null-pointer-constant)
endif () endif ()
set(WERROR_FLAG -Werror) set(WERROR_FLAG -Werror)
endif () endif ()
@ -187,18 +221,17 @@ if (FMT_MASTER_PROJECT AND CMAKE_GENERATOR MATCHES "Visual Studio")
join(netfxpath join(netfxpath
"C:\\Program Files\\Reference Assemblies\\Microsoft\\Framework\\" "C:\\Program Files\\Reference Assemblies\\Microsoft\\Framework\\"
".NETFramework\\v4.0") ".NETFramework\\v4.0")
file(WRITE run-msbuild.bat " file(WRITE run-msbuild.bat "${MSBUILD_SETUP}
${MSBUILD_SETUP}
${CMAKE_MAKE_PROGRAM} -p:FrameworkPathOverride=\"${netfxpath}\" %*") ${CMAKE_MAKE_PROGRAM} -p:FrameworkPathOverride=\"${netfxpath}\" %*")
endif () endif ()
# Sets up a top-level fmt target. Targets that depend on other top-level targets # Sets up a top-level fmt target. Targets that depend on other top-level targets
# should call this because they'll automatically get the required properties. # should call this because they'll automatically get the required properties.
function(setup_target target kind) function (setup_target target kind)
add_library(fmt::${target} ALIAS ${target}) add_library(fmt::${target} ALIAS ${target})
target_include_directories(${target} target_include_directories(
${FMT_SYSTEM_HEADERS_ATTRIBUTE} BEFORE ${kind} ${target} ${FMT_SYSTEM_HEADERS_ATTRIBUTE} BEFORE ${kind}
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${FMT_INC_DIR}>) $<INSTALL_INTERFACE:${FMT_INC_DIR}>)
@ -206,23 +239,39 @@ function(setup_target target kind)
# Unicode is always supported on compilers other than MSVC. # Unicode is always supported on compilers other than MSVC.
elseif (FMT_UNICODE) elseif (FMT_UNICODE)
# Unicode support requires compiling with /utf-8. # Unicode support requires compiling with /utf-8.
target_compile_options(${target} ${kind} target_compile_options(
${target} ${kind}
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>:/utf-8>) $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>:/utf-8>)
else () else ()
target_compile_definitions(${target} ${kind} FMT_UNICODE=0) target_compile_definitions(${target} ${kind} FMT_UNICODE=0)
endif () endif ()
set_target_properties(${target} PROPERTIES set_target_properties(
VERSION ${FMT_VERSION} ${target}
SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR} PROPERTIES VERSION ${FMT_VERSION}
DEBUG_POSTFIX "${FMT_DEBUG_POSTFIX}") SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR}
endfunction() DEBUG_POSTFIX "${FMT_DEBUG_POSTFIX}")
endfunction ()
set(FMT_HEADERS) set(FMT_HEADERS)
foreach (header args.h base.h chrono.h color.h compile.h core.h format.h foreach (
format-inl.h os.h ostream.h printf.h ranges.h std.h xchar.h) header
args.h
base.h
chrono.h
color.h
compile.h
core.h
format.h
format-inl.h
os.h
ostream.h
printf.h
ranges.h
std.h
xchar.h)
set(FMT_HEADERS ${FMT_HEADERS} include/fmt/${header}) set(FMT_HEADERS ${FMT_HEADERS} include/fmt/${header})
endforeach() endforeach ()
# Add the main fmt library. # Add the main fmt library.
add_library(fmt src/format.cc ${FMT_HEADERS} README.md ChangeLog.md) add_library(fmt src/format.cc ${FMT_HEADERS} README.md ChangeLog.md)
@ -256,7 +305,10 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
endif () endif ()
if (BUILD_SHARED_LIBS) if (BUILD_SHARED_LIBS)
target_compile_definitions(fmt PRIVATE FMT_LIB_EXPORT INTERFACE FMT_SHARED) target_compile_definitions(
fmt
PRIVATE FMT_LIB_EXPORT
INTERFACE FMT_SHARED)
endif () endif ()
if (FMT_SAFE_DURATION_CAST) if (FMT_SAFE_DURATION_CAST)
target_compile_definitions(fmt PUBLIC FMT_SAFE_DURATION_CAST) target_compile_definitions(fmt PUBLIC FMT_SAFE_DURATION_CAST)
@ -268,7 +320,7 @@ include(CMakeParseArguments)
# #
# Usage: # Usage:
# add_module_library(<name> [sources...] [USE_CMAKE_MODULES TRUE]) # add_module_library(<name> [sources...] [USE_CMAKE_MODULES TRUE])
function(add_module_library name) function (add_module_library name)
cmake_parse_arguments(AML "" "USE_CMAKE_MODULES" "" ${ARGN}) cmake_parse_arguments(AML "" "USE_CMAKE_MODULES" "" ${ARGN})
set(sources ${AML_UNPARSED_ARGUMENTS}) set(sources ${AML_UNPARSED_ARGUMENTS})
@ -282,7 +334,8 @@ function(add_module_library name)
if (NOT CMAKE_GENERATOR STREQUAL "Ninja") if (NOT CMAKE_GENERATOR STREQUAL "Ninja")
set(BMI_DIR "${CMAKE_CURRENT_BINARY_DIR}") set(BMI_DIR "${CMAKE_CURRENT_BINARY_DIR}")
file(TO_NATIVE_PATH "${BMI_DIR}/${name}.ifc" BMI) file(TO_NATIVE_PATH "${BMI_DIR}/${name}.ifc" BMI)
target_compile_options(${name} target_compile_options(
${name}
PRIVATE /interface /ifcOutput ${BMI} PRIVATE /interface /ifcOutput ${BMI}
INTERFACE /reference fmt=${BMI}) INTERFACE /reference fmt=${BMI})
set_target_properties(${name} PROPERTIES ADDITIONAL_CLEAN_FILES ${BMI}) set_target_properties(${name} PROPERTIES ADDITIONAL_CLEAN_FILES ${BMI})
@ -291,9 +344,9 @@ function(add_module_library name)
endif () endif ()
if (${AML_USE_CMAKE_MODULES}) if (${AML_USE_CMAKE_MODULES})
target_sources(${name} PUBLIC FILE_SET fmt TYPE CXX_MODULES target_sources(${name} PUBLIC FILE_SET fmt TYPE CXX_MODULES FILES
FILES ${sources}) ${sources})
return () return()
endif () endif ()
if (CMAKE_COMPILER_IS_GNUCXX) if (CMAKE_COMPILER_IS_GNUCXX)
@ -318,10 +371,10 @@ function(add_module_library name)
set(pcms ${pcms} ${CMAKE_CURRENT_BINARY_DIR}/${pcm}) set(pcms ${pcms} ${CMAKE_CURRENT_BINARY_DIR}/${pcm})
add_custom_command( add_custom_command(
OUTPUT ${pcm} OUTPUT ${pcm}
COMMAND ${CMAKE_CXX_COMPILER} COMMAND
-std=c++${std} -x c++-module --precompile -c ${CMAKE_CXX_COMPILER} -std=c++${std} -x c++-module --precompile -c -o
-o ${pcm} ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${pcm} ${CMAKE_CURRENT_SOURCE_DIR}/${src}
"-I$<JOIN:$<TARGET_PROPERTY:${name},INCLUDE_DIRECTORIES>,;-I>" "-I$<JOIN:$<TARGET_PROPERTY:${name},INCLUDE_DIRECTORIES>,;-I>"
# Required by the -I generator expression above. # Required by the -I generator expression above.
COMMAND_EXPAND_LISTS COMMAND_EXPAND_LISTS
DEPENDS ${src}) DEPENDS ${src})
@ -342,11 +395,11 @@ function(add_module_library name)
endforeach () endforeach ()
endif () endif ()
target_sources(${name} PRIVATE ${sources}) target_sources(${name} PRIVATE ${sources})
endfunction() endfunction ()
if (FMT_MODULE) if (FMT_MODULE)
add_module_library(fmt-module src/fmt.cc add_module_library(fmt-module src/fmt.cc USE_CMAKE_MODULES
USE_CMAKE_MODULES ${FMT_USE_CMAKE_MODULES}) ${FMT_USE_CMAKE_MODULES})
setup_target(fmt-module PUBLIC) setup_target(fmt-module PUBLIC)
endif () endif ()
@ -367,23 +420,32 @@ add_library(fmt::fmt-c ALIAS fmt-c)
# Install targets. # Install targets.
if (FMT_INSTALL) if (FMT_INSTALL)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
set_verbose(FMT_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/fmt CACHE STRING set_verbose(
"Installation directory for cmake files, a relative path that " FMT_CMAKE_DIR
"will be joined with ${CMAKE_INSTALL_PREFIX} or an absolute " ${CMAKE_INSTALL_LIBDIR}/cmake/fmt
"path.") CACHE
STRING
"Installation directory for cmake files, a relative path that "
"will be joined with ${CMAKE_INSTALL_PREFIX} or an absolute "
"path.")
set(version_config ${PROJECT_BINARY_DIR}/fmt-config-version.cmake) set(version_config ${PROJECT_BINARY_DIR}/fmt-config-version.cmake)
set(project_config ${PROJECT_BINARY_DIR}/fmt-config.cmake) set(project_config ${PROJECT_BINARY_DIR}/fmt-config.cmake)
set(pkgconfig ${PROJECT_BINARY_DIR}/fmt.pc) set(pkgconfig ${PROJECT_BINARY_DIR}/fmt.pc)
set(targets_export_name fmt-targets) set(targets_export_name fmt-targets)
set_verbose(FMT_LIB_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING set_verbose(
"Installation directory for libraries, a relative path that " FMT_LIB_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING
"will be joined to ${CMAKE_INSTALL_PREFIX} or an absolute path.") "Installation directory for libraries, a relative path that "
"will be joined to ${CMAKE_INSTALL_PREFIX} or an absolute path.")
set_verbose(FMT_PKGCONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig CACHE STRING set_verbose(
"Installation directory for pkgconfig (.pc) files, a relative " FMT_PKGCONFIG_DIR
"path that will be joined with ${CMAKE_INSTALL_PREFIX} or an " ${CMAKE_INSTALL_LIBDIR}/pkgconfig
"absolute path.") CACHE
STRING
"Installation directory for pkgconfig (.pc) files, a relative "
"path that will be joined with ${CMAKE_INSTALL_PREFIX} or an "
"absolute path.")
# Generate the version, config and target files into the build directory. # Generate the version, config and target files into the build directory.
write_basic_package_version_file( write_basic_package_version_file(
@ -394,13 +456,10 @@ if (FMT_INSTALL)
join_paths(libdir_for_pc_file "\${exec_prefix}" "${FMT_LIB_DIR}") join_paths(libdir_for_pc_file "\${exec_prefix}" "${FMT_LIB_DIR}")
join_paths(includedir_for_pc_file "\${prefix}" "${FMT_INC_DIR}") join_paths(includedir_for_pc_file "\${prefix}" "${FMT_INC_DIR}")
configure_file( configure_file("${PROJECT_SOURCE_DIR}/support/cmake/fmt.pc.in" "${pkgconfig}"
"${PROJECT_SOURCE_DIR}/support/cmake/fmt.pc.in" @ONLY)
"${pkgconfig}"
@ONLY)
configure_package_config_file( configure_package_config_file(
${PROJECT_SOURCE_DIR}/support/cmake/fmt-config.cmake.in ${PROJECT_SOURCE_DIR}/support/cmake/fmt-config.cmake.in ${project_config}
${project_config}
INSTALL_DESTINATION ${FMT_CMAKE_DIR}) INSTALL_DESTINATION ${FMT_CMAKE_DIR})
set(INSTALL_TARGETS fmt fmt-header-only fmt-c) set(INSTALL_TARGETS fmt fmt-header-only fmt-c)
@ -413,68 +472,75 @@ if (FMT_INSTALL)
endif () endif ()
# Install the library and headers. # Install the library and headers.
install(TARGETS ${INSTALL_TARGETS} install(
COMPONENT fmt_core TARGETS ${INSTALL_TARGETS}
EXPORT ${targets_export_name} COMPONENT fmt_core
LIBRARY DESTINATION ${FMT_LIB_DIR} EXPORT ${targets_export_name}
ARCHIVE DESTINATION ${FMT_LIB_DIR} LIBRARY DESTINATION ${FMT_LIB_DIR}
PUBLIC_HEADER DESTINATION ${FMT_INC_DIR}/fmt ARCHIVE DESTINATION ${FMT_LIB_DIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} PUBLIC_HEADER DESTINATION ${FMT_INC_DIR}/fmt
${INSTALL_FILE_SET}) RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ${INSTALL_FILE_SET})
# Use a namespace because CMake provides better diagnostics for namespaced # Use a namespace because CMake provides better diagnostics for namespaced
# imported targets. # imported targets.
export(TARGETS ${INSTALL_TARGETS} NAMESPACE fmt:: export(
FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake) TARGETS ${INSTALL_TARGETS}
NAMESPACE fmt::
FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
# Install version, config and target files. # Install version, config and target files.
install(FILES ${project_config} ${version_config} install(
DESTINATION ${FMT_CMAKE_DIR} FILES ${project_config} ${version_config}
COMPONENT fmt_core) DESTINATION ${FMT_CMAKE_DIR}
install(EXPORT ${targets_export_name} DESTINATION ${FMT_CMAKE_DIR} COMPONENT fmt_core)
NAMESPACE fmt:: install(
COMPONENT fmt_core) EXPORT ${targets_export_name}
DESTINATION ${FMT_CMAKE_DIR}
NAMESPACE fmt::
COMPONENT fmt_core)
install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}" install(
COMPONENT fmt_core) FILES "${pkgconfig}"
DESTINATION "${FMT_PKGCONFIG_DIR}"
COMPONENT fmt_core)
endif () endif ()
function(add_doc_target) function (add_doc_target)
find_program(DOXYGEN doxygen find_program(DOXYGEN doxygen PATHS "$ENV{ProgramFiles}/doxygen/bin"
PATHS "$ENV{ProgramFiles}/doxygen/bin" "$ENV{ProgramFiles\(x86\)}/doxygen/bin")
"$ENV{ProgramFiles\(x86\)}/doxygen/bin")
if (NOT DOXYGEN) if (NOT DOXYGEN)
message(STATUS "Target 'doc' disabled because doxygen not found") message(STATUS "Target 'doc' disabled because doxygen not found")
return () return()
endif () endif ()
find_program(MKDOCS mkdocs) find_program(MKDOCS mkdocs)
if (NOT MKDOCS) if (NOT MKDOCS)
message(STATUS "Target 'doc' disabled because mkdocs not found") message(STATUS "Target 'doc' disabled because mkdocs not found")
return () return()
endif () endif ()
set(sources ) set(sources)
foreach (source api.md index.md syntax.md get-started.md fmt.css fmt.js) foreach (source api.md index.md syntax.md get-started.md fmt.css fmt.js)
set(sources ${sources} doc/${source}) set(sources ${sources} doc/${source})
endforeach() endforeach ()
add_custom_target( add_custom_target(
doc doc
COMMAND COMMAND
${CMAKE_COMMAND} ${CMAKE_COMMAND} -E env
-E env PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}/support/python PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}/support/python ${MKDOCS} build -f
${MKDOCS} build -f ${CMAKE_CURRENT_SOURCE_DIR}/support/mkdocs.yml ${CMAKE_CURRENT_SOURCE_DIR}/support/mkdocs.yml
# MkDocs requires the site dir to be outside of the doc dir. # MkDocs requires the site dir to be outside of the doc dir.
--site-dir ${CMAKE_CURRENT_BINARY_DIR}/doc-html --site-dir ${CMAKE_CURRENT_BINARY_DIR}/doc-html --no-directory-urls
--no-directory-urls
SOURCES ${sources}) SOURCES ${sources})
include(GNUInstallDirs) include(GNUInstallDirs)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc-html/ install(
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/fmt DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc-html/
COMPONENT fmt_doc OPTIONAL) DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/fmt
endfunction() COMPONENT fmt_doc
OPTIONAL)
endfunction ()
if (FMT_DOC) if (FMT_DOC)
add_doc_target() add_doc_target()
@ -500,7 +566,7 @@ endif ()
set(gitignore ${PROJECT_SOURCE_DIR}/.gitignore) set(gitignore ${PROJECT_SOURCE_DIR}/.gitignore)
if (FMT_MASTER_PROJECT AND EXISTS ${gitignore}) if (FMT_MASTER_PROJECT AND EXISTS ${gitignore})
# Get the list of ignored files from .gitignore. # Get the list of ignored files from .gitignore.
file (STRINGS ${gitignore} lines) file(STRINGS ${gitignore} lines)
list(REMOVE_ITEM lines /doc/html) list(REMOVE_ITEM lines /doc/html)
foreach (line ${lines}) foreach (line ${lines})
string(REPLACE "." "[.]" line "${line}") string(REPLACE "." "[.]" line "${line}")

View File

@ -1,7 +1,11 @@
# A CMake script to find SetEnv.cmd. # A CMake script to find SetEnv.cmd.
find_program(WINSDK_SETENV NAMES SetEnv.cmd find_program(
PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]/bin") WINSDK_SETENV
NAMES SetEnv.cmd
PATHS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]/bin"
)
if (WINSDK_SETENV AND PRINT_PATH) if (WINSDK_SETENV AND PRINT_PATH)
execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${WINSDK_SETENV}") execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${WINSDK_SETENV}")
endif () endif ()

View File

@ -1,26 +1,28 @@
# This module provides function for joining paths # This module provides function for joining paths known from from most languages
# known from from most languages
# #
# Original license: # Original license:
# SPDX-License-Identifier: (MIT OR CC0-1.0) # SPDX-License-Identifier: (MIT OR CC0-1.0)
# Explicit permission given to distribute this module under # Explicit permission given to distribute this module under the terms of the
# the terms of the project as described in /LICENSE.rst. # project as described in /LICENSE.md.
# Copyright 2020 Jan Tojnar # Copyright 2020 Jan Tojnar
# https://github.com/jtojnar/cmake-snips # https://github.com/jtojnar/cmake-snips
# #
# Modelled after Pythons os.path.join # Modelled after Pythons os.path.join
# https://docs.python.org/3.7/library/os.path.html#os.path.join # https://docs.python.org/3.7/library/os.path.html#os.path.join
# Windows not supported # Windows not supported
function(join_paths joined_path first_path_segment)
set(temp_path "${first_path_segment}") function (join_paths joined_path first_path_segment)
foreach(current_segment IN LISTS ARGN) set(temp_path "${first_path_segment}")
if(NOT ("${current_segment}" STREQUAL "")) foreach (current_segment IN LISTS ARGN)
if(IS_ABSOLUTE "${current_segment}") if (NOT ("${current_segment}" STREQUAL ""))
set(temp_path "${current_segment}") if (IS_ABSOLUTE "${current_segment}")
else() set(temp_path "${current_segment}")
set(temp_path "${temp_path}/${current_segment}") else ()
endif() set(temp_path "${temp_path}/${current_segment}")
endif() endif ()
endforeach() endif ()
set(${joined_path} "${temp_path}" PARENT_SCOPE) endforeach ()
endfunction() set(${joined_path}
"${temp_path}"
PARENT_SCOPE)
endfunction ()

View File

@ -2,13 +2,13 @@ add_subdirectory(gtest)
set(TEST_MAIN_SRC test-main.cc gtest-extra.cc gtest-extra.h util.cc) set(TEST_MAIN_SRC test-main.cc gtest-extra.cc gtest-extra.h util.cc)
add_library(test-main STATIC ${TEST_MAIN_SRC}) add_library(test-main STATIC ${TEST_MAIN_SRC})
target_include_directories(test-main PUBLIC target_include_directories(
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>) test-main PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
target_link_libraries(test-main gtest fmt) target_link_libraries(test-main gtest fmt)
# Adds a test. # Adds a test.
# Usage: add_fmt_test(name srcs...) # Usage: add_fmt_test(name srcs...)
function(add_fmt_test name) function (add_fmt_test name)
cmake_parse_arguments(ADD_FMT_TEST "HEADER_ONLY;MODULE" "" "" ${ARGN}) cmake_parse_arguments(ADD_FMT_TEST "HEADER_ONLY;MODULE" "" "" ${ARGN})
set(sources ${name}.cc ${ADD_FMT_TEST_UNPARSED_ARGUMENTS}) set(sources ${name}.cc ${ADD_FMT_TEST_UNPARSED_ARGUMENTS})
@ -38,7 +38,7 @@ function(add_fmt_test name)
target_compile_options(${name} PRIVATE ${WERROR_FLAG}) target_compile_options(${name} PRIVATE ${WERROR_FLAG})
endif () endif ()
add_test(NAME ${name} COMMAND ${name}) add_test(NAME ${name} COMMAND ${name})
endfunction() endfunction ()
add_fmt_test(args-test) add_fmt_test(args-test)
add_fmt_test(base-test) add_fmt_test(base-test)
@ -60,10 +60,10 @@ add_fmt_test(ranges-test ranges-odr-test.cc)
add_fmt_test(no-builtin-types-test HEADER_ONLY) add_fmt_test(no-builtin-types-test HEADER_ONLY)
add_fmt_test(scan-test HEADER_ONLY) add_fmt_test(scan-test HEADER_ONLY)
add_fmt_test(std-test) add_fmt_test(std-test)
try_compile(compile_result_unused try_compile(
${CMAKE_CURRENT_BINARY_DIR} compile_result_unused ${CMAKE_CURRENT_BINARY_DIR}
SOURCES ${CMAKE_CURRENT_LIST_DIR}/detect-stdfs.cc SOURCES ${CMAKE_CURRENT_LIST_DIR}/detect-stdfs.cc
OUTPUT_VARIABLE RAWOUTPUT) OUTPUT_VARIABLE RAWOUTPUT)
string(REGEX REPLACE ".*libfound \"([^\"]*)\".*" "\\1" STDLIBFS "${RAWOUTPUT}") string(REGEX REPLACE ".*libfound \"([^\"]*)\".*" "\\1" STDLIBFS "${RAWOUTPUT}")
if (STDLIBFS) if (STDLIBFS)
target_link_libraries(std-test ${STDLIBFS}) target_link_libraries(std-test ${STDLIBFS})
@ -74,8 +74,8 @@ if (MSVC)
endif () endif ()
add_fmt_test(xchar-test) add_fmt_test(xchar-test)
add_fmt_test(enforce-checks-test) add_fmt_test(enforce-checks-test)
target_compile_definitions(enforce-checks-test PRIVATE target_compile_definitions(enforce-checks-test
-DFMT_ENFORCE_COMPILE_STRING) PRIVATE -DFMT_ENFORCE_COMPILE_STRING)
add_executable(perf-sanity perf-sanity.cc) add_executable(perf-sanity perf-sanity.cc)
target_link_libraries(perf-sanity fmt::fmt) target_link_libraries(perf-sanity fmt::fmt)
@ -88,20 +88,20 @@ endif ()
if (NOT DEFINED MSVC_STATIC_RUNTIME AND MSVC) if (NOT DEFINED MSVC_STATIC_RUNTIME AND MSVC)
foreach (flag_var foreach (flag_var
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if (${flag_var} MATCHES "^(/|-)(MT|MTd)") if (${flag_var} MATCHES "^(/|-)(MT|MTd)")
set(MSVC_STATIC_RUNTIME ON) set(MSVC_STATIC_RUNTIME ON)
break() break()
endif () endif ()
endforeach () endforeach ()
endif () endif ()
if (NOT MSVC_STATIC_RUNTIME) if (NOT MSVC_STATIC_RUNTIME)
add_executable(posix-mock-test add_executable(posix-mock-test posix-mock-test.cc ../src/format.cc
posix-mock-test.cc ../src/format.cc ${TEST_MAIN_SRC}) ${TEST_MAIN_SRC})
target_include_directories( target_include_directories(posix-mock-test
posix-mock-test PRIVATE ${PROJECT_SOURCE_DIR}/include) PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(posix-mock-test gtest) target_link_libraries(posix-mock-test gtest)
if (FMT_PEDANTIC) if (FMT_PEDANTIC)
target_compile_options(posix-mock-test PRIVATE ${PEDANTIC_COMPILE_FLAGS}) target_compile_options(posix-mock-test PRIVATE ${PEDANTIC_COMPILE_FLAGS})
@ -123,34 +123,38 @@ if (FMT_PEDANTIC)
endif () endif ()
if (HAVE_FNO_EXCEPTIONS_FLAG) if (HAVE_FNO_EXCEPTIONS_FLAG)
add_library(noexception-test ../src/format.cc noexception-test.cc) add_library(noexception-test ../src/format.cc noexception-test.cc)
target_include_directories( target_include_directories(noexception-test
noexception-test PRIVATE ${PROJECT_SOURCE_DIR}/include) PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_compile_options(noexception-test PRIVATE -fno-exceptions) target_compile_options(noexception-test PRIVATE -fno-exceptions)
target_compile_options(noexception-test PRIVATE ${PEDANTIC_COMPILE_FLAGS}) target_compile_options(noexception-test PRIVATE ${PEDANTIC_COMPILE_FLAGS})
endif () endif ()
# Test that the library compiles without locale. # Test that the library compiles without locale.
add_library(nolocale-test ../src/format.cc) add_library(nolocale-test ../src/format.cc)
target_include_directories( target_include_directories(nolocale-test
nolocale-test PRIVATE ${PROJECT_SOURCE_DIR}/include) PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_compile_definitions( target_compile_definitions(nolocale-test
nolocale-test PRIVATE FMT_STATIC_THOUSANDS_SEPARATOR=1) PRIVATE FMT_STATIC_THOUSANDS_SEPARATOR=1)
endif () endif ()
# These tests are disabled on Windows because they take too long. # 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 # They are disabled on GCC < 4.9 because it can't parse UDLs without a space
# a space after `operator""` but that is an incorrect syntax for any more # after operator"" but that is an incorrect syntax for any more modern compiler.
# modern compiler. if (FMT_PEDANTIC
if (FMT_PEDANTIC AND NOT WIN32 AND NOT ( AND NOT WIN32
CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND AND NOT (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION
CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)) VERSION_LESS 4.9))
# Test if incorrect API usages produce compilation error. # Test if incorrect API usages produce compilation error.
add_test(compile-error-test ${CMAKE_CTEST_COMMAND} add_test(
compile-error-test
${CMAKE_CTEST_COMMAND}
--build-and-test --build-and-test
"${CMAKE_CURRENT_SOURCE_DIR}/compile-error-test" "${CMAKE_CURRENT_SOURCE_DIR}/compile-error-test"
"${CMAKE_CURRENT_BINARY_DIR}/compile-error-test" "${CMAKE_CURRENT_BINARY_DIR}/compile-error-test"
--build-generator ${CMAKE_GENERATOR} --build-generator
--build-makeprogram ${CMAKE_MAKE_PROGRAM} ${CMAKE_GENERATOR}
--build-makeprogram
${CMAKE_MAKE_PROGRAM}
--build-options --build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}" "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}"
@ -159,13 +163,18 @@ if (FMT_PEDANTIC AND NOT WIN32 AND NOT (
"-DFMT_DIR=${CMAKE_SOURCE_DIR}") "-DFMT_DIR=${CMAKE_SOURCE_DIR}")
# Test if the targets are found from the build directory. # Test if the targets are found from the build directory.
add_test(find-package-test ${CMAKE_CTEST_COMMAND} add_test(
-C ${CMAKE_BUILD_TYPE} find-package-test
${CMAKE_CTEST_COMMAND}
-C
${CMAKE_BUILD_TYPE}
--build-and-test --build-and-test
"${CMAKE_CURRENT_SOURCE_DIR}/find-package-test" "${CMAKE_CURRENT_SOURCE_DIR}/find-package-test"
"${CMAKE_CURRENT_BINARY_DIR}/find-package-test" "${CMAKE_CURRENT_BINARY_DIR}/find-package-test"
--build-generator ${CMAKE_GENERATOR} --build-generator
--build-makeprogram ${CMAKE_MAKE_PROGRAM} ${CMAKE_GENERATOR}
--build-makeprogram
${CMAKE_MAKE_PROGRAM}
--build-options --build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}" "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}"
@ -175,13 +184,18 @@ if (FMT_PEDANTIC AND NOT WIN32 AND NOT (
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
# Test if the targets are found when add_subdirectory is used. # Test if the targets are found when add_subdirectory is used.
add_test(add-subdirectory-test ${CMAKE_CTEST_COMMAND} add_test(
-C ${CMAKE_BUILD_TYPE} add-subdirectory-test
${CMAKE_CTEST_COMMAND}
-C
${CMAKE_BUILD_TYPE}
--build-and-test --build-and-test
"${CMAKE_CURRENT_SOURCE_DIR}/add-subdirectory-test" "${CMAKE_CURRENT_SOURCE_DIR}/add-subdirectory-test"
"${CMAKE_CURRENT_BINARY_DIR}/add-subdirectory-test" "${CMAKE_CURRENT_BINARY_DIR}/add-subdirectory-test"
--build-generator ${CMAKE_GENERATOR} --build-generator
--build-makeprogram ${CMAKE_MAKE_PROGRAM} ${CMAKE_GENERATOR}
--build-makeprogram
${CMAKE_MAKE_PROGRAM}
--build-options --build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}" "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}"
@ -191,13 +205,18 @@ endif ()
# This test is disabled on Windows because it is POSIX-specific. # This test is disabled on Windows because it is POSIX-specific.
if (FMT_PEDANTIC AND NOT WIN32) if (FMT_PEDANTIC AND NOT WIN32)
add_test(static-export-test ${CMAKE_CTEST_COMMAND} add_test(
-C ${CMAKE_BUILD_TYPE} static-export-test
${CMAKE_CTEST_COMMAND}
-C
${CMAKE_BUILD_TYPE}
--build-and-test --build-and-test
"${CMAKE_CURRENT_SOURCE_DIR}/static-export-test" "${CMAKE_CURRENT_SOURCE_DIR}/static-export-test"
"${CMAKE_CURRENT_BINARY_DIR}/static-export-test" "${CMAKE_CURRENT_BINARY_DIR}/static-export-test"
--build-generator ${CMAKE_GENERATOR} --build-generator
--build-makeprogram ${CMAKE_MAKE_PROGRAM} ${CMAKE_GENERATOR}
--build-makeprogram
${CMAKE_MAKE_PROGRAM}
--build-options --build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}" "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}"

View File

@ -3,7 +3,8 @@
cmake_minimum_required(VERSION 3.8...3.25) cmake_minimum_required(VERSION 3.8...3.25)
project(compile-error-test CXX) project(compile-error-test CXX)
set(fmt_headers " set(fmt_headers
"
#include <fmt/format.h> #include <fmt/format.h>
#include <fmt/xchar.h> #include <fmt/xchar.h>
#include <fmt/ostream.h> #include <fmt/ostream.h>
@ -13,7 +14,7 @@ set(fmt_headers "
set(error_test_names "") set(error_test_names "")
set(non_error_test_content "") set(non_error_test_content "")
# For error tests (we expect them to produce compilation error): # For error tests (we expect them to produce compilation error)
# * adds a name of test into `error_test_names` list # * adds a name of test into `error_test_names` list
# * generates a single source file (with the same name) for each test # * generates a single source file (with the same name) for each test
# For non-error tests (we expect them to compile successfully): # For non-error tests (we expect them to compile successfully):
@ -23,64 +24,74 @@ function (expect_compile name code_fragment)
string(MAKE_C_IDENTIFIER "${name}" test_name) string(MAKE_C_IDENTIFIER "${name}" test_name)
if (EXPECT_COMPILE_ERROR) if (EXPECT_COMPILE_ERROR)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/${test_name}.cc" " file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/${test_name}.cc"
"
${fmt_headers} ${fmt_headers}
void ${test_name}() { void ${test_name}() {
${code_fragment} ${code_fragment}
} }
") ")
set(error_test_names_copy "${error_test_names}") set(error_test_names_copy "${error_test_names}")
list(APPEND error_test_names_copy "${test_name}") list(APPEND error_test_names_copy "${test_name}")
set(error_test_names "${error_test_names_copy}" PARENT_SCOPE) set(error_test_names
else() "${error_test_names_copy}"
set(non_error_test_content " PARENT_SCOPE)
${non_error_test_content} else ()
void ${test_name}() { set(non_error_test_content
${code_fragment} "
}" PARENT_SCOPE) ${non_error_test_content}
endif() void ${test_name}() {
${code_fragment}
}"
PARENT_SCOPE)
endif ()
endfunction () endfunction ()
# Generates a source file for non-error test with `non_error_test_content` and # Generates a source file for non-error test with `non_error_test_content` and
# CMake project file with all error and single non-error test targets. # CMake project file with all error and single non-error test targets.
function (run_tests) function (run_tests)
set(cmake_targets "") set(cmake_targets "")
foreach(test_name IN LISTS error_test_names) foreach (test_name IN LISTS error_test_names)
set(cmake_targets " set(cmake_targets
${cmake_targets} "
add_library(test-${test_name} ${test_name}.cc) ${cmake_targets}
target_link_libraries(test-${test_name} PRIVATE fmt::fmt) add_library(test-${test_name} ${test_name}.cc)
") target_link_libraries(test-${test_name} PRIVATE fmt::fmt)
endforeach() ")
endforeach ()
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/non_error_test.cc" " file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/non_error_test.cc"
"
${fmt_headers} ${fmt_headers}
${non_error_test_content} ${non_error_test_content}
") ")
set(cmake_targets " set(cmake_targets
${cmake_targets} "
add_library(non-error-test non_error_test.cc) ${cmake_targets}
target_link_libraries(non-error-test PRIVATE fmt::fmt) add_library(non-error-test non_error_test.cc)
") target_link_libraries(non-error-test PRIVATE fmt::fmt)
")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/CMakeLists.txt" " file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/CMakeLists.txt"
"
cmake_minimum_required(VERSION 3.8...3.25) cmake_minimum_required(VERSION 3.8...3.25)
project(tests CXX) project(tests CXX)
add_subdirectory(${FMT_DIR} fmt) add_subdirectory(${FMT_DIR} fmt)
${cmake_targets} ${cmake_targets}
") ")
set(build_directory "${CMAKE_CURRENT_BINARY_DIR}/test/build") set(build_directory "${CMAKE_CURRENT_BINARY_DIR}/test/build")
file(MAKE_DIRECTORY "${build_directory}") file(MAKE_DIRECTORY "${build_directory}")
execute_process( execute_process(
COMMAND COMMAND
"${CMAKE_COMMAND}" "${CMAKE_COMMAND}" "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}" "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}"
"-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}" "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}"
"-DCMAKE_GENERATOR=${CMAKE_GENERATOR}" "-DCMAKE_GENERATOR=${CMAKE_GENERATOR}"
"-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}" "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}" "-DFMT_DIR=${FMT_DIR}"
"-DFMT_DIR=${FMT_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}/test" "${CMAKE_CURRENT_BINARY_DIR}/test"
WORKING_DIRECTORY "${build_directory}" WORKING_DIRECTORY "${build_directory}"
RESULT_VARIABLE result_var RESULT_VARIABLE result_var
@ -88,30 +99,32 @@ function (run_tests)
ERROR_VARIABLE output_var) ERROR_VARIABLE output_var)
if (NOT result_var EQUAL 0) if (NOT result_var EQUAL 0)
message(FATAL_ERROR "Unable to configure:\n${output_var}") message(FATAL_ERROR "Unable to configure:\n${output_var}")
endif() endif ()
foreach(test_name IN LISTS error_test_names) foreach (test_name IN LISTS error_test_names)
execute_process( execute_process(
COMMAND COMMAND "${CMAKE_COMMAND}" --build "${build_directory}" --target
"${CMAKE_COMMAND}" --build "${build_directory}" --target "test-${test_name}" "test-${test_name}"
WORKING_DIRECTORY "${build_directory}" WORKING_DIRECTORY "${build_directory}"
RESULT_VARIABLE result_var RESULT_VARIABLE result_var
OUTPUT_VARIABLE output_var OUTPUT_VARIABLE output_var
ERROR_QUIET) ERROR_QUIET)
if (result_var EQUAL 0) if (result_var EQUAL 0)
message(SEND_ERROR "No compile error for \"${test_name}\":\n${output_var}") message(
SEND_ERROR "No compile error for \"${test_name}\":\n${output_var}")
endif () endif ()
endforeach() endforeach ()
execute_process( execute_process(
COMMAND COMMAND "${CMAKE_COMMAND}" --build "${build_directory}" --target
"${CMAKE_COMMAND}" --build "${build_directory}" --target "non-error-test" "non-error-test"
WORKING_DIRECTORY "${build_directory}" WORKING_DIRECTORY "${build_directory}"
RESULT_VARIABLE result_var RESULT_VARIABLE result_var
OUTPUT_VARIABLE output_var OUTPUT_VARIABLE output_var
ERROR_VARIABLE output_var) ERROR_VARIABLE output_var)
if (NOT result_var EQUAL 0) if (NOT result_var EQUAL 0)
message(SEND_ERROR "Compile error for combined non-error test:\n${output_var}") message(
SEND_ERROR "Compile error for combined non-error test:\n${output_var}")
endif () endif ()
endfunction () endfunction ()
@ -120,95 +133,133 @@ expect_compile(check "")
expect_compile(check-error "compilation_error" ERROR) expect_compile(check-error "compilation_error" ERROR)
# Formatting a wide character with a narrow format string is forbidden. # Formatting a wide character with a narrow format string is forbidden.
expect_compile(wide-character-narrow-format-string "fmt::format(L\"{}\", L'a');") expect_compile(wide-character-narrow-format-string
expect_compile(wide-character-narrow-format-string-error "fmt::format(\"{}\", L'a');" ERROR) "fmt::format(L\"{}\", L'a');")
expect_compile(wide-character-narrow-format-string-error
"fmt::format(\"{}\", L'a');" ERROR)
# Formatting a wide string with a narrow format string is forbidden. # Formatting a wide string with a narrow format string is forbidden.
expect_compile(wide-string-narrow-format-string "fmt::format(L\"{}\", L\"foo\");") expect_compile(wide-string-narrow-format-string
expect_compile(wide-string-narrow-format-string-error "fmt::format(\"{}\", L\"foo\");" ERROR) "fmt::format(L\"{}\", L\"foo\");")
expect_compile(wide-string-narrow-format-string-error
"fmt::format(\"{}\", L\"foo\");" ERROR)
# Formatting a narrow string with a wide format string is forbidden because # Formatting a narrow string with a wide format string is forbidden because
# mixing UTF-8 with UTF-16/32 can result in an invalid output. # mixing UTF-8 with UTF-16/32 can result in an invalid output.
expect_compile(narrow-string-wide-format-string "fmt::format(L\"{}\", L\"foo\");") expect_compile(narrow-string-wide-format-string
expect_compile(narrow-string-wide-format-string-error "fmt::format(L\"{}\", \"foo\");" ERROR) "fmt::format(L\"{}\", L\"foo\");")
expect_compile(narrow-string-wide-format-string-error
"fmt::format(L\"{}\", \"foo\");" ERROR)
expect_compile(cast-to-string " expect_compile(
cast-to-string
"
struct S { struct S {
operator std::string() const { return std::string(); } operator std::string() const { return std::string(); }
}; };
fmt::format(\"{}\", std::string(S())); fmt::format(\"{}\", std::string(S()));
") ")
expect_compile(cast-to-string-error " expect_compile(
cast-to-string-error
"
struct S { struct S {
operator std::string() const { return std::string(); } operator std::string() const { return std::string(); }
}; };
fmt::format(\"{}\", S()); fmt::format(\"{}\", S());
" ERROR) "
ERROR)
# Formatting a function # Formatting a function
expect_compile(format-function " expect_compile(
format-function
"
void (*f)(); void (*f)();
fmt::format(\"{}\", fmt::ptr(f)); fmt::format(\"{}\", fmt::ptr(f));
") ")
expect_compile(format-function-error " expect_compile(
format-function-error
"
void (*f)(); void (*f)();
fmt::format(\"{}\", f); fmt::format(\"{}\", f);
" ERROR) "
ERROR)
# Formatting an unformattable argument should always be a compile time error # Formatting an unformattable argument should always be a compile time error
expect_compile(format-lots-of-arguments-with-unformattable " expect_compile(
format-lots-of-arguments-with-unformattable
"
struct E {}; struct E {};
fmt::format(\"\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, E()); fmt::format(\"\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, E());
" ERROR) "
expect_compile(format-lots-of-arguments-with-function " ERROR)
expect_compile(
format-lots-of-arguments-with-function
"
void (*f)(); void (*f)();
fmt::format(\"\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, f); fmt::format(\"\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, f);
" ERROR) "
ERROR)
if (CMAKE_CXX_STANDARD GREATER_EQUAL 20) if (CMAKE_CXX_STANDARD GREATER_EQUAL 20)
# Compile-time argument type check # Compile-time argument type check
expect_compile(format-string-number-spec " expect_compile(
format-string-number-spec
"
#ifdef FMT_HAS_CONSTEVAL #ifdef FMT_HAS_CONSTEVAL
fmt::format(\"{:d}\", 42); fmt::format(\"{:d}\", 42);
#endif #endif
") ")
expect_compile(format-string-number-spec-error " expect_compile(
format-string-number-spec-error
"
#ifdef FMT_HAS_CONSTEVAL #ifdef FMT_HAS_CONSTEVAL
fmt::format(\"{:d}\", \"I am not a number\"); fmt::format(\"{:d}\", \"I am not a number\");
#else #else
#error #error
#endif #endif
" ERROR) "
expect_compile(print-string-number-spec-error " ERROR)
expect_compile(
print-string-number-spec-error
"
#ifdef FMT_HAS_CONSTEVAL #ifdef FMT_HAS_CONSTEVAL
fmt::print(\"{:d}\", \"I am not a number\"); fmt::print(\"{:d}\", \"I am not a number\");
#else #else
#error #error
#endif #endif
" ERROR) "
expect_compile(print-stream-string-number-spec-error " ERROR)
expect_compile(
print-stream-string-number-spec-error
"
#ifdef FMT_HAS_CONSTEVAL #ifdef FMT_HAS_CONSTEVAL
fmt::print(std::cout, \"{:d}\", \"I am not a number\"); fmt::print(std::cout, \"{:d}\", \"I am not a number\");
#else #else
#error #error
#endif #endif
" ERROR) "
ERROR)
# Compile-time argument name check # Compile-time argument name check
expect_compile(format-string-name " expect_compile(
format-string-name
"
#if defined(FMT_HAS_CONSTEVAL) && FMT_USE_NONTYPE_TEMPLATE_ARGS #if defined(FMT_HAS_CONSTEVAL) && FMT_USE_NONTYPE_TEMPLATE_ARGS
using namespace fmt::literals; using namespace fmt::literals;
fmt::print(\"{foo}\", \"foo\"_a=42); fmt::print(\"{foo}\", \"foo\"_a=42);
#endif #endif
") ")
expect_compile(format-string-name-error " expect_compile(
format-string-name-error
"
#if defined(FMT_HAS_CONSTEVAL) && FMT_USE_NONTYPE_TEMPLATE_ARGS #if defined(FMT_HAS_CONSTEVAL) && FMT_USE_NONTYPE_TEMPLATE_ARGS
using namespace fmt::literals; using namespace fmt::literals;
fmt::print(\"{foo}\", \"bar\"_a=42); fmt::print(\"{foo}\", \"bar\"_a=42);
#else #else
#error #error
#endif #endif
" ERROR) "
ERROR)
endif () endif ()
# Run all tests # Run all tests

View File

@ -17,8 +17,8 @@ set(CMAKE_CUDA_STANDARD_REQUIRED 14)
# In this test, we assume that the user is going to compile CUDA source code # In this test, we assume that the user is going to compile CUDA source code
# with some libraries (fmt in this case). # with some libraries (fmt in this case).
# #
# In addition to that, this test invokes both the C++ host compiler and NVCC # In addition to that, this test invokes both the C++ host compiler and NVCC by
# by providing another (non-CUDA) C++ source code. # providing another (non-CUDA) C++ source code.
if (${CMAKE_VERSION} VERSION_LESS 3.15) if (${CMAKE_VERSION} VERSION_LESS 3.15)
# https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html # https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html
list(APPEND CUDA_NVCC_FLAGS "-std=c++14") list(APPEND CUDA_NVCC_FLAGS "-std=c++14")
@ -38,36 +38,40 @@ if (${CMAKE_VERSION} VERSION_LESS 3.15)
# See Also: # See Also:
# https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ # https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
# https://github.com/Microsoft/vscode-cpptools/issues/2595 # https://github.com/Microsoft/vscode-cpptools/issues/2595
target_compile_options(fmt-in-cuda-test PRIVATE /Zc:__cplusplus /permissive-) target_compile_options(fmt-in-cuda-test PRIVATE /Zc:__cplusplus
/permissive-)
endif () endif ()
else() else ()
# now using a "new" way of handling CUDA # now using a "new" way of handling CUDA
add_executable(fmt-in-cuda-test cuda-cpp14.cu cpp14.cc) add_executable(fmt-in-cuda-test cuda-cpp14.cu cpp14.cc)
set_target_properties(fmt-in-cuda-test PROPERTIES CUDA_SEPARABLE_COMPILATION ON) set_target_properties(fmt-in-cuda-test PROPERTIES CUDA_SEPARABLE_COMPILATION
ON)
target_compile_features(fmt-in-cuda-test PRIVATE cxx_std_14) target_compile_features(fmt-in-cuda-test PRIVATE cxx_std_14)
if (MSVC) if (MSVC)
# with MSVC, 'cxx_std_14' will only propagate to the host code (MSVC), but will # with MSVC, 'cxx_std_14' will only propagate to the host code (MSVC), but
# not set __cplusplus correctly anyway, while nvcc will ignore it. # will not set __cplusplus correctly anyway, while nvcc will ignore it. If
# If specified for nvcc on the command line as '-std=c++14' nvcc will emit this # specified for nvcc on the command line as '-std=c++14' nvcc will emit this
# message instead: # message instead: nvcc warning : The -std=c++14 flag is not supported with
# nvcc warning : The -std=c++14 flag is not supported with the configured host # the configured host compiler. Flag will be ignored.
# compiler. Flag will be ignored. set_property(
set_property(SOURCE cuda-cpp14.cu APPEND PROPERTY SOURCE cuda-cpp14.cu
COMPILE_OPTIONS -Xcompiler /std:c++14 -Xcompiler /Zc:__cplusplus) APPEND
set_property(SOURCE cpp14.cc APPEND PROPERTY PROPERTY COMPILE_OPTIONS -Xcompiler /std:c++14 -Xcompiler /Zc:__cplusplus)
COMPILE_OPTIONS /std:c++14 /Zc:__cplusplus) set_property(
endif() SOURCE cpp14.cc
endif() APPEND
PROPERTY COMPILE_OPTIONS /std:c++14 /Zc:__cplusplus)
endif ()
endif ()
get_target_property(IN_USE_CUDA_STANDARD fmt-in-cuda-test CUDA_STANDARD) get_target_property(IN_USE_CUDA_STANDARD fmt-in-cuda-test CUDA_STANDARD)
message(STATUS "cuda_standard: ${IN_USE_CUDA_STANDARD}") message(STATUS "cuda_standard: ${IN_USE_CUDA_STANDARD}")
get_target_property(IN_USE_CUDA_STANDARD_REQUIRED get_target_property(IN_USE_CUDA_STANDARD_REQUIRED fmt-in-cuda-test
fmt-in-cuda-test CUDA_STANDARD_REQUIRED) CUDA_STANDARD_REQUIRED)
message(STATUS "cuda_standard_required: ${IN_USE_CUDA_STANDARD_REQUIRED}") message(STATUS "cuda_standard_required: ${IN_USE_CUDA_STANDARD_REQUIRED}")
# We don't use PUBLIC or other keyword for reasons explained in the # We don't use PUBLIC or other keyword for reasons explained in the
# CUDA_LINK_LIBRARIES_KEYWORD section in # CUDA_LINK_LIBRARIES_KEYWORD section in
# https://cmake.org/cmake/help/latest/module/FindCUDA.html # https://cmake.org/cmake/help/latest/module/FindCUDA.html
target_link_libraries(fmt-in-cuda-test fmt::fmt) target_link_libraries(fmt-in-cuda-test fmt::fmt)

View File

@ -1,5 +1,4 @@
# Copyright (c) 2019, Paul Dreik # Copyright (c) 2019, Paul Dreik
# License: see LICENSE.rst in the fmt root directory
# Link in the main function. Useful for reproducing, kcov, gdb, afl, valgrind. # Link in the main function. Useful for reproducing, kcov, gdb, afl, valgrind.
# (Note that libFuzzer can also reproduce, just pass it the files.) # (Note that libFuzzer can also reproduce, just pass it the files.)
@ -7,11 +6,13 @@ option(FMT_FUZZ_LINKMAIN "Enables the reproduce mode, instead of libFuzzer" On)
# For oss-fuzz - insert $LIB_FUZZING_ENGINE into the link flags, but only for # For oss-fuzz - insert $LIB_FUZZING_ENGINE into the link flags, but only for
# the fuzz targets, otherwise the CMake configuration step fails. # the fuzz targets, otherwise the CMake configuration step fails.
set(FMT_FUZZ_LDFLAGS "" CACHE STRING "LDFLAGS for the fuzz targets") set(FMT_FUZZ_LDFLAGS
""
CACHE STRING "LDFLAGS for the fuzz targets")
# Adds a binary for reproducing, i.e. no fuzzing, just enables replaying data # Adds a binary for reproducing, i.e. no fuzzing, just enables replaying data
# through the fuzzers. # through the fuzzers.
function(add_fuzzer source) function (add_fuzzer source)
get_filename_component(basename ${source} NAME_WE) get_filename_component(basename ${source} NAME_WE)
set(name ${basename}-fuzzer) set(name ${basename}-fuzzer)
add_executable(${name} ${source} fuzzer-common.h) add_executable(${name} ${source} fuzzer-common.h)
@ -23,8 +24,9 @@ function(add_fuzzer source)
target_link_libraries(${name} PRIVATE ${FMT_FUZZ_LDFLAGS}) target_link_libraries(${name} PRIVATE ${FMT_FUZZ_LDFLAGS})
endif () endif ()
target_compile_features(${name} PRIVATE cxx_std_14) target_compile_features(${name} PRIVATE cxx_std_14)
endfunction() endfunction ()
foreach (source chrono-duration.cc chrono-timepoint.cc float.cc named-arg.cc one-arg.cc two-args.cc) foreach (source chrono-duration.cc chrono-timepoint.cc float.cc named-arg.cc
one-arg.cc two-args.cc)
add_fuzzer(${source}) add_fuzzer(${source})
endforeach () endforeach ()

View File

@ -1,12 +1,10 @@
#------------------------------------------------------------------------------ # Compile Google Test ourselves instead of using pre-compiled libraries. See the
# Build the google test library # Google Test FAQ "Why is it not recommended to install a pre-compiled copy of
# Google Test (for example, into /usr/local)?" at
# http://code.google.com/p/googletest/wiki/FAQ for more details.
# Compile Google Test ourselves instead of using pre-compiled libraries. add_library(gtest STATIC gmock-gtest-all.cc gmock/gmock.h gtest/gtest.h
# See the Google Test FAQ "Why is it not recommended to install a gtest/gtest-spi.h)
# pre-compiled copy of Google Test (for example, into /usr/local)?"
# at http://code.google.com/p/googletest/wiki/FAQ for more details.
add_library(gtest STATIC
gmock-gtest-all.cc gmock/gmock.h gtest/gtest.h gtest/gtest-spi.h)
target_compile_definitions(gtest PUBLIC GTEST_HAS_STD_WSTRING=1) target_compile_definitions(gtest PUBLIC GTEST_HAS_STD_WSTRING=1)
target_include_directories(gtest SYSTEM PUBLIC .) target_include_directories(gtest SYSTEM PUBLIC .)
target_compile_features(gtest PUBLIC cxx_std_11) target_compile_features(gtest PUBLIC cxx_std_11)