diff --git a/CMakeLists.txt b/CMakeLists.txt index 168c0dbf..3a00eb10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,7 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules) include(GNUInstallDirs) include(CTest) -include(Sqlpp23TargetHelper) +include(sqlpp23_target_helper) option(BUILD_MYSQL_CONNECTOR "Build MySQL Connector" OFF) option(BUILD_MARIADB_CONNECTOR "Build MariaDB Connector" OFF) diff --git a/cmake/Sqlpp23TargetHelper.cmake b/cmake/sqlpp23_target_helper.cmake similarity index 92% rename from cmake/Sqlpp23TargetHelper.cmake rename to cmake/sqlpp23_target_helper.cmake index 35f3eb87..6b5600c9 100644 --- a/cmake/Sqlpp23TargetHelper.cmake +++ b/cmake/sqlpp23_target_helper.cmake @@ -130,11 +130,15 @@ function(add_common) # Initialize helper variables based on target type (regular or module) if(ARG_MODULE_INTERFACE) set(TARGET_SUFFIX "_module") - # FILE_SETs of type CXX_MODULES cannot have the INTERFACE scope (exept - # on IMPORTED targets) and INTERFACE libraries only allow INTERFACE - # scope on their properties. That's why we cannot use the INTERFACE - # library type. For details see the discussion at - # https://discourse.cmake.org/t/header-only-libraries-and-c-20-modules/10680/11 + # CMake has the following two limitations: + # - FILE_SETs of type CXX_MODULES cannot have the INTERFACE scope (except on IMPORTED targets). + # - INTERFACE libraries only allow INTERFACE scope on their properties. + # From these two limitations it follows that INTERFACE libraries cannot have FILE_SETs of type + # CXX_MODULES. That's why, as a workaround, we use an OBJECT library. + # + # For details see the discussion at + # https://discourse.cmake.org/t/header-only-libraries-and-c-20-modules/10680 + # where the CMake devs explain that this limitation exists to prevent possible ODR violations. set(LIB_TYPE OBJECT) set(LIB_PROP_SCOPE PUBLIC) else() diff --git a/cmake/sqlpp23_testing_helper.cmake b/cmake/sqlpp23_testing_helper.cmake new file mode 100644 index 00000000..becee726 --- /dev/null +++ b/cmake/sqlpp23_testing_helper.cmake @@ -0,0 +1,60 @@ +# Copyright (c) 2026, Vesselin Atanasov +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +function(add_testing_target) + set(options) + set(oneValueArgs NAME) + set(multiValueArgs DEFINES MOD_DEPS) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(BUILD_WITH_MODULES) + # We are building with modules, so the _testing target created by this function MUST be a regular + # (non-INTERFACE) library. Otherwise, the object files owned by the OBJECT library dependencies + # in MOD_DEPS won't be linked, and we are going to get missing symbols during the linking (namely + # the static module initializer function won't be found). + # + # For details on how OBJECT libraries are linked see + # https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#object-libraries + # https://cmake.org/cmake/help/latest/command/target_link_libraries.html#linking-object-libraries + set(LIB_TYPE) + set(LIB_PROP_SCOPE PUBLIC) + else() + # We are building without modules and the _testing target created by this function won't have any + # compiled files, and CMake will not let us build a empty regular (non-INTERFACE) library. So in + # this case we have to use an INTERFACE library. + set(LIB_TYPE INTERFACE) + set(LIB_PROP_SCOPE INTERFACE) + endif() + set(TARGET_NAME "sqlpp23_${ARG_NAME}_testing") + add_library(${TARGET_NAME} ${LIB_TYPE}) + if(ARG_DEFINES) + target_compile_definitions(${TARGET_NAME} ${LIB_PROP_SCOPE} ${ARG_DEFINES}) + endif() + target_link_libraries(${TARGET_NAME} ${LIB_PROP_SCOPE} sqlpp23_testing) + if(BUILD_WITH_MODULES) + set(MOD_FILE "${PROJECT_SOURCE_DIR}/tests/${ARG_NAME}/modules/sqlpp23.test.${ARG_NAME}.tables.cppm") + target_sources(${TARGET_NAME} PUBLIC FILE_SET CXX_MODULES FILES "${MOD_FILE}") + target_link_libraries(${TARGET_NAME} PUBLIC sqlpp23::core_module ${ARG_MOD_DEPS}) + endif() +endfunction() diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index cf7eac9d..7ff9da39 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -22,30 +22,9 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -if(BUILD_WITH_MODULES) - add_library(sqlpp23.test.core.tables.module) - target_sources(sqlpp23.test.core.tables.module - PUBLIC - FILE_SET all_my_modules TYPE CXX_MODULES FILES - modules/sqlpp23.test.core.tables.cppm - ) - target_link_libraries(sqlpp23.test.core.tables.module PUBLIC sqlpp23::core_module) -endif() +include(sqlpp23_testing_helper) -add_library(sqlpp23_core_testing INTERFACE) -target_include_directories(sqlpp23_core_testing INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) - -if(BUILD_WITH_MODULES) - target_link_libraries(sqlpp23_core_testing INTERFACE - sqlpp23_testing - sqlpp23::mock_db_module - sqlpp23.test.core.tables.module - ) -else() - target_link_libraries(sqlpp23_core_testing INTERFACE - sqlpp23_testing - ) -endif() +add_testing_target(NAME core MOD_DEPS sqlpp23::mock_db_module) add_subdirectory(asserts) add_subdirectory(constraints) diff --git a/tests/mysql/CMakeLists.txt b/tests/mysql/CMakeLists.txt index 828b1306..cd73eafa 100644 --- a/tests/mysql/CMakeLists.txt +++ b/tests/mysql/CMakeLists.txt @@ -22,34 +22,15 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -if(BUILD_WITH_MODULES) - add_library(sqlpp23.test.mysql.tables.module) - target_sources(sqlpp23.test.mysql.tables.module - PUBLIC - FILE_SET all_my_modules TYPE CXX_MODULES FILES - modules/sqlpp23.test.mysql.tables.cppm - ) - target_link_libraries(sqlpp23.test.mysql.tables.module PUBLIC sqlpp23::core_module) -endif() +include(sqlpp23_testing_helper) find_package(Threads REQUIRED) -add_library(sqlpp23_mysql_testing INTERFACE) -target_include_directories(sqlpp23_mysql_testing INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) -if(BUILD_WITH_MODULES) - target_link_libraries(sqlpp23_mysql_testing INTERFACE - sqlpp23_testing - sqlpp23::mysql_module - sqlpp23.test.mysql.tables.module - ) -else() - target_link_libraries(sqlpp23_mysql_testing INTERFACE - sqlpp23_testing - ) -endif() +set(DEFINES) if (MSVC) - target_compile_options(sqlpp23_mysql_testing INTERFACE -DNOMINMAX) + list(APPEND DEFINES -DNOMINMAX) endif () +add_testing_target(NAME mysql DEFINES ${DEFINES} MOD_DEPS sqlpp23::mysql_module) add_subdirectory(asserts) add_subdirectory(constraints) diff --git a/tests/postgresql/CMakeLists.txt b/tests/postgresql/CMakeLists.txt index d4eff8dd..0f358ba8 100644 --- a/tests/postgresql/CMakeLists.txt +++ b/tests/postgresql/CMakeLists.txt @@ -22,30 +22,9 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -if(BUILD_WITH_MODULES) - add_library(sqlpp23.test.postgresql.tables.module) - target_sources(sqlpp23.test.postgresql.tables.module - PUBLIC - FILE_SET all_my_modules TYPE CXX_MODULES FILES - modules/sqlpp23.test.postgresql.tables.cppm - ) - target_link_libraries(sqlpp23.test.postgresql.tables.module PUBLIC sqlpp23::core_module) -endif() +include(sqlpp23_testing_helper) -add_library(sqlpp23_postgresql_testing INTERFACE) -target_include_directories(sqlpp23_postgresql_testing INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) - -if(BUILD_WITH_MODULES) - target_link_libraries(sqlpp23_postgresql_testing INTERFACE - sqlpp23_testing - sqlpp23::postgresql_module - sqlpp23.test.postgresql.tables.module - ) -else() - target_link_libraries(sqlpp23_postgresql_testing INTERFACE - sqlpp23_testing - ) -endif() +add_testing_target(NAME postgresql MOD_DEPS sqlpp23::postgresql_module) add_subdirectory(asserts) add_subdirectory(constraints) diff --git a/tests/sqlite3/CMakeLists.txt b/tests/sqlite3/CMakeLists.txt index 9cffd503..59a34883 100644 --- a/tests/sqlite3/CMakeLists.txt +++ b/tests/sqlite3/CMakeLists.txt @@ -22,38 +22,17 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -if(BUILD_WITH_MODULES) - add_library(sqlpp23.test.sqlite3.tables.module) - target_sources(sqlpp23.test.sqlite3.tables.module - PUBLIC - FILE_SET all_my_modules TYPE CXX_MODULES FILES - modules/sqlpp23.test.sqlite3.tables.cppm - ) - target_link_libraries(sqlpp23.test.sqlite3.tables.module PUBLIC sqlpp23::core_module) -endif() +include(sqlpp23_testing_helper) -add_library(sqlpp23_sqlite3_testing INTERFACE) -target_include_directories(sqlpp23_sqlite3_testing INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) - -if(BUILD_WITH_MODULES) - target_link_libraries(sqlpp23_sqlite3_testing INTERFACE - sqlpp23_testing - sqlpp23::sqlite3_module - sqlpp23.test.sqlite3.tables.module - ) -else() - target_link_libraries(sqlpp23_sqlite3_testing INTERFACE - sqlpp23_testing - ) -endif() +add_testing_target(NAME sqlite3 MOD_DEPS sqlpp23::sqlite3_module) function(sqlpp_slite3_test_add_target_link_libraries name) -target_link_libraries(${name} PRIVATE sqlpp23_testing sqlpp23_sqlite3_testing) -if (BUILD_SQLCIPHER_CONNECTOR) - target_link_libraries(${name} PRIVATE sqlpp23::sqlcipher) -else() - target_link_libraries(${name} PRIVATE sqlpp23::sqlite3) -endif() + target_link_libraries(${name} PRIVATE sqlpp23_testing sqlpp23_sqlite3_testing) + if (BUILD_SQLCIPHER_CONNECTOR) + target_link_libraries(${name} PRIVATE sqlpp23::sqlcipher) + else() + target_link_libraries(${name} PRIVATE sqlpp23::sqlite3) + endif() endfunction() add_subdirectory(asserts)