1
- cmake_minimum_required (VERSION 3.8...3.26 )
1
+ cmake_minimum_required (VERSION 3.8...3.28 )
2
2
3
3
# Fallback for using newer policies on CMake <3.12.
4
4
if (${CMAKE_VERSION} VERSION_LESS 3.12 )
@@ -36,6 +36,12 @@ function(enable_module target)
36
36
endif ()
37
37
endfunction ()
38
38
39
+ set (FMT_USE_CMAKE_MODULES FALSE )
40
+ if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.28 AND
41
+ CMAKE_GENERATOR STREQUAL "Ninja" )
42
+ set (FMT_USE_CMAKE_MODULES TRUE )
43
+ endif ()
44
+
39
45
# Adds a library compiled with C++20 module support.
40
46
# `enabled` is a CMake variables that specifies if modules are enabled.
41
47
# If modules are disabled `add_module_library` falls back to creating a
@@ -53,6 +59,7 @@ function(add_module_library name)
53
59
if (NOT ${${AML_IF}} )
54
60
# Create a non-modular library.
55
61
target_sources (${name} PRIVATE ${AML_FALLBACK} )
62
+ set_target_properties (${name} PROPERTIES CXX_SCAN_FOR_MODULES OFF )
56
63
return ()
57
64
endif ()
58
65
@@ -62,48 +69,55 @@ function(add_module_library name)
62
69
target_compile_options (${name} PUBLIC -fmodules-ts )
63
70
endif ()
64
71
65
- # `std` is affected by CMake options and may be higher than C++20.
66
- get_target_property (std ${name} CXX_STANDARD )
67
-
68
- if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
69
- set (pcms )
70
- foreach (src ${sources} )
71
- get_filename_component (pcm ${src} NAME_WE )
72
- set (pcm ${pcm} .pcm )
73
-
74
- # Propagate -fmodule-file=*.pcm to targets that link with this library.
75
- target_compile_options (
76
- ${name} PUBLIC -fmodule-file=${CMAKE_CURRENT_BINARY_DIR}/${pcm} )
77
-
78
- # Use an absolute path to prevent target_link_libraries prepending -l
79
- # to it.
80
- set (pcms ${pcms} ${CMAKE_CURRENT_BINARY_DIR} /${pcm} )
81
- add_custom_command (
82
- OUTPUT ${pcm}
83
- COMMAND ${CMAKE_CXX_COMPILER}
84
- -std=c++${std} -x c++-module --precompile -c
85
- -o ${pcm} ${CMAKE_CURRENT_SOURCE_DIR} /${src}
86
- "-I$<JOIN:$<TARGET_PROPERTY:${name} ,INCLUDE_DIRECTORIES>,;-I>"
87
- # Required by the -I generator expression above.
88
- COMMAND_EXPAND_LISTS
89
- DEPENDS ${src} )
90
- endforeach ()
91
-
92
- # Add .pcm files as sources to make sure they are built before the library.
93
- set (sources )
94
- foreach (pcm ${pcms} )
95
- get_filename_component (pcm_we ${pcm} NAME_WE )
96
- set (obj ${pcm_we} .o )
97
- # Use an absolute path to prevent target_link_libraries prepending -l.
98
- set (sources ${sources} ${pcm} ${CMAKE_CURRENT_BINARY_DIR} /${obj} )
99
- add_custom_command (
100
- OUTPUT ${obj}
101
- COMMAND ${CMAKE_CXX_COMPILER} $< TARGET_PROPERTY:${name} ,COMPILE_OPTIONS>
102
- -c -o ${obj} ${pcm}
103
- DEPENDS ${pcm} )
104
- endforeach ()
105
- endif ()
106
- target_sources (${name} PRIVATE ${sources} )
72
+ target_compile_definitions (${name} PRIVATE FMT_MODULE )
73
+
74
+ if (FMT_USE_CMAKE_MODULES )
75
+ target_sources (${name} PUBLIC FILE_SET fmt TYPE CXX_MODULES
76
+ FILES ${sources} )
77
+ else ()
78
+ # `std` is affected by CMake options and may be higher than C++20.
79
+ get_target_property (std ${name} CXX_STANDARD )
80
+
81
+ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
82
+ set (pcms )
83
+ foreach (src ${sources} )
84
+ get_filename_component (pcm ${src} NAME_WE )
85
+ set (pcm ${pcm} .pcm )
86
+
87
+ # Propagate -fmodule-file=*.pcm to targets that link with this library.
88
+ target_compile_options (
89
+ ${name} PUBLIC -fmodule-file=${CMAKE_CURRENT_BINARY_DIR}/${pcm} )
90
+
91
+ # Use an absolute path to prevent target_link_libraries prepending -l
92
+ # to it.
93
+ set (pcms ${pcms} ${CMAKE_CURRENT_BINARY_DIR} /${pcm} )
94
+ add_custom_command (
95
+ OUTPUT ${pcm}
96
+ COMMAND ${CMAKE_CXX_COMPILER}
97
+ -std=c++${std} -x c++-module --precompile -c
98
+ -o ${pcm} ${CMAKE_CURRENT_SOURCE_DIR} /${src}
99
+ "-I$<JOIN:$<TARGET_PROPERTY:${name} ,INCLUDE_DIRECTORIES>,;-I>"
100
+ # Required by the -I generator expression above.
101
+ COMMAND_EXPAND_LISTS
102
+ DEPENDS ${src} )
103
+ endforeach ()
104
+
105
+ # Add .pcm files as sources to make sure they are built before the library.
106
+ set (sources )
107
+ foreach (pcm ${pcms} )
108
+ get_filename_component (pcm_we ${pcm} NAME_WE )
109
+ set (obj ${pcm_we} .o )
110
+ # Use an absolute path to prevent target_link_libraries prepending -l.
111
+ set (sources ${sources} ${pcm} ${CMAKE_CURRENT_BINARY_DIR} /${obj} )
112
+ add_custom_command (
113
+ OUTPUT ${obj}
114
+ COMMAND ${CMAKE_CXX_COMPILER} $< TARGET_PROPERTY:${name} ,COMPILE_OPTIONS>
115
+ -c -o ${obj} ${pcm}
116
+ DEPENDS ${pcm} )
117
+ endforeach ()
118
+ endif ()
119
+ target_sources (${name} PRIVATE ${sources} )
120
+ endif ()
107
121
endfunction ()
108
122
109
123
include (CMakeParseArguments )
@@ -150,9 +164,10 @@ option(FMT_INSTALL "Generate the install target." ON)
150
164
option (FMT_TEST "Generate the test target." ${FMT_MASTER_PROJECT} )
151
165
option (FMT_FUZZ "Generate the fuzz target." OFF )
152
166
option (FMT_CUDA_TEST "Generate the cuda-test target." OFF )
153
- option (FMT_OS "Include core requiring OS (Windows/Posix) " ON )
167
+ option (FMT_OS "Include OS-specific APIs. " ON )
154
168
option (FMT_MODULE "Build a module instead of a traditional library." OFF )
155
169
option (FMT_SYSTEM_HEADERS "Expose headers with marking them as system." OFF )
170
+ option (FMT_UNICODE "Enable Unicode support." ON )
156
171
157
172
if (FMT_TEST AND FMT_MODULE )
158
173
# The tests require {fmt} to be compiled as traditional library
@@ -167,18 +182,18 @@ if (CMAKE_SYSTEM_NAME STREQUAL "MSDOS")
167
182
message (STATUS "MSDOS is incompatible with gtest" )
168
183
endif ()
169
184
170
- # Get version from core .h
171
- file (READ include /fmt/core .h core_h )
172
- if (NOT core_h MATCHES "FMT_VERSION ([0-9]+)([0-9][0-9])([0-9][0-9])" )
173
- message (FATAL_ERROR "Cannot get FMT_VERSION from core .h." )
185
+ # Get version from base .h
186
+ file (READ include /fmt/base .h base_h )
187
+ if (NOT base_h MATCHES "FMT_VERSION ([0-9]+)([0-9][0-9])([0-9][0-9])" )
188
+ message (FATAL_ERROR "Cannot get FMT_VERSION from base .h." )
174
189
endif ()
175
190
# Use math to skip leading zeros if any.
176
191
math (EXPR CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1} )
177
192
math (EXPR CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2} )
178
193
math (EXPR CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3} )
179
194
join (FMT_VERSION ${CPACK_PACKAGE_VERSION_MAJOR} .${CPACK_PACKAGE_VERSION_MINOR}.
180
195
${CPACK_PACKAGE_VERSION_PATCH} )
181
- message (STATUS "Version : ${FMT_VERSION} " )
196
+ message (STATUS "{fmt} version : ${FMT_VERSION} " )
182
197
183
198
message (STATUS "Build type: ${CMAKE_BUILD_TYPE} " )
184
199
@@ -274,20 +289,21 @@ function(add_headers VAR)
274
289
endfunction ()
275
290
276
291
# Define the fmt library, its includes and the needed defines.
277
- add_headers (FMT_HEADERS args.h chrono.h color.h compile.h core.h format.h
292
+ add_headers (FMT_HEADERS args.h base.h chrono.h color.h compile.h core.h format.h
278
293
format-inl.h os.h ostream.h printf.h ranges.h std.h
279
294
xchar.h )
280
295
set (FMT_SOURCES src/format.cc )
281
- if (FMT_OS )
282
- set (FMT_SOURCES ${FMT_SOURCES} src/os.cc )
283
- endif ()
284
296
285
297
add_module_library (fmt src/fmt.cc FALLBACK
286
298
${FMT_SOURCES} ${FMT_HEADERS} README.md ChangeLog.md
287
299
IF FMT_MODULE )
288
300
add_library (fmt::fmt ALIAS fmt )
289
301
if (FMT_MODULE )
290
302
enable_module (fmt )
303
+ elseif (FMT_OS )
304
+ target_sources (fmt PRIVATE src/os.cc )
305
+ else ()
306
+ target_compile_definitions (fmt PRIVATE FMT_OS=0 )
291
307
endif ()
292
308
293
309
if (FMT_WERROR )
@@ -339,6 +355,12 @@ endif ()
339
355
add_library (fmt-header-only INTERFACE )
340
356
add_library (fmt::fmt-header-only ALIAS fmt-header-only )
341
357
358
+ if (MSVC AND FMT_UNICODE )
359
+ # Unicode support requires compiling with /utf-8.
360
+ target_compile_options (fmt PUBLIC $< $< COMPILE_LANGUAGE:CXX> :/utf-8> )
361
+ target_compile_options (fmt-header-only INTERFACE $< $< COMPILE_LANGUAGE:CXX> :/utf-8> )
362
+ endif ()
363
+
342
364
target_compile_definitions (fmt-header-only INTERFACE FMT_HEADER_ONLY=1 )
343
365
target_compile_features (fmt-header-only INTERFACE cxx_std_11 )
344
366
@@ -388,12 +410,18 @@ if (FMT_INSTALL)
388
410
389
411
set (INSTALL_TARGETS fmt fmt-header-only )
390
412
413
+ set (INSTALL_FILE_SET )
414
+ if (FMT_USE_CMAKE_MODULES )
415
+ set (INSTALL_FILE_SET FILE_SET fmt DESTINATION "${FMT_INC_DIR} /fmt" )
416
+ endif ()
417
+
391
418
# Install the library and headers.
392
419
install (TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name}
393
420
LIBRARY DESTINATION ${FMT_LIB_DIR}
394
421
ARCHIVE DESTINATION ${FMT_LIB_DIR}
395
422
PUBLIC_HEADER DESTINATION "${FMT_INC_DIR} /fmt"
396
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )
423
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
424
+ ${INSTALL_FILE_SET} )
397
425
398
426
# Use a namespace because CMake provides better diagnostics for namespaced
399
427
# imported targets.
@@ -410,8 +438,44 @@ if (FMT_INSTALL)
410
438
install (FILES "${pkgconfig} " DESTINATION "${FMT_PKGCONFIG_DIR} " )
411
439
endif ()
412
440
441
+ function (add_doc_target )
442
+ find_program (DOXYGEN doxygen
443
+ PATHS "$ENV{ProgramFiles} /doxygen/bin"
444
+ "$ENV{ProgramFiles\( x86\) }/doxygen/bin" )
445
+ if (NOT DOXYGEN )
446
+ message (STATUS "Target 'doc' disabled because doxygen not found" )
447
+ return ()
448
+ endif ()
449
+
450
+ find_program (MKDOCS mkdocs )
451
+ if (NOT MKDOCS )
452
+ message (STATUS "Target 'doc' disabled because mkdocs not found" )
453
+ return ()
454
+ endif ()
455
+
456
+ set (sources )
457
+ foreach (source api.md index.md syntax.md get -started.md fmt.css fmt.js )
458
+ set (sources ${sources} doc /${source} )
459
+ endforeach ()
460
+
461
+ add_custom_target (
462
+ doc
463
+ COMMAND
464
+ ${CMAKE_COMMAND}
465
+ -E env PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}/support/python
466
+ ${MKDOCS} build -f ${CMAKE_CURRENT_SOURCE_DIR} /support/mkdocs.yml
467
+ # MkDocs requires the site dir to be outside of the doc dir.
468
+ --site-dir ${CMAKE_CURRENT_BINARY_DIR} /doc-html
469
+ --no-directory-urls
470
+ SOURCES ${sources} )
471
+
472
+ include (GNUInstallDirs )
473
+ install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} /doc-html/
474
+ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR} /doc/fmt OPTIONAL )
475
+ endfunction ()
476
+
413
477
if (FMT_DOC )
414
- add_subdirectory ( doc )
478
+ add_doc_target ( )
415
479
endif ()
416
480
417
481
if (FMT_TEST )
@@ -441,8 +505,7 @@ if (FMT_MASTER_PROJECT AND EXISTS ${gitignore})
441
505
string (REPLACE "*" ".*" line "${line} " )
442
506
set (ignored_files ${ignored_files} "${line} $" "${line} /" )
443
507
endforeach ()
444
- set (ignored_files ${ignored_files}
445
- /.git /breathe /format-benchmark sphinx/ .buildinfo .doctrees )
508
+ set (ignored_files ${ignored_files} /.git /build/doxyxml .vagrant )
446
509
447
510
set (CPACK_SOURCE_GENERATOR ZIP )
448
511
set (CPACK_SOURCE_IGNORE_FILES ${ignored_files} )
0 commit comments