Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
240 changes: 161 additions & 79 deletions Source/Cmlx/fmt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.8...3.26)
cmake_minimum_required(VERSION 3.8...3.28)

# Fallback for using newer policies on CMake <3.12.
if(${CMAKE_VERSION} VERSION_LESS 3.12)
Expand All @@ -9,7 +9,9 @@ endif()
# the master project.
if(NOT DEFINED FMT_MASTER_PROJECT)
set(FMT_MASTER_PROJECT OFF)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
# NOTE: source vs current_source detection is unreliable this heuristic is
# more generally applicable esp w.r.t FetchContent
if(NOT DEFINED PROJECT_NAME)
set(FMT_MASTER_PROJECT ON)
message(STATUS "CMake version: ${CMAKE_VERSION}")
endif()
Expand All @@ -29,16 +31,25 @@ endfunction()
# DEPRECATED! Should be merged into add_module_library.
function(enable_module target)
if(MSVC)
set(BMI ${CMAKE_CURRENT_BINARY_DIR}/${target}.ifc)
target_compile_options(
${target}
PRIVATE /interface /ifcOutput ${BMI}
INTERFACE /reference fmt=${BMI})
set_target_properties(${target} PROPERTIES ADDITIONAL_CLEAN_FILES ${BMI})
set_source_files_properties(${BMI} PROPERTIES GENERATED ON)
if(NOT CMAKE_GENERATOR STREQUAL "Ninja")
set(BMI_DIR "${CMAKE_CURRENT_BINARY_DIR}")
file(TO_NATIVE_PATH "${BMI_DIR}/${target}.ifc" BMI)
target_compile_options(
${target}
PRIVATE /interface /ifcOutput ${BMI}
INTERFACE /reference fmt=${BMI})
set_target_properties(${target} PROPERTIES ADDITIONAL_CLEAN_FILES ${BMI})
set_source_files_properties(${BMI} PROPERTIES GENERATED ON)
endif()
endif()
endfunction()

set(FMT_USE_CMAKE_MODULES FALSE)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.28 AND CMAKE_GENERATOR STREQUAL
"Ninja")
set(FMT_USE_CMAKE_MODULES TRUE)
endif()

# Adds a library compiled with C++20 module support. `enabled` is a CMake
# variables that specifies if modules are enabled. If modules are disabled
# `add_module_library` falls back to creating a non-modular library.
Expand All @@ -55,6 +66,7 @@ function(add_module_library name)
if(NOT ${${AML_IF}})
# Create a non-modular library.
target_sources(${name} PRIVATE ${AML_FALLBACK})
set_target_properties(${name} PROPERTIES CXX_SCAN_FOR_MODULES OFF)
return()
endif()

Expand All @@ -64,48 +76,54 @@ function(add_module_library name)
target_compile_options(${name} PUBLIC -fmodules-ts)
endif()

# `std` is affected by CMake options and may be higher than C++20.
get_target_property(std ${name} CXX_STANDARD)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(pcms)
foreach(src ${sources})
get_filename_component(pcm ${src} NAME_WE)
set(pcm ${pcm}.pcm)

# Propagate -fmodule-file=*.pcm to targets that link with this library.
target_compile_options(
${name} PUBLIC -fmodule-file=${CMAKE_CURRENT_BINARY_DIR}/${pcm})

# Use an absolute path to prevent target_link_libraries prepending -l to
# it.
set(pcms ${pcms} ${CMAKE_CURRENT_BINARY_DIR}/${pcm})
add_custom_command(
OUTPUT ${pcm}
COMMAND
${CMAKE_CXX_COMPILER} -std=c++${std} -x c++-module --precompile -c -o
${pcm} ${CMAKE_CURRENT_SOURCE_DIR}/${src}
"-I$<JOIN:$<TARGET_PROPERTY:${name},INCLUDE_DIRECTORIES>,;-I>"
# Required by the -I generator expression above.
COMMAND_EXPAND_LISTS
DEPENDS ${src})
endforeach()

# Add .pcm files as sources to make sure they are built before the library.
set(sources)
foreach(pcm ${pcms})
get_filename_component(pcm_we ${pcm} NAME_WE)
set(obj ${pcm_we}.o)
# Use an absolute path to prevent target_link_libraries prepending -l.
set(sources ${sources} ${pcm} ${CMAKE_CURRENT_BINARY_DIR}/${obj})
add_custom_command(
OUTPUT ${obj}
COMMAND ${CMAKE_CXX_COMPILER} $<TARGET_PROPERTY:${name},COMPILE_OPTIONS>
-c -o ${obj} ${pcm}
DEPENDS ${pcm})
endforeach()
if(FMT_USE_CMAKE_MODULES)
target_sources(${name} PUBLIC FILE_SET fmt TYPE CXX_MODULES FILES
${sources})
else()
# `std` is affected by CMake options and may be higher than C++20.
get_target_property(std ${name} CXX_STANDARD)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(pcms)
foreach(src ${sources})
get_filename_component(pcm ${src} NAME_WE)
set(pcm ${pcm}.pcm)

