[med-svn] [Git][med-team/spdlog][upstream] New upstream version 1.15.1+ds

Shengqi Chen (@harry) gitlab at salsa.debian.org
Wed Feb 12 15:12:54 GMT 2025



Shengqi Chen pushed to branch upstream at Debian Med / spdlog


Commits:
a959b81e by Shengqi Chen at 2025-02-12T23:06:08+08:00
New upstream version 1.15.1+ds
- - - - -


29 changed files:

- .github/workflows/macos.yml
- CMakeLists.txt
- README.md
- example/example.cpp
- include/spdlog/cfg/env.h
- include/spdlog/common.h
- include/spdlog/details/file_helper-inl.h
- include/spdlog/details/os-inl.h
- include/spdlog/details/os.h
- include/spdlog/fmt/bin_to_hex.h
- include/spdlog/sinks/ansicolor_sink-inl.h
- include/spdlog/sinks/ansicolor_sink.h
- include/spdlog/sinks/basic_file_sink-inl.h
- include/spdlog/sinks/basic_file_sink.h
- include/spdlog/sinks/daily_file_sink.h
- include/spdlog/sinks/null_sink.h
- include/spdlog/sinks/rotating_file_sink-inl.h
- include/spdlog/sinks/rotating_file_sink.h
- include/spdlog/sinks/stdout_sinks-inl.h
- include/spdlog/tweakme.h
- include/spdlog/version.h
- src/bundled_fmtlib_format.cpp
- tests/CMakeLists.txt
- tests/test_cfg.cpp
- tests/test_custom_callbacks.cpp
- tests/test_daily_logger.cpp
- tests/test_file_logging.cpp
- tests/test_misc.cpp
- tests/test_sink.h


Changes:

=====================================
.github/workflows/macos.yml
=====================================
@@ -9,6 +9,15 @@ jobs:
   build:
     runs-on: macOS-latest
     name: "macOS Clang (C++11, Release)"
+    strategy:
+      fail-fast: true
+      matrix:
+        config:
+            - USE_STD_FORMAT: 'ON'
+              BUILD_EXAMPLE: 'OFF'
+            - USE_STD_FORMAT: 'OFF'
+              BUILD_EXAMPLE: 'ON'
+              
     steps:
       - uses: actions/checkout at v4
       - name: Build
@@ -17,12 +26,13 @@ jobs:
           cmake .. \
             -DCMAKE_BUILD_TYPE=Release \
             -DCMAKE_CXX_STANDARD=11 \
-            -DSPDLOG_BUILD_EXAMPLE=ON \
-            -DSPDLOG_BUILD_EXAMPLE_HO=ON \
+            -DSPDLOG_BUILD_EXAMPLE=${{ matrix.config.BUILD_EXAMPLE }} \
+            -DSPDLOG_BUILD_EXAMPLE_HO=${{ matrix.config.BUILD_EXAMPLE }} \
             -DSPDLOG_BUILD_WARNINGS=ON \
             -DSPDLOG_BUILD_BENCH=OFF \
             -DSPDLOG_BUILD_TESTS=ON \
             -DSPDLOG_BUILD_TESTS_HO=OFF \
+            -DSPDLOG_USE_STD_FORMAT=${{ matrix.config.USE_STD_FORMAT }} \
             -DSPDLOG_SANITIZE_ADDRESS=OFF
           make -j 4
           ctest -j 4 --output-on-failure


=====================================
CMakeLists.txt
=====================================
@@ -18,39 +18,39 @@ include(GNUInstallDirs)
 # ---------------------------------------------------------------------------------------
 # Set default build to release
 # ---------------------------------------------------------------------------------------
-if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
     set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose Release or Debug" FORCE)
-endif()
+endif ()
 
 # ---------------------------------------------------------------------------------------
 # Compiler config
 # ---------------------------------------------------------------------------------------
-if(SPDLOG_USE_STD_FORMAT)
+if (SPDLOG_USE_STD_FORMAT)
     set(CMAKE_CXX_STANDARD 20)
     set(CMAKE_CXX_STANDARD_REQUIRED ON)
-elseif(NOT CMAKE_CXX_STANDARD)
+elseif (NOT CMAKE_CXX_STANDARD)
     set(CMAKE_CXX_STANDARD 11)
     set(CMAKE_CXX_STANDARD_REQUIRED ON)
-endif()
+endif ()
 
 
 set(CMAKE_CXX_EXTENSIONS OFF)
 
-if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN" OR CMAKE_SYSTEM_NAME MATCHES "MSYS" OR CMAKE_SYSTEM_NAME MATCHES "MINGW")
+if (CMAKE_SYSTEM_NAME MATCHES "CYGWIN" OR CMAKE_SYSTEM_NAME MATCHES "MSYS" OR CMAKE_SYSTEM_NAME MATCHES "MINGW")
     set(CMAKE_CXX_EXTENSIONS ON)
-endif()
+endif ()
 
 # ---------------------------------------------------------------------------------------
 # Set SPDLOG_MASTER_PROJECT to ON if we are building spdlog
 # ---------------------------------------------------------------------------------------
 # Check if spdlog is being used directly or via add_subdirectory, but allow overriding
-if(NOT DEFINED SPDLOG_MASTER_PROJECT)
-    if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
+if (NOT DEFINED SPDLOG_MASTER_PROJECT)
+    if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
         set(SPDLOG_MASTER_PROJECT ON)
-    else()
+    else ()
         set(SPDLOG_MASTER_PROJECT OFF)
-    endif()
-endif()
+    endif ()
+endif ()
 
 option(SPDLOG_BUILD_ALL "Build all artifacts" OFF)
 
