From 5c614c9fe431b573eb901af9cbda83e65f659086 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 26 Dec 2025 15:45:01 -0600 Subject: [PATCH 1/7] fix: static constexpr -> inline constexpr --- source/include/sio/definitions.h | 32 ++++++++++++++++---------------- source/include/sio/memcpy.h | 4 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/source/include/sio/definitions.h b/source/include/sio/definitions.h index b2921445..c3b285cb 100644 --- a/source/include/sio/definitions.h +++ b/source/include/sio/definitions.h @@ -108,35 +108,35 @@ namespace sio { using block_list = std::vector ; /// The null byte definition - static constexpr byte null_byte = '\0' ; + inline constexpr byte null_byte = '\0' ; - static constexpr byte padding_bytes [4] = {null_byte} ; + inline constexpr byte padding_bytes [4] = {null_byte} ; /// Kilo byte unit - static constexpr std::size_t kbyte = 0x00000400 ; + inline constexpr std::size_t kbyte = 0x00000400 ; /// Mega byte unit - static constexpr std::size_t mbyte = 0x00100000 ; + inline constexpr std::size_t mbyte = 0x00100000 ; /// The compression bit mask - static constexpr unsigned int compression_bit = 0x00000001 ; + inline constexpr unsigned int compression_bit = 0x00000001 ; /// The bit alignment mask - static constexpr unsigned int bit_align = 0x00000003 ; + inline constexpr unsigned int bit_align = 0x00000003 ; /// The additional padding added in buffer IO - static constexpr unsigned int padding = 3 ; + inline constexpr unsigned int padding = 3 ; /// The additional padding mask - static constexpr unsigned int padding_mask = 0xfffffffc ; + inline constexpr unsigned int padding_mask = 0xfffffffc ; /// The record marker - static constexpr unsigned int record_marker = 0xabadcafe ; + inline constexpr unsigned int record_marker = 0xabadcafe ; /// The block marker - static constexpr unsigned int block_marker = 0xdeadbeef ; + inline constexpr unsigned int block_marker = 0xdeadbeef ; /// The maximum length of a record name - static constexpr std::size_t max_record_name_len = 64 ; + inline constexpr std::size_t max_record_name_len = 64 ; /// The maximum length of a record_info in memory - static constexpr std::size_t max_record_info_len = 2*sizeof(sio::ifstream::pos_type) + 5*sizeof(unsigned int) + max_record_name_len ; + inline constexpr std::size_t max_record_info_len = 2*sizeof(sio::ifstream::pos_type) + 5*sizeof(unsigned int) + max_record_name_len ; // TODO: Do we still need all of this ?? - static constexpr std::size_t single_len = 1 ; - static constexpr std::size_t double_len = 2 ; - static constexpr std::size_t quad_len = 4 ; - static constexpr std::size_t octo_len = 8 ; + inline constexpr std::size_t single_len = 1 ; + inline constexpr std::size_t double_len = 2 ; + inline constexpr std::size_t quad_len = 4 ; + inline constexpr std::size_t octo_len = 8 ; /** * @brief record_info struct. diff --git a/source/include/sio/memcpy.h b/source/include/sio/memcpy.h index 93bf79cd..5744a587 100644 --- a/source/include/sio/memcpy.h +++ b/source/include/sio/memcpy.h @@ -16,13 +16,13 @@ namespace sio { */ template struct sizeof_helper { - static constexpr std::size_t size = sizeof(T) ; + inline static constexpr std::size_t size = sizeof(T) ; }; #define SIO_FORCE_SIZEOF( TYPE, SIZE ) \ template <> \ struct sizeof_helper { \ - static constexpr std::size_t size = SIZE ; \ + inline static constexpr std::size_t size = SIZE ; \ } SIO_FORCE_SIZEOF( char, 1 ) ; From 4c095b031311a94419fb0dd555ee0ca7dc83c10f Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 26 Dec 2025 15:45:41 -0600 Subject: [PATCH 2/7] feat: module exports for core SIO types and interfaces --- source/src/sio_module.ixx | 109 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 source/src/sio_module.ixx diff --git a/source/src/sio_module.ixx b/source/src/sio_module.ixx new file mode 100644 index 00000000..948634b7 --- /dev/null +++ b/source/src/sio_module.ixx @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Module interface for SIO - Simple I/O library +// +// This module exports the core SIO types and interfaces. + +module; + +// Global module fragment - includes go here +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#include <_types.h> +#include <_types/_uint16_t.h> +#include <_types/_uint32_t.h> +#include <_types/_uint64_t.h> +#include <_types/_uint8_t.h> +#include +#include +#else +#include +#endif + +// SIO headers +#include "sio/definitions.h" +#include "sio/exception.h" +#include "sio/version.h" +#include "sio/buffer.h" +#include "sio/block.h" +#include "sio/io_device.h" +#include "sio/memcpy.h" +#include "sio/api.h" +#include "sio/compression/zlib.h" + +export module sio; + +// Export SIO namespace and types +export namespace sio { + // Type aliases from definitions.h + using sio::byte; + using sio::byte_array; + using sio::byte_traits; + using sio::index_type; + using sio::options_type; + using sio::version_type; + using sio::ptr_type; + using sio::pointed_at_map; + using sio::pointer_to_map; + using sio::ifstream; + using sio::ofstream; + using sio::fstream; + using sio::block_ptr; + using sio::block_list; + + // Constants from definitions.h + using sio::null_byte; + using sio::padding_bytes; + using sio::kbyte; + using sio::mbyte; + using sio::compression_bit; + using sio::bit_align; + using sio::padding; + using sio::padding_mask; + using sio::record_marker; + using sio::block_marker; + using sio::max_record_name_len; + using sio::max_record_info_len; + using sio::single_len; + using sio::double_len; + using sio::quad_len; + using sio::octo_len; + + // Structs and enums from definitions.h + using sio::record_info; + using sio::validate; + using sio::valid_record_name; + + // Exception types + using sio::exception; + using sio::error_code; + + // Version class + using sio::version; + + // Core classes + using sio::buffer; + using sio::buffer_span; + using sio::block; + using sio::read_device; + using sio::write_device; + + // Memory copy utilities + using sio::memcpy; + using sio::sizeof_helper; + + // API class and functions + using sio::api; + + // Compression + using sio::zlib_compression; +} From 030b69a7890993b5f47cefa4558d55b2199e4a71 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 26 Dec 2025 15:51:35 -0600 Subject: [PATCH 3/7] feat: support SIO_ENABLE_CXX_MODULES CMake option (default OFF) --- CMakeLists.txt | 10 ++++++ cmake/SIOModules.cmake | 74 ++++++++++++++++++++++++++++++++++++++++++ source/CMakeLists.txt | 22 +++++++++++-- 3 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 cmake/SIOModules.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index b130e10d..56cbc7e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,9 @@ INCLUDE(GNUInstallDirs) LIST( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ) +# Load C++20 module support +INCLUDE( SIOModules ) + # options OPTION( SIO_EXAMPLES "Switch ON to build SIO examples" ON ) OPTION( INSTALL_DOC "Set to OFF to skip build/install Documentation" OFF ) @@ -38,6 +41,13 @@ ENDIF() # ZLIB package IF( SIO_BUILTIN_ZLIB ) ADD_SUBDIRECTORY( zlib ) + # Install ZLIB when SIO modules are enabled (needed for export) + IF( SIO_ENABLE_CXX_MODULES ) + INSTALL( TARGETS ZLIB + EXPORT SIOTargets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + ENDIF() ELSE() FIND_PACKAGE( ZLIB REQUIRED ) ENDIF() diff --git a/cmake/SIOModules.cmake b/cmake/SIOModules.cmake new file mode 100644 index 00000000..4aa2df4d --- /dev/null +++ b/cmake/SIOModules.cmake @@ -0,0 +1,74 @@ +#--------------------------------------------------------------------------------------------------- +# CMake support for C++20 modules in SIO +# +# This file provides macros and options for generating and using C++20 module interfaces +# for the SIO library. +#--------------------------------------------------------------------------------------------------- + +# Option to enable C++20 module generation +option(SIO_ENABLE_CXX_MODULES "Generate C++20 module interface files (.ixx) for SIO" OFF) + +# Check if modules are actually supported +if(SIO_ENABLE_CXX_MODULES) + # Check CMake version + if(CMAKE_VERSION VERSION_LESS 3.29) + message(WARNING "C++20 modules require CMake 3.29 or later (found ${CMAKE_VERSION}). Disabling module support.") + set(SIO_ENABLE_CXX_MODULES OFF CACHE BOOL "C++20 modules disabled due to CMake version" FORCE) + endif() + + # Check generator + if(CMAKE_GENERATOR STREQUAL "Unix Makefiles") + message(WARNING "C++20 modules are not supported with the Unix Makefiles generator. Please use Ninja. Disabling module support.") + set(SIO_ENABLE_CXX_MODULES OFF CACHE BOOL "C++20 modules disabled due to generator" FORCE) + endif() + + # Check compiler support + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14.0) + message(WARNING "C++20 modules require GCC 14 or later (found ${CMAKE_CXX_COMPILER_VERSION}). Disabling module support.") + set(SIO_ENABLE_CXX_MODULES OFF CACHE BOOL "C++20 modules disabled due to compiler version" FORCE) + endif() + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0) + message(WARNING "C++20 modules require Clang 18 or later (found ${CMAKE_CXX_COMPILER_VERSION}). Disabling module support.") + set(SIO_ENABLE_CXX_MODULES OFF CACHE BOOL "C++20 modules disabled due to compiler version" FORCE) + endif() + else() + message(WARNING "C++20 modules have only been tested with GCC 14+ and Clang 18+. Found ${CMAKE_CXX_COMPILER_ID}. Proceed at your own risk.") + endif() +endif() + +if(SIO_ENABLE_CXX_MODULES) + message(STATUS "C++20 module support is ENABLED for SIO") + message(STATUS " - CMake version: ${CMAKE_VERSION}") + message(STATUS " - Generator: ${CMAKE_GENERATOR}") + message(STATUS " - Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") +else() + message(STATUS "C++20 module support is DISABLED for SIO") +endif() + +#--------------------------------------------------------------------------------------------------- +# SIO_ADD_MODULE_INTERFACE( target module_file ) +# +# Add a C++20 module interface to the SIO target +# +# Arguments: +# target - The target to which the module should be added +# module_file - The .ixx file implementing the module interface +#--------------------------------------------------------------------------------------------------- +function(SIO_ADD_MODULE_INTERFACE target module_file) + if(NOT SIO_ENABLE_CXX_MODULES) + return() + endif() + + message(STATUS "Adding C++20 module 'sio' to target '${target}'") + + # Add the module file to the target as a CXX_MODULES file set + # Use PUBLIC so the module gets installed and can be used by downstream projects + target_sources(${target} + PUBLIC + FILE_SET CXX_MODULES + BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} + FILES ${module_file} + ) +endfunction() diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 4333e448..a94375b6 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -26,9 +26,25 @@ IF( SIO_MACROS_WITH_EXCEPTION ) TARGET_COMPILE_DEFINITIONS(sio PUBLIC "-DSIO_MACROS_WITH_EXCEPTION=1") ENDIF() -SIO_INSTALL_SHARED_LIBRARY( sio - EXPORT SIOTargets - DESTINATION ${CMAKE_INSTALL_LIBDIR} ) +# Add C++20 module interface if enabled (before install) +IF( SIO_ENABLE_CXX_MODULES ) + SIO_ADD_MODULE_INTERFACE( sio ${CMAKE_CURRENT_SOURCE_DIR}/src/sio_module.ixx ) + # Install library with module file set + INSTALL( TARGETS sio + EXPORT SIOTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + FILE_SET CXX_MODULES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sio + PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + ) +ELSE() + # Install library without modules + SIO_INSTALL_SHARED_LIBRARY( sio + EXPORT SIOTargets + DESTINATION ${CMAKE_INSTALL_LIBDIR} ) +ENDIF() # install SIO headers SIO_INSTALL_DIRECTORY( include/sio DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) From 61d31a288424030717cf77bf975b67c3afbd8671 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 26 Dec 2025 16:03:49 -0600 Subject: [PATCH 4/7] fix: mv sio_module.ixx to ensure canonical install path --- source/CMakeLists.txt | 4 ++-- source/{src => }/sio_module.ixx | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename source/{src => }/sio_module.ixx (100%) diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index a94375b6..202975cd 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -28,12 +28,12 @@ ENDIF() # Add C++20 module interface if enabled (before install) IF( SIO_ENABLE_CXX_MODULES ) - SIO_ADD_MODULE_INTERFACE( sio ${CMAKE_CURRENT_SOURCE_DIR}/src/sio_module.ixx ) + SIO_ADD_MODULE_INTERFACE( sio ${CMAKE_CURRENT_SOURCE_DIR}/sio_module.ixx ) # Install library with module file set INSTALL( TARGETS sio EXPORT SIOTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - FILE_SET CXX_MODULES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sio + FILE_SET CXX_MODULES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sio/modules PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE diff --git a/source/src/sio_module.ixx b/source/sio_module.ixx similarity index 100% rename from source/src/sio_module.ixx rename to source/sio_module.ixx From 39f23e5d64eaa2ec5e76c649a1ef101826a46fd3 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 26 Dec 2025 17:08:49 -0600 Subject: [PATCH 5/7] fix: use conventional static inline constexpr ordering --- source/include/sio/memcpy.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/include/sio/memcpy.h b/source/include/sio/memcpy.h index 5744a587..ab03f832 100644 --- a/source/include/sio/memcpy.h +++ b/source/include/sio/memcpy.h @@ -16,13 +16,13 @@ namespace sio { */ template struct sizeof_helper { - inline static constexpr std::size_t size = sizeof(T) ; + static inline constexpr std::size_t size = sizeof(T) ; }; #define SIO_FORCE_SIZEOF( TYPE, SIZE ) \ template <> \ struct sizeof_helper { \ - inline static constexpr std::size_t size = SIZE ; \ + static inline constexpr std::size_t size = SIZE ; \ } SIO_FORCE_SIZEOF( char, 1 ) ; From f16fa9f6365c9cb35400899233049a29becd47eb Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 26 Dec 2025 17:25:44 -0600 Subject: [PATCH 6/7] docs: improve cmake SIO_ADD_MODULE_INTERFACE documentation --- cmake/SIOModules.cmake | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/cmake/SIOModules.cmake b/cmake/SIOModules.cmake index 4aa2df4d..655bdc7d 100644 --- a/cmake/SIOModules.cmake +++ b/cmake/SIOModules.cmake @@ -50,11 +50,24 @@ endif() #--------------------------------------------------------------------------------------------------- # SIO_ADD_MODULE_INTERFACE( target module_file ) # -# Add a C++20 module interface to the SIO target +# Add a C++20 module interface to a SIO target. +# +# This function conditionally adds a module interface file to the specified target when +# SIO_ENABLE_CXX_MODULES is ON. The module interface is added as a PUBLIC CXX_MODULES file set, +# which makes it available for installation and use by downstream projects. +# +# When SIO_ENABLE_CXX_MODULES is OFF, this function returns immediately without any action. # # Arguments: -# target - The target to which the module should be added -# module_file - The .ixx file implementing the module interface +# target - The target to which the module interface should be added +# module_file - The .ixx file implementing the module interface (absolute or relative path) +# +# Example: +# SIO_ADD_MODULE_INTERFACE(sio ${CMAKE_CURRENT_SOURCE_DIR}/sio_module.ixx) +# +# Note: +# The module_file should be installed separately using INSTALL(TARGETS ... FILE_SET CXX_MODULES) +# when SIO_ENABLE_CXX_MODULES is ON. #--------------------------------------------------------------------------------------------------- function(SIO_ADD_MODULE_INTERFACE target module_file) if(NOT SIO_ENABLE_CXX_MODULES) From 4a2a337b0925115e260ca66bbdce46274af1d816 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 26 Dec 2025 18:27:11 -0600 Subject: [PATCH 7/7] docs: add comment about SIO::ZLIB target visibility --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 56cbc7e7..9a0475d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,9 @@ ENDIF() IF( SIO_BUILTIN_ZLIB ) ADD_SUBDIRECTORY( zlib ) # Install ZLIB when SIO modules are enabled (needed for export) + # Note: This makes ZLIB visible to downstream users as SIO::ZLIB when modules are enabled. + # This is required by CMake's export mechanism for targets with FILE_SET CXX_MODULES. + # The ZLIB target is static and should not conflict with system ZLIB libraries. IF( SIO_ENABLE_CXX_MODULES ) INSTALL( TARGETS ZLIB EXPORT SIOTargets