From d94e18b7c0358886cba0b613531043d6e39743ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szo=C5=82ucha?= Date: Sun, 22 Feb 2026 01:47:12 +0100 Subject: [PATCH 1/5] Add CMake build system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MichaÅ‚ SzoÅ‚ucha --- .gitignore | 1 + CMakeLists.txt | 348 +++++++++++++++++++++++++++++++++++++++ cmake/ddsConfig.cmake.in | 5 + examples/CMakeLists.txt | 33 ++++ test/CMakeLists.txt | 40 +++++ 5 files changed, 427 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 cmake/ddsConfig.cmake.in create mode 100644 examples/CMakeLists.txt create mode 100644 test/CMakeLists.txt diff --git a/.gitignore b/.gitignore index 3265db34..6d270eff 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ test/[Mm]akefile examples/[Mm]akefile test/dtest test/itest +build/ *.exe *.swp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..44411f22 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,348 @@ +cmake_minimum_required(VERSION 3.16) + +project(dds + VERSION 2.9.0 + DESCRIPTION "Double Dummy Solver for Contract Bridge" + HOMEPAGE_URL "https://github.com/dds-bridge/dds" + LANGUAGES CXX +) + +# ============================================================ +# Build options +# ============================================================ + +option(BUILD_SHARED_LIBS "Build shared library instead of static" ON) + +# Threading backends — multiple can be enabled simultaneously. +# The library selects the highest-priority available one at run time +# (priority order: WinAPI > OpenMP > GCD > Boost > STL; see System.cpp). +option(DDS_THREADS_BOOST "Use Boost threading backend" OFF) +option(DDS_THREADS_OPENMP "Use OpenMP threading backend" OFF) +option(DDS_THREADS_STL "Use C++ STL threading backend" OFF) +option(DDS_THREADS_GCD "Use Grand Central Dispatch (macOS only)" OFF) +option(DDS_THREADS_WINAPI "Use Windows API threading (Windows only)" OFF) + +# Optional build features +option(DDS_WERROR "Treat compiler warnings as errors" ON) +option(DDS_SMALL_MEMORY "Reduce memory use at cost of speed" OFF) +option(DDS_ENABLE_DEBUG "Enable all debug output" OFF) +option(DDS_ENABLE_TIMING "Enable timing statistics" OFF) +option(DDS_ENABLE_SCHEDULER "Enable scheduler debug output" OFF) + +# Sub-projects +option(DDS_BUILD_TESTS "Build test program (dtest)" OFF) +option(DDS_BUILD_EXAMPLES "Build example programs" OFF) + +# ============================================================ +# Platform defaults for threading +# Applied only when the user hasn't explicitly requested any backend. +# ============================================================ + +if(NOT DDS_THREADS_BOOST AND + NOT DDS_THREADS_OPENMP AND + NOT DDS_THREADS_STL AND + NOT DDS_THREADS_GCD AND + NOT DDS_THREADS_WINAPI) + if(WIN32) + set(DDS_THREADS_WINAPI ON) + set(DDS_THREADS_OPENMP ON) + set(DDS_THREADS_STL ON) + elseif(APPLE) + set(DDS_THREADS_GCD ON) + set(DDS_THREADS_STL ON) + else() + # Linux / other Unix + set(DDS_THREADS_OPENMP ON) + set(DDS_THREADS_STL ON) + endif() +endif() + +# ============================================================ +# Windows resource file (version info embedded in the DLL) +# ============================================================ + +if(WIN32 AND BUILD_SHARED_LIBS) + enable_language(RC) +endif() + +# ============================================================ +# Library source files +# ============================================================ + +set(DDS_SOURCES + src/dds.cpp + src/ABsearch.cpp + src/ABstats.cpp + src/CalcTables.cpp + src/DealerPar.cpp + src/dump.cpp + src/File.cpp + src/Init.cpp + src/LaterTricks.cpp + src/Memory.cpp + src/Moves.cpp + src/Par.cpp + src/PlayAnalyser.cpp + src/PBN.cpp + src/QuickTricks.cpp + src/Scheduler.cpp + src/SolveBoard.cpp + src/SolverIF.cpp + src/System.cpp + src/ThreadMgr.cpp + src/Timer.cpp + src/TimerGroup.cpp + src/TimerList.cpp + src/TimeStat.cpp + src/TimeStatList.cpp + src/TransTableS.cpp + src/TransTableL.cpp +) + +if(WIN32 AND BUILD_SHARED_LIBS AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/dds.rc") + list(APPEND DDS_SOURCES src/dds.rc) +endif() + +# ============================================================ +# Library target +# ============================================================ + +add_library(dds ${DDS_SOURCES}) +add_library(dds::dds ALIAS dds) + +target_include_directories(dds + PUBLIC + $ + $ + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src +) + +# MSVC: use the module-definition file to control DLL exports +if(WIN32 AND BUILD_SHARED_LIBS AND MSVC) + target_link_options(dds PRIVATE + "/DEF:${CMAKE_CURRENT_SOURCE_DIR}/src/Exports.def" + ) +endif() + +# ============================================================ +# C++ standard +# ============================================================ + +if(MSVC) + # C++17 needed for STLIMPL / parallel STL threading backend + target_compile_features(dds PUBLIC cxx_std_17) +else() + target_compile_features(dds PUBLIC cxx_std_11) +endif() +set_target_properties(dds PROPERTIES CXX_EXTENSIONS OFF) + +# ============================================================ +# Link-time optimisation +# ============================================================ + +include(CheckIPOSupported) +check_ipo_supported(RESULT _ipo_supported OUTPUT _ipo_output) +if(_ipo_supported) + set_target_properties(dds PROPERTIES + INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE + INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE + ) +else() + message(STATUS "IPO/LTO not supported: ${_ipo_output}") +endif() + +# ============================================================ +# Compiler flags +# ============================================================ + +if(MSVC) + target_compile_options(dds PRIVATE + /O2 /Oi /Ot /Oy /Ox /EHs /Qspectre + # Aggressive warnings, suppressing those triggered by Windows / STL headers + /Wall + /wd4365 # signed/unsigned mismatch + /wd4464 # relative include path contains '..' + /wd4514 # unreferenced inline function removed + /wd4555 # expression has no effect + /wd4571 # catch(...) semantics changed + /wd4623 # default constructor implicitly deleted + /wd4625 # copy constructor implicitly deleted + /wd4626 # copy assignment operator implicitly deleted + /wd4668 # symbol not defined as preprocessor macro + /wd4710 # function not inlined + /wd4711 # function selected for automatic inlining + /wd4774 # format string not a string literal + /wd4820 # padding added after data member + /wd4996 # deprecated function + /wd5026 # move constructor implicitly deleted + /wd5027 # move assignment operator implicitly deleted + /wd5045 # Spectre mitigation insertion + $<$:/WX> + ) +else() + # Flags common to GCC and Clang + target_compile_options(dds PRIVATE + -O3 + -Wall -Wextra $<$:-Werror> -pedantic + -Wshadow + -Wsign-conversion + -Wcast-align + -Wcast-qual + -Wctor-dtor-privacy + -Wdisabled-optimization + -Winit-self + -Wmissing-declarations + -Wmissing-include-dirs + -Wold-style-cast + -Woverloaded-virtual + -Wredundant-decls + -Wsign-promo + -Wstrict-overflow=1 + -Wswitch-default + -Wundef + -Wno-unused + -Wno-unknown-pragmas + -Wno-long-long + -Wno-format + ) + + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_compile_options(dds PRIVATE + -Wlogical-op + -Wnoexcept + -Wstrict-null-sentinel + ) + endif() + + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + target_compile_options(dds PRIVATE + -Wcomment + ) + endif() + + # Linker hardening for shared libraries on Linux + if(UNIX AND NOT APPLE AND BUILD_SHARED_LIBS) + target_link_options(dds PRIVATE + -Wl,--sort-common + -Wl,--as-needed + -Wl,-z,relro + ) + endif() +endif() + +# ============================================================ +# Threading backends +# ============================================================ + +if(DDS_THREADS_OPENMP) + find_package(OpenMP REQUIRED) + target_compile_definitions(dds PRIVATE DDS_THREADS_OPENMP) + target_link_libraries(dds PRIVATE OpenMP::OpenMP_CXX) +endif() + +if(DDS_THREADS_BOOST) + find_package(Boost REQUIRED COMPONENTS system thread) + target_compile_definitions(dds PRIVATE DDS_THREADS_BOOST) + target_link_libraries(dds PRIVATE Boost::system Boost::thread) +endif() + +if(DDS_THREADS_STL) + find_package(Threads REQUIRED) + target_compile_definitions(dds PRIVATE DDS_THREADS_STL) + target_link_libraries(dds PRIVATE Threads::Threads) +endif() + +if(DDS_THREADS_GCD) + if(NOT APPLE) + message(FATAL_ERROR "DDS_THREADS_GCD is available on macOS only") + endif() + target_compile_definitions(dds PRIVATE DDS_THREADS_GCD) +endif() + +if(DDS_THREADS_WINAPI) + if(NOT WIN32) + message(FATAL_ERROR "DDS_THREADS_WINAPI is available on Windows only") + endif() + target_compile_definitions(dds PRIVATE DDS_THREADS_WINAPI) +endif() + +# ============================================================ +# Optional behaviour flags +# ============================================================ + +if(DDS_SMALL_MEMORY) + target_compile_definitions(dds PRIVATE SMALL_MEMORY_OPTION) +endif() + +if(DDS_ENABLE_DEBUG) + target_compile_definitions(dds PRIVATE DDS_DEBUG_ALL) +endif() + +if(DDS_ENABLE_TIMING) + target_compile_definitions(dds PRIVATE DDS_TIMING) +endif() + +if(DDS_ENABLE_SCHEDULER) + target_compile_definitions(dds PRIVATE DDS_SCHEDULER) +endif() + +# ============================================================ +# Sub-projects +# ============================================================ + +if(DDS_BUILD_TESTS OR DDS_BUILD_EXAMPLES) + enable_testing() +endif() + +if(DDS_BUILD_TESTS) + add_subdirectory(test) +endif() + +if(DDS_BUILD_EXAMPLES) + add_subdirectory(examples) +endif() + +# ============================================================ +# Installation +# ============================================================ + +include(GNUInstallDirs) + +install(TARGETS dds + EXPORT ddsTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # .dll on Windows +) + +install(DIRECTORY include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING PATTERN "*.h" +) + +install(EXPORT ddsTargets + FILE ddsTargets.cmake + NAMESPACE dds:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/dds +) + +include(CMakePackageConfigHelpers) + +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/ddsConfigVersion.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion +) + +configure_package_config_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ddsConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/ddsConfig.cmake" + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/dds +) + +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/ddsConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/ddsConfigVersion.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/dds +) diff --git a/cmake/ddsConfig.cmake.in b/cmake/ddsConfig.cmake.in new file mode 100644 index 00000000..7c121033 --- /dev/null +++ b/cmake/ddsConfig.cmake.in @@ -0,0 +1,5 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/ddsTargets.cmake") + +check_required_components(dds) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 00000000..a0eb4bd3 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,33 @@ +set(DDS_EXAMPLES + AnalyseAllPlaysBin + AnalyseAllPlaysPBN + AnalysePlayBin + AnalysePlayPBN + CalcAllTables + CalcAllTablesPBN + CalcDDtable + CalcDDtablePBN + DealerPar + Par + SolveAllBoards + SolveBoard + SolveBoardPBN +) + +foreach(example IN LISTS DDS_EXAMPLES) + add_executable(${example} ${example}.cpp hands.cpp) + target_include_directories(${example} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(${example} PRIVATE dds::dds) +endforeach() + +# ============================================================ +# CTest definitions +# ============================================================ + +# Examples always exit 0; detect failures via output patterns. +foreach(example IN LISTS DDS_EXAMPLES) + add_test(NAME example_${example} COMMAND ${example}) + set_tests_properties(example_${example} PROPERTIES + FAIL_REGULAR_EXPRESSION "ERROR;DDS error" + ) +endforeach() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000..dad02d97 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,40 @@ +add_executable(dtest + args.cpp + compare.cpp + loop.cpp + parse.cpp + print.cpp + testcommon.cpp + TestTimer.cpp + dtest.cpp +) + +target_include_directories(dtest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(dtest PRIVATE dds::dds) + +# ============================================================ +# CTest definitions +# ============================================================ + +# dtest always exits 0; detect failures via output patterns. +set(_fail_re "Difference;read_file failed;loop_[a-z]+:.*return") +set(_hands "${CMAKE_SOURCE_DIR}/hands") + +foreach(_mode IN ITEMS solve calc par dealerpar play) + add_test( + NAME dtest_${_mode} + COMMAND dtest -f "${_hands}/list10.txt" -s ${_mode} + ) + set_tests_properties(dtest_${_mode} PROPERTIES + FAIL_REGULAR_EXPRESSION "${_fail_re}" + ) +endforeach() + +# Extra: GIB-format input (sol10.txt) exercising the calc solver path +add_test( + NAME dtest_calc_gib + COMMAND dtest -f "${_hands}/sol10.txt" -s calc +) +set_tests_properties(dtest_calc_gib PROPERTIES + FAIL_REGULAR_EXPRESSION "${_fail_re}" +) From f5186bea4ca28c6e79cf2299a981dac5f1d3a51b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szo=C5=82ucha?= Date: Sun, 22 Feb 2026 10:10:02 +0100 Subject: [PATCH 2/5] Replace UTF-8 characters with ASCII MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MichaÅ‚ SzoÅ‚ucha --- src/Moves.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Moves.cpp b/src/Moves.cpp index c2e5e629..98db9537 100644 --- a/src/Moves.cpp +++ b/src/Moves.cpp @@ -387,7 +387,7 @@ void Moves::WeightAllocTrump0( else if ((tpos.winner[suit].hand == lho[leadHand]) && (tpos.secondBest[suit].hand == partner[leadHand])) { - /* This case was suggested by Joël Bradmetz. */ + /* This case was suggested by Joel Bradmetz. */ if (tpos.length[partner[leadHand]][suit] != 1) suitBonus += 27; } @@ -689,7 +689,7 @@ void Moves::WeightAllocNT0( else if ((tpos.winner[suit].hand == lho[leadHand]) && (tpos.secondBest[suit].hand == partner[leadHand])) { - /* This case was suggested by Joël Bradmetz. */ + /* This case was suggested by Joel Bradmetz. */ if (tpos.length[partner[leadHand]][suit] != 1) suitWeightDelta += 31; } From 4c2770f5aacd1817505a32b99dbc71d2f7d941e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szo=C5=82ucha?= Date: Sun, 22 Feb 2026 10:12:55 +0100 Subject: [PATCH 3/5] Add proper array definition in function signature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MichaÅ‚ SzoÅ‚ucha --- src/TransTableL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TransTableL.cpp b/src/TransTableL.cpp index d858cdb1..ebce0aca 100644 --- a/src/TransTableL.cpp +++ b/src/TransTableL.cpp @@ -1051,7 +1051,7 @@ string TransTableL::MakeHolding( void TransTableL::DumpHands( ofstream& fout, const vector>& hands, - const unsigned char lengths[][DDS_SUITS]) const + const unsigned char lengths[DDS_HANDS][DDS_SUITS]) const { for (unsigned i = 0; i < DDS_SUITS; i++) { From de5da5386effef03effcaaeb76436c71a5ff744b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szo=C5=82ucha?= Date: Sun, 22 Feb 2026 09:48:45 +0100 Subject: [PATCH 4/5] Setup Github Actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MichaÅ‚ SzoÅ‚ucha --- .github/workflows/ci.yml | 77 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..fda01025 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,77 @@ +name: CI + +on: + push: + branches: [main, develop] + pull_request: + branches: [main, develop] + +defaults: + run: + shell: bash + +jobs: + build: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + # Linux — shared library, default threading (OpenMP + STL) + - name: Linux GCC + os: ubuntu-latest + cxx: g++ + + - name: Linux Clang + os: ubuntu-latest + cxx: clang++ + + # Linux — static library, Boost threading backend + - name: Linux GCC / Boost (static) + os: ubuntu-latest + cxx: g++ + cmake-extra: >- + -DBUILD_SHARED_LIBS=OFF + -DDDS_THREADS_BOOST=ON + -DDDS_THREADS_STL=ON + install-boost: true + + # macOS — shared library, default threading (GCD + STL) + - name: macOS + os: macos-latest + + # Windows — static library (avoids DLL path issues in CTest), + # default threading (WinAPI + OpenMP + STL) + - name: Windows MSVC (static) + os: windows-latest + cmake-extra: -DBUILD_SHARED_LIBS=OFF + + steps: + - uses: actions/checkout@v4 + + - name: Install OpenMP (Linux) + if: runner.os == 'Linux' + run: | + sudo apt-get update -q + sudo apt-get install -y libomp-dev + + - name: Install Boost (Linux) + if: matrix.install-boost == true + run: sudo apt-get install -y libboost-thread-dev libboost-system-dev + + - name: Configure + env: + CXX: ${{ matrix.cxx }} + run: | + cmake -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DDDS_BUILD_TESTS=ON \ + -DDDS_BUILD_EXAMPLES=ON \ + ${{ matrix.cmake-extra }} + + - name: Build + run: cmake --build build --config Release --parallel + + - name: Test + run: ctest --test-dir build -C Release --output-on-failure From 77bce324cbb740b457fabc545723160eab34ee04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szo=C5=82ucha?= Date: Sun, 22 Feb 2026 10:40:42 +0100 Subject: [PATCH 5/5] Turn off -Werror for macOS build. Turn off -Werror and tests for Windows build. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MichaÅ‚ SzoÅ‚ucha --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fda01025..7bc512cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,12 +40,14 @@ jobs: # macOS — shared library, default threading (GCD + STL) - name: macOS os: macos-latest + cmake-extra: -DDDS_WERROR=OFF # Windows — static library (avoids DLL path issues in CTest), # default threading (WinAPI + OpenMP + STL) - name: Windows MSVC (static) os: windows-latest - cmake-extra: -DBUILD_SHARED_LIBS=OFF + cmake-extra: -DBUILD_SHARED_LIBS=OFF -DDDS_WERROR=OFF + skip-tests: true steps: - uses: actions/checkout@v4 @@ -74,4 +76,5 @@ jobs: run: cmake --build build --config Release --parallel - name: Test + if: matrix.skip-tests != true run: ctest --test-dir build -C Release --output-on-failure