@@ -77,9 +77,9 @@ option(SPDLOG_BUILD_BENCH "Build benchmarks (Requires https://github.com/google/
 # sanitizer options
 option(SPDLOG_SANITIZE_ADDRESS "Enable address sanitizer in tests" OFF)
 option(SPDLOG_SANITIZE_THREAD "Enable thread sanitizer in tests" OFF)
-if(SPDLOG_SANITIZE_ADDRESS AND SPDLOG_SANITIZE_THREAD)
+if (SPDLOG_SANITIZE_ADDRESS AND SPDLOG_SANITIZE_THREAD)
     message(FATAL_ERROR "SPDLOG_SANITIZE_ADDRESS and SPDLOG_SANITIZE_THREAD are mutually exclusive")
-endif()
+endif ()
 
 # warning options
 option(SPDLOG_BUILD_WARNINGS "Enable compiler warnings" OFF)
@@ -92,60 +92,61 @@ option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF)
 option(SPDLOG_FMT_EXTERNAL_HO "Use external fmt header-only library instead of bundled" OFF)
 option(SPDLOG_NO_EXCEPTIONS "Compile with -fno-exceptions. Call abort() on any spdlog exceptions" OFF)
 
-if(SPDLOG_FMT_EXTERNAL AND SPDLOG_FMT_EXTERNAL_HO)
+if (SPDLOG_FMT_EXTERNAL AND SPDLOG_FMT_EXTERNAL_HO)
     message(FATAL_ERROR "SPDLOG_FMT_EXTERNAL and SPDLOG_FMT_EXTERNAL_HO are mutually exclusive")
-endif()
+endif ()
 
-if(SPDLOG_USE_STD_FORMAT AND SPDLOG_FMT_EXTERNAL_HO)
+if (SPDLOG_USE_STD_FORMAT AND SPDLOG_FMT_EXTERNAL_HO)
     message(FATAL_ERROR "SPDLOG_USE_STD_FORMAT and SPDLOG_FMT_EXTERNAL_HO are mutually exclusive")
-endif()
+endif ()
 
-if(SPDLOG_USE_STD_FORMAT AND SPDLOG_FMT_EXTERNAL)
+if (SPDLOG_USE_STD_FORMAT AND SPDLOG_FMT_EXTERNAL)
     message(FATAL_ERROR "SPDLOG_USE_STD_FORMAT and SPDLOG_FMT_EXTERNAL are mutually exclusive")
-endif()
+endif ()
 
 # misc tweakme options
-if(WIN32)
+if (WIN32)
     option(SPDLOG_WCHAR_SUPPORT "Support wchar api" OFF)
     option(SPDLOG_WCHAR_FILENAMES "Support wchar filenames" OFF)
-    option(SPDLOG_WCHAR_CONSOLE "Support wchar output to console" OFF)    
-else()
+    option(SPDLOG_WCHAR_CONSOLE "Support wchar output to console" OFF)
+else ()
     set(SPDLOG_WCHAR_SUPPORT OFF CACHE BOOL "non supported option" FORCE)
     set(SPDLOG_WCHAR_FILENAMES OFF CACHE BOOL "non supported option" FORCE)
     set(SPDLOG_WCHAR_CONSOLE OFF CACHE BOOL "non supported option" FORCE)
-endif()
+endif ()
 
-if(MSVC)    
-    option(SPDLOG_MSVC_UTF8 "Enable/disable msvc /utf-8 flag required by fmt lib" ON)   
-endif()
+if (MSVC)
+    option(SPDLOG_MSVC_UTF8 "Enable/disable msvc /utf-8 flag required by fmt lib" ON)
+endif ()
 
-if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
     option(SPDLOG_CLOCK_COARSE "Use CLOCK_REALTIME_COARSE instead of the regular clock," OFF)
-else()
+else ()
     set(SPDLOG_CLOCK_COARSE OFF CACHE BOOL "non supported option" FORCE)
-endif()
+endif ()
 
 option(SPDLOG_PREVENT_CHILD_FD "Prevent from child processes to inherit log file descriptors" OFF)
 option(SPDLOG_NO_THREAD_ID "prevent spdlog from querying the thread id on each log call if thread id is not needed" OFF)
 option(SPDLOG_NO_TLS "prevent spdlog from using thread local storage" OFF)
 option(
-    SPDLOG_NO_ATOMIC_LEVELS
-    "prevent spdlog from using of std::atomic log levels (use only if your code never modifies log levels concurrently"
-    OFF)
+        SPDLOG_NO_ATOMIC_LEVELS
+        "prevent spdlog from using of std::atomic log levels (use only if your code never modifies log levels concurrently"
+        OFF)
 option(SPDLOG_DISABLE_DEFAULT_LOGGER "Disable default logger creation" OFF)
+option(SPDLOG_FWRITE_UNLOCKED "Use the unlocked variant of fwrite. Leave this on unless your libc doesn't have it" ON)
 
 # clang-tidy
 option(SPDLOG_TIDY "run clang-tidy" OFF)
 
-if(SPDLOG_TIDY)
+if (SPDLOG_TIDY)
     set(CMAKE_CXX_CLANG_TIDY "clang-tidy")
     set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
     message(STATUS "Enabled clang-tidy")
-endif()
+endif ()
 
-if(SPDLOG_BUILD_PIC)
+if (SPDLOG_BUILD_PIC)
     set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-endif()
+endif ()
 
 find_package(Threads REQUIRED)
 message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
@@ -154,52 +155,52 @@ message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
 # ---------------------------------------------------------------------------------------
 set(SPDLOG_SRCS src/spdlog.cpp src/stdout_sinks.cpp src/color_sinks.cpp src/file_sinks.cpp src/async.cpp src/cfg.cpp)
 
