This commit is contained in:
tooomm 2026-08-08 12:19:37 -07:00 • committed by GitHub
commit e643652b3b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 480 additions and 333 deletions

View file

@ -1,33 +1,127 @@
#!/bin/bash #!/usr/bin/env bash
# This script is to be used by the ci environment from the project root directory, do not use it from somewhere else. # Compiles Cockatrice inside GitHub Actions CI, run only from project root directory (GITHUB_WORKSPACE)
#
# Build flow and script structure:
# - Read options
# - Pre-checks (CI, Servatrice schema)
# - Prepare compilation (CMake options, OS-specific configuration)
# - Pre-buld (ccache)
# - Build (Configure, Compile)
# - Post-build (ccache, Inspect, Test, Install, Package)
#
# Supported command-line options:
# --ccache [<size>] Use ccache (USE_CCACHE) (optionally: provide cache size, e.g. "500M" or "1G" (CCACHE_SIZE))
# --cmake-generator <generator> Sets the CMake generator (CMAKE_GENERATOR), e.g. "Ninja", "Visual Studio 18 2026"
# --debug Sets the build type (BUILDTYPE --> CMAKE_BUILD_TYPE)
# --dir <dir> Sets the name of the build dir (BUILD_DIR)
# --evict-ccache <age> Evicts compiler cache older than <age> after build (CCACHE_EVICTION_AGE), e.g. "7d"
# --install Runs cmake install (MAKE_INSTALL)
# --no-client Compiles without Cockatrice and Oracle (MAKE_NO_CLIENT)
# --package [<package type>] Runs cmake package (MAKE_PACKAGE) (optionally: define type (PACKAGE_TYPE)), e.g. "DEB" [Linux only?]
# --release Sets the build type (BUILDTYPE --> CMAKE_BUILD_TYPE)
# --server Compiles Servatrice (MAKE_SERVER)
# --suffix <suffix> Renames package with provided suffix (PACKAGE_SUFFIX), e.g. "-macOS15"
# --target-macos-version <version> Sets the min OS version (TARGET_MACOS_VERSION), e.g. "14" [macOS only]
# --test Runs tests (MAKE_TEST)
# --vcpkg Use vcpkg package manager to resolve dependencies (USE_VCPKG)
#
# Exit codes:
# 1 --> Failure
# 3 --> Invalid argument(s)
# Compiles cockatrice inside of a ci environment set -euo pipefail
# --install runs make install
# --package [<package type>] runs make package, optionally force the type
# --suffix <suffix> renames package with this suffix, requires arg
# --server compiles servatrice
# --test runs tests
# --debug or --release sets the build type ie CMAKE_BUILD_TYPE
# --ccache [<size>] uses ccache and shows stats, optionally provide size
# --evict-ccache <age> runs ccache eviction based on given age after build
# --dir <dir> sets the name of the build dir, default is "build"
# --cmake-generator <generator> sets CMAKE_GENERATOR as used by cmake
# --target-macos-version <version> sets the min os version - only used for macOS builds
# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_NO_CLIENT MAKE_TEST USE_CCACHE CCACHE_SIZE CCACHE_EVICTION_AGE BUILD_DIR CMAKE_GENERATOR TARGET_MACOS_VERSION
# (correspond to args: --debug/--release --install --package <package type> --suffix <suffix> --server --test --ccache <ccache_size> --dir <dir>)
# exitcode: 1 for failure, 3 for invalid arguments
# Read arguments
### Initialize configuration variables:
# Precedence: command-line options > environment variables > built-in script defaults
BUILDTYPE="${BUILDTYPE:-Release}" # See "--debug" and "--release" flags (defaults to "Release" if omitted)
BUILD_DIR="${BUILD_DIR:-build}" # See value for "--dir" option (defaults to "build" if omitted)
CCACHE_EVICTION_AGE="${CCACHE_EVICTION_AGE:-}" # See value for "--evict-ccache" option
CCACHE_SIZE="${CCACHE_SIZE:-}" # See value for "--ccache" option
CMAKE_GENERATOR="${CMAKE_GENERATOR:-}" # See "--cmake-generator" option
MAKE_INSTALL="${MAKE_INSTALL:-0}" # See "--install" flag
MAKE_NO_CLIENT="${MAKE_NO_CLIENT:-0}" # See "--no-client" flag
MAKE_PACKAGE="${MAKE_PACKAGE:-0}" # See "--package" option
MAKE_SERVER="${MAKE_SERVER:-0}" # See "--server" flag
MAKE_TEST="${MAKE_TEST:-0}" # See "--test" flag
PACKAGE_SUFFIX="${PACKAGE_SUFFIX:-}" # See "--suffix" option
PACKAGE_TYPE="${PACKAGE_TYPE:-}" # See value for "--package" option
TARGET_MACOS_VERSION="${TARGET_MACOS_VERSION:-}" # See "--target-macos-version" option
USE_CCACHE="${USE_CCACHE:-0}" # See "--ccache" option
USE_VCPKG="${USE_VCPKG:-0}" # See "--vcpkg" flag
### Read options
while [[ $# != 0 ]]; do while [[ $# != 0 ]]; do
case "$1" in case "$1" in
'--')
# Flags (no argument)
'--debug')
BUILDTYPE="Debug"
shift shift
;; ;;
'--install') '--install')
MAKE_INSTALL=1 MAKE_INSTALL=1
shift shift
;; ;;
'--no-client')
MAKE_NO_CLIENT=1
shift
;;
'--release')
BUILDTYPE="Release"
shift
;;
'--server')
MAKE_SERVER=1
shift
;;
'--test')
MAKE_TEST=1
shift
;;
'--vcpkg')
USE_VCPKG=1
shift
;;
# Options (accept an argument)
'--ccache')
USE_CCACHE=1
shift
if [[ $# != 0 && ${1:0:1} != - ]]; then
CCACHE_SIZE="$1"
shift
fi
;;
'--cmake-generator')
shift
if [[ $# == 0 ]]; then
echo "::error file=$0::--cmake-generator expects an argument"
exit 3
fi
CMAKE_GENERATOR="$1"
shift
;;
'--dir')
shift
if [[ $# == 0 ]]; then
echo "::error file=$0::--dir expects an argument"
exit 3
fi
BUILD_DIR="$1"
shift
;;
'--evict-ccache')
shift
if [[ $# == 0 ]]; then
echo "::error file=$0::--evict-ccache expects an argument"
exit 3
fi
CCACHE_EVICTION_AGE="$1"
shift
;;
'--package') '--package')
MAKE_PACKAGE=1 MAKE_PACKAGE=1
shift shift
@ -45,65 +139,6 @@ while [[ $# != 0 ]]; do
PACKAGE_SUFFIX="$1" PACKAGE_SUFFIX="$1"
shift shift
;; ;;
'--server')
MAKE_SERVER=1
shift
;;
'--no-client')
MAKE_NO_CLIENT=1
shift
;;
'--test')
MAKE_TEST=1
shift
;;
'--debug')
BUILDTYPE="Debug"
shift
;;
'--release')
BUILDTYPE="Release"
shift
;;
'--ccache')
USE_CCACHE=1
shift
if [[ $# != 0 && ${1:0:1} != - ]]; then
CCACHE_SIZE="$1"
shift
fi
;;
'--evict-ccache')
shift
if [[ $# == 0 ]]; then
echo "::error file=$0::--evict-ccache expects an argument"
exit 3
fi
CCACHE_EVICTION_AGE=$1
shift
;;
'--vcpkg')
USE_VCPKG=1
shift
;;
'--dir')
shift
if [[ $# == 0 ]]; then
echo "::error file=$0::--dir expects an argument"
exit 3
fi
BUILD_DIR="$1"
shift
;;
'--cmake-generator')
shift
if [[ $# == 0 ]]; then
echo "::error file=$0::--cmake-generator expects an argument"
exit 3
fi
export CMAKE_GENERATOR=$1
shift
;;
'--target-macos-version') '--target-macos-version')
shift shift
if [[ $# == 0 ]]; then if [[ $# == 0 ]]; then
@ -113,70 +148,82 @@ while [[ $# != 0 ]]; do
TARGET_MACOS_VERSION="$1" TARGET_MACOS_VERSION="$1"
shift shift
;; ;;
# Positional arguments are not supported
'--')
shift
if [[ $# != 0 ]]; then
echo "::error file=$0::Unexpected positional arguments: $*"
exit 3
fi
break
;;
# Unknown options
*) *)
echo "::error file=$0::unrecognized option: $1" echo "::error file=$0::Unrecognized option: $1"
exit 3 exit 3
;; ;;
esac esac
done done
set -e
# Setup ### Pre-checks
./servatrice/check_schema_version.sh
if [[ ! $BUILDTYPE ]]; then # CI context (GitHub Actions provided environment variable)
BUILDTYPE=Release if [[ -z ${RUNNER_OS:-} ]]; then
echo "::notice::RUNNER_OS (GitHub Actions CI environment variable) is not available and OS-specific build configuration will be skipped"
fi fi
if [[ ! $BUILD_DIR ]]; then
BUILD_DIR="build" # Schema version consistency
if [[ $MAKE_SERVER == 1 ]]; then
./servatrice/check_schema_version.sh
fi fi
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
# Set minimum CMake Version
export CMAKE_POLICY_VERSION_MINIMUM=3.10
# Add cmake flags ### Prepare compilation
# CMake options
flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE") flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
if [[ $MAKE_SERVER ]]; then
flags+=("-DWITH_SERVER=1") if [[ -n $CMAKE_GENERATOR ]]; then
flags+=(-G "$CMAKE_GENERATOR")
fi fi
if [[ $MAKE_NO_CLIENT ]]; then if [[ $MAKE_NO_CLIENT == 1 ]]; then
flags+=("-DWITH_CLIENT=0" "-DWITH_ORACLE=0") flags+=("-DWITH_CLIENT=0" "-DWITH_ORACLE=0")
fi fi
if [[ $MAKE_TEST ]]; then if [[ $MAKE_SERVER == 1 ]]; then
flags+=("-DWITH_SERVER=1")
fi
if [[ $MAKE_TEST == 1 ]]; then
flags+=("-DTEST=1") flags+=("-DTEST=1")
fi fi
if [[ $USE_CCACHE ]]; then if [[ -n $PACKAGE_TYPE ]]; then
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
fi
if [[ $USE_CCACHE == 1 ]]; then
flags+=("-DUSE_CCACHE=1") flags+=("-DUSE_CCACHE=1")
if [[ $CCACHE_SIZE ]]; then if [[ -n $CCACHE_SIZE ]]; then
# note, this setting persists after running the script # Note: Setting persists after running the script
ccache --max-size "$CCACHE_SIZE" ccache --max-size "$CCACHE_SIZE"
fi fi
fi fi
if [[ $PACKAGE_TYPE ]]; then if [[ $USE_VCPKG == 1 ]]; then
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
fi
if [[ $USE_VCPKG ]]; then
flags+=("-DUSE_VCPKG=1") flags+=("-DUSE_VCPKG=1")
flags+=("-DVCPKG_INSTALL_OPTIONS=--x-abi-tools-use-exact-versions") flags+=("-DVCPKG_INSTALL_OPTIONS=--x-abi-tools-use-exact-versions")
fi fi
# Add cmake --build flags # CMake --build options
buildflags=(--config "$BUILDTYPE") buildflags=(--config "$BUILDTYPE")
function ccachestatsverbose() { if [[ ${RUNNER_OS:-} == "Windows" ]]; then
# note, verbose only works on newer ccache, discard the error # Enable MSBuild switches for MTT, see https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
local got # and https://devblogs.microsoft.com/cppblog/cpp-build-throughput-investigation-and-tune-up/#multitooltask-mtt
if got="$(ccache --show-stats --verbose 2>/dev/null)"; then buildflags+=(-- -p:UseMultiToolTask=true -p:EnableClServerMode=true)
echo "$got" fi
else
ccache --show-stats
fi
}
# Compile # Other OS-specific configuration (GitHub Actions runner)
if [[ $RUNNER_OS == macOS ]]; then 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, # 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 # which sets a few environment variables
if QTDIR=$(find "$GITHUB_WORKSPACE/Qt" -depth -maxdepth 2 -name macos -type d -print -quit); then if QTDIR=$(find "$GITHUB_WORKSPACE/Qt" -depth -maxdepth 2 -name macos -type d -print -quit); then
@ -185,42 +232,52 @@ if [[ $RUNNER_OS == macOS ]]; then
echo "could not find QTDIR!" echo "could not find QTDIR!"
exit 2 exit 2
fi fi
# the qtdir is located at Qt/[qtversion]/macos
# we use find to get the first subfolder with the name "macos" # The qtdir is located at Qt/<qtversion>/macos
# this works independent of the qt version as there should be only one version installed on the runner at a time # 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 export QTDIR
if [[ $TARGET_MACOS_VERSION ]]; then if [[ -n $TARGET_MACOS_VERSION ]]; then
# CMAKE_OSX_DEPLOYMENT_TARGET is a vanilla cmake flag needed to compile to target macOS version # CMAKE_OSX_DEPLOYMENT_TARGET is a vanilla CMake option needed to compile to target macOS version
flags+=("-DCMAKE_OSX_DEPLOYMENT_TARGET=$TARGET_MACOS_VERSION") flags+=("-DCMAKE_OSX_DEPLOYMENT_TARGET=$TARGET_MACOS_VERSION")
if [[ $USE_VCPKG == 1 ]]; then
echo "vcpkg triplet"
# vcpkg dependencies need a vcpkg triplet file to compile to the 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 # An easy way is to copy the x64-osx.cmake file and modify it
triplets_dir="/tmp/cmake/triplets" triplets_dir="/tmp/cmake/triplets"
triplet_version="custom-triplet" triplet_version="custom-triplet"
triplet_file="$triplets_dir/$triplet_version.cmake" triplet_file="$triplets_dir/$triplet_version.cmake"
arch=$(uname -m) arch=$(uname -m)
if [[ $arch == x86_64 ]]; then if [[ $arch == x86_64 ]]; then
arch="x64" arch="x64"
fi fi
mkdir -p "$triplets_dir" mkdir -p "$triplets_dir"
triplet_source="../vcpkg/triplets/$arch-osx.cmake" triplet_source="./vcpkg/triplets/$arch-osx.cmake"
if [[ ! -f "$triplet_source" ]]; then if [[ ! -f "$triplet_source" ]]; then
triplet_source="../vcpkg/triplets/community/$arch-osx.cmake" triplet_source="./vcpkg/triplets/community/$arch-osx.cmake"
fi fi
cp "$triplet_source" "$triplet_file" cp "$triplet_source" "$triplet_file"
echo "set(VCPKG_CMAKE_SYSTEM_VERSION $TARGET_MACOS_VERSION)" >>"$triplet_file" echo "set(VCPKG_CMAKE_SYSTEM_VERSION $TARGET_MACOS_VERSION)" >>"$triplet_file"
echo "set(VCPKG_OSX_DEPLOYMENT_TARGET $TARGET_MACOS_VERSION)" >>"$triplet_file" echo "set(VCPKG_OSX_DEPLOYMENT_TARGET $TARGET_MACOS_VERSION)" >>"$triplet_file"
flags+=("-DVCPKG_OVERLAY_TRIPLETS=$triplets_dir") flags+=("-DVCPKG_OVERLAY_TRIPLETS=$triplets_dir")
flags+=("-DVCPKG_HOST_TRIPLET=$triplet_version") flags+=("-DVCPKG_HOST_TRIPLET=$triplet_version")
flags+=("-DVCPKG_TARGET_TRIPLET=$triplet_version") flags+=("-DVCPKG_TARGET_TRIPLET=$triplet_version")
echo "::endgroup::"
echo "::group::Generated triplet $triplet_file" echo "::group::Generated triplet $triplet_file"
cat "$triplet_file" cat "$triplet_file"
echo "::endgroup::" echo "::endgroup::"
fi fi
fi
echo "::group::Signing Certificate" echo "::group::Setup signing certificate"
if [[ -n "$MACOS_CERTIFICATE_NAME" ]]; then if [[ -n $MACOS_CERTIFICATE_NAME ]]; then
echo "$MACOS_CERTIFICATE" | base64 --decode >"certificate.p12" echo "$MACOS_CERTIFICATE" | base64 --decode >"certificate.p12"
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
security default-keychain -s build.keychain security default-keychain -s build.keychain
@ -234,9 +291,9 @@ if [[ $RUNNER_OS == macOS ]]; then
fi fi
echo "::endgroup::" echo "::endgroup::"
if [[ $MAKE_PACKAGE ]]; then if [[ $MAKE_PACKAGE == 1 ]]; then
# Workaround https://github.com/actions/runner-images/issues/7522 # 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" hdiutil_script="/tmp/hdiutil.sh"
# shellcheck disable=SC2016 # shellcheck disable=SC2016
echo '#!/bin/bash echo '#!/bin/bash
@ -252,44 +309,78 @@ if [[ $RUNNER_OS == macOS ]]; then
flags+=(-DCPACK_COMMAND_HDIUTIL="$hdiutil_script") flags+=(-DCPACK_COMMAND_HDIUTIL="$hdiutil_script")
fi fi
elif [[ $RUNNER_OS == Windows ]]; then elif [[ ${RUNNER_OS:-} == "Windows" ]]; then
# Enable 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) elif [[ ${RUNNER_OS:-} == "Linux" ]]; then
:
fi fi
if [[ $USE_CCACHE ]]; then
echo "::group::Show ccache stats" ### Pre-build
ccachestatsverbose
# ccache
if [[ $USE_CCACHE == 1 ]]; then
echo "::group::Show ccache configuration"
ccache --version
ccache --show-config
echo " -----"
ccache --show-stats
ccache --show-compression
echo " -----"
ccache --show-stats --verbose
ccache --show-compression
echo " -----"
ccache --zero-stats
echo " -----"
ccache --show-stats
echo " -----"
ccache --show-stats --verbose
echo "::endgroup::" echo "::endgroup::"
fi fi
echo "::group::Configure cmake"
### Build
# Configure CMake
echo "::group::Generate buildsystem"
cmake --version cmake --version
echo "Running cmake with flags: ${flags[*]}" echo "Running CMake configuration with following flags: ${flags[*]}"
cmake .. "${flags[@]}" cmake -S . -B "$BUILD_DIR" "${flags[@]}"
echo "::endgroup::" echo "::endgroup::"
# Compile
echo "::group::Build project" echo "::group::Build project"
echo "Running cmake --build with flags: ${buildflags[*]}" echo "Running CMake with following build flags: ${buildflags[*]}"
cmake --build . "${buildflags[@]}" cmake --build "$BUILD_DIR" "${buildflags[@]}"
echo "::endgroup::" echo "::endgroup::"
if [[ $USE_CCACHE ]]; then
if [[ $CCACHE_EVICTION_AGE ]]; then ### Post-build
# ccache
if [[ $USE_CCACHE == 1 ]]; then
if [[ -n $CCACHE_EVICTION_AGE ]]; then
echo "::group::evict ccache files older than $CCACHE_EVICTION_AGE" echo "::group::evict ccache files older than $CCACHE_EVICTION_AGE"
ccache --evict-older-than "$CCACHE_EVICTION_AGE" ccache --evict-older-than "$CCACHE_EVICTION_AGE"
echo "::endgroup::" echo "::endgroup::"
fi fi
echo "::group::Show ccache stats again"
ccachestatsverbose echo "::group::Show ccache statistics"
ccache --show-stats --verbose
ccache --show-compression
echo "::endgroup::" 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!" echo "::error file=$0::ccache eviction is enabled while ccache is disabled!"
fi fi
if [[ $RUNNER_OS == macOS ]]; then # Inspect
if [[ ${RUNNER_OS:-} == "macOS" ]]; then
echo "::group::Inspect Mach-O binaries" echo "::group::Inspect Mach-O binaries"
for app in cockatrice oracle servatrice; do for app in cockatrice oracle servatrice; do
binary="$GITHUB_WORKSPACE/build/$app/$app.app/Contents/MacOS/$app" binary="$GITHUB_WORKSPACE/build/$app/$app.app/Contents/MacOS/$app"
echo "Inspecting $app..." echo "Inspecting $app..."
@ -298,30 +389,49 @@ if [[ $RUNNER_OS == macOS ]]; then
lipo -info "$binary" lipo -info "$binary"
echo "" echo ""
done done
echo "::endgroup::" echo "::endgroup::"
fi fi
if [[ $MAKE_TEST ]]; then # Test
if [[ $MAKE_TEST == 1 ]]; then
echo "::group::Run tests" echo "::group::Run tests"
ctest -C "$BUILDTYPE" --output-on-failure ctest --version
ctest --build-config "$BUILDTYPE" --test-dir "$BUILD_DIR" --output-on-failure
echo "::endgroup::" echo "::endgroup::"
fi fi
if [[ $MAKE_INSTALL ]]; then # Install
if [[ $MAKE_INSTALL == 1 ]]; then
echo "::group::Install" echo "::group::Install"
cmake --build . --target install --config "$BUILDTYPE" cmake --install "$BUILD_DIR" --config "$BUILDTYPE"
echo "::endgroup::" echo "::endgroup::"
fi fi
if [[ $MAKE_PACKAGE ]]; then # Package
if [[ $MAKE_PACKAGE == 1 ]]; then
echo "::group::Debug NSIS / CPack"
cat "_CPack_Packages/win64/NSIS/NSISOutput.log"
echo " -----"
find . -name "NSIS.definitions.nsh"
find "$BUILD_DIR" -name "NSIS.definitions.nsh"
ls -l "$BUILD_DIR/NSIS.definitions.nsh"
echo "::endgroup:"
echo "::group::Create package" echo "::group::Create package"
cmake --build . --target package --config "$BUILDTYPE" cpack --version
(
cd "$BUILD_DIR"
cpack
)
# cpack --config "$BUILD_DIR/CPackConfig.cmake"
# cmake --build "$BUILD_DIR" --target package
#TODO included --config? compare with former isntall and other --target variants used
echo "::endgroup::" echo "::endgroup::"
if [[ $PACKAGE_SUFFIX ]]; then if [[ -n $PACKAGE_SUFFIX ]]; then
echo "::group::Update package name" echo "::group::Update package name"
cd .. .ci/name_build.sh "$PACKAGE_SUFFIX"
BUILD_DIR="$BUILD_DIR" .ci/name_build.sh "$PACKAGE_SUFFIX"
echo "::endgroup::" echo "::endgroup::"
fi fi
fi fi

View file

@ -1,9 +1,9 @@
#!/bin/bash #!/bin/bash
# fetch master branch # Fetch master branch
git fetch origin master git fetch origin master
# unshallow if needed # Unshallow if needed
echo "Finding merge base" echo "Finding merge base"
if ! git merge-base origin/master HEAD; then if ! git merge-base origin/master HEAD; then
echo "Could not find merge base, unshallowing repo" echo "Could not find merge base, unshallowing repo"
@ -32,7 +32,6 @@ case $err in
*** *** *** ***
*********************************************************** ***********************************************************
Exiting...
EOM EOM
exit 2 exit 2
;; ;;
@ -48,7 +47,6 @@ EOM
*** *** *** ***
*********************************************************** ***********************************************************
Exiting...
EOM EOM
exit 0 exit 0
;; ;;

View file

@ -1,49 +1,55 @@
#!/bin/bash #!/usr/bin/env bash
# used by the ci to rename build artifacts
# renames the file to [original name][SUFFIX].[original extension]
# where SUFFIX is either available in the environment or as the first arg
# expected to be run in the build directory unless BUILD_DIR is set
# adds output to GITHUB_OUTPUT
builddir="${BUILD_DIR:=.}"
findrx="Cockatrice-*.*"
if [[ $1 ]]; then # Used by the CI build script to rename package artifacts
SUFFIX="$1" #
fi # Appends PACKAGE_SUFFIX to the package's filename
# <package> = <filename><extension>
# <package_new> = <filename><PACKAGE_SUFFIX><extension>
# PACKAGE_SUFFIX must be passed as the first argument to the script
# Adds output to GITHUB_OUTPUT
#
# Expected to be run in the repository root where CPack executes from and places its output binary
# Expects <extension> to be e.g. ".dmg", ".deb" or ".exe" (".tar.gz" etc. with more than one dot will break)
# If multiple packages match <package_pattern>, the first match is used
# check env set -euo pipefail
if [[ ! $SUFFIX ]]; then
echo "::error file=$0::SUFFIX is missing" # Initialize PACKAGE_SUFFIX from positional argument
PACKAGE_SUFFIX="${1:-}"
# Check variable
if [[ -z $PACKAGE_SUFFIX ]]; then
echo "::error file=$0::Missing required argument: PACKAGE_SUFFIX"
exit 2 exit 2
fi fi
set -e package_pattern="Cockatrice-*.*"
# find file # Find package in current directory
found="$(find "$builddir" -maxdepth 1 -type f -name "$findrx" -print -quit)" package_path="$(find "$PWD" -maxdepth 1 -type f -name "$package_pattern" -print -quit)"
path="${found%/*}" # remove all including first "/" from right side
file="${found##*/}" # remove all including last "/" from left side if [[ -z "$package_path" ]]; then
if [[ ! $file ]]; then echo "::error file=$0::Could not find package"
echo "::error file=$0::could not find package"
exit 1
fi
oldpwd="$PWD"
if ! cd "$path"; then
echo "::error file=$0::could not get file path"
exit 1 exit 1
fi fi
# set filename # <package> = <filename><extension>
name="${file%.*}" # remove all including first "." from right side package="${package_path##*/}" # e.g. "Cockatrice-3.0.0.deb"
new_name="$name$SUFFIX" filename="${package%.*}" # e.g. "Cockatrice-3.0.0"
extension="${file##*.}" # remove all including last "." from left side extension=".${package##*.}" # e.g. ".deb"
filename="$new_name.$extension"
echo "renaming '$file' to '$filename'"
mv "$file" "$filename"
cd "$oldpwd" # Rename package (build artifact)
relative_path="$path/$filename" filename_new="$filename$PACKAGE_SUFFIX"
ls -l "$relative_path" package_new="$filename_new$extension"
echo "path=$relative_path" >>"$GITHUB_OUTPUT" package_path_new="$PWD/$package_new"
echo "name=$new_name" >>"$GITHUB_OUTPUT"
echo "fullname=$filename" >>"$GITHUB_OUTPUT" echo "Renaming '$package' to '$package_new'"
mv "$package_path" "$package_path_new"
du -h "$package_path_new"
#TODO remove package_path as it's default working direcotry / repo root?
{
echo "package_path=$package_path_new" >> "$GITHUB_OUTPUT"
echo "package=$package_new" >> "$GITHUB_OUTPUT"
echo "filename=$filename_new" >> "$GITHUB_OUTPUT"
} >> "$GITHUB_OUTPUT"

View file

@ -227,18 +227,18 @@ jobs:
with: with:
archive: false archive: false
if-no-files-found: error if-no-files-found: error
path: ${{ steps.build.outputs.path }} path: ${{ steps.build.outputs.package }} # package is resolved against github.workspace
- name: "Upload to release" - name: "Upload to release"
id: upload_release id: upload_release
if: matrix.package != 'skip' && needs.configure.outputs.tag != null if: matrix.package != 'skip' && needs.configure.outputs.tag != null
shell: bash shell: bash
env: env:
asset_name: ${{ steps.build.outputs.fullname }} package: ${{ steps.build.outputs.package }}
asset_path: ${{ steps.build.outputs.path }} package_path: ${{ steps.build.outputs.package_path }} # <-- to check
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
tag_name: ${{ needs.configure.outputs.tag }} tag_name: ${{ needs.configure.outputs.tag }}
run: gh release upload "$tag_name" "$asset_path#$asset_name" run: gh release upload "$tag_name" "$package_path#$package" # <-- to check
- name: "Attest binary provenance" - name: "Attest binary provenance"
id: attestation id: attestation
@ -246,15 +246,15 @@ jobs:
uses: actions/attest@v4 uses: actions/attest@v4
with: with:
show-summary: false show-summary: false
subject-path: ${{ steps.build.outputs.path }} subject-path: ${{ steps.build.outputs.package_path }} # <-- to check
- name: "Verify binary attestation" - name: "Verify binary attestation"
if: steps.attestation.outcome == 'success' if: steps.attestation.outcome == 'success'
shell: bash shell: bash
env: env:
BUILD_PATH: ${{ steps.build.outputs.path }} PACKAGE_PATH: ${{ steps.build.outputs.package_path }} # <-- to check
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
run: gh attestation verify "$BUILD_PATH" --repo Cockatrice/Cockatrice run: gh attestation verify "$PACKAGE_PATH" --repo Cockatrice/Cockatrice
build-vcpkg: build-vcpkg:
strategy: strategy:
@ -422,7 +422,7 @@ jobs:
- name: "[Windows] Install NSIS" - name: "[Windows] Install NSIS"
if: matrix.os == 'Windows' if: matrix.os == 'Windows'
shell: bash shell: bash
run: choco install nsis run: choco install nsis --no-progress
- name: "Setup vcpkg cache" - name: "Setup vcpkg cache"
id: vcpkg-cache id: vcpkg-cache
@ -451,6 +451,11 @@ jobs:
VCPKG_BINARY_SOURCES: 'clear;files,${{ steps.vcpkg-cache.outputs.path }},readwrite' VCPKG_BINARY_SOURCES: 'clear;files,${{ steps.vcpkg-cache.outputs.path }},readwrite'
VCPKG_DISABLE_METRICS: 1 VCPKG_DISABLE_METRICS: 1
run: .ci/compile.sh --server --test --vcpkg run: .ci/compile.sh --server --test --vcpkg
continue-on-error: true
- name: "[Windows] DEBUG: Print NSIS log output"
if: matrix.os == 'Windows'
run: cat "_CPack_Packages/win64/NSIS/NSISOutput.log"
# Delete used cache to emulate a ccache update. See https://github.com/actions/cache/issues/342 # Delete used cache to emulate a ccache update. See https://github.com/actions/cache/issues/342
- name: "[macOS] Delete remote compiler cache (ccache)" - name: "[macOS] Delete remote compiler cache (ccache)"
@ -475,20 +480,20 @@ jobs:
if: matrix.os == 'macOS' && matrix.make_package && needs.configure.outputs.tag != null if: matrix.os == 'macOS' && matrix.make_package && needs.configure.outputs.tag != null
id: sign_macos id: sign_macos
env: env:
BUILD_PATH: ${{ steps.build.outputs.path }} PACKAGE_PATH: ${{ steps.build.outputs.package_path }}
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }} MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }} MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
run: | run: |
if [[ -n "$MACOS_CERTIFICATE_NAME" ]] if [[ -n "$MACOS_CERTIFICATE_NAME" ]]
then then
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
/usr/bin/codesign --sign="$MACOS_CERTIFICATE_NAME" --entitlements=".ci/macos.entitlements" --options=runtime --force --deep --timestamp --verbose "$BUILD_PATH" /usr/bin/codesign --sign="$MACOS_CERTIFICATE_NAME" --entitlements=".ci/macos.entitlements" --options=runtime --force --deep --timestamp --verbose "$PACKAGE_PATH"
fi fi
- name: "[macOS] Notarize app bundle" - name: "[macOS] Notarize app bundle"
if: matrix.os == 'macOS' && steps.sign_macos.outcome == 'success' if: matrix.os == 'macOS' && steps.sign_macos.outcome == 'success'
env: env:
BUILD_PATH: ${{ steps.build.outputs.path }} PACKAGE_PATH: ${{ steps.build.outputs.package_path }}
MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }} MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }} MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }} MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
@ -503,7 +508,7 @@ jobs:
# Therefore, we create a zip file containing our app bundle, so that we can send it to the # Therefore, we create a zip file containing our app bundle, so that we can send it to the
# notarization service # notarization service
echo "Creating temp notarization archive" echo "Creating temp notarization archive"
ditto -c -k --keepParent "$BUILD_PATH" "notarization.zip" ditto -c -k --keepParent "$PACKAGE_PATH" "notarization.zip"
# Here we send the notarization request to the Apple's Notarization service, waiting for the result. # Here we send the notarization request to the Apple's Notarization service, waiting for the result.
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App # This typically takes a few seconds inside a CI environment, but it might take more depending on the App
@ -515,7 +520,7 @@ jobs:
# Finally, we need to "attach the staple" to our executable, which will allow our app to be # Finally, we need to "attach the staple" to our executable, which will allow our app to be
# validated by macOS even when an internet connection is not available. # validated by macOS even when an internet connection is not available.
echo "Attach staple" echo "Attach staple"
xcrun stapler staple "$BUILD_PATH" xcrun stapler staple "$PACKAGE_PATH"
fi fi
- name: "Upload artifact" - name: "Upload artifact"
@ -525,14 +530,14 @@ jobs:
with: with:
archive: false archive: false
if-no-files-found: error if-no-files-found: error
path: ${{ steps.build.outputs.path }} path: ${{ steps.build.outputs.package_path }}
- name: "[Windows] Upload PDBs (Program Databases)" - name: "[Windows] Upload PDBs (Program Databases)"
if: matrix.os == 'Windows' && github.ref_type != 'tag' if: matrix.os == 'Windows' && github.ref_type != 'tag'
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
if-no-files-found: error if-no-files-found: error
name: ${{ steps.build.outputs.name }}-PDBs name: ${{ steps.build.outputs.filename }}-PDBs
path: | path: |
build/cockatrice/Release/*.pdb build/cockatrice/Release/*.pdb
build/oracle/Release/*.pdb build/oracle/Release/*.pdb
@ -543,11 +548,11 @@ jobs:
id: upload_release id: upload_release
shell: bash shell: bash
env: env:
asset_name: ${{ steps.build.outputs.fullname }} package: ${{ steps.build.outputs.package }}
asset_path: ${{ steps.build.outputs.path }} package_path: ${{ steps.build.outputs.package_path }}
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
tag_name: ${{ needs.configure.outputs.tag }} tag_name: ${{ needs.configure.outputs.tag }}
run: gh release upload "$tag_name" "$asset_path#$asset_name" run: gh release upload "$tag_name" "$package_path#$package"
- name: "Attest binary provenance" - name: "Attest binary provenance"
if: steps.upload_release.outcome == 'success' if: steps.upload_release.outcome == 'success'
@ -555,12 +560,12 @@ jobs:
uses: actions/attest@v4 uses: actions/attest@v4
with: with:
show-summary: false show-summary: false
subject-path: ${{ steps.build.outputs.path }} subject-path: ${{ steps.build.outputs.package_path }}
- name: "Verify binary attestation" - name: "Verify binary attestation"
if: steps.attestation.outcome == 'success' if: steps.attestation.outcome == 'success'
shell: bash shell: bash
env: env:
BUILD_PATH: ${{ steps.build.outputs.path }} PACKAGE_PATH: ${{ steps.build.outputs.package_path }}
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
run: gh attestation verify "$BUILD_PATH" --repo Cockatrice/Cockatrice run: gh attestation verify "$PACKAGE_PATH" --repo Cockatrice/Cockatrice

View file

@ -1,11 +1,11 @@
# Cockatrice's main CMakeLists.txt # Cockatrice's main CMakeLists.txt
# #
# This is basically a wrapper to enable/disable the compilation # This is basically a wrapper to enable/disable the compilation
# of the different projects: servatrice, cockatrice, test # of the different projects: cockatrice, servatrice, test
# This file sets all the variables shared between the projects # This file sets all the variables shared between the projects
# like the installation path, compilation flags etc.. # like the installation path, compilation flags etc..
# cmake 3.16 is required if using qt6 # CMake 3.16 is required if using Qt6
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
# Early detect ccache # Early detect ccache
@ -27,20 +27,16 @@ option(USE_VCPKG "Use vcpkg regardless of OS" OFF)
# Default to "Release" build type # Default to "Release" build type
# User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call # User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call
if(DEFINED CMAKE_BUILD_TYPE) if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE
${CMAKE_BUILD_TYPE}
CACHE STRING "Type of build"
)
else()
set(CMAKE_BUILD_TYPE set(CMAKE_BUILD_TYPE
Release Release
CACHE STRING "Type of build" CACHE STRING "Build type"
) )
endif() endif()
if(USE_CCACHE) if(USE_CCACHE)
find_program(CCACHE_PROGRAM ccache) find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM) if(CCACHE_PROGRAM)
# Support Unix Makefiles and Ninja # Support Unix Makefiles and Ninja
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
@ -54,6 +50,7 @@ if(WIN32 OR USE_VCPKG)
${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake
CACHE STRING "Vcpkg toolchain file" CACHE STRING "Vcpkg toolchain file"
) )
# Qt path set by user or env var # Qt path set by user or env var
if(QTDIR if(QTDIR
OR DEFINED ENV{QTDIR} OR DEFINED ENV{QTDIR}
@ -76,22 +73,23 @@ endif()
# Version can be overriden by git tags, see cmake/getversion.cmake # Version can be overriden by git tags, see cmake/getversion.cmake
project("Cockatrice" VERSION 3.1.0) 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) if(NOT DEFINED GIT_TAG_RELEASENAME)
set(GIT_TAG_RELEASENAME "Graduation Day") set(GIT_TAG_RELEASENAME "Graduation Day")
endif() endif()
# Use c++20 for all targets # Use C++20 for all targets
set(CMAKE_CXX_STANDARD set(CMAKE_CXX_STANDARD
20 20
CACHE STRING "C++ ISO Standard" CACHE STRING "C++ ISO Standard"
) )
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS OFF)
# Set conventional loops # Set conventional loops
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
# Search path for cmake modules # Search path for CMake modules
set(COCKATRICE_CMAKE_PATH "${PROJECT_SOURCE_DIR}/cmake") set(COCKATRICE_CMAKE_PATH "${PROJECT_SOURCE_DIR}/cmake")
list(INSERT CMAKE_MODULE_PATH 0 "${COCKATRICE_CMAKE_PATH}") list(INSERT CMAKE_MODULE_PATH 0 "${COCKATRICE_CMAKE_PATH}")
@ -102,14 +100,14 @@ include(createversionfile)
# Define a proper install path # Define a proper install path
if(UNIX) if(UNIX)
if(APPLE)
# macOS if(APPLE) # macOS
# Due to the special bundle structure ignore # Due to the special bundle structure ignore the prefix eventually set by the user
# the prefix eventually set by the user.
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/release) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/release)
# Force ccache usage if available # Force ccache usage if available
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE) get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
if(RULE_LAUNCH_COMPILE) if(RULE_LAUNCH_COMPILE)
message(STATUS "Force enabling CCache usage under macOS") message(STATUS "Force enabling CCache usage under macOS")
# Set up wrapper scripts # Set up wrapper scripts
@ -123,39 +121,52 @@ if(UNIX)
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c") set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx") 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) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
#fix package build
# Fix package build
if(PREFIX) if(PREFIX)
set(CMAKE_INSTALL_PREFIX ${PREFIX}) set(CMAKE_INSTALL_PREFIX ${PREFIX})
else() else()
set(CMAKE_INSTALL_PREFIX /usr/local) set(CMAKE_INSTALL_PREFIX /usr/local)
endif() endif()
endif() endif()
endif() endif()
elseif(WIN32)
elseif(WIN32) # Windows
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/rundir/${CMAKE_BUILD_TYPE}) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/rundir/${CMAKE_BUILD_TYPE})
endif() endif()
# Define proper compilation flags # Define proper compilation flags
if(MSVC) if(MSVC) # Microsoft Visual C++ compiler
# Disable Warning C4251, C++20 compatibility, Multi-threaded Builds, Warn Detection, Unwind Semantics, Debug Symbols # /wd4251 Suppress C4251 (DLL interface) warnings
set(CMAKE_CXX_FLAGS "/wd4251 /Zc:__cplusplus /std:c++20 /permissive- /W4 /MP /EHsc /Zi") # /W4 Enable warning level 4
# Visual Studio: Maximum Optimization, Multi-threaded DLL # /MP Enable multi-threaded building
# /EHsc Enable standard C++ exception handling
# /Zi Generate debugging information (Program Databases, PDBs)
set(CMAKE_CXX_FLAGS "/wd4251 /W4 /MP /EHsc /Zi")
# /Ox Enable maximum optimization
# /MD Link against the multi-threaded DLL runtime library (Release CRT)
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD") set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD")
# Visual Studio: No Optimization, Multi-threaded Debug DLL
# /Od Disable optimization
# /MDd Link against the multi-threaded Debug DLL runtime library (Debug CRT)
set(CMAKE_CXX_FLAGS_DEBUG "/Od /MDd") set(CMAKE_CXX_FLAGS_DEBUG "/Od /MDd")
# Generate PDB, even when in release (So developers can better analyze crash logs) # Generate PDBs, even when in release (Allow developers to better analyze crash logs)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF") 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) add_compile_definitions(_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING)
elseif(CMAKE_COMPILER_IS_GNUCXX) elseif(CMAKE_COMPILER_IS_GNUCXX)
# linux/gcc, bsd/gcc, windows/mingw # Linux/GCC, BSD/GCC, Windows/MinGW
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
set(CMAKE_CXX_FLAGS_RELEASE "-s -O2") set(CMAKE_CXX_FLAGS_RELEASE "-s -O2")
if(WARNING_AS_ERROR) if(WARNING_AS_ERROR)
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -Werror") set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -Werror")
else() else()
@ -174,23 +185,26 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
-Wno-error=delete-non-virtual-dtor -Wno-error=delete-non-virtual-dtor
-Wno-error=sign-compare -Wno-error=sign-compare
-Wno-error=missing-declarations -Wno-error=missing-declarations
-Wno-error=sfinae-incomplete # GCC 16+: Qt MOC + protobuf forward decls trigger this -Wno-error=sfinae-incomplete # GCC 16+: Qt MOC + protobuf forward declarations trigger this
) )
foreach(FLAG ${ADDITIONAL_DEBUG_FLAGS}) foreach(FLAG ${ADDITIONAL_DEBUG_FLAGS})
check_cxx_compiler_flag("${FLAG}" CXX_HAS_WARNING_${FLAG}) check_cxx_compiler_flag("${FLAG}" CXX_HAS_WARNING_${FLAG})
if(CXX_HAS_WARNING_${FLAG}) if(CXX_HAS_WARNING_${FLAG})
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}")
endif() endif()
endforeach() endforeach()
else()
# other: osx/llvm, bsd/llvm else() # Other: macOS/LLVM, BSD/LLVM
set(CMAKE_CXX_FLAGS_RELEASE "-O2") set(CMAKE_CXX_FLAGS_RELEASE "-O2")
if(WARNING_AS_ERROR) if(WARNING_AS_ERROR)
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Werror -Wno-unused-parameter") set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Werror -Wno-unused-parameter")
else() else()
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra") set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra")
endif() endif()
endif() 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 the RNG to compile w/o warning
@ -225,6 +239,7 @@ set(CMAKE_AUTOMOC TRUE)
# Find other needed libraries # Find other needed libraries
find_package(Protobuf CONFIG) find_package(Protobuf CONFIG)
if(NOT Protobuf_FOUND) if(NOT Protobuf_FOUND)
find_package(Protobuf REQUIRED) find_package(Protobuf REQUIRED)
endif() endif()
@ -233,9 +248,11 @@ if(${Protobuf_VERSION} VERSION_LESS "3.21.0.0" AND NOT EXISTS "${Protobuf_PROTOC
message(FATAL_ERROR "No protoc command found!") message(FATAL_ERROR "No protoc command found!")
endif() endif()
#Find OpenSSL # Find OpenSSL
if(WIN32) if(WIN32)
find_package(OpenSSL REQUIRED) find_package(OpenSSL REQUIRED)
if(OPENSSL_FOUND) if(OPENSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIRS}) include_directories(${OPENSSL_INCLUDE_DIRS})
else() else()
@ -246,7 +263,7 @@ if(WIN32)
endif() endif()
endif() endif()
#Find VCredist # Find Visual C++ Redistributable
if(MSVC) if(MSVC)
find_package(VCredistRuntime) find_package(VCredistRuntime)
endif() endif()
@ -256,7 +273,9 @@ set(CPACK_PACKAGE_CONTACT "Zach Halpern <zach@cockatrice.us>")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_NAME}") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_NAME}")
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team") set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
set(CPACK_PACKAGE_DESCRIPTION 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_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
@ -265,7 +284,8 @@ set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_VERSION_FILENAME}") set(CPACK_PACKAGE_FILE_NAME "${PROJECT_VERSION_FILENAME}")
if(UNIX) if(UNIX)
if(APPLE)
if(APPLE) # macOS
set(CPACK_GENERATOR DragNDrop ${CPACK_GENERATOR}) set(CPACK_GENERATOR DragNDrop ${CPACK_GENERATOR})
set(CPACK_GENERATOR "DragNDrop") set(CPACK_GENERATOR "DragNDrop")
set(CPACK_DMG_FORMAT "UDBZ") set(CPACK_DMG_FORMAT "UDBZ")
@ -275,8 +295,8 @@ if(UNIX)
set(CPACK_DMG_DS_STORE_SETUP_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeDMGSetup.script") 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_DMG_BACKGROUND_IMAGE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/dmgBackground.tif")
set(CPACK_PRE_BUILD_SCRIPTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/SignMacApplications.cmake") set(CPACK_PRE_BUILD_SCRIPTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/SignMacApplications.cmake")
else()
# linux else() # Linux
if(CPACK_GENERATOR STREQUAL "RPM") if(CPACK_GENERATOR STREQUAL "RPM")
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2") set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
set(CPACK_RPM_MAIN_COMPONENT "cockatrice") set(CPACK_RPM_MAIN_COMPONENT "cockatrice")
@ -287,7 +307,7 @@ if(UNIX)
endif() endif()
set(CPACK_RPM_PACKAGE_GROUP "Amusements/Games") set(CPACK_RPM_PACKAGE_GROUP "Amusements/Games")
set(CPACK_RPM_PACKAGE_URL "http://github.com/Cockatrice/Cockatrice") 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 set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
/usr/share/applications /usr/share/applications
/usr/share/icons /usr/share/icons
@ -304,24 +324,25 @@ if(UNIX)
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice") set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
if(Qt6_FOUND) if(Qt6_FOUND)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-qpa-plugins, qt6-image-formats-plugins") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-qpa-plugins, qt6-image-formats-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
elseif(Qt5_FOUND) elseif(Qt5_FOUND)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5")
endif() endif()
endif() endif()
endif() endif()
elseif(WIN32)
elseif(WIN32) # Windows
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR}) set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
if("${CMAKE_GENERATOR_PLATFORM}" MATCHES "(x64)") if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(TRICE_IS_64_BIT 1) set(TRICE_IS_64_BIT 1)
else() else()
set(TRICE_IS_64_BIT 0) set(TRICE_IS_64_BIT 0)
endif() 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") 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) if(VCREDISTRUNTIME_FOUND)
install(FILES "${VCREDISTRUNTIME_FILE}" DESTINATION ./) install(FILES "${VCREDISTRUNTIME_FILE}" DESTINATION ./)
endif() endif()
@ -368,6 +389,6 @@ if(TEST)
endif() endif()
if(Qt6_FOUND AND Qt6_VERSION_MINOR GREATER_EQUAL 3) 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() qt6_finalize_project()
endif() endif()

View file

@ -1,30 +1,30 @@
#!/bin/bash #!/bin/bash
# This script will run clang-format on all modified, non-3rd-party C++/Header files. # This script will run Clang-Format on all modified, non-3rd-party C++/Header files.
# Optionally runs cmake-format on all modified cmake files. # Optionally runs cmake-format on all modified cmake files.
# Optionally runs shellcheck on all modified shell files. # Optionally runs ShellCheck on all modified shell files.
# Uses clang-format, cmake-format, git, diff, find and shellcheck # Uses clang-format, cmake-format, git, diff, find and shellcheck
# Never, ever, should this receive a path with a newline in it. Don't bother proofing it for that. # Never, ever, should this receive a path with a newline in it. Don't bother proofing it for that.
set -o pipefail set -o pipefail
# go to the project root directory, this file should be located in the project root directory # Go to the project root directory, this file should be located in the project root directory
olddir="$PWD" olddir="$PWD"
cd "${BASH_SOURCE%/*}/" || exit 2 # could not find path, this could happen with special links etc. cd "${BASH_SOURCE%/*}/" || exit 2 # could not find path, this could happen with special links etc.
# defaults # Defaults
include=("cockatrice/src" \ include=("cockatrice/src" \
libcockatrice_* \ libcockatrice_* \
"oracle/src" \ "oracle/src" \
"servatrice/src" \ "servatrice/src" \
"tests") "tests")
exclude=("libcockatrice_rng/libcockatrice/rng/sfmt/" \ exclude=("libcockatrice_rng/libcockatrice/rng/sfmt/" \
"libcockatrice_utility/libcockatrice/utility/peglib.h" \ "libcockatrice_utility/libcockatrice/utility/peglib.h" \
"oracle/src/lzma/" \ "oracle/src/lzma/" \
"oracle/src/qt-json/" \ "oracle/src/qt-json/" \
"oracle/src/zip/" \ "oracle/src/zip/" \
"servatrice/src/smtp/") "servatrice/src/smtp/")
exts=("cpp" "h" "proto") extensions=("cpp" "h" "proto")
cf_cmd="clang-format" cf_cmd="clang-format"
branch="origin/master" branch="origin/master"
cmakefile="CMakeLists.txt" cmakefile="CMakeLists.txt"
@ -33,9 +33,9 @@ cmakeinclude=("cmake/gtest-CMakeLists.txt.in")
scripts="*.sh" scripts="*.sh"
color="--" color="--"
verbosity=0 verbosity=0
sep="----------" separator=" ----------"
# parse options # Parse options
while [[ $* ]]; do while [[ $* ]]; do
case "$1" in case "$1" in
'-b'|'--branch') '-b'|'--branch')
@ -58,7 +58,7 @@ while [[ $* ]]; do
;; ;;
'-h'|'--help') '-h'|'--help')
cat <<EOM cat <<EOM
A bash script to automatically format your code using clang-format. A bash script to automatically format your code using Clang-Format.
If no options are given, all dirty source files are edited in place. If no options are given, all dirty source files are edited in place.
If <dir>s are given, all source files in those directories of the project root If <dir>s are given, all source files in those directories of the project root
@ -165,7 +165,7 @@ EOM
;; ;;
*) *)
if [[ ! $dashdash && $1 =~ ^-- ]]; then if [[ ! $dashdash && $1 =~ ^-- ]]; then
echo "error in parsing arguments of $0: $1 is an unrecognized option" >&2 echo "Error in parsing arguments of $0: $1 is an unrecognized option" >&2
exit 2 # input error exit 2 # input error
fi fi
if [[ ! $1 ]] || next_dir=$(cd "$olddir" && cd -- "$1" && pwd); then if [[ ! $1 ]] || next_dir=$(cd "$olddir" && cd -- "$1" && pwd); then
@ -175,13 +175,13 @@ EOM
fi fi
if [[ $1 ]]; then if [[ $1 ]]; then
if [[ $next_dir != $PWD/* ]]; then if [[ $next_dir != $PWD/* ]]; then
echo "error in parsing arguments of $0: $next_dir is not in $PWD" >&2 echo "Error in parsing arguments of $0: $next_dir is not in $PWD" >&2
exit 2 # input error exit 2 # input error
fi fi
include+=("$next_dir") include+=("$next_dir")
fi fi
else else
echo "error in parsing arguments of $0: $1 is not a directory" >&2 echo "Error in parsing arguments of $0: $1 is not a directory" >&2
exit 2 # input error exit 2 # input error
fi fi
if ! [[ $set_branch ]]; then if ! [[ $set_branch ]]; then
@ -192,39 +192,39 @@ EOM
esac esac
done done
# check availability of clang-format # Check availability of Clang-Format
if ! hash $cf_cmd 2>/dev/null; then if ! hash $cf_cmd 2>/dev/null; then
echo "could not find $cf_cmd" >&2 echo "could not find $cf_cmd" >&2
# find any clang-format-x.x in /usr/bin # Find any "clang-format-x.x" in /usr/bin
cf_cmd=$(find /usr/bin -regex '.*/clang-format-[0-9]+\.[0-9]+' -print -quit) cf_cmd=$(find /usr/bin -regex '.*/clang-format-[0-9]+\.[0-9]+' -print -quit)
if [[ $cf_cmd ]]; then if [[ $cf_cmd ]]; then
echo "found $cf_cmd instead" >&2 echo "Found $cf_cmd instead" >&2
else else
exit 3 # special exit code for missing dependency exit 3 # special exit code for missing dependency
fi fi
fi fi
# check availability of cmake-format # Check availability of cmake-format
if [[ $do_cmake ]] && ! hash cmake-format 2>/dev/null; then if [[ $do_cmake ]] && ! hash cmake-format 2>/dev/null; then
echo "could not find cmake-format" >&2 echo "Could not find cmake-format" >&2
exit 3 exit 3
fi fi
# check availability of shellcheck # Check availability of ShellCheck
if [[ $do_shell ]] && ! hash shellcheck 2>/dev/null; then if [[ $do_shell ]] && ! hash shellcheck 2>/dev/null; then
echo "could not find shellcheck" >&2 echo "Could not find shellcheck" >&2
exit 3 exit 3
fi fi
if [[ $branch ]]; then if [[ $branch ]]; then
# get all dirty files through git # Get all dirty files through git
if ! base=$(git merge-base "$branch" HEAD); then if ! base=$(git merge-base "$branch" HEAD); then
echo "could not find git merge base" >&2 echo "Could not find git merge base" >&2
exit 2 # input error exit 2 # input error
fi fi
mapfile -t basenames < <(git diff --diff-filter=d --name-only "$base") mapfile -t basenames < <(git diff --diff-filter=d --name-only "$base")
names=() names=()
for ex in "${exts[@]}"; do for ex in "${extensions[@]}"; do
for path in "${include[@]}"; do for path in "${include[@]}"; do
for name in "${basenames[@]}"; do for name in "${basenames[@]}"; do
rx="^$path/.*\\.$ex$" rx="^$path/.*\\.$ex$"
@ -260,7 +260,7 @@ if [[ $branch ]]; then
fi fi
else else
exts_o=() exts_o=()
for ext in "${exts[@]}"; do for ext in "${extensions[@]}"; do
exts_o+=(-o -name "*\\.$ext") exts_o+=(-o -name "*\\.$ext")
done done
unset "exts_o[0]" # remove first -o unset "exts_o[0]" # remove first -o
@ -274,7 +274,7 @@ else
fi fi
fi fi
# filter excludes # Filter excludes
for path in "${exclude[@]}"; do for path in "${exclude[@]}"; do
for i in "${!names[@]}"; do for i in "${!names[@]}"; do
rx="^$path" rx="^$path"
@ -284,12 +284,12 @@ for path in "${exclude[@]}"; do
done done
done done
# optionally print version # Optionally print version
if [[ $print_version ]]; then if [[ $print_version ]]; then
$cf_cmd -version $cf_cmd -version
[[ $do_cmake ]] && echo "cmake-format version $(cmake-format --version)" [[ $do_cmake ]] && echo "cmake-format version $(cmake-format --version)"
[[ $do_shell ]] && echo "shellcheck $(shellcheck --version | grep "version:")" [[ $do_shell ]] && echo "ShellCheck $(shellcheck --version | grep "version:")"
echo "$sep" echo "$separator"
fi fi
if [[ ! ${cmake_names[*]} ]]; then if [[ ! ${cmake_names[*]} ]]; then
@ -302,7 +302,7 @@ if [[ ! ( ${names[*]} || $do_cmake || $do_shell ) ]]; then
exit 0 # nothing to format means format is successful! exit 0 # nothing to format means format is successful!
fi fi
# format # Format
case $mode in case $mode in
diff) diff)
declare -i code=0 declare -i code=0
@ -326,9 +326,10 @@ case $mode in
fi fi
done done
if (( code>0 )); then if (( code>0 )); then
echo "$sep" echo "$separator"
echo "Affected file(s):"
for name in "${files_to_format[@]}"; do for name in "${files_to_format[@]}"; do
echo "$name" echo " $name"
done done
fi fi
exit $code exit $code
@ -374,15 +375,15 @@ case $mode in
cmake-format -i "${cmake_names[@]}" cmake-format -i "${cmake_names[@]}"
fi fi
if [[ $do_shell ]]; then if [[ $do_shell ]]; then
echo "warning: --shell is not compatible with the current mode but shell files were modified!" >&2 echo "Warning: --shell is not compatible with the current mode but shell files were modified!" >&2
echo "recommendation: try $0 --diff --shell" >&2 echo "Recommendation: try $0 --diff --shell" >&2
fi fi
if (( verbosity>0 )); then if (( verbosity>0 )); then
count="${#names[*]}" count="${#names[*]}"
if [[ $do_cmake ]]; then if [[ $do_cmake ]]; then
(( count+=${#cmake_names[*]} )) (( count+=${#cmake_names[*]} ))
fi fi
echo "parsed $count files that differ from base $branch" echo "Parsed $count files that differ from base $branch"
fi fi
;; ;;
esac esac

View file

@ -2,24 +2,27 @@
set -e set -e
echo "::group::Check Servatrice database schema version"
version_line="$(grep 'INSERT INTO cockatrice_schema_version' servatrice/servatrice.sql)" version_line="$(grep 'INSERT INTO cockatrice_schema_version' servatrice/servatrice.sql)"
version_line="${version_line#*VALUES(}" version_line="${version_line#*VALUES(}"
declare -i schema_ver="${version_line%%)*}" declare -i schema_ver="${version_line%%)*}"
# shellcheck disable=2012 latest_migration="$(printf '%s\n' servatrice/migrations/*.sql | sed 's#.*/##' | sort | tail -n1)"
latest_migration="$(ls -1 servatrice/migrations/ | tail -n1)"
xtoysql="${latest_migration#servatrice_}" xtoysql="${latest_migration#servatrice_}"
xtoy="${xtoysql%.sql}" 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_}" declare -i new_ver="10#${xtoy#*_to_}"
echo "Schema version: $schema_ver"
echo "Latest migration: $latest_migration ($old_ver → $new_ver)"
if ((old_ver >= new_ver)); then if ((old_ver >= new_ver)); then
echo "New version $new_ver is not newer than $old_ver" echo "New version $new_ver is not newer than $old_ver"
exit 1 exit 1
fi fi
if ((schema_ver != new_ver)); then if ((schema_ver != new_ver)); then
echo "Schema version $schema_ver does not equal new version $new_ver" echo "Schema version $schema_ver does not match new version $new_ver"
exit 1 exit 1
fi fi
@ -34,3 +37,6 @@ if ! grep -q "$expected_define" servatrice/src/servatrice_database_interface.h;
echo "servatrice_database_interface.h does not contain expected #define: $expected_define" echo "servatrice_database_interface.h does not contain expected #define: $expected_define"
exit 1 exit 1
fi fi
echo " ✓ Database schema version is consistent"
echo "::endgroup::"

View file

@ -11,10 +11,9 @@ 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_counter_test COMMAND server_counter_test)
add_test(NAME deck_hash_performance_test COMMAND deck_hash_performance_test) add_test(NAME deck_hash_performance_test COMMAND deck_hash_performance_test)
set_tests_properties(dummy_test PROPERTIES TIMEOUT 5)
set_tests_properties(deck_hash_performance_test PROPERTIES TIMEOUT 5) set_tests_properties(deck_hash_performance_test PROPERTIES TIMEOUT 5)
# Find GTest
add_executable(dummy_test dummy_test.cpp) add_executable(dummy_test dummy_test.cpp)
add_executable(expression_test expression_test.cpp) add_executable(expression_test expression_test.cpp)
add_executable(clamped_arithmetic_test clamped_arithmetic_test.cpp) add_executable(clamped_arithmetic_test clamped_arithmetic_test.cpp)
@ -24,6 +23,7 @@ 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_card_counter_test server_card_counter_test.cpp)
add_executable(server_counter_test server_counter_test.cpp) add_executable(server_counter_test server_counter_test.cpp)
# Find GTest
find_package(GTest) find_package(GTest)
if(NOT GTEST_FOUND) if(NOT GTEST_FOUND)