diff --git a/.ci/Fedora41/Dockerfile b/.ci/Fedora43/Dockerfile similarity index 95% rename from .ci/Fedora41/Dockerfile rename to .ci/Fedora43/Dockerfile index fc9e86c2e..27570cf99 100644 --- a/.ci/Fedora41/Dockerfile +++ b/.ci/Fedora43/Dockerfile @@ -1,4 +1,4 @@ -FROM fedora:41 +FROM fedora:43 RUN dnf install -y \ ccache \ diff --git a/.ci/Servatrice_Debian11/Dockerfile b/.ci/Servatrice_Debian11/Dockerfile new file mode 100644 index 000000000..fadc9e0e7 --- /dev/null +++ b/.ci/Servatrice_Debian11/Dockerfile @@ -0,0 +1,21 @@ +FROM debian:11 + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + build-essential \ + ccache \ + clang-format \ + cmake \ + file \ + g++ \ + git \ + libmariadb-dev-compat \ + libprotobuf-dev \ + libqt5sql5-mysql \ + libqt5websockets5-dev \ + ninja-build \ + protobuf-compiler \ + qttools5-dev \ + qttools5-dev-tools \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* diff --git a/.ci/Ubuntu22.04/Dockerfile b/.ci/Ubuntu22.04/Dockerfile index ff2e6e43b..93c8fdea9 100644 --- a/.ci/Ubuntu22.04/Dockerfile +++ b/.ci/Ubuntu22.04/Dockerfile @@ -9,20 +9,18 @@ RUN apt-get update && \ file \ g++ \ git \ - libgl-dev \ liblzma-dev \ libmariadb-dev-compat \ libprotobuf-dev \ - libqt6multimedia6 \ - libqt6sql6-mysql \ - libqt6svg6-dev \ - libqt6websockets6-dev \ + libqt5multimedia5-plugins \ + libqt5sql5-mysql \ + libqt5svg5-dev \ + libqt5websockets5-dev \ ninja-build \ protobuf-compiler \ - qt6-image-formats-plugins \ - qt6-l10n-tools \ - qt6-multimedia-dev \ - qt6-tools-dev \ - qt6-tools-dev-tools \ + qt5-image-formats-plugins \ + qtmultimedia5-dev \ + qttools5-dev \ + qttools5-dev-tools \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* diff --git a/.ci/Ubuntu26.04/Dockerfile b/.ci/Ubuntu26.04/Dockerfile new file mode 100644 index 000000000..7b0cd389f --- /dev/null +++ b/.ci/Ubuntu26.04/Dockerfile @@ -0,0 +1,29 @@ +FROM ubuntu:26.04 + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + ccache \ + clang-format \ + cmake \ + file \ + g++ \ + git \ + libgl-dev \ + liblzma-dev \ + libmariadb-dev-compat \ + libprotobuf-dev \ + libqt6multimedia6 \ + libqt6sql6-mysql \ + ninja-build \ + protobuf-compiler \ + qt6-image-formats-plugins \ + qt6-l10n-tools \ + qt6-multimedia-dev \ + qt6-svg-dev \ + qt6-tools-dev \ + qt6-tools-dev-tools \ + qt6-websockets-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* diff --git a/.ci/compile.sh b/.ci/compile.sh index 2938e0902..7ebdd6e4e 100755 --- a/.ci/compile.sh +++ b/.ci/compile.sh @@ -10,8 +10,11 @@ # --test runs tests # --debug or --release sets the build type ie CMAKE_BUILD_TYPE # --ccache [] uses ccache and shows stats, optionally provide size +# --evict-ccache runs ccache eviction based on given age after build # --dir sets the name of the build dir, default is "build" -# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_TEST USE_CCACHE CCACHE_SIZE BUILD_DIR CMAKE_GENERATOR +# --cmake-generator sets CMAKE_GENERATOR as used by cmake +# --target-macos-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 --suffix --server --test --ccache --dir ) # exitcode: 1 for failure, 3 for invalid arguments @@ -46,6 +49,10 @@ while [[ $# != 0 ]]; do MAKE_SERVER=1 shift ;; + '--no-client') + MAKE_NO_CLIENT=1 + shift + ;; '--test') MAKE_TEST=1 shift @@ -66,6 +73,19 @@ while [[ $# != 0 ]]; do 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 @@ -75,6 +95,24 @@ while [[ $# != 0 ]]; do 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') + shift + if [[ $# == 0 ]]; then + echo "::error file=$0::--target-macos-version expects an argument" + exit 3 + fi + TARGET_MACOS_VERSION="$1" + shift + ;; *) echo "::error file=$0::unrecognized option: $1" exit 3 @@ -103,6 +141,9 @@ flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE") if [[ $MAKE_SERVER ]]; then flags+=("-DWITH_SERVER=1") fi +if [[ $MAKE_NO_CLIENT ]]; then + flags+=("-DWITH_CLIENT=0" "-DWITH_ORACLE=0") +fi if [[ $MAKE_TEST ]]; then flags+=("-DTEST=1") fi @@ -116,6 +157,9 @@ fi if [[ $PACKAGE_TYPE ]]; then flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE") fi +if [[ $USE_VCPKG ]]; then + flags+=("-DUSE_VCPKG=1") +fi # Add cmake --build flags buildflags=(--config "$BUILDTYPE") @@ -132,9 +176,47 @@ function ccachestatsverbose() { # Compile 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 + echo "found QTDIR at $QTDIR" + else + 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 + export QTDIR + + if [[ $TARGET_MACOS_VERSION ]]; then + # CMAKE_OSX_DEPLOYMENT_TARGET is a vanilla cmake flag 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" + fi + mkdir -p "$triplets_dir" + cp "../vcpkg/triplets/$arch-osx.cmake" "$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 $MACOS_CERTIFICATE | base64 --decode > certificate.p12 + echo "$MACOS_CERTIFICATE" | base64 --decode >"certificate.p12" security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain security default-keychain -s build.keychain security set-keychain-settings -t 3600 -l build.keychain @@ -146,6 +228,29 @@ if [[ $RUNNER_OS == macOS ]]; then echo "No signing certificate configured. Skipping set up of keychain in macOS environment." fi echo "::endgroup::" + + if [[ $MAKE_PACKAGE ]]; then + # Workaround https://github.com/actions/runner-images/issues/7522 + # have hdiutil repeat the command 10 times in hope of success + hdiutil_script="/tmp/hdiutil.sh" + # shellcheck disable=SC2016 + echo '#!/bin/bash + i=0 + while ! hdiutil "$@"; do + if (( ++i >= 10 )); then + echo "Error: hdiutil failed $i times!" >&2 + break + fi + sleep 1 + done' >"$hdiutil_script" + chmod +x "$hdiutil_script" + flags+=(-DCPACK_COMMAND_HDIUTIL="$hdiutil_script") + fi + +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) fi if [[ $USE_CCACHE ]]; then @@ -156,23 +261,39 @@ fi echo "::group::Configure cmake" cmake --version +echo "Running cmake with flags: ${flags[*]}" cmake .. "${flags[@]}" echo "::endgroup::" echo "::group::Build project" -if [[ $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 - cmake --build . "${buildflags[@]}" -- -p:UseMultiToolTask=true -p:EnableClServerMode=true -else - cmake --build . "${buildflags[@]}" -fi +echo "Running cmake --build with flags: ${buildflags[*]}" +cmake --build . "${buildflags[@]}" echo "::endgroup::" if [[ $USE_CCACHE ]]; then + if [[ $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 + echo "::error file=$0::ccache eviction is enabled while ccache is disabled!" +fi + +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" + echo "Inspecting $app..." + vtool -show-build "$binary" + file "$binary" + lipo -info "$binary" + echo "" + done + echo "::endgroup::" fi if [[ $MAKE_TEST ]]; then @@ -189,12 +310,6 @@ fi if [[ $MAKE_PACKAGE ]]; then echo "::group::Create package" - - if [[ $RUNNER_OS == macOS ]]; then - # Workaround https://github.com/actions/runner-images/issues/7522 - echo "killing XProtectBehaviorService"; sudo pkill -9 XProtect >/dev/null || true; - echo "waiting for XProtectBehaviorService kill"; while pgrep "XProtect"; do sleep 3; done; - fi cmake --build . --target package --config "$BUILDTYPE" echo "::endgroup::" diff --git a/.ci/docker.sh b/.ci/docker.sh index a9fcfcc5b..46112daaa 100644 --- a/.ci/docker.sh +++ b/.ci/docker.sh @@ -3,17 +3,28 @@ # This script is to be used by the ci environment from the project root directory, do not use it from somewhere else. # Creates or loads docker images to use in compilation, creates RUN function to start compilation on the docker image. -# sets the name of the docker image, these correspond to directories in .ci +# +# usage: source