# Propagate -fmodule-file=*.pcm to targets that link with this library.
target_compile_options(
${name} PUBLIC -fmodule-file=${CMAKE_CURRENT_BINARY_DIR}/${pcm})

# Use an absolute path to prevent target_link_libraries prepending -l to
# it.
set(pcms ${pcms} ${CMAKE_CURRENT_BINARY_DIR}/${pcm})
add_custom_command(
OUTPUT ${pcm}
COMMAND
${CMAKE_CXX_COMPILER} -std=c++${std} -x c++-module --precompile -c
-o ${pcm} ${CMAKE_CURRENT_SOURCE_DIR}/${src}
"-I$<JOIN:$<TARGET_PROPERTY:${name},INCLUDE_DIRECTORIES>,;-I>"
# Required by the -I generator expression above.
COMMAND_EXPAND_LISTS
DEPENDS ${src})
endforeach()

# Add .pcm files as sources to make sure they are built before the
# library.
set(sources)
foreach(pcm ${pcms})
get_filename_component(pcm_we ${pcm} NAME_WE)
set(obj ${pcm_we}.o)
# Use an absolute path to prevent target_link_libraries prepending -l.
set(sources ${sources} ${pcm} ${CMAKE_CURRENT_BINARY_DIR}/${obj})
add_custom_command(
OUTPUT ${obj}
COMMAND ${CMAKE_CXX_COMPILER}
$<TARGET_PROPERTY:${name},COMPILE_OPTIONS> -c -o ${obj} ${pcm}
DEPENDS ${pcm})
endforeach()
endif()
target_sources(${name} PRIVATE ${sources})
endif()
target_sources(${name} PRIVATE ${sources})
endfunction()

include(CMakeParseArguments)
Expand Down Expand Up @@ -152,13 +170,14 @@ option(FMT_WERROR "Halt the compilation with an error on compiler warnings."

# Options that control generation of various targets.
option(FMT_DOC "Generate the doc target." ${FMT_MASTER_PROJECT})
option(FMT_INSTALL "Generate the install target." ON)
option(FMT_INSTALL "Generate the install target." ${FMT_MASTER_PROJECT})
option(FMT_TEST "Generate the test target." ${FMT_MASTER_PROJECT})
option(FMT_FUZZ "Generate the fuzz target." OFF)
option(FMT_CUDA_TEST "Generate the cuda-test target." OFF)
option(FMT_OS "Include core requiring OS (Windows/Posix) " ON)
option(FMT_OS "Include OS-specific APIs." ON)
option(FMT_MODULE "Build a module instead of a traditional library." OFF)
option(FMT_SYSTEM_HEADERS "Expose headers with marking them as system." OFF)
option(FMT_UNICODE "Enable Unicode support." ON)

if(FMT_TEST AND FMT_MODULE)
# The tests require {fmt} to be compiled as traditional library
Expand All @@ -173,27 +192,26 @@ if(CMAKE_SYSTEM_NAME STREQUAL "MSDOS")
message(STATUS "MSDOS is incompatible with gtest")
endif()

# Get version from core.h
file(READ include/fmt/core.h core_h)
if(NOT core_h MATCHES "FMT_VERSION ([0-9]+)([0-9][0-9])([0-9][0-9])")
message(FATAL_ERROR "Cannot get FMT_VERSION from core.h.")
# Get version from base.h
file(READ include/fmt/base.h base_h)
if(NOT base_h MATCHES "FMT_VERSION ([0-9]+)([0-9][0-9])([0-9][0-9])")
message(FATAL_ERROR "Cannot get FMT_VERSION from base.h.")
endif()
# Use math to skip leading zeros if any.
math(EXPR CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
math(EXPR CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
math(EXPR CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3})
join(FMT_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.
${CPACK_PACKAGE_VERSION_PATCH})
message(STATUS "Version: ${FMT_VERSION}")
message(STATUS "{fmt} version: ${FMT_VERSION}")

message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")

if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
endif()

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/support/cmake")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/support/cmake")

include(CheckCXXCompilerFlag)
include(JoinPaths)
Expand Down Expand Up @@ -251,7 +269,13 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
endif()
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wshift-overflow=2
-Wnull-dereference -Wduplicated-cond)
-Wduplicated-cond)
# Workaround for GCC regression [12/13/14/15 regression] New (since gcc 12)
# false positive null-dereference in vector.resize
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108860
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnull-dereference)
endif()
endif()
set(WERROR_FLAG -Werror)
endif()
Expand Down Expand Up @@ -311,9 +335,11 @@ function(add_headers VAR)
endfunction()