-if(NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
+if (NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
     list(APPEND SPDLOG_SRCS src/bundled_fmtlib_format.cpp)
-endif()
+endif ()
 
-if(SPDLOG_BUILD_SHARED OR BUILD_SHARED_LIBS)
-    if(WIN32)
+if (SPDLOG_BUILD_SHARED OR BUILD_SHARED_LIBS)
+    if (WIN32)
         configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY)
         list(APPEND SPDLOG_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-    endif()
+    endif ()
     add_library(spdlog SHARED ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS})
     target_compile_definitions(spdlog PUBLIC SPDLOG_SHARED_LIB)
-    if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+    if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
         target_compile_options(spdlog PUBLIC $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<NOT:$<COMPILE_LANGUAGE:CUDA>>>:/wd4251
-                                             /wd4275>)
-    endif()
-    if(NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
+                /wd4275>)
+    endif ()
+    if (NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
         target_compile_definitions(spdlog PRIVATE FMT_LIB_EXPORT PUBLIC FMT_SHARED)
-    endif()
-else()
+    endif ()
+else ()
     add_library(spdlog STATIC ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS})
-endif()
+endif ()
 
 add_library(spdlog::spdlog ALIAS spdlog)
 
 set(SPDLOG_INCLUDES_LEVEL "")
-if(SPDLOG_SYSTEM_INCLUDES)
+if (SPDLOG_SYSTEM_INCLUDES)
     set(SPDLOG_INCLUDES_LEVEL "SYSTEM")
-endif()
+endif ()
 
 target_compile_definitions(spdlog PUBLIC SPDLOG_COMPILED_LIB)
 target_include_directories(spdlog ${SPDLOG_INCLUDES_LEVEL} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
-                                                                  "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
+        "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
 target_link_libraries(spdlog PUBLIC Threads::Threads)
 spdlog_enable_warnings(spdlog)
 
 set_target_properties(spdlog PROPERTIES VERSION ${SPDLOG_VERSION} SOVERSION
-                                                                  ${SPDLOG_VERSION_MAJOR}.${SPDLOG_VERSION_MINOR})
+        ${SPDLOG_VERSION_MAJOR}.${SPDLOG_VERSION_MINOR})
 set_target_properties(spdlog PROPERTIES DEBUG_POSTFIX d)
 
-if(COMMAND target_precompile_headers AND SPDLOG_ENABLE_PCH)
+if (COMMAND target_precompile_headers AND SPDLOG_ENABLE_PCH)
     configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pch.h.in ${PROJECT_BINARY_DIR}/spdlog_pch.h @ONLY)
     target_precompile_headers(spdlog PRIVATE ${PROJECT_BINARY_DIR}/spdlog_pch.h)
-endif()
+endif ()
 
 # sanitizer support
-if(SPDLOG_SANITIZE_ADDRESS)
+if (SPDLOG_SANITIZE_ADDRESS)
     spdlog_enable_addr_sanitizer(spdlog)
 elseif (SPDLOG_SANITIZE_THREAD)
     spdlog_enable_thread_sanitizer(spdlog)
@@ -212,113 +213,132 @@ add_library(spdlog_header_only INTERFACE)
 add_library(spdlog::spdlog_header_only ALIAS spdlog_header_only)
 
 target_include_directories(
-    spdlog_header_only ${SPDLOG_INCLUDES_LEVEL} INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
-                                                          "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
+        spdlog_header_only ${SPDLOG_INCLUDES_LEVEL} INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
+        "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
 target_link_libraries(spdlog_header_only INTERFACE Threads::Threads)
 
 # ---------------------------------------------------------------------------------------
 # Use fmt package if using external fmt
 # ---------------------------------------------------------------------------------------
-if(SPDLOG_FMT_EXTERNAL OR SPDLOG_FMT_EXTERNAL_HO)
-    if(NOT TARGET fmt::fmt)
+if (SPDLOG_FMT_EXTERNAL OR SPDLOG_FMT_EXTERNAL_HO)
+    if (NOT TARGET fmt::fmt)
         find_package(fmt CONFIG REQUIRED)
-    endif()
+    endif ()
     target_compile_definitions(spdlog PUBLIC SPDLOG_FMT_EXTERNAL)
     target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_FMT_EXTERNAL)
 
     # use external fmt-header-only
-    if(SPDLOG_FMT_EXTERNAL_HO)
+    if (SPDLOG_FMT_EXTERNAL_HO)
         target_link_libraries(spdlog PUBLIC fmt::fmt-header-only)
         target_link_libraries(spdlog_header_only INTERFACE fmt::fmt-header-only)
-    else() # use external compile fmt
+    else () # use external compile fmt
         target_link_libraries(spdlog PUBLIC fmt::fmt)
         target_link_libraries(spdlog_header_only INTERFACE fmt::fmt)
-    endif()
+    endif ()
 
     set(PKG_CONFIG_REQUIRES fmt) # add dependency to pkg-config
-endif()
+endif ()
+
+# ---------------------------------------------------------------------------------------
+# Check if fwrite_unlocked/_fwrite_nolock is available
+# ---------------------------------------------------------------------------------------
+if (SPDLOG_FWRITE_UNLOCKED)
+    include(CheckSymbolExists)
+    if (WIN32)
+        check_symbol_exists(_fwrite_nolock "stdio.h" HAVE_FWRITE_UNLOCKED)
+    else ()
+        check_symbol_exists(fwrite_unlocked "stdio.h" HAVE_FWRITE_UNLOCKED)
+    endif ()
+    if (HAVE_FWRITE_UNLOCKED)
+        target_compile_definitions(spdlog PRIVATE SPDLOG_FWRITE_UNLOCKED)
+        target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_FWRITE_UNLOCKED)
+    endif ()
+endif ()
 
 # ---------------------------------------------------------------------------------------
 # Add required libraries for Android CMake build
 # ---------------------------------------------------------------------------------------
-if(ANDROID)
+if (ANDROID)
     target_link_libraries(spdlog PUBLIC log)
     target_link_libraries(spdlog_header_only INTERFACE log)
-endif()
+endif ()
 
 # ---------------------------------------------------------------------------------------
 # Misc definitions according to tweak options
 # ---------------------------------------------------------------------------------------
 set(SPDLOG_WCHAR_TO_UTF8_SUPPORT ${SPDLOG_WCHAR_SUPPORT})
 set(SPDLOG_UTF8_TO_WCHAR_CONSOLE ${SPDLOG_WCHAR_CONSOLE})
