diff --git a/.ci/compile.sh b/.ci/compile.sh index f20432893..4c66a8493 100755 --- a/.ci/compile.sh +++ b/.ci/compile.sh @@ -122,54 +122,58 @@ done set -e -# Setup -./servatrice/check_schema_version.sh -if [[ ! $BUILDTYPE ]]; then +# Schema version consistency +if [[ $MAKE_SERVER == "1" ]]; then + ./servatrice/check_schema_version.sh +fi + +# Use default values if unset +if [[ -z $BUILDTYPE ]]; then BUILDTYPE=Release fi -if [[ ! $BUILD_DIR ]]; then +if [[ -z $BUILD_DIR ]]; then BUILD_DIR="build" fi mkdir -p "$BUILD_DIR" cd "$BUILD_DIR" -# Set minimum CMake Version -export CMAKE_POLICY_VERSION_MINIMUM=3.10 - -# Add cmake flags +# CMake options flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE") -if [[ $MAKE_SERVER ]]; then +if [[ $MAKE_SERVER == "1" ]]; then flags+=("-DWITH_SERVER=1") fi -if [[ $MAKE_NO_CLIENT ]]; then +if [[ $MAKE_NO_CLIENT == "1" ]]; then flags+=("-DWITH_CLIENT=0" "-DWITH_ORACLE=0") fi -if [[ $MAKE_TEST ]]; then +if [[ $MAKE_TEST == "1" ]]; then flags+=("-DTEST=1") fi -if [[ $USE_CCACHE ]]; then +if [[ $USE_CCACHE == "1" ]]; then flags+=("-DUSE_CCACHE=1") + # PCH-aware caching is required or ccache refuses to cache any TU that # consumes a precompiled header, silently recompiling everything on every run. ccache --set-config sloppiness=pch_defines,time_macros - if [[ $CCACHE_SIZE ]]; then - # note, this setting persists after running the script + + if [[ -n $CCACHE_SIZE ]]; then + # This setting persists after running the script ccache --max-size "$CCACHE_SIZE" fi fi -if [[ $PACKAGE_TYPE ]]; then +if [[ -n $PACKAGE_TYPE ]]; then flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE") fi -if [[ $USE_VCPKG ]]; then +if [[ $USE_VCPKG == "1" ]]; then flags+=("-DUSE_VCPKG=1") flags+=("-DVCPKG_INSTALL_OPTIONS=--x-abi-tools-use-exact-versions") fi -# Add cmake --build flags +# CMake --build options buildflags=(--config "$BUILDTYPE") function ccachestatsverbose() { - # note, verbose only works on newer ccache, discard the error + ccache --version + # Verbose only works on newer ccache, discard the error local got if got="$(ccache --show-stats --verbose 2>/dev/null)"; then echo "$got" @@ -178,8 +182,8 @@ function ccachestatsverbose() { fi } -# Compile -if [[ $RUNNER_OS == macOS ]]; then +# Prepare compilation +if [[ $RUNNER_OS == "macOS" ]]; then # QTDIR is needed for macOS since we actually only use the cached thin Qt binaries instead of the install-qt-action, # which sets a few environment variables if QTDIR=$(find "$GITHUB_WORKSPACE/Qt" -depth -maxdepth 2 -name macos -type d -print -quit); then @@ -188,42 +192,51 @@ if [[ $RUNNER_OS == macOS ]]; then echo "could not find QTDIR!" exit 2 fi - # the qtdir is located at Qt/[qtversion]/macos - # we use find to get the first subfolder with the name "macos" - # this works independent of the qt version as there should be only one version installed on the runner at a time + # QTDIR is located at Qt//macos + # We use find to get the first subfolder with the name "macos" + # This works independent of the Qt version as there should be only one version installed on the runner at a time export QTDIR - if [[ $TARGET_MACOS_VERSION ]]; then - # CMAKE_OSX_DEPLOYMENT_TARGET is a vanilla cmake flag needed to compile to target macOS version + if [[ -n $TARGET_MACOS_VERSION ]]; then + # CMAKE_OSX_DEPLOYMENT_TARGET is a vanilla CMake option needed to compile to target macOS version flags+=("-DCMAKE_OSX_DEPLOYMENT_TARGET=$TARGET_MACOS_VERSION") - # vcpkg dependencies need a vcpkg triplet file to compile to the target macOS version - # an easy way is to copy the x64-osx.cmake file and modify it - triplets_dir="/tmp/cmake/triplets" - triplet_version="custom-triplet" - triplet_file="$triplets_dir/$triplet_version.cmake" - arch=$(uname -m) - if [[ $arch == x86_64 ]]; then - arch="x64" + if [[ $USE_VCPKG == "1" ]]; then + # vcpkg dependencies need a vcpkg triplet file to compile to the target macOS version + # An easy way is to copy the x64-osx.cmake file and modify it + echo "::group::vcpkg triplet" + triplets_dir="/tmp/cmake/triplets" + triplet_version="custom-triplet" + triplet_file="$triplets_dir/$triplet_version.cmake" + arch=$(uname -m) + + if [[ $arch == x86_64 ]]; then + arch="x64" + fi + + mkdir -p "$triplets_dir" + triplet_source="../vcpkg/triplets/$arch-osx.cmake" + + if [[ ! -f "$triplet_source" ]]; then + triplet_source="../vcpkg/triplets/community/$arch-osx.cmake" + fi + + cp "$triplet_source" "$triplet_file" + echo "set(VCPKG_CMAKE_SYSTEM_VERSION $TARGET_MACOS_VERSION)" >>"$triplet_file" + echo "set(VCPKG_OSX_DEPLOYMENT_TARGET $TARGET_MACOS_VERSION)" >>"$triplet_file" + flags+=("-DVCPKG_OVERLAY_TRIPLETS=$triplets_dir") + flags+=("-DVCPKG_HOST_TRIPLET=$triplet_version") + flags+=("-DVCPKG_TARGET_TRIPLET=$triplet_version") + echo "::endgroup::" + + echo "::group::Generated triplet $triplet_file" + cat "$triplet_file" + echo "::endgroup::" fi - mkdir -p "$triplets_dir" - triplet_source="../vcpkg/triplets/$arch-osx.cmake" - if [[ ! -f "$triplet_source" ]]; then - triplet_source="../vcpkg/triplets/community/$arch-osx.cmake" - fi - cp "$triplet_source" "$triplet_file" - echo "set(VCPKG_CMAKE_SYSTEM_VERSION $TARGET_MACOS_VERSION)" >>"$triplet_file" - echo "set(VCPKG_OSX_DEPLOYMENT_TARGET $TARGET_MACOS_VERSION)" >>"$triplet_file" - flags+=("-DVCPKG_OVERLAY_TRIPLETS=$triplets_dir") - flags+=("-DVCPKG_HOST_TRIPLET=$triplet_version") - flags+=("-DVCPKG_TARGET_TRIPLET=$triplet_version") - echo "::group::Generated triplet $triplet_file" - cat "$triplet_file" - echo "::endgroup::" fi - echo "::group::Signing Certificate" - if [[ -n "$MACOS_CERTIFICATE_NAME" ]]; then + echo "::group::Setup signing certificate" + if [[ -n $MACOS_CERTIFICATE_NAME ]]; then echo "$MACOS_CERTIFICATE" | base64 --decode >"certificate.p12" security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain security default-keychain -s build.keychain @@ -237,9 +250,9 @@ if [[ $RUNNER_OS == macOS ]]; then fi echo "::endgroup::" - if [[ $MAKE_PACKAGE ]]; then + if [[ $MAKE_PACKAGE == "1" ]]; then # Workaround https://github.com/actions/runner-images/issues/7522 - # have hdiutil repeat the command 10 times in hope of success + # Have hdiutil repeat the command 10 times in hope of success hdiutil_script="/tmp/hdiutil.sh" # shellcheck disable=SC2016 echo '#!/bin/bash @@ -255,43 +268,46 @@ if [[ $RUNNER_OS == macOS ]]; then flags+=(-DCPACK_COMMAND_HDIUTIL="$hdiutil_script") fi -elif [[ $RUNNER_OS == Windows ]]; then - # Enable MTT, see https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/ +elif [[ $RUNNER_OS == "Windows" ]]; then + # Enable MSBuild switches for MTT, see https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/ # and https://devblogs.microsoft.com/cppblog/cpp-build-throughput-investigation-and-tune-up/#multitooltask-mtt buildflags+=(-- -p:UseMultiToolTask=true -p:EnableClServerMode=true) fi -if [[ $USE_CCACHE ]]; then +if [[ $USE_CCACHE == "1" ]]; then echo "::group::Show ccache stats" ccachestatsverbose echo "::endgroup::" fi -echo "::group::Configure cmake" +# Configure CMake +echo "::group::Generate build system" cmake --version -echo "Running cmake with flags: ${flags[*]}" +echo "Running CMake configuration with following flags: ${flags[*]}" cmake .. "${flags[@]}" echo "::endgroup::" +# Build echo "::group::Build project" -echo "Running cmake --build with flags: ${buildflags[*]}" -cmake --build . "${buildflags[@]}" +echo "Running CMake with following build flags: ${buildflags[*]}" +cmake --build . --verbose "${buildflags[@]}" echo "::endgroup::" -if [[ $USE_CCACHE ]]; then - if [[ $CCACHE_EVICTION_AGE ]]; then - echo "::group::evict ccache files older than $CCACHE_EVICTION_AGE" +# Post-build +if [[ $USE_CCACHE == "1" ]]; then + if [[ -n $CCACHE_EVICTION_AGE ]]; then + echo "::group::Evict ccache files older than $CCACHE_EVICTION_AGE" ccache --evict-older-than "$CCACHE_EVICTION_AGE" echo "::endgroup::" fi echo "::group::Show ccache stats again" ccachestatsverbose echo "::endgroup::" -elif [[ $CCACHE_EVICTION_AGE ]]; then +elif [[ -n $CCACHE_EVICTION_AGE ]]; then echo "::error file=$0::ccache eviction is enabled while ccache is disabled!" fi -if [[ $RUNNER_OS == macOS ]]; then +if [[ $RUNNER_OS == "macOS" ]]; then echo "::group::Inspect Mach-O binaries" for app in cockatrice oracle servatrice; do binary="$GITHUB_WORKSPACE/build/$app/$app.app/Contents/MacOS/$app" @@ -304,24 +320,29 @@ if [[ $RUNNER_OS == macOS ]]; then echo "::endgroup::" fi -if [[ $MAKE_TEST ]]; then +# Test +if [[ $MAKE_TEST == "1" ]]; then echo "::group::Run tests" + ctest --version ctest -C "$BUILDTYPE" --output-on-failure echo "::endgroup::" fi -if [[ $MAKE_INSTALL ]]; then +# Install +if [[ $MAKE_INSTALL == "1" ]]; then echo "::group::Install" cmake --build . --target install --config "$BUILDTYPE" echo "::endgroup::" fi -if [[ $MAKE_PACKAGE ]]; then +# Package +if [[ $MAKE_PACKAGE == "1" ]]; then echo "::group::Create package" + cpack --version cmake --build . --target package --config "$BUILDTYPE" echo "::endgroup::" - if [[ $PACKAGE_SUFFIX ]]; then + if [[ -n $PACKAGE_SUFFIX ]]; then echo "::group::Update package name" cd .. BUILD_DIR="$BUILD_DIR" .ci/name_build.sh "$PACKAGE_SUFFIX" diff --git a/.github/workflows/desktop-build.yml b/.github/workflows/desktop-build.yml index bd528f245..4306f80f8 100644 --- a/.github/workflows/desktop-build.yml +++ b/.github/workflows/desktop-build.yml @@ -426,7 +426,7 @@ jobs: - name: "[Windows] Install NSIS" if: matrix.os == 'Windows' shell: bash - run: choco install nsis + run: choco install nsis --no-progress - name: "Setup vcpkg cache" id: vcpkg-cache diff --git a/CMakeLists.txt b/CMakeLists.txt index 293e25dd9..e2bb77235 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,41 +1,36 @@ # Cockatrice's main CMakeLists.txt # -# This is basically a wrapper to enable/disable the compilation -# of the different projects: servatrice, cockatrice, test -# This file sets all the variables shared between the projects -# like the installation path, compilation flags etc.. +# 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.. -# 3.16 required for Qt6 and target_precompile_headers() +# 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 tests +# Compile Tests option(TEST "Build tests" OFF) + +# Check for translation updates +option(UPDATE_TRANSLATIONS "Update translations on compile" OFF) +# Use compiler cache (ccache) +option(USE_CCACHE "Cache the build results with ccache" ON) # Use vcpkg regardless of OS option(USE_VCPKG "Use vcpkg regardless of OS" OFF) +# Treat warnings as errors (Debug builds only) +option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON) # Default to "Release" build type # User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call -if(DEFINED CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE - ${CMAKE_BUILD_TYPE} - CACHE STRING "Type of build" - ) -else() +if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release - CACHE STRING "Type of build" + CACHE STRING "Build type" ) endif() @@ -88,22 +83,20 @@ endif() # Version can be overriden by git tags, see cmake/getversion.cmake project("Cockatrice" VERSION 3.1.0) -# Set release name if not provided via env/cmake var +# Set release name if not provided via ENV/CMake var if(NOT DEFINED GIT_TAG_RELEASENAME) set(GIT_TAG_RELEASENAME "Graduation Day") endif() -# Use c++20 for all targets -set(CMAKE_CXX_STANDARD - 20 - CACHE STRING "C++ ISO Standard" -) -set(CMAKE_CXX_STANDARD_REQUIRED True) +# Requires ISO C++20 standard (without compiler-specific extensions) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) # Set conventional loops -set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) -# Search path for cmake modules +# Search path for CMake modules set(COCKATRICE_CMAKE_PATH "${PROJECT_SOURCE_DIR}/cmake") list(INSERT CMAKE_MODULE_PATH 0 "${COCKATRICE_CMAKE_PATH}") @@ -114,31 +107,31 @@ 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. + 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 available - 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") + if(USE_CCACHE) + get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE) + if(RULE_LAUNCH_COMPILE) + message(STATUS "Force enabling ccache usage") - # 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") + # 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 + else() # Linux / BSD if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - #fix package build + # Fix package build if(PREFIX) set(CMAKE_INSTALL_PREFIX ${PREFIX}) else() @@ -146,47 +139,74 @@ if(UNIX) endif() endif() endif() -elseif(WIN32) +elseif(WIN32) # Windows (including 64bit) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/rundir/${CMAKE_BUILD_TYPE}) endif() -# Define proper compilation flags -if(MSVC) - # Disable Warning C4251, C++20 compatibility, Multi-threaded Builds, Warn Detection, Unwind Semantics, Debug Symbols - set(CMAKE_CXX_FLAGS "/wd4251 /Zc:__cplusplus /std:c++20 /permissive- /W4 /MP /EHsc /Zi") - # Visual Studio: Maximum Optimization, Multi-threaded DLL - set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD") - # Visual Studio: No Optimization, Multi-threaded Debug DLL +# Define compiler flags +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # MS 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 char set to UTF-8 + # /W4 Enable warning level 4 + # /Zc:__cplusplus Enable C++20 detection in headers + # /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 PDB, even when in release (So developers can better analyze crash logs) + # Generate PDBs, even when building release target to allow developers to 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_COMPILER_IS_GNUCXX) - # linux/gcc, bsd/gcc, windows/mingw +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # GCC compiler include(CheckCXXCompilerFlag) - set(CMAKE_CXX_FLAGS_RELEASE "-s -O2") + # -O2 Balanced optimization + # -s Remove symbols from the executable <-- do we want that? we add symbols to windows builds explicitly. Check pdb's and how debug symbols work & can be striped during packaging // non-gcc & clang section also does not have it + set(CMAKE_CXX_FLAGS_RELEASE "-O2 -s") + + # -ggdb Produce GDB debugging symbols + # -O0 Disable optimization + # -Wall Enable broad set of useful warnings + # -Wextra Enable 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() - if(APPLE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++20") - endif() + # Test without, CMAKE_CXX-ESTENSIONS are defined as OFF, so no sense to add them here but not turning the general setting ON? + # -std=gnu++20 Enable GNU C++20 extensions + # if(APPLE) # macOS/GCC + # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++20") + # endif() + # -Wcast-align Catch unsafe pointer casts + # -Wmissing-declarations Catch defined functions without prior declaration + # -Wno-error=extra Downgrade some -Wextra warnings from errors to warnings + # -Wno-error=delete-non-virtual-dtor xxx + # -Wno-error=sign-compare Downgrade comparing signed vs. unsigned integers from errors to warnings + # -Wno-error=missing-declarations Downgrade -Wmissing-declarations from errors to warnings + # -Wno-error=sfinae-incomplete GCC 16+: Qt MOC + protobuf forward declarations trigger this set(ADDITIONAL_DEBUG_FLAGS -Wcast-align -Wmissing-declarations - -Wno-long-long - -Wno-error=extra - -Wno-error=delete-non-virtual-dtor - -Wno-error=sign-compare - -Wno-error=missing-declarations - -Wno-error=sfinae-incomplete # GCC 16+: Qt MOC + protobuf forward decls trigger this + -Wno-error=extra # <-- consider removing this, check without as it makes most of added -Wextra warnings non-fatal + -Wno-error=delete-non-virtual-dtor # <-- see if still needed? + -Wno-error=sign-compare # <-- test without + -Wno-error=missing-declarations # <-- test without + -Wno-error=sfinae-incomplete # <-- test again without and see if comment still holds true ) foreach(FLAG ${ADDITIONAL_DEBUG_FLAGS}) @@ -198,9 +218,17 @@ elseif(CMAKE_COMPILER_IS_GNUCXX) # Reduce compiler I/O by using pipes between stages instead of temp files set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe") -else() - # other: osx/llvm, bsd/llvm + +elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # Clang compiler + # -O2 Balanced optimization set(CMAKE_CXX_FLAGS_RELEASE "-O2") + + # -g Include debug information (equivalent to -ggdb for GCC) + # -O0 Disable optimization + # -Wall Enable broad set of useful warnings + # -Wextra Enable 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() @@ -208,21 +236,26 @@ else() endif() # Reduce compiler I/O by using pipes between stages instead of temp files - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe") # <-- required for clang? see adding pr description again + +else() # Undefined compiler + message(WARNING "Unknown C++ compiler: ${CMAKE_CXX_COMPILER_ID}") + endif() -# GNU systems need to define the Mersenne exponent for the RNG to compile w/o warning +# GNU systems need to define the Mersenne Exponent for SFMT for the RNG to compile without warning +# Consider making this target specific --> target_compile_definitions(libcockatrice_rng PRIVATE SFMT_MEXP=19937) if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - add_definitions("-DSFMT_MEXP=19937") + 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) + set(_lib_suffix 64) # 64bit else() - set(_lib_suffix 32) + set(_lib_suffix 32) # 32bit endif() if(DEFINED QTDIR${_lib_suffix}) @@ -251,16 +284,16 @@ if(${Protobuf_VERSION} VERSION_LESS "3.21.0.0" AND NOT EXISTS "${Protobuf_PROTOC message(FATAL_ERROR "No protoc command found!") endif() -#Find OpenSSL -if(WIN32) +# Find OpenSSL +if(WIN32) # Windows (including 64bit) find_package(OpenSSL REQUIRED) if(OPENSSL_FOUND) include_directories(${OPENSSL_INCLUDE_DIRS}) endif() endif() -#Find VCredist -if(MSVC) +# Find Visual C++ Redistributable +if(MSVC) # MS Visual C++ compiler find_package(VCredistRuntime) endif() @@ -269,7 +302,9 @@ set(CPACK_PACKAGE_CONTACT "Zach Halpern ") 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." + "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}") @@ -278,7 +313,7 @@ set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") set(CPACK_PACKAGE_FILE_NAME "${PROJECT_VERSION_FILENAME}") if(UNIX) - if(APPLE) + if(APPLE) # macOS set(CPACK_GENERATOR DragNDrop ${CPACK_GENERATOR}) set(CPACK_GENERATOR "DragNDrop") set(CPACK_DMG_FORMAT "UDBZ") @@ -288,15 +323,14 @@ if(UNIX) 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 + 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 + # Stop directories from creating package conflicts set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /usr/share/applications /usr/share/icons @@ -312,21 +346,21 @@ if(UNIX) 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 + set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libqt6sql6-mysql") # for connecting Servatrice to a MySQL DB endif() endif() -elseif(WIN32) +elseif(WIN32) # Windows (including 64bit) set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR}) - if("${CMAKE_GENERATOR_PLATFORM}" MATCHES "(x64)") - set(TRICE_IS_64_BIT 1) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(TRICE_IS_64_BIT 1) # 64bit else() - set(TRICE_IS_64_BIT 0) + set(TRICE_IS_64_BIT 0) # 32bit endif() - # Configure file with custom definitions for NSIS. + # Configure file with custom definitions for NSIS configure_file("${COCKATRICE_CMAKE_PATH}/NSIS.definitions.nsh.in" "${PROJECT_BINARY_DIR}/NSIS.definitions.nsh") - # include vcredist into the package; NSIS will take care of running it + # Include vcredist into the package - NSIS will take care of running it if(VCREDISTRUNTIME_FOUND) install(FILES "${VCREDISTRUNTIME_FILE}" DESTINATION ./) endif() @@ -334,27 +368,24 @@ endif() include(CPack) +add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_card ${CMAKE_BINARY_DIR}/libcockatrice_card) +add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_deck_list ${CMAKE_BINARY_DIR}/libcockatrice_deck_list) add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_interfaces ${CMAKE_BINARY_DIR}/libcockatrice_interfaces) add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_protocol ${CMAKE_BINARY_DIR}/libcockatrice_protocol) +add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_rng ${CMAKE_BINARY_DIR}/libcockatrice_rng) +add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_utility ${CMAKE_BINARY_DIR}/libcockatrice_utility) + if(WITH_CLIENT - OR WITH_SERVER OR WITH_ORACLE + OR WITH_SERVER ) 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_SERVER) - add_subdirectory(servatrice) - set(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS}) +if(WITH_CLIENT OR WITH_ORACLE) + add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_filters ${CMAKE_BINARY_DIR}/libcockatrice_filters) + add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_models ${CMAKE_BINARY_DIR}/libcockatrice_models) + add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_settings ${CMAKE_BINARY_DIR}/libcockatrice_settings) endif() if(WITH_CLIENT) @@ -367,12 +398,24 @@ if(WITH_ORACLE) set(CPACK_INSTALL_CMAKE_PROJECTS "Oracle;Oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS}) endif() +if(WITH_SERVER) + add_subdirectory(servatrice) + set(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS}) +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 6.3+ requires project finalization to support translations qt6_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}") diff --git a/servatrice/check_schema_version.sh b/servatrice/check_schema_version.sh index c4aadf356..8b645b5d2 100755 --- a/servatrice/check_schema_version.sh +++ b/servatrice/check_schema_version.sh @@ -10,7 +10,7 @@ declare -i schema_ver="${version_line%%)*}" latest_migration="$(ls -1 servatrice/migrations/ | tail -n1)" xtoysql="${latest_migration#servatrice_}" xtoy="${xtoysql%.sql}" -declare -i old_ver="10#${xtoy%_to_*}" #declare as integer with base 10, numbers with a leading 0 are normally interpreted as base 16 +declare -i old_ver="10#${xtoy%_to_*}" # declare as integer with base 10, numbers with a leading 0 are normally interpreted as base 16 declare -i new_ver="10#${xtoy#*_to_}" if ((old_ver >= new_ver)); then diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7bb834d7e..5c100c94e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,56 +3,71 @@ enable_testing() add_test(NAME dummy_test COMMAND dummy_test) -add_test(NAME expression_test COMMAND expression_test) +add_executable(dummy_test dummy_test.cpp) +# Add timeout to prevent hanging in case of issues with the general GTest setup +set_tests_properties(dummy_test PROPERTIES TIMEOUT 5) + add_test(NAME clamped_arithmetic_test COMMAND clamped_arithmetic_test) -add_test(NAME test_age_formatting COMMAND test_age_formatting) -add_test(NAME password_hash_test COMMAND password_hash_test) -add_test(NAME playmat_resolver_test COMMAND playmat_resolver_test) -add_test(NAME server_card_counter_test COMMAND server_card_counter_test) -add_test(NAME server_counter_test COMMAND server_counter_test) -add_test(NAME server_rate_limiter_test COMMAND server_rate_limiter_test) -add_test(NAME server_developer_role_test COMMAND server_developer_role_test) -add_test(NAME server_game_join_test COMMAND server_game_join_test) -add_test(NAME warning_categories_test COMMAND warning_categories_test) -add_test(NAME lag_monitor_test COMMAND lag_monitor_test) -add_test(NAME latency_tracker_test COMMAND latency_tracker_test) -add_test(NAME metrics_registry_test COMMAND metrics_registry_test) -add_test(NAME loader_local_matching_test COMMAND loader_local_matching_test) +add_executable(clamped_arithmetic_test clamped_arithmetic_test.cpp) add_test(NAME deck_hash_performance_test COMMAND deck_hash_performance_test) -set_tests_properties(deck_hash_performance_test PROPERTIES TIMEOUT 15) - -# Find GTest - -add_executable(dummy_test dummy_test.cpp) -add_executable(expression_test expression_test.cpp) -add_executable(clamped_arithmetic_test clamped_arithmetic_test.cpp) -add_executable(test_age_formatting test_age_formatting.cpp) -add_executable(password_hash_test password_hash_test.cpp) -add_executable(playmat_resolver_test playmat_resolver_test.cpp) add_executable(deck_hash_performance_test deck_hash_performance_test.cpp) -add_executable(server_card_counter_test server_card_counter_test.cpp) -add_executable(server_counter_test server_counter_test.cpp) -add_executable(server_rate_limiter_test server_rate_limiter_test.cpp) -add_executable(server_developer_role_test server_developer_role_test.cpp) -add_executable(server_game_join_test server_game_join_test.cpp) -add_executable(warning_categories_test warning_categories_test.cpp) +set_tests_properties(deck_hash_performance_test PROPERTIES TIMEOUT 10) + +add_test(NAME expression_test COMMAND expression_test) +add_executable(expression_test expression_test.cpp) + +add_test(NAME lag_monitor_test COMMAND lag_monitor_test) add_executable(lag_monitor_test ${CMAKE_SOURCE_DIR}/cockatrice/src/client/lag_monitor.cpp lag_monitor_test.cpp) target_include_directories(lag_monitor_test PRIVATE ${CMAKE_SOURCE_DIR}/cockatrice/src) + +add_test(NAME latency_tracker_test COMMAND latency_tracker_test) add_executable(latency_tracker_test latency_tracker_test.cpp) -add_executable(metrics_registry_test ../servatrice/src/metrics_registry.cpp metrics_registry_test.cpp) + +add_test(NAME loader_local_matching_test COMMAND loader_local_matching_test) add_executable( - loader_local_matching_test - ${CMAKE_SOURCE_DIR}/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp + ${VERSION_STRING_CPP} + ${CMAKE_SOURCE_DIR}/cockatrice/src/client/network/update/client/release_channel.cpp ${CMAKE_SOURCE_DIR}/cockatrice/src/client/settings/cache_settings.cpp ${CMAKE_SOURCE_DIR}/cockatrice/src/client/settings/card_counter_settings.cpp ${CMAKE_SOURCE_DIR}/cockatrice/src/client/settings/shortcuts_settings.cpp - ${CMAKE_SOURCE_DIR}/cockatrice/src/client/network/update/client/release_channel.cpp - ${VERSION_STRING_CPP} + ${CMAKE_SOURCE_DIR}/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp + loader_local_matching_test loader_local_matching_test.cpp ) target_include_directories(loader_local_matching_test PRIVATE ${CMAKE_SOURCE_DIR}/cockatrice/src) +add_test(NAME metrics_registry_test COMMAND metrics_registry_test) +add_executable(metrics_registry_test ../servatrice/src/metrics_registry.cpp metrics_registry_test.cpp) + +add_test(NAME password_hash_test COMMAND password_hash_test) +add_executable(password_hash_test password_hash_test.cpp) + +add_test(NAME playmat_resolver_test COMMAND playmat_resolver_test) +add_executable(playmat_resolver_test playmat_resolver_test.cpp) + +add_test(NAME server_card_counter_test COMMAND server_card_counter_test) +add_executable(server_card_counter_test server_card_counter_test.cpp) + +add_test(NAME server_counter_test COMMAND server_counter_test) +add_executable(server_counter_test server_counter_test.cpp) + +add_test(NAME server_developer_role_test COMMAND server_developer_role_test) +add_executable(server_developer_role_test server_developer_role_test.cpp) + +add_test(NAME server_game_join_test COMMAND server_game_join_test) +add_executable(server_game_join_test server_game_join_test.cpp) + +add_test(NAME server_rate_limiter_test COMMAND server_rate_limiter_test) +add_executable(server_rate_limiter_test server_rate_limiter_test.cpp) + +add_test(NAME test_age_formatting COMMAND test_age_formatting) +add_executable(test_age_formatting test_age_formatting.cpp) + +add_test(NAME warning_categories_test COMMAND warning_categories_test) +add_executable(warning_categories_test warning_categories_test.cpp) + +# Find GTest find_package(GTest) if(NOT GTEST_FOUND) @@ -79,22 +94,22 @@ if(NOT GTEST_FOUND) set(GTEST_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/gtest-src/include") set(GTEST_BOTH_LIBRARIES gtest) add_dependencies(dummy_test gtest) - add_dependencies(expression_test gtest) add_dependencies(clamped_arithmetic_test gtest) - add_dependencies(test_age_formatting gtest) - add_dependencies(password_hash_test gtest) - add_dependencies(playmat_resolver_test gtest) add_dependencies(deck_hash_performance_test gtest) - add_dependencies(server_card_counter_test gtest) - add_dependencies(server_counter_test gtest) - add_dependencies(server_rate_limiter_test gtest) - add_dependencies(server_developer_role_test gtest) - add_dependencies(server_game_join_test gtest) - add_dependencies(warning_categories_test gtest) + add_dependencies(expression_test gtest) add_dependencies(lag_monitor_test gtest) add_dependencies(latency_tracker_test gtest) - add_dependencies(metrics_registry_test gtest) add_dependencies(loader_local_matching_test gtest) + add_dependencies(metrics_registry_test gtest) + add_dependencies(password_hash_test gtest) + add_dependencies(playmat_resolver_test gtest) + add_dependencies(server_card_counter_test gtest) + add_dependencies(server_counter_test gtest) + add_dependencies(server_developer_role_test gtest) + add_dependencies(server_game_join_test gtest) + add_dependencies(server_rate_limiter_test gtest) + add_dependencies(test_age_formatting gtest) + add_dependencies(warning_categories_test gtest) endif() include_directories(${GTEST_INCLUDE_DIRS}) @@ -147,8 +162,8 @@ target_link_libraries( loader_local_matching_test libcockatrice_settings Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} ) -add_subdirectory(card_zone_algorithms) add_subdirectory(carddatabase) +add_subdirectory(card_zone_algorithms) add_subdirectory(deck_list_model) add_subdirectory(deck_list_zones) add_subdirectory(loading_from_clipboard)