# Define the fmt library, its includes and the needed defines.
set(FMT_HEADERS)
add_headers(
FMT_HEADERS
args.h
base.h
chrono.h
color.h
compile.h
Expand All @@ -327,9 +353,6 @@ add_headers(
std.h
xchar.h)
set(FMT_SOURCES src/format.cc)
if(FMT_OS)
set(FMT_SOURCES ${FMT_SOURCES} src/os.cc)
endif()

add_module_library(
fmt
Expand All @@ -344,6 +367,10 @@ add_module_library(
add_library(fmt::fmt ALIAS fmt)
if(FMT_MODULE)
enable_module(fmt)
elseif(FMT_OS)
target_sources(fmt PRIVATE src/os.cc)
else()
target_compile_definitions(fmt PRIVATE FMT_OS=0)
endif()

if(FMT_WERROR)
Expand All @@ -360,7 +387,7 @@ else()
endif()

target_include_directories(
fmt ${FMT_SYSTEM_HEADERS_ATTRIBUTE}
fmt ${FMT_SYSTEM_HEADERS_ATTRIBUTE} BEFORE
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${FMT_INC_DIR}>)

Expand Down Expand Up @@ -404,11 +431,24 @@ endif()
add_library(fmt-header-only INTERFACE)
add_library(fmt::fmt-header-only ALIAS fmt-header-only)

if(NOT MSVC)
# Unicode is always supported on compilers other than MSVC.
elseif(FMT_UNICODE)
# Unicode support requires compiling with /utf-8.
target_compile_options(
fmt PUBLIC $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>:/utf-8>)
target_compile_options(
fmt-header-only
INTERFACE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>:/utf-8>)
else()
target_compile_definitions(fmt PUBLIC FMT_UNICODE=0)
endif()

target_compile_definitions(fmt-header-only INTERFACE FMT_HEADER_ONLY=1)
target_compile_features(fmt-header-only INTERFACE cxx_std_11)

target_include_directories(
fmt-header-only ${FMT_SYSTEM_HEADERS_ATTRIBUTE}
fmt-header-only ${FMT_SYSTEM_HEADERS_ATTRIBUTE} BEFORE
INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${FMT_INC_DIR}>)

Expand Down Expand Up @@ -459,14 +499,20 @@ if(FMT_INSTALL)

set(INSTALL_TARGETS fmt fmt-header-only)

set(INSTALL_FILE_SET)
if(FMT_USE_CMAKE_MODULES)
set(INSTALL_FILE_SET FILE_SET fmt DESTINATION "${FMT_INC_DIR}/fmt")
endif()

# Install the library and headers.
install(
TARGETS ${INSTALL_TARGETS}
COMPONENT fmt_core
EXPORT ${targets_export_name}
LIBRARY DESTINATION ${FMT_LIB_DIR}
ARCHIVE DESTINATION ${FMT_LIB_DIR}
PUBLIC_HEADER DESTINATION "${FMT_INC_DIR}/fmt"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ${INSTALL_FILE_SET})

# Use a namespace because CMake provides better diagnostics for namespaced
# imported targets.
Expand All @@ -476,18 +522,61 @@ if(FMT_INSTALL)
FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)

# Install version, config and target files.
install(FILES ${project_config} ${version_config}
DESTINATION ${FMT_CMAKE_DIR})
install(
FILES ${project_config} ${version_config}
DESTINATION ${FMT_CMAKE_DIR}
COMPONENT fmt_core)
install(
EXPORT ${targets_export_name}
DESTINATION ${FMT_CMAKE_DIR}
NAMESPACE fmt::)
NAMESPACE fmt::
COMPONENT fmt_core)

install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}")
install(
FILES "${pkgconfig}"
DESTINATION "${FMT_PKGCONFIG_DIR}"
COMPONENT fmt_core)
endif()

function(add_doc_target)
find_program(DOXYGEN doxygen PATHS "$ENV{ProgramFiles}/doxygen/bin"
"$ENV{ProgramFiles\(x86\)}/doxygen/bin")
if(NOT DOXYGEN)
message(STATUS "Target 'doc' disabled because doxygen not found")
return()
endif()

find_program(MKDOCS mkdocs)
if(NOT MKDOCS)
message(STATUS "Target 'doc' disabled because mkdocs not found")
return()
endif()

set(sources)
foreach(source api.md index.md syntax.md get-started.md fmt.css fmt.js)
set(sources ${sources} doc/${source})
endforeach()

add_custom_target(
doc
COMMAND
${CMAKE_COMMAND} -E env
PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}/support/python ${MKDOCS} build -f
${CMAKE_CURRENT_SOURCE_DIR}/support/mkdocs.yml
# MkDocs requires the site dir to be outside of the doc dir.
--site-dir ${CMAKE_CURRENT_BINARY_DIR}/doc-html --no-directory-urls
SOURCES ${sources})

include(GNUInstallDirs)
install(
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc-html/
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/fmt
COMPONENT fmt_doc
OPTIONAL)
endfunction()

if(FMT_DOC)
add_subdirectory(doc)
add_doc_target()
endif()

if(FMT_TEST)
Expand Down Expand Up @@ -517,14 +606,7 @@ if(FMT_MASTER_PROJECT AND EXISTS ${gitignore})
string(REPLACE "*" ".*" line "${line}")
set(ignored_files ${ignored_files} "${line}$" "${line}/")
endforeach()
set(ignored_files
${ignored_files}
/.git
/breathe
/format-benchmark
sphinx/
.buildinfo
.doctrees)
set(ignored_files ${ignored_files} /.git /build/doxyxml .vagrant)

set(CPACK_SOURCE_GENERATOR ZIP)
set(CPACK_SOURCE_IGNORE_FILES ${ignored_files})
Expand Down
Loading
Loading