-foreach(
-    SPDLOG_OPTION
-    SPDLOG_WCHAR_TO_UTF8_SUPPORT
-    SPDLOG_UTF8_TO_WCHAR_CONSOLE
-    SPDLOG_WCHAR_FILENAMES
-    SPDLOG_NO_EXCEPTIONS
-    SPDLOG_CLOCK_COARSE
-    SPDLOG_PREVENT_CHILD_FD
-    SPDLOG_NO_THREAD_ID
-    SPDLOG_NO_TLS
-    SPDLOG_NO_ATOMIC_LEVELS
-    SPDLOG_DISABLE_DEFAULT_LOGGER
-    SPDLOG_USE_STD_FORMAT)
-    if(${SPDLOG_OPTION})
+foreach (
+        SPDLOG_OPTION
+        SPDLOG_WCHAR_TO_UTF8_SUPPORT
+        SPDLOG_UTF8_TO_WCHAR_CONSOLE
+        SPDLOG_WCHAR_FILENAMES
+        SPDLOG_NO_EXCEPTIONS
+        SPDLOG_CLOCK_COARSE
+        SPDLOG_PREVENT_CHILD_FD
+        SPDLOG_NO_THREAD_ID
+        SPDLOG_NO_TLS
+        SPDLOG_NO_ATOMIC_LEVELS
+        SPDLOG_DISABLE_DEFAULT_LOGGER
+        SPDLOG_USE_STD_FORMAT)
+    if (${SPDLOG_OPTION})
         target_compile_definitions(spdlog PUBLIC ${SPDLOG_OPTION})
         target_compile_definitions(spdlog_header_only INTERFACE ${SPDLOG_OPTION})
-    endif()
-endforeach()
+    endif ()
+endforeach ()
 
-if(MSVC)
+if (MSVC)
     target_compile_options(spdlog PRIVATE "/Zc:__cplusplus")
     target_compile_options(spdlog_header_only INTERFACE "/Zc:__cplusplus")
-    if(SPDLOG_MSVC_UTF8)
-	    target_compile_options(spdlog PUBLIC "/utf-8")
-	    target_compile_options(spdlog_header_only INTERFACE "/utf-8")    
-     endif()
-endif()
+    if (SPDLOG_MSVC_UTF8)
+        # fmtlib requires the /utf-8 flag when building with msvc.
+        # see https://github.com/fmtlib/fmt/pull/4159 on the purpose of the additional
+        # "$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>"
+        target_compile_options(spdlog PUBLIC $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>:/utf-8>)
+        target_compile_options(spdlog_header_only INTERFACE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>:/utf-8>)
+    endif ()
+endif ()
 
 # ---------------------------------------------------------------------------------------
 # If exceptions are disabled, disable them in the bundled fmt as well
 # ---------------------------------------------------------------------------------------
