Cockatrice/CMakeLists.txt
tooomm 3931447729
Some checks are pending
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
Build Desktop / Configure (push) Waiting to run
Build Desktop / vcpkg baseline (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Fedora 45 release (push) Blocked by required conditions
Build Desktop / Fedora 45 debug (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 sanitize (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 cover (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 27 Debug (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / Prune caches (push) Waiting to run
Build Docker / Servatrice (arm) (push) Waiting to run
Build Docker / Servatrice (x86) (push) Waiting to run
Build Docker / Publish multi-platform Servatrice image (push) Blocked by required conditions
[Build] Clean up CMake compiler flags and CI build script (#7219)
Compiler flags are applied once and for the right compiler:

- Detect the toolchain by CMAKE_CXX_COMPILER_ID (MSVC / GNU / Clang,
  warn on an unknown one).
- MSVC: drop /std:c++20 (CMAKE_CXX_STANDARD already adds it) and the
  outdated C4251 suppression, add /utf-8, and use /O2 instead of /Ox.
- GCC: drop the no-op -Wno-long-long and the macOS-only -std=gnu++20
  override; CMAKE_CXX_EXTENSIONS=OFF now owns the dialect.
- Use add_compile_definitions for SFMT_MEXP instead of add_definitions.

CI build script:

- Only run the schema version check for server builds.
- Accept boolean env flags as 1 and say so in the header.
- Print ccache, ctest and cpack versions next to their log groups.
- Only build the macOS vcpkg triplet when vcpkg is actually used.
- Drop the extra cmake --build verbosity.
- Install NSIS without chocolatey progress noise.

Co-authored-by: toomm <toomm@users.noreply.github.com>
2026-11-07 18:37:09 +01:00

569 lines
24 KiB
CMake

# Cockatrice's main CMakeLists.txt
#
# This is basically a wrapper to enable/disable the compilation of the different projects:
# Cockatrice, Oracle, Servatrice, Test
# This file sets all the variables shared between the projects
# like the installation path, compilation flags etc..
# CMake 3.16 is required for Qt6 and target_precompile_headers()
cmake_minimum_required(VERSION 3.16)
# Use compiler cache (ccache)
option(USE_CCACHE "Cache the build results with ccache" ON)
# Treat warnings as errors (Debug builds only)
option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON)
# Check for translation updates
option(UPDATE_TRANSLATIONS "Update translations on compile" OFF)
# Compile Cockatrice
option(WITH_CLIENT "Build Cockatrice client" ON)
# Compile Oracle
option(WITH_ORACLE "Build Cockatrice card database tool (Oracle)" ON)
# Compile Servatrice
option(WITH_SERVER "Build Cockatrice server (Servatrice)" OFF)
# Compile GUI tests (QtTesting widget-level playback)
option(WITH_GUI_TEST "Build the QtTesting-based GUI test harness" OFF)
# Compile tests
option(TEST "Build tests" OFF)
# Build with AddressSanitizer and UndefinedBehaviorSanitizer
option(ENABLE_SANITIZERS "Build with AddressSanitizer and UndefinedBehaviorSanitizer" OFF)
# Build instrumented for GCC line coverage, reported with gcovr
option(ENABLE_COVERAGE "Build instrumented for GCC line coverage" OFF)
# Use vcpkg regardless of OS
option(USE_VCPKG "Use vcpkg regardless of OS" OFF)
# The GUI test harness lives in a submodule; a checkout without it must still configure.
if(WITH_GUI_TEST AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/external/qttesting/CMakeLists.txt")
message(WARNING "WITH_GUI_TEST is ON but external/qttesting is missing, so GUI tests are disabled.\n"
"Run 'git submodule update --init external/qttesting' to enable them."
)
set(WITH_GUI_TEST OFF)
endif()
# Default to "Release" build type
# A user-provided CMAKE_BUILD_TYPE must be checked before the PROJECT() call
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE
Release
CACHE STRING "Build type"
)
endif()
# ccache does not support MSVC and must not auto-engage on Windows
# (it is installed unintentionally on the Windows CI runner).
# NOTE: this keys off the target OS, so a mingw/Ninja configuration on Windows
# also opts out of ccache even though the GNUCXX branch below supports it.
if(USE_CCACHE AND NOT WIN32)
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
# Support Unix Makefiles and Ninja
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
# PCH-aware caching, matching .ci/compile.sh: without this ccache refuses
# to cache any TU that consumes a precompiled header, so every PCH-backed
# target recompiles from scratch on each build.
# The include_file_mtime/include_file_ctime entries that CI also sets are
# deliberately not set here: --set-config writes the user's global
# ccache.conf, and those two would turn off the modified-during-compile
# check for every project on the machine, not just this one.
execute_process(COMMAND ${CCACHE_PROGRAM} --set-config sloppiness=pch_defines,time_macros)
message(STATUS "Found CCache ${CCACHE_PROGRAM}")
endif()
elseif(USE_CCACHE AND WIN32)
# An explicit opt-in must not disappear silently on Windows.
message(STATUS "ccache disabled: not supported for the MSVC toolchain on Windows")
endif()
if(WIN32 OR USE_VCPKG)
# Use vcpkg toolchain on Windows (and on macOS in CI)
set(CMAKE_TOOLCHAIN_FILE
${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake
CACHE STRING "Vcpkg toolchain file"
)
# Qt path set by user or env var
if(QTDIR
OR QTDIR32
OR QTDIR64
OR DEFINED ENV{QTDIR}
OR DEFINED ENV{QTDIR32}
OR DEFINED ENV{QTDIR64}
)
else()
set(QTDIR
""
CACHE PATH "Path to Qt (e.g. C:/Qt/6.4.2/msvc2019_64)"
)
message(
WARNING
"QTDIR variable is missing. Please set this variable to specify path to Qt (e.g. C:/Qt/6.4.2/msvc2019_64)"
)
endif()
endif()
# A project name is needed for CPack
# Version can be overriden by git tags, see cmake/getversion.cmake
project("Cockatrice" VERSION 3.2.0)
# Set release name if not provided via ENV/CMake var
if(NOT DEFINED GIT_TAG_RELEASENAME)
set(GIT_TAG_RELEASENAME "Reality Check")
endif()
# Use C++20 for all targets
set(CMAKE_CXX_STANDARD
20
CACHE STRING "C++ ISO Standard"
)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Set conventional loops
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
# Search path for cmake modules
set(COCKATRICE_CMAKE_PATH "${PROJECT_SOURCE_DIR}/cmake")
list(INSERT CMAKE_MODULE_PATH 0 "${COCKATRICE_CMAKE_PATH}")
include(getversion)
# Create a header and a cpp file containing the version hash
include(createversionfile)
# Define a proper install path
if(UNIX)
if(APPLE) # macOS
# Due to the special bundle structure ignore the prefix eventually set by the user
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/release)
# Force ccache usage if requested and available
if(USE_CCACHE)
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
if(RULE_LAUNCH_COMPILE)
message(STATUS "Force enabling ccache usage under macOS")
# Set up wrapper scripts
configure_file("${COCKATRICE_CMAKE_PATH}/launch-c.in" launch-c)
configure_file("${COCKATRICE_CMAKE_PATH}/launch-cxx.in" launch-cxx)
execute_process(COMMAND chmod a+rx "${CMAKE_BINARY_DIR}/launch-c" "${CMAKE_BINARY_DIR}/launch-cxx")
# Set Xcode project attributes to route compilation through our scripts
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
endif()
endif()
else() # Linux / BSD
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
# Fix package build
if(PREFIX)
set(CMAKE_INSTALL_PREFIX ${PREFIX})
else()
set(CMAKE_INSTALL_PREFIX /usr/local)
endif()
endif()
endif()
elseif(WIN32) # Windows (including 64-bit)
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/rundir/${CMAKE_BUILD_TYPE})
endif()
# Define compiler flags
if(MSVC) # Microsoft Visual C++ compiler
# /EHsc Enable standard C++ exception handling
# /MP Enable parallel compilation
# /permissive- Enable more standards-conforming behavior
# /utf-8 Set source file encoding and execution character set to UTF-8
# /W4 Enable warning level 4
# /Zc:__cplusplus Enable correct __cplusplus reporting
# /Zi Generate debugging information (Program Database, PDB)
set(CMAKE_CXX_FLAGS "/EHsc /MP /permissive- /utf-8 /W4 /Zc:__cplusplus /Zi")
# /O2 Balanced optimization
# /MD Link against the multi-threaded DLL runtime library (Release CRT)
set(CMAKE_CXX_FLAGS_RELEASE "/O2 /MD")
# /Od Disable optimization
# /MDd Link against the multi-threaded Debug DLL runtime library (Debug CRT)
set(CMAKE_CXX_FLAGS_DEBUG "/Od /MDd")
# Generate PDBs, even in release builds, so developers can better analyze crash logs
# /DEBUG Enable debug symbols and PDB generation
# /OPT:REF Remove unreferenced functions/data
# /OPT:ICF Fold identical COMDAT functions/data
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
add_compile_definitions(_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # GCC compiler
include(CheckCXXCompilerFlag)
# -O2 Balanced optimization
# -s Remove symbols from the executable
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -s")
# -ggdb Produce GDB debugging symbols
# -O0 Disable optimization
# -Wall Enable a broad set of useful warnings
# -Wextra Enable a set of extra warnings
# -Werror Treat warnings as compilation errors
if(WARNING_AS_ERROR)
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -Werror")
else()
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra")
endif()
# -Wcast-align Catch unsafe pointer casts
# -Wmissing-declarations Catch defined functions without a prior declaration
# -Wno-error=extra Downgrade some -Wextra warnings from errors to warnings
# -Wno-error=delete-non-virtual-dtor Downgrade delete-non-virtual-dtor from error to warning
# -Wno-error=sign-compare Downgrade signed/unsigned comparison from error to warning
# -Wno-error=missing-declarations Downgrade -Wmissing-declarations from error to warning
# -Wno-error=sfinae-incomplete GCC 16+: Qt MOC + protobuf forward decls trigger this
set(ADDITIONAL_DEBUG_FLAGS
-Wcast-align
-Wmissing-declarations
-Wno-error=extra
-Wno-error=delete-non-virtual-dtor
-Wno-error=sign-compare
-Wno-error=missing-declarations
-Wno-error=sfinae-incomplete
)
foreach(FLAG ${ADDITIONAL_DEBUG_FLAGS})
check_cxx_compiler_flag("${FLAG}" CXX_HAS_WARNING_${FLAG})
if(CXX_HAS_WARNING_${FLAG})
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}")
endif()
endforeach()
# Reduce compiler I/O by using pipes between stages instead of temp files
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # Clang and AppleClang compilers
# -O2 Balanced optimization
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
# -g Include debug information
# -O0 Disable optimization
# -Wall Enable a broad set of useful warnings
# -Wextra Enable a set of extra warnings
# -Werror Treat warnings as compilation errors
# -Wno-unused-parameter Suppress warnings about unused function parameters (common in Qt callbacks)
if(WARNING_AS_ERROR)
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Werror -Wno-unused-parameter")
else()
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra")
endif()
# Reduce compiler I/O by using pipes between stages instead of temp files
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe")
else() # Unknown compiler
message(WARNING "Unknown C++ compiler: ${CMAKE_CXX_COMPILER_ID}")
endif()
# Always included, because they define cockatrice_disable_sanitizers_for() and
# cockatrice_disable_coverage_for() for the vendored trees. They only touch the global flags
# when ENABLE_SANITIZERS or ENABLE_COVERAGE is on.
include(Sanitizers)
include(Coverage)
include(CrashReporting)
# Debug information is what makes a cached object large, and a build configuration needs more
# room than a per-leg cache bound can spare when it carries full DWARF: ccache then fills to
# its limit and evicts the entries the next build is about to ask for, so it serves a few
# percent of calls while holding most of a build. CI sets a lower level so one whole
# configuration fits; level 1 keeps file and line, which is what a failing test or a sanitizer
# backtrace reports. Empty (the default) leaves local, distro and release builds exactly as
# they were. This comes after CrashReporting, so the -g it adds for Sentry symbols cannot
# raise the level again.
set(COCKATRICE_DEBUG_INFO_LEVEL
""
CACHE STRING "DWARF level for Debug and Release objects (empty keeps the built-in flags)"
)
if(NOT COCKATRICE_DEBUG_INFO_LEVEL STREQUAL "")
if(MSVC)
message(WARNING "COCKATRICE_DEBUG_INFO_LEVEL is ignored on MSVC")
else()
string(APPEND CMAKE_CXX_FLAGS_DEBUG " -g${COCKATRICE_DEBUG_INFO_LEVEL}")
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -g${COCKATRICE_DEBUG_INFO_LEVEL}")
endif()
endif()
# GNU systems need to define the Mersenne exponent for SFMT, so the RNG compiles without warnings
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
add_compile_definitions(SFMT_MEXP=19937)
endif()
find_package(Threads REQUIRED)
# Determine 32 or 64 bit build
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_lib_suffix 64)
else()
set(_lib_suffix 32)
endif()
if(NOT "${QTDIR${_lib_suffix}}" STREQUAL "")
list(APPEND CMAKE_PREFIX_PATH "${QTDIR${_lib_suffix}}")
elseif(NOT "${QTDIR}" STREQUAL "")
list(APPEND CMAKE_PREFIX_PATH "${QTDIR}")
elseif(NOT "$ENV{QTDIR${_lib_suffix}}" STREQUAL "")
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR${_lib_suffix}}")
elseif(NOT "$ENV{QTDIR}" STREQUAL "")
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR}")
endif()
message(STATUS "Update Translations: ${UPDATE_TRANSLATIONS}")
include(FindQtRuntime)
# Reject APIs that were deprecated before the oldest Qt release we support
# (6.4). Qt 6.5 renamed the switch, so use whichever spelling the found
# version understands while still compiling everywhere.
if(Qt6_VERSION VERSION_GREATER_EQUAL 6.5)
add_compile_definitions(QT_DISABLE_DEPRECATED_UP_TO=0x060400)
else()
add_compile_definitions(QT_DISABLE_DEPRECATED_BEFORE=0x060400)
endif()
# Set once here for every target: these variables are inherited by the
# subdirectories, so the per-directory copies were redundant. Only the
# variables are set; qt_standard_project_setup would also change the runtime
# output directories and the install RPATH.
set(CMAKE_AUTOMOC TRUE)
set(CMAKE_AUTOUIC TRUE)
set(CMAKE_AUTORCC TRUE)
# Find other needed libraries
find_package(Protobuf CONFIG)
if(NOT Protobuf_FOUND)
find_package(Protobuf REQUIRED)
endif()
if(${Protobuf_VERSION} VERSION_LESS "3.21.0.0" AND NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
message(FATAL_ERROR "No protoc command found!")
endif()
# Find OpenSSL
if(WIN32) # Windows (including 64-bit)
find_package(OpenSSL REQUIRED)
if(OPENSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIRS})
endif()
endif()
# Find Visual C++ Redistributable
if(MSVC)
find_package(VCredistRuntime)
endif()
# Package builder
set(CPACK_PACKAGE_CONTACT "Zach Halpern <zach@cockatrice.us>")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_NAME}")
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
set(CPACK_PACKAGE_DESCRIPTION
"Cockatrice is an open-source, multiplatform application for playing tabletop card games over a network. The program's server design prevents users from manipulating the game for unfair advantage. The client also provides a single-player mode, which allows users to brew while offline."
)
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_VERSION_FILENAME}")
if(UNIX)
if(APPLE)
set(CPACK_GENERATOR DragNDrop ${CPACK_GENERATOR})
set(CPACK_GENERATOR "DragNDrop")
set(CPACK_DMG_FORMAT "UDBZ")
set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
set(CPACK_SYSTEM_NAME "OSX")
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice/resources/appicon.icns")
set(CPACK_DMG_DS_STORE_SETUP_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeDMGSetup.script")
set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/dmgBackground.tif")
set(CPACK_PRE_BUILD_SCRIPTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/SignMacApplications.cmake")
else()
# linux
if(CPACK_GENERATOR STREQUAL "RPM")
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
set(CPACK_RPM_MAIN_COMPONENT "cockatrice")
set(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt6-qtimageformats, qt6-qtmultimedia, qt6-qtsvg, qt6-qttools")
set(CPACK_RPM_PACKAGE_GROUP "Amusements/Games")
set(CPACK_RPM_PACKAGE_URL "http://github.com/Cockatrice/Cockatrice")
# stop directories from making package conflicts
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
/usr/share/applications
/usr/share/icons
/usr/share/icons/hicolor
/usr/share/icons/hicolor/48x48
/usr/share/icons/hicolor/48x48/apps
/usr/share/icons/hicolor/scalable
/usr/share/icons/hicolor/scalable/apps
)
else()
set(CPACK_GENERATOR DEB)
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-image-formats-plugins, qt6-qpa-plugins")
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libqt6sql6-mysql") # for connecting servatrice to a mysql db
endif()
endif()
elseif(WIN32)
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(TRICE_IS_64_BIT 1)
else()
set(TRICE_IS_64_BIT 0)
endif()
# Configure file with custom definitions for NSIS.
configure_file("${COCKATRICE_CMAKE_PATH}/NSIS.definitions.nsh.in" "${PROJECT_BINARY_DIR}/NSIS.definitions.nsh")
# Installer-log sender for the AbortInstall Sentry hook (values parsed out of COCKATRICE_SENTRY_DSN in
# cmake/CrashReporting.cmake). Generated only when a DSN was parsed: cmake/NSIS.template.in embeds it under
# the same CPACK_SENTRY_ENABLED check, so a build without reporting never references or carries the helper.
if(CPACK_SENTRY_ENABLED)
configure_file(
"${COCKATRICE_CMAKE_PATH}/SendInstallerLog.ps1.in" "${PROJECT_BINARY_DIR}/SendInstallerLog.ps1" @ONLY
)
endif()
# Every runtime DLL a Windows install has to contain, as paths relative to the
# install root. .ci/compile.sh reads this and fails the build when the packaged
# installer is missing one of them, or carries a runtime it does not know about.
#
# All three applications are packaged into the same directory on Windows, so
# this is the union of their Qt module lists, not just the client's: Servatrice
# contributes Qt6Sql.dll and Oracle contributes nothing the client lacks, and a
# client-only manifest leaves Qt6Sql.dll unasserted even though servatrice.exe
# is installed next to cockatrice.exe and cannot start without it.
#
# A statically linked Qt module ships no runtime DLL, so requiring one would
# fail the package check on a static build for no reason. cockatrice/CMakeLists.txt
# installs the runtime of every module listed here, and skips static ones the
# same way, so the two can never disagree.
#
# Only the Qt modules, and that is deliberate. protobuf, Abseil, liblzma, zlib
# and OpenSSL also ride in on the "*.dll" glob, and a client whose runtime is
# absent, stale or of the wrong architecture fails to start with "abseil_dll.dll
# is either not designed to run on Windows or it contains an error", so they
# are exactly the files worth asserting.
#
# Their names cannot be derived from the vcpkg bin directory, which is what a
# first attempt did and what a Windows build immediately refuted: bin holds
# everything vcpkg installed, not everything the applications import. It also
# contains gmock.dll, libprotobuf-lite.dll, libprotoc.dll, legacy.dll and three
# pthreadVC*.dll FindThreads probes, none of which any shipped executable
# links, so requiring them failed a build over a package that was correct.
#
# Deriving them from the executables' own import tables is the real answer,
# and fixup_bundle already walks it to decide what to copy. Until that result
# is available to CMake, requiring the vcpkg half would mean guessing names
# again, which is what produced this bug report in the first place. So assert
# what is derived from the build's own link lists and leave the rest to the
# purge in cmake/NSIS.template.in, which removes every DLL regardless of name.
set(_required_runtime "")
foreach(_qt_module IN LISTS COCKATRICE_QT_MODULES SERVATRICE_QT_MODULES ORACLE_QT_MODULES)
get_target_property(_qt_module_type ${_qt_module} TYPE)
if(_qt_module_type STREQUAL "SHARED_LIBRARY")
string(REGEX REPLACE "^Qt6::" "" _qt_component "${_qt_module}")
list(APPEND _required_runtime "Qt6${_qt_component}.dll")
endif()
endforeach()
list(APPEND _required_runtime "Plugins/platforms/qwindows.dll")
list(REMOVE_DUPLICATES _required_runtime)
list(SORT _required_runtime)
string(REPLACE ";" "\n" _required_runtime "${_required_runtime}")
file(WRITE "${PROJECT_BINARY_DIR}/required-runtime.txt" "${_required_runtime}\n")
# include vcredist into the package; NSIS will take care of running it
if(VCREDISTRUNTIME_FOUND)
install(FILES "${VCREDISTRUNTIME_FILE}" DESTINATION ./)
endif()
endif()
include(CPack)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_interfaces ${CMAKE_BINARY_DIR}/libcockatrice_interfaces)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_protocol ${CMAKE_BINARY_DIR}/libcockatrice_protocol)
if(WITH_CLIENT
OR WITH_SERVER
OR WITH_ORACLE
)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_network ${CMAKE_BINARY_DIR}/libcockatrice_network)
endif()
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_deck_list ${CMAKE_BINARY_DIR}/libcockatrice_deck_list)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_rng ${CMAKE_BINARY_DIR}/libcockatrice_rng)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_card ${CMAKE_BINARY_DIR}/libcockatrice_card)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_utility ${CMAKE_BINARY_DIR}/libcockatrice_utility)
if(WITH_ORACLE OR WITH_CLIENT)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_settings ${CMAKE_BINARY_DIR}/libcockatrice_settings)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_models ${CMAKE_BINARY_DIR}/libcockatrice_models)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_filters ${CMAKE_BINARY_DIR}/libcockatrice_filters)
endif()
if(WITH_CLIENT)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_game ${CMAKE_BINARY_DIR}/libcockatrice_game)
endif()
if(WITH_SERVER)
add_subdirectory(servatrice)
set(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
endif()
if(WITH_CLIENT)
add_subdirectory(cockatrice)
set(CPACK_INSTALL_CMAKE_PROJECTS "Cockatrice;Cockatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
endif()
if(WIN32 AND WITH_CLIENT)
# Runs from the installer's $PLUGINSDIR when a purge fails, and is never installed
# (see LogProcessesUsingInstallDir in cmake/NSIS.template.in), so it has no install
# rules and is not part of the client's staged tree.
add_subdirectory(${CMAKE_SOURCE_DIR}/tools/installer-holder-probe ${CMAKE_BINARY_DIR}/tools/installer-holder-probe)
endif()
if(WITH_ORACLE)
add_subdirectory(oracle)
set(CPACK_INSTALL_CMAKE_PROJECTS "Oracle;Oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
endif()
if(WITH_GUI_TEST)
set(QtTesting_QT_VERSION "6")
# QtTesting registers its own unit tests when BUILD_TESTING is on. They target the
# Qt version the harness was written for and fail on Qt 6.11 (toolbutton
# long-press recording), and they are not Cockatrice's tests, so suppress them
# for the duration of the subdirectory instead of painting ctest red.
if(DEFINED BUILD_TESTING)
set(_cockatrice_saved_build_testing ${BUILD_TESTING})
endif()
set(BUILD_TESTING
OFF
CACHE BOOL "Build the testing tree." FORCE
)
add_subdirectory(external/qttesting)
if(DEFINED _cockatrice_saved_build_testing)
set(BUILD_TESTING
${_cockatrice_saved_build_testing}
CACHE BOOL "Build the testing tree." FORCE
)
else()
unset(BUILD_TESTING CACHE)
endif()
# cl.exe has no warnings-as-errors here, and it rejects -Wno-error with D8021.
if(NOT MSVC)
target_compile_options(qttesting PRIVATE -Wno-error)
endif()
endif()
if(TEST)
include(CTest)
add_subdirectory(tests)
endif()
if(Qt6_FOUND AND Qt6_VERSION_MINOR GREATER_EQUAL 3)
# Qt6.3+ requires project finalization to support translations
qt_finalize_project()
endif()
# Print compiler identification at configuration time
message(STATUS "C++ compiler: ${CMAKE_CXX_COMPILER_ID}")
message(STATUS "C++ compiler version: ${CMAKE_CXX_COMPILER_VERSION}")
message(STATUS "C++ compiler path: ${CMAKE_CXX_COMPILER}")
message(STATUS "C++ standard: ${CMAKE_CXX_STANDARD}")
message(STATUS "C++ extensions: ${CMAKE_CXX_EXTENSIONS}")