-if(SPDLOG_NO_EXCEPTIONS)
-    if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
+if (SPDLOG_NO_EXCEPTIONS)
+    if (NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
         target_compile_definitions(spdlog PUBLIC FMT_EXCEPTIONS=0)
-    endif()
-    if(NOT MSVC)
+    endif ()
+    if (NOT MSVC)
         target_compile_options(spdlog PRIVATE -fno-exceptions)
-    else()
+    else ()
         target_compile_options(spdlog PRIVATE /EHs-c-)
-    endif()
-endif()
+    endif ()
+endif ()
 # ---------------------------------------------------------------------------------------
 # Build binaries
 # ---------------------------------------------------------------------------------------
-if(SPDLOG_BUILD_EXAMPLE OR SPDLOG_BUILD_EXAMPLE_HO OR SPDLOG_BUILD_ALL)
+if (SPDLOG_BUILD_EXAMPLE OR SPDLOG_BUILD_EXAMPLE_HO OR SPDLOG_BUILD_ALL)
     message(STATUS "Generating example(s)")
     add_subdirectory(example)
     spdlog_enable_warnings(example)
-    if(SPDLOG_BUILD_EXAMPLE_HO)
+    if (SPDLOG_BUILD_EXAMPLE_HO)
         spdlog_enable_warnings(example_header_only)
-    endif()
-endif()
+    endif ()
+endif ()
 
-if(SPDLOG_BUILD_TESTS OR SPDLOG_BUILD_TESTS_HO OR SPDLOG_BUILD_ALL)
+if (SPDLOG_BUILD_TESTS OR SPDLOG_BUILD_TESTS_HO OR SPDLOG_BUILD_ALL)
     message(STATUS "Generating tests")
     enable_testing()
     add_subdirectory(tests)
-endif()
+endif ()
 
-if(SPDLOG_BUILD_BENCH OR SPDLOG_BUILD_ALL)
+if (SPDLOG_BUILD_BENCH OR SPDLOG_BUILD_ALL)
     message(STATUS "Generating benchmarks")
     add_subdirectory(bench)
-endif()
+endif ()
 
 # ---------------------------------------------------------------------------------------
 # Install
 # ---------------------------------------------------------------------------------------
-if(SPDLOG_INSTALL)
+if (SPDLOG_INSTALL)
     message(STATUS "Generating install")
     set(project_config_in "${CMAKE_CURRENT_LIST_DIR}/cmake/spdlogConfig.cmake.in")
     set(project_config_out "${CMAKE_CURRENT_BINARY_DIR}/spdlogConfig.cmake")
@@ -333,30 +353,30 @@ if(SPDLOG_INSTALL)
     # ---------------------------------------------------------------------------------------
     install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" PATTERN "fmt/bundled" EXCLUDE)
     install(
-        TARGETS spdlog spdlog_header_only
-        EXPORT spdlog
-        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+            TARGETS spdlog spdlog_header_only
+            EXPORT spdlog
+            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
 
-    if(NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
+    if (NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
         install(DIRECTORY include/${PROJECT_NAME}/fmt/bundled/
                 DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/fmt/bundled/")
-    endif()
+    endif ()
 
     # ---------------------------------------------------------------------------------------
     # Install pkg-config file
     # ---------------------------------------------------------------------------------------
-    if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
+    if (IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
         set(PKG_CONFIG_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
-    else()
+    else ()
         set(PKG_CONFIG_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
-    endif()
-    if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
+    endif ()
+    if (IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
         set(PKG_CONFIG_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
-    else()
+    else ()
         set(PKG_CONFIG_LIBDIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
-    endif()
+    endif ()
     get_target_property(PKG_CONFIG_DEFINES spdlog INTERFACE_COMPILE_DEFINITIONS)
     string(REPLACE ";" " -D" PKG_CONFIG_DEFINES "${PKG_CONFIG_DEFINES}")
     string(CONCAT PKG_CONFIG_DEFINES "-D" "${PKG_CONFIG_DEFINES}")
@@ -367,7 +387,7 @@ if(SPDLOG_INSTALL)
     # Install CMake config files
     # ---------------------------------------------------------------------------------------
     export(TARGETS spdlog spdlog_header_only NAMESPACE spdlog::
-           FILE "${CMAKE_CURRENT_BINARY_DIR}/${config_targets_file}")
+            FILE "${CMAKE_CURRENT_BINARY_DIR}/${config_targets_file}")
     install(EXPORT spdlog DESTINATION ${export_dest_dir} NAMESPACE spdlog:: FILE ${config_targets_file})
 
     include(CMakePackageConfigHelpers)
@@ -380,4 +400,4 @@ if(SPDLOG_INSTALL)
     # Support creation of installable packages
     # ---------------------------------------------------------------------------------------
     include(cmake/spdlogCPack.cmake)
-endif()
+endif ()


=====================================
README.md
=====================================
@@ -303,7 +303,7 @@ struct fmt::formatter<my_type> : fmt::formatter<std::string>
 {
     auto format(my_type my, format_context &ctx) const -> decltype(ctx.out())
     {
-        return format_to(ctx.out(), "[my_type i={}]", my.i);
+        return fmt::format_to(ctx.out(), "[my_type i={}]", my.i);
     }
 };
 
@@ -387,6 +387,9 @@ void android_example()
 int main (int argc, char *argv[])
 {
     spdlog::cfg::load_env_levels();
+    // or specify the env variable name:
+    // MYAPP_LEVEL=info,mylogger=trace && ./example
+    // spdlog::cfg::load_env_levels("MYAPP_LEVEL");
     // or from the command line:
     // ./example SPDLOG_LEVEL=info,mylogger=trace
     // #include "spdlog/cfg/argv.h" // for loading levels from argv


=====================================
example/example.cpp
=====================================
@@ -148,6 +148,9 @@ void load_levels_example() {
     // Set the log level to "info" and mylogger to "trace":
     // SPDLOG_LEVEL=info,mylogger=trace && ./example
     spdlog::cfg::load_env_levels();
+    // or specify the env variable name:
+    // MYAPP_LEVEL=info,mylogger=trace && ./example
+    // spdlog::cfg::load_env_levels("MYAPP_LEVEL");
     // or from command line:
     // ./example SPDLOG_LEVEL=info,mylogger=trace
     // #include "spdlog/cfg/argv.h" // for loading levels from argv
@@ -281,7 +284,7 @@ struct fmt::formatter<my_type> : fmt::formatter<std::string> {
 template <>
 struct std::formatter<my_type> : std::formatter<std::string> {
     auto format(my_type my, format_context &ctx) const -> decltype(ctx.out()) {
-        return format_to(ctx.out(), "[my_type i={}]", my.i);
+        return std::format_to(ctx.out(), "[my_type i={}]", my.i);
     }
 };
 #endif


=====================================
include/spdlog/cfg/env.h
=====================================
@@ -25,8 +25,8 @@
 
 namespace spdlog {
 namespace cfg {
-inline void load_env_levels() {
-    auto env_val = details::os::getenv("SPDLOG_LEVEL");
+inline void load_env_levels(const char* var = "SPDLOG_LEVEL") {
+    auto env_val = details::os::getenv(var);
     if (!env_val.empty()) {
         helpers::load_levels(env_val);
     }


=====================================
include/spdlog/common.h
=====================================
@@ -364,12 +364,7 @@ SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(spdlog::wstring_view
 }
 #endif
 
-#ifndef SPDLOG_USE_STD_FORMAT
-template <typename T, typename... Args>
-inline fmt::basic_string_view<T> to_string_view(fmt::basic_format_string<T, Args...> fmt) {
-    return fmt;
-}
-#elif __cpp_lib_format >= 202207L
+#if defined(SPDLOG_USE_STD_FORMAT) &&  __cpp_lib_format >= 202207L
 template <typename T, typename... Args>
 SPDLOG_CONSTEXPR_FUNC std::basic_string_view<T> to_string_view(
     std::basic_format_string<T, Args...> fmt) SPDLOG_NOEXCEPT {


=====================================
include/spdlog/details/file_helper-inl.h
=====================================
@@ -101,7 +101,8 @@ SPDLOG_INLINE void file_helper::write(const memory_buf_t &buf) {
     if (fd_ == nullptr) return;
     size_t msg_size = buf.size();
     auto data = buf.data();
-    if (std::fwrite(data, 1, msg_size, fd_) != msg_size) {
+
+    if (!details::os::fwrite_bytes(data, msg_size, fd_)) {
         throw_spdlog_ex("Failed writing to file " + os::filename_to_str(filename_), errno);
     }
 }


=====================================
include/spdlog/details/os-inl.h
=====================================
@@ -589,6 +589,18 @@ SPDLOG_INLINE bool fsync(FILE *fp) {
 #endif
 }
 
+// Do non-locking fwrite if possible by the os or use the regular locking fwrite
+// Return true on success.
+SPDLOG_INLINE bool fwrite_bytes(const void *ptr, const size_t n_bytes, FILE *fp) {
+    #if defined(_WIN32) && defined(SPDLOG_FWRITE_UNLOCKED)
+    return _fwrite_nolock(ptr, 1, n_bytes, fp) == n_bytes;
+    #elif defined(SPDLOG_FWRITE_UNLOCKED)
+    return ::fwrite_unlocked(ptr, 1, n_bytes, fp) == n_bytes;
+    #else
+    return std::fwrite(ptr, 1, n_bytes, fp) == n_bytes;
+    #endif
+}
+
 }  // namespace os
 }  // namespace details
 }  // namespace spdlog


=====================================
include/spdlog/details/os.h
=====================================
@@ -114,6 +114,10 @@ SPDLOG_API std::string getenv(const char *field);
 // Return true on success.
 SPDLOG_API bool fsync(FILE *fp);
 
+// Do non-locking fwrite if possible by the os or use the regular locking fwrite
+// Return true on success.
+SPDLOG_API bool fwrite_bytes(const void *ptr, const size_t n_bytes, FILE *fp);
+
 }  // namespace os
 }  // namespace details
 }  // namespace spdlog


=====================================
include/spdlog/fmt/bin_to_hex.h
=====================================
@@ -102,7 +102,7 @@ namespace
 
 template <typename T>
 struct formatter<spdlog::details::dump_info<T>, char> {
-    const char delimiter = ' ';
+    char delimiter = ' ';
     bool put_newlines = true;
     bool put_delimiters = true;
     bool use_uppercase = false;


=====================================
include/spdlog/sinks/ansicolor_sink-inl.h
=====================================
@@ -20,7 +20,7 @@ SPDLOG_INLINE ansicolor_sink<ConsoleMutex>::ansicolor_sink(FILE *target_file, co
       formatter_(details::make_unique<spdlog::pattern_formatter>())
 
 {
-    set_color_mode(mode);
+    set_color_mode_(mode);
     colors_.at(level::trace) = to_string_(white);
     colors_.at(level::debug) = to_string_(cyan);
     colors_.at(level::info) = to_string_(green);
@@ -82,12 +82,18 @@ SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_formatter(
 }
 
 template <typename ConsoleMutex>
-SPDLOG_INLINE bool ansicolor_sink<ConsoleMutex>::should_color() {
+SPDLOG_INLINE bool ansicolor_sink<ConsoleMutex>::should_color() const {
     return should_do_colors_;
 }
 
 template <typename ConsoleMutex>
 SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color_mode(color_mode mode) {
+    std::lock_guard<mutex_t> lock(mutex_);
+    set_color_mode_(mode);
+}
+
+template <typename ConsoleMutex>
+SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color_mode_(color_mode mode) {
     switch (mode) {
         case color_mode::always:
             should_do_colors_ = true;
@@ -105,15 +111,15 @@ SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color_mode(color_mode mode)
 }
 
 template <typename ConsoleMutex>
-SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_ccode_(const string_view_t &color_code) {
-    fwrite(color_code.data(), sizeof(char), color_code.size(), target_file_);
+SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_ccode_(const string_view_t &color_code) const {
+    details::os::fwrite_bytes(color_code.data(), color_code.size(), target_file_);
 }
 
 template <typename ConsoleMutex>
 SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted,
                                                               size_t start,
-                                                              size_t end) {
-    fwrite(formatted.data() + start, sizeof(char), end - start, target_file_);
+                                                              size_t end) const {
+    details::os::fwrite_bytes(formatted.data() + start, end - start, target_file_);
 }
 
 template <typename ConsoleMutex>


=====================================
include/spdlog/sinks/ansicolor_sink.h
=====================================
@@ -36,7 +36,7 @@ public:
 
     void set_color(level::level_enum color_level, string_view_t color);
     void set_color_mode(color_mode mode);
-    bool should_color();
+    bool should_color() const;
 
     void log(const details::log_msg &msg) override;
     void flush() override;
@@ -84,8 +84,9 @@ private:
     bool should_do_colors_;
     std::unique_ptr<spdlog::formatter> formatter_;
     std::array<std::string, level::n_levels> colors_;
-    void print_ccode_(const string_view_t &color_code);
-    void print_range_(const memory_buf_t &formatted, size_t start, size_t end);
+    void set_color_mode_(color_mode mode);
+    void print_ccode_(const string_view_t &color_code) const;
+    void print_range_(const memory_buf_t &formatted, size_t start, size_t end) const;
     static std::string to_string_(const string_view_t &sv);
 };
 


=====================================
include/spdlog/sinks/basic_file_sink-inl.h
=====================================
@@ -26,6 +26,12 @@ SPDLOG_INLINE const filename_t &basic_file_sink<Mutex>::filename() const {
     return file_helper_.filename();
 }
 
+template <typename Mutex>
+SPDLOG_INLINE void basic_file_sink<Mutex>::truncate() {
+    std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
+    file_helper_.reopen(true);
+}
+
 template <typename Mutex>
 SPDLOG_INLINE void basic_file_sink<Mutex>::sink_it_(const details::log_msg &msg) {
     memory_buf_t formatted;


=====================================
include/spdlog/sinks/basic_file_sink.h
=====================================
@@ -23,6 +23,7 @@ public:
                              bool truncate = false,
                              const file_event_handlers &event_handlers = {});
     const filename_t &filename() const;
+    void truncate();
 
 protected:
     void sink_it_(const details::log_msg &msg) override;


=====================================
include/spdlog/sinks/daily_file_sink.h
=====================================
@@ -62,7 +62,6 @@ struct daily_filename_format_calculator {
  * Rotating file sink based on date.
  * If truncate != false , the created file will be truncated.
  * If max_files > 0, retain only the last max_files and delete previous.
- * If max_files > 0, retain only the last max_files and delete previous.
  * Note that old log files from previous executions will not be deleted by this class,
  * rotation and deletion is only applied while the program is running.
  */


=====================================
include/spdlog/sinks/null_sink.h
=====================================
@@ -13,7 +13,7 @@ namespace spdlog {
 namespace sinks {
 
 template <typename Mutex>
-class null_sink : public base_sink<Mutex> {
+class null_sink final : public base_sink<Mutex> {
 protected:
     void sink_it_(const details::log_msg &) override {}
     void flush_() override {}


=====================================
include/spdlog/sinks/rotating_file_sink-inl.h
=====================================
@@ -69,6 +69,12 @@ SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::filename() {
     return file_helper_.filename();
 }
 
+template <typename Mutex>
+SPDLOG_INLINE void rotating_file_sink<Mutex>::rotate_now() {
+    std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
+    rotate_();
+}
+
 template <typename Mutex>
 SPDLOG_INLINE void rotating_file_sink<Mutex>::sink_it_(const details::log_msg &msg) {
     memory_buf_t formatted;


=====================================
include/spdlog/sinks/rotating_file_sink.h
=====================================
@@ -28,6 +28,7 @@ public:
                        const file_event_handlers &event_handlers = {});
     static filename_t calc_filename(const filename_t &filename, std::size_t index);
     filename_t filename();
+    void rotate_now();
 
 protected:
     void sink_it_(const details::log_msg &msg) override;


=====================================
include/spdlog/sinks/stdout_sinks-inl.h
=====================================
@@ -10,6 +10,7 @@
 #include <memory>
 #include <spdlog/details/console_globals.h>
 #include <spdlog/pattern_formatter.h>
+#include <spdlog/details/os.h>
 
 #ifdef _WIN32
     // under windows using fwrite to non-binary stream results in \r\r\n (see issue #1675)
@@ -22,7 +23,7 @@
 
     #include <io.h>     // _get_osfhandle(..)
     #include <stdio.h>  // _fileno(..)
-#endif                  // WIN32
+#endif                  // _WIN32
 
 namespace spdlog {
 
@@ -44,7 +45,7 @@ SPDLOG_INLINE stdout_sink_base<ConsoleMutex>::stdout_sink_base(FILE *file)
     if (handle_ == INVALID_HANDLE_VALUE && file != stdout && file != stderr) {
         throw_spdlog_ex("spdlog::stdout_sink_base: _get_osfhandle() failed", errno);
     }
-#endif  // WIN32
+#endif  // _WIN32
 }
 
 template <typename ConsoleMutex>
@@ -67,8 +68,8 @@ SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::log(const details::log_msg &m
     std::lock_guard<mutex_t> lock(mutex_);
     memory_buf_t formatted;
     formatter_->format(msg, formatted);
-    ::fwrite(formatted.data(), sizeof(char), formatted.size(), file_);
-#endif                // WIN32
+    details::os::fwrite_bytes(formatted.data(), formatted.size(), file_);
+#endif                // _WIN32
     ::fflush(file_);  // flush every line to terminal
 }
 


=====================================
include/spdlog/tweakme.h
=====================================
@@ -104,6 +104,13 @@
 //
 // #define SPDLOG_LEVEL_NAMES { "MY TRACE", "MY DEBUG", "MY INFO", "MY WARNING", "MY ERROR", "MY
 // CRITICAL", "OFF" }
+//
+// For C++17 use string_view_literals:
+//
+// #include <string_view>
+// using namespace std::string_view_literals;
+// #define SPDLOG_LEVEL_NAMES { "MY TRACE"sv, "MY DEBUG"sv, "MY INFO"sv, "MY WARNING"sv, "MY ERROR"sv, "MY
+// CRITICAL"sv, "OFF"sv }
 ///////////////////////////////////////////////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////////


=====================================
include/spdlog/version.h
=====================================
@@ -5,7 +5,7 @@
 
 #define SPDLOG_VER_MAJOR 1
 #define SPDLOG_VER_MINOR 15
-#define SPDLOG_VER_PATCH 0
+#define SPDLOG_VER_PATCH 1
 
 #define SPDLOG_TO_VERSION(major, minor, patch) (major * 10000 + minor * 100 + patch)
 #define SPDLOG_VERSION SPDLOG_TO_VERSION(SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH)


=====================================
src/bundled_fmtlib_format.cpp
=====================================
@@ -18,7 +18,8 @@ template FMT_API auto dragonbox::to_decimal(float x) noexcept
 template FMT_API auto dragonbox::to_decimal(double x) noexcept
     -> dragonbox::decimal_fp<double>;
 
-#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
+#if FMT_USE_LOCALE
+// DEPRECATED! locale_ref in the detail namespace
 template FMT_API locale_ref::locale_ref(const std::locale& loc);
 template FMT_API auto locale_ref::get<std::locale>() const -> std::locale;
 #endif
@@ -29,8 +30,10 @@ template FMT_API auto thousands_sep_impl(locale_ref)
     -> thousands_sep_result<char>;
 template FMT_API auto decimal_point_impl(locale_ref) -> char;
 
+// DEPRECATED!
 template FMT_API void buffer<char>::append(const char*, const char*);
 
+// DEPRECATED!
 template FMT_API void vformat_to(buffer<char>&, string_view,
                                  typename vformat_args<>::type, locale_ref);
 
@@ -45,4 +48,5 @@ template FMT_API void buffer<wchar_t>::append(const wchar_t*, const wchar_t*);
 }  // namespace detail
 FMT_END_NAMESPACE
 
+
 #endif  // !SPDLOG_FMT_EXTERNAL


=====================================
tests/CMakeLists.txt
=====================================
@@ -48,7 +48,8 @@ set(SPDLOG_UTESTS_SOURCES
     test_cfg.cpp
     test_time_point.cpp
     test_stopwatch.cpp
-    test_circular_q.cpp)
+    test_circular_q.cpp
+    test_bin_to_hex.cpp)
 
 if(NOT SPDLOG_NO_EXCEPTIONS)
     list(APPEND SPDLOG_UTESTS_SOURCES test_errors.cpp)
@@ -58,10 +59,6 @@ if(systemd_FOUND)
     list(APPEND SPDLOG_UTESTS_SOURCES test_systemd.cpp)
 endif()
 
-if(NOT SPDLOG_USE_STD_FORMAT)
-    list(APPEND SPDLOG_UTESTS_SOURCES test_bin_to_hex.cpp)
-endif()
-
 enable_testing()
 
 function(spdlog_prepare_test test_target spdlog_lib)


=====================================
tests/test_cfg.cpp
=====================================
@@ -19,6 +19,15 @@ TEST_CASE("env", "[cfg]") {
 #endif
     load_env_levels();
     REQUIRE(l1->level() == spdlog::level::warn);
+
+#ifdef CATCH_PLATFORM_WINDOWS
+    _putenv_s("MYAPP_LEVEL", "l1=trace");
+#else
+    setenv("MYAPP_LEVEL", "l1=trace", 1);
+#endif
+    load_env_levels("MYAPP_LEVEL");
+    REQUIRE(l1->level() == spdlog::level::trace);
+
     spdlog::set_default_logger(spdlog::create<test_sink_st>("cfg-default"));
     REQUIRE(spdlog::default_logger()->level() == spdlog::level::info);
 }


=====================================
tests/test_custom_callbacks.cpp
=====================================
@@ -16,7 +16,8 @@ TEST_CASE("custom_callback_logger", "[custom_callback_logger]") {
             spdlog::memory_buf_t formatted;
             formatter.format(msg, formatted);
             auto eol_len = strlen(spdlog::details::os::default_eol);
-            lines.emplace_back(formatted.begin(), formatted.end() - eol_len);
+            using diff_t = typename std::iterator_traits<decltype(formatted.end())>::difference_type; 
+            lines.emplace_back(formatted.begin(), formatted.end() - static_cast<diff_t>(eol_len));
         });
     std::shared_ptr<spdlog::sinks::test_sink_st> test_sink(new spdlog::sinks::test_sink_st);
 


=====================================
tests/test_daily_logger.cpp
=====================================
@@ -46,12 +46,10 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger]") {
 
 struct custom_daily_file_name_calculator {
     static spdlog::filename_t calc_filename(const spdlog::filename_t &basename, const tm &now_tm) {
-        filename_memory_buf_t w;
-        spdlog::fmt_lib::format_to(std::back_inserter(w), SPDLOG_FILENAME_T("{}{:04d}{:02d}{:02d}"),
+        
+        return spdlog::fmt_lib::format(SPDLOG_FILENAME_T("{}{:04d}{:02d}{:02d}"),
                                    basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1,
-                                   now_tm.tm_mday);
-
-        return SPDLOG_BUF_TO_STRING(w);
+                                   now_tm.tm_mday);        
     }
 };
 


=====================================
tests/test_file_logging.cpp
=====================================
@@ -45,6 +45,26 @@ TEST_CASE("flush_on", "[flush_on]") {
                                     default_eol, default_eol, default_eol));
 }
 
+TEST_CASE("simple_file_logger", "[truncate]") {
+    prepare_logdir();
+    const spdlog::filename_t filename = SPDLOG_FILENAME_T(SIMPLE_LOG);
+    const bool truncate = true;
+    const auto sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, truncate);
+    const auto logger = std::make_shared<spdlog::logger>("simple_file_logger", sink);
+
+    logger->info("Test message {}", 3.14);
+    logger->info("Test message {}", 2.71);
+    logger->flush();
+    REQUIRE(count_lines(SIMPLE_LOG) == 2);
+    
+    sink->truncate();
+    REQUIRE(count_lines(SIMPLE_LOG) == 0);
+
+    logger->info("Test message {}", 6.28);
+    logger->flush();
+    REQUIRE(count_lines(SIMPLE_LOG) == 1);
+}
+
 TEST_CASE("rotating_file_logger1", "[rotating_logger]") {
     prepare_logdir();
     size_t max_size = 1024 * 10;
@@ -101,3 +121,23 @@ TEST_CASE("rotating_file_logger3", "[rotating_logger]") {
     REQUIRE_THROWS_AS(spdlog::rotating_logger_mt("logger", basename, max_size, 0),
                       spdlog::spdlog_ex);
 }
+
+// test on-demand rotation of logs
+TEST_CASE("rotating_file_logger4", "[rotating_logger]") {
+    prepare_logdir();
+    size_t max_size = 1024 * 10;
+    spdlog::filename_t basename = SPDLOG_FILENAME_T(ROTATING_LOG);
+    auto sink = std::make_shared<spdlog::sinks::rotating_file_sink_st>(basename, max_size, 2);
+    auto logger = std::make_shared<spdlog::logger>("rotating_sink_logger", sink);
+
+    logger->info("Test message - pre-rotation");
+    logger->flush();
+
+    sink->rotate_now();
+
+    logger->info("Test message - post-rotation");
+    logger->flush();
+
+    REQUIRE(get_filesize(ROTATING_LOG) > 0);
+    REQUIRE(get_filesize(ROTATING_LOG ".1") > 0);
+}


=====================================
tests/test_misc.cpp
=====================================
@@ -1,3 +1,7 @@
+#ifdef _WIN32 // to prevent fopen warning on windows
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
 #include "includes.h"
 #include "test_sink.h"
 
@@ -185,3 +189,34 @@ TEST_CASE("utf8 to utf16 conversion using windows api", "[windows utf]") {
     REQUIRE(std::wstring(buffer.data(), buffer.size()) == std::wstring(L"\x306d\x3053"));
 }
 #endif
+
+struct auto_closer {
+    FILE* fp = nullptr;
+    explicit auto_closer(FILE* f) : fp(f) {}
+    auto_closer(const auto_closer&) = delete;
+    auto_closer& operator=(const auto_closer&) = delete;
+    ~auto_closer() {
+        if (fp != nullptr) (void)std::fclose(fp);
+    }
+};
+
+TEST_CASE("os::fwrite_bytes", "[os]") {
+    using spdlog::details::os::fwrite_bytes;
+    using spdlog::details::os::create_dir;
+    const char* filename = "log_tests/test_fwrite_bytes.txt";
+    const char *msg = "hello";
+    prepare_logdir();
+    REQUIRE(create_dir(SPDLOG_FILENAME_T("log_tests")) == true);
+    {
+        auto_closer closer(std::fopen(filename, "wb"));
+        REQUIRE(closer.fp != nullptr);
+        REQUIRE(fwrite_bytes(msg, std::strlen(msg), closer.fp) == true);
+        REQUIRE(fwrite_bytes(msg, 0, closer.fp) == true);
+        std::fflush(closer.fp);
+        REQUIRE(spdlog::details::os::filesize(closer.fp) == 5);
+    }
+    // fwrite_bytes should return false on write failure
+    auto_closer closer(std::fopen(filename, "r"));
+    REQUIRE(closer.fp != nullptr);
+    REQUIRE_FALSE(fwrite_bytes("Hello", 5, closer.fp));
+}


=====================================
tests/test_sink.h
=====================================
@@ -47,8 +47,9 @@ protected:
         base_sink<Mutex>::formatter_->format(msg, formatted);
         // save the line without the eol
         auto eol_len = strlen(details::os::default_eol);
+        using diff_t = typename std::iterator_traits<decltype(formatted.end())>::difference_type; 
         if (lines_.size() < lines_to_save) {
-            lines_.emplace_back(formatted.begin(), formatted.end() - eol_len);
+            lines_.emplace_back(formatted.begin(), formatted.end() - static_cast<diff_t>(eol_len));
         }
         msg_counter_++;
         std::this_thread::sleep_for(delay_);



View it on GitLab: https://salsa.debian.org/med-team/spdlog/-/commit/a959b81edde226715e379879250335121466587f

-- 
View it on GitLab: https://salsa.debian.org/med-team/spdlog/-/commit/a959b81edde226715e379879250335121466587f
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20250212/7e4b3373/attachment-0001.htm>


More information about the debian-med-commit mailing list