Linux GCC/Clang Qt6.7 TinyDrivers #108
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# MySQL | |
# --- | |
# Forces TLS connections with the caching_sha2_password and certificate validation, also validates | |
# certificate's CN for issuer and subject. | |
# ccache | |
# --- | |
# Uses /ccache_drivers folder and the compressed cache size is 1.8G (after whole workflow finishes) | |
name: Linux GCC/Clang Qt6.7 TinyDrivers | |
# Invoke manually from the command-line using the gh command, eg.: | |
# gh workflow run --ref silverqx-develop | |
# The reason for this is that I have 2 self-hosted runners on one PC (one for Linux and other for | |
# Windows) and I'm not able to serialize all these workflows and because of that I would have to | |
# decrease parallel and it would take hours to finish, so all Linux workflows must be invoked | |
# manually. | |
on: workflow_dispatch | |
concurrency: | |
group: tinyorm-linux | |
# I will not remove the build folders before a job execution it's not necessary and | |
# it will be faster this way. I can still remove them manually if needed or | |
# if something goes wrong. | |
jobs: | |
build: | |
name: cmake build / ctest | |
# Self-hosted runner is Fedora 40 | |
runs-on: [ self-hosted, linux ] | |
env: | |
# Settings (constant variables) | |
TINY_QT_VERSION: 6.7.2 | |
TINY_QT_SPEC: linux_gcc_64 | |
# Don't use more than 3 cores, I also saw blue screen with zram :/ | |
# Currenlty using 16G swap file to be safe | |
TINY_PARALLEL_GCC: 3 | |
TINY_PARALLEL_CLANG: 8 | |
# State variables | |
TINY_VCPKG_NEEDS_UPGRADE: false | |
strategy: | |
matrix: | |
lto: [ OFF ] | |
drivers-type: [ Shared, Loadable, Static ] | |
build-type: | |
- key: debug | |
name: Debug | |
- key: release | |
name: Release | |
compiler: | |
- key: clang | |
name: clang18 | |
command: clang++-18 | |
linker-command: ld.lld | |
- key: gcc | |
name: gcc14 | |
command: g++-14 | |
linker-command: ld | |
include: | |
- lto: ON | |
drivers-type: Loadable | |
build-type: | |
key: release | |
name: Release | |
compiler: | |
key: clang | |
name: clang18 | |
command: clang++-18 | |
linker-command: ld.lld | |
- lto: ON | |
drivers-type: Loadable | |
build-type: | |
key: release | |
name: Release | |
compiler: | |
key: gcc | |
name: gcc14 | |
command: g++-14 | |
linker-command: ld | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
path: main | |
- name: TinyORM prepare environment | |
run: | | |
runnerWorkPath=$(realpath "$RUNNER_WORKSPACE/..") | |
echo "TinyRunnerWorkPath=$runnerWorkPath" >> $GITHUB_ENV | |
# Parallel gcc to 3 and Clang to 8 is maximum what my computer allows but I decided to use | |
# the different strategy, I will use the on: workflow_dispatch for all self-hosted actions | |
# and these workflows are invoked automatically one from other: | |
# gh workflow run --ref silverqx-develop | |
# -- | |
# For gcc14 with the parallel 4 I saw 15.1GB maximum memory usage out of 15.6GB and that is | |
# very close to the edge, so I have to decrease it to 3 (also saw the blue screen on Fedora | |
# with zram only without the swap file). | |
# For clang18 it was ~11.6 out of 15.6GB so parallel 8 is ok. | |
[[ '${{ matrix.compiler.key }}' == 'gcc' ]] && parallel=$TINY_PARALLEL_GCC || \ | |
parallel=$TINY_PARALLEL_CLANG | |
echo "TinyParallel=$parallel" >> $GITHUB_ENV | |
echo "TinyParallelVcpkg=$(nproc)" >> $GITHUB_ENV | |
tinyormPath=$(realpath ./main) | |
echo "TinyORMPath=$tinyormPath" >> $GITHUB_ENV | |
tinyormBuildName='TinyDrivers-${{ matrix.compiler.name }}-${{ matrix.drivers-type }}-${{ matrix.build-type.key }}' | |
[[ '${{ matrix.lto }}' == 'ON' ]] && tinyormBuildName="$tinyormBuildName-lto" | |
echo "TinyORMBuildName=$tinyormBuildName" >> $GITHUB_ENV | |
tinyormBuildTree="$RUNNER_WORKSPACE/TinyORM-builds-cmake/build-$tinyormBuildName" | |
echo "TinyORMBuildTree=$tinyormBuildTree" >> $GITHUB_ENV | |
# Remove all before the first _ character eg. linux_gcc_64 -> gcc_64 | |
echo "TinyQtSpecPlain=${TINY_QT_SPEC#*_}" >> $GITHUB_ENV | |
- name: MySQL service check status | |
run: | | |
mysqladmin --password="$DB_MYSQL_PASSWORD" ping | |
env: | |
DB_MYSQL_PASSWORD: ${{ secrets.DB_MYSQL_PASSWORD_SELF }} | |
- name: Print MySQL database version | |
run: | | |
mysql --version | |
# lukka/get-cmake@latest needed because of Fedora | |
- name: CMake and Ninja install latest versions | |
uses: lukka/get-cmake@latest | |
with: | |
useLocalCache: true | |
useCloudCache: false | |
# Don't use the default CCACHE_DIR path on self-hosted runners | |
- name: Ccache prepare environment | |
run: | | |
ccacheDirPath="$RUNNER_WORKSPACE/ccache_drivers" | |
echo "CCACHE_DIR=$ccacheDirPath" >> $GITHUB_ENV | |
# I'm managing the ccache configuration manually on self-hosted runners using the ccache.conf | |
# because it's used by more actions. | |
- name: Ccache print version and configuration | |
run: | | |
echo '::group::Print version' | |
ccache --version | |
echo '::endgroup::' | |
echo '::group::Print ccache config' | |
ccache --show-config | |
echo '::endgroup::' | |
# Don't define VCPKG_DEFAULT_BINARY_CACHE as Linux VM image is strictly for GH actions use only | |
- name: vcpkg prepare environment | |
run: | | |
echo "VCPKG_ROOT=$VCPKG_INSTALLATION_ROOT" >> $GITHUB_ENV | |
echo 'VCPKG_DEFAULT_TRIPLET=x64-linux-dynamic' >> $GITHUB_ENV | |
echo "VCPKG_MAX_CONCURRENCY=$TinyParallelVcpkg" >> $GITHUB_ENV | |
- name: vcpkg needs upgrade? (once per day) | |
run: | | |
vcpkgUpgradedAtFilepath="$RUNNER_WORKSPACE/.vcpkg_upgraded_at" | |
if [ ! -f "$vcpkgUpgradedAtFilepath" ] || [ ! -r "$vcpkgUpgradedAtFilepath" ] || \ | |
! read datePreviousUpgradeRaw < "$vcpkgUpgradedAtFilepath" | |
then | |
echo 'TINY_VCPKG_NEEDS_UPGRADE=true' >> $GITHUB_ENV | |
exit 0 | |
fi | |
datePreviousUpgrade=$(date --date="$datePreviousUpgradeRaw" +%s) | |
if [ $? -ne 0 ] || [ -z "$datePreviousUpgrade" ]; then | |
echo "Parsing the '.vcpkg_upgraded_at' failed." >&2 | |
exit 1 | |
fi | |
dateToday=$(date --date=$(date +%Y-%m-%d) +%s) | |
if [ "$datePreviousUpgrade" -lt "$dateToday" ]; then | |
echo 'TINY_VCPKG_NEEDS_UPGRADE=true' >> $GITHUB_ENV | |
fi | |
- name: vcpkg upgrade repository (latest version) | |
if: env.TINY_VCPKG_NEEDS_UPGRADE == 'true' | |
run: | | |
cd "$VCPKG_INSTALLATION_ROOT" | |
git switch master | |
git fetch --tags origin | |
git reset --hard origin/master | |
./bootstrap-vcpkg.sh | |
date +%Y-%m-%d > "$RUNNER_WORKSPACE/.vcpkg_upgraded_at" | |
- name: Qt v${{ env.TINY_QT_VERSION }} prepare environment | |
run: | | |
echo "$TINY_QT_ROOT/$TINY_QT_VERSION/$TinyQtSpecPlain/bin" >> $GITHUB_PATH | |
echo "LD_LIBRARY_PATH=$TINY_QT_ROOT/$TINY_QT_VERSION/$TinyQtSpecPlain/lib${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH" >> $GITHUB_ENV | |
- name: Compiler print version (${{ matrix.compiler.command }}) | |
run: | | |
${{ matrix.compiler.command }} --version | |
- name: Linker print version (${{ matrix.compiler.linker-command }}) | |
run: | | |
${{ matrix.compiler.linker-command }} --version | |
- name: CMake print version | |
run: | | |
cmake --version | |
- name: Ninja print version | |
run: | | |
ninja --version | |
- name: vcpkg print version | |
run: | | |
vcpkg --version | |
- name: Qt print version | |
run: | | |
qmake -query QT_VERSION | |
- name: Ccache clear statistics | |
run: | | |
ccache --zero-stats | |
# BUILD_TREE_DEPLOY isn't needed because CMake forces linker to write absolute paths to exe, but | |
# I enable it anyway to test this feature. | |
# CMAKE_DISABLE_PRECOMPILE_HEADERS=ON is correct as we need to test missing #include-s. | |
- name: TinyORM cmake configure (${{ env.TinyORMBuildName }}) | |
working-directory: ${{ env.TinyORMPath }} | |
run: >- | |
cmake --log-level=DEBUG --log-context | |
-S . | |
-B "$TinyORMBuildTree" | |
-G Ninja | |
-D CMAKE_CXX_COMPILER_LAUNCHER:FILEPATH=ccache | |
-D CMAKE_CXX_COMPILER:FILEPATH=${{ matrix.compiler.command }} | |
-D CMAKE_TOOLCHAIN_FILE:FILEPATH="$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" | |
-D CMAKE_DISABLE_PRECOMPILE_HEADERS:BOOL=ON | |
-D CMAKE_EXPORT_PACKAGE_REGISTRY:BOOL=OFF | |
-D CMAKE_BUILD_TYPE:STRING=${{ matrix.build-type.name }} | |
-D CMAKE_CXX_SCAN_FOR_MODULES:BOOL=OFF | |
-D CMAKE_INTERPROCEDURAL_OPTIMIZATION:BOOL=${{ matrix.lto }} | |
-D VCPKG_APPLOCAL_DEPS:BOOL=OFF | |
-D VERBOSE_CONFIGURE:BOOL=ON | |
-D BUILD_TREE_DEPLOY:BOOL=ON | |
-D LEAN_HEADERS:BOOL=ON | |
-D STRICT_MODE:BOOL=ON | |
-D MYSQL_PING:BOOL=ON | |
-D BUILD_TESTS:BOOL=ON | |
-D ORM:BOOL=ON | |
-D TOM:BOOL=ON | |
-D TOM_EXAMPLE:BOOL=ON | |
-D BUILD_DRIVERS:BOOL=ON | |
-D DRIVERS_TYPE:STRING=${{ matrix.drivers-type }} | |
- name: TinyORM cmake build ✨ (${{ env.TinyORMBuildName }}) | |
working-directory: ${{ env.TinyORMBuildTree }} | |
run: | | |
cmake --build . --target all --parallel $TinyParallel | |
- name: Ccache print statistics | |
run: | | |
ccache --show-stats --verbose | |
- name: libTinyOrm print .comment section | |
working-directory: ${{ env.TinyORMBuildTree }} | |
run: >- | |
[[ '${{ matrix.build-type.key }}' == 'debug' ]] && | |
tinyLibTinyOrm='libTinyOrmd.so' || | |
tinyLibTinyOrm='libTinyOrm.so' | |
readelf --string-dump .comment "./$tinyLibTinyOrm" | |
- name: TinyORM add on the $LD_LIBRARY_PATH | |
run: | | |
echo "LD_LIBRARY_PATH=$TinyORMBuildTree${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH" >> $env:GITHUB_ENV | |
# Used migrate:fresh instead (is safer) | |
- name: Create and Seed tables for unit tests 🎉 | |
working-directory: ${{ env.TinyORMBuildTree }}/tests/testdata_tom | |
run: | | |
./tom_testdata migrate:fresh --database=tinyorm_testdata_tom_mysql --seed --no-ansi | |
env: | |
DB_MYSQL_CHARSET: ${{ secrets.DB_MYSQL_CHARSET }} | |
DB_MYSQL_COLLATION: ${{ secrets.DB_MYSQL_COLLATION }} | |
DB_MYSQL_DATABASE: ${{ secrets.DB_MYSQL_DATABASE }} | |
DB_MYSQL_HOST: ${{ secrets.DB_MYSQL_HOST_SELF }} | |
DB_MYSQL_PASSWORD: ${{ secrets.DB_MYSQL_PASSWORD_SELF }} | |
DB_MYSQL_SSL_CA: ${{ secrets.DB_MYSQL_DATA_SELF_LINUX }}/ca.pem | |
DB_MYSQL_SSL_CERT: ${{ secrets.DB_MYSQL_DATA_SELF_LINUX }}/client-cert.pem | |
DB_MYSQL_SSL_KEY: ${{ secrets.DB_MYSQL_DATA_SELF_LINUX }}/client-key.pem | |
DB_MYSQL_SSL_MODE: ${{ secrets.DB_MYSQL_SSL_MODE }} | |
DB_MYSQL_USERNAME: ${{ secrets.DB_MYSQL_USERNAME_SELF }} | |
TOM_TESTDATA_ENV: ${{ vars.TOM_TESTDATA_ENV }} | |
- name: TinyORM execute ctest 🔥 | |
working-directory: ${{ env.TinyORMBuildTree }} | |
run: | | |
ctest --output-on-failure --parallel 16 | |
env: | |
DB_MYSQL_CHARSET: ${{ secrets.DB_MYSQL_CHARSET }} | |
DB_MYSQL_COLLATION: ${{ secrets.DB_MYSQL_COLLATION }} | |
DB_MYSQL_DATABASE: ${{ secrets.DB_MYSQL_DATABASE }} | |
DB_MYSQL_HOST: ${{ secrets.DB_MYSQL_HOST_SELF }} | |
DB_MYSQL_PASSWORD: ${{ secrets.DB_MYSQL_PASSWORD_SELF }} | |
DB_MYSQL_SSL_CA: ${{ secrets.DB_MYSQL_DATA_SELF_LINUX }}/ca.pem | |
DB_MYSQL_SSL_CERT: ${{ secrets.DB_MYSQL_DATA_SELF_LINUX }}/client-cert.pem | |
DB_MYSQL_SSL_KEY: ${{ secrets.DB_MYSQL_DATA_SELF_LINUX }}/client-key.pem | |
DB_MYSQL_SSL_MODE: ${{ secrets.DB_MYSQL_SSL_MODE }} | |
DB_MYSQL_USERNAME: ${{ secrets.DB_MYSQL_USERNAME_SELF }} | |
TOM_TESTS_ENV: ${{ vars.TOM_TESTS_ENV }} | |
- name: Tom example test some commands (MySQL) 🚀 | |
working-directory: ${{ env.TinyORMBuildTree }}/examples/tom | |
run: | | |
./tom migrate:fresh --database=tinyorm_tom_mysql --seed --no-ansi | |
./tom migrate:uninstall --reset --database=tinyorm_tom_mysql --no-ansi | |
./tom migrate:install --database=tinyorm_tom_mysql --no-ansi | |
./tom migrate --database=tinyorm_tom_mysql --seed --no-ansi | |
./tom migrate:status --database=tinyorm_tom_mysql --no-ansi | |
./tom migrate:refresh --database=tinyorm_tom_mysql --seed --no-ansi | |
./tom migrate:reset --database=tinyorm_tom_mysql --no-ansi | |
./tom migrate:uninstall --database=tinyorm_tom_mysql --no-ansi | |
# Restore my development environment | |
./tom migrate --database=tinyorm_tom_mysql --seed --no-ansi | |
env: | |
DB_MYSQL_CHARSET: ${{ secrets.DB_MYSQL_CHARSET }} | |
DB_MYSQL_COLLATION: ${{ secrets.DB_MYSQL_COLLATION }} | |
DB_MYSQL_DATABASE: ${{ secrets.DB_MYSQL_DATABASE }} | |
DB_MYSQL_HOST: ${{ secrets.DB_MYSQL_HOST_SELF }} | |
DB_MYSQL_PASSWORD: ${{ secrets.DB_MYSQL_PASSWORD_SELF }} | |
DB_MYSQL_SSL_CA: ${{ secrets.DB_MYSQL_DATA_SELF_LINUX }}/ca.pem | |
DB_MYSQL_SSL_CERT: ${{ secrets.DB_MYSQL_DATA_SELF_LINUX }}/client-cert.pem | |
DB_MYSQL_SSL_KEY: ${{ secrets.DB_MYSQL_DATA_SELF_LINUX }}/client-key.pem | |
DB_MYSQL_SSL_MODE: ${{ secrets.DB_MYSQL_SSL_MODE }} | |
DB_MYSQL_USERNAME: ${{ secrets.DB_MYSQL_USERNAME_SELF }} | |
TOM_EXAMPLE_ENV: ${{ vars.TOM_EXAMPLE_ENV }} | |
# The tom_testdata will be needed in vcpkg-linux-drivers.yml so we need to copy this executable, | |
# the reason for this is to always have the latest tom_testdata and to avoid manual rebuilds if | |
# any shared library is updated on which the tom_testdata depends to avoid crashes. | |
- name: Install tom_testdata for vcpkg-linux-drivers.yml | |
if: matrix.compiler.key == 'gcc' && matrix.drivers-type == 'Static' && matrix.build-type.key == 'release' | |
working-directory: ${{ env.TinyORMBuildTree }}/tests/testdata_tom | |
run: | | |
mkdir -p "$RUNNER_WORKSPACE/.local/bin" | |
cp --force --target-directory="$RUNNER_WORKSPACE/.local/bin" ./tom_testdata | |
# The reason for this is the concurrency:group: can contain only two in_progress workflows, | |
# one will be in_progress and the second will be queued (waiting until the first finish), | |
# and all others will be canceled. | |
# Jobs are run randomly! They are sorted from 0 to strategy.job-total - 1 in GitHub UI, so | |
# the first job has index 0, the second job has index 1, ... | |
# Execute the next workflow inly if it's active and isn't disabled (disabled_manually state). | |
# Also, if the step fails due to any error, continue (eg. network unreachable or similar). | |
- name: Run vcpkg-linux.yml workflow | |
continue-on-error: true | |
if: strategy.job-index == 0 | |
working-directory: ${{ env.TinyORMPath }} | |
run: | | |
workflowState=$(gh workflow list --all --json path,state \ | |
--jq '.[] | select (.path | endswith("/vcpkg-linux.yml")) | .state') | |
if [ $? -eq 0 ] && [[ "$workflowState" == 'active' ]]; then | |
gh workflow run vcpkg-linux.yml --ref "$GITHUB_REF_NAME" | |
fi | |
env: | |
GH_TOKEN: ${{ github.token }} | |
- name: Cancel vcpkg-linux.yml workflow (on failure) | |
if: ${{ failure() }} | |
working-directory: ${{ env.TinyORMPath }} | |
run: | | |
databaseId=$(gh run list --workflow vcpkg-linux.yml --event workflow_dispatch \ | |
--json databaseId,conclusion,status \ | |
--jq '.[] | select (.status == "pending") | select (.conclusion == "") | .databaseId') | |
if [ $? -eq 0 ] && [[ "$databaseId" != "" && "$databaseId" =~ ^[0-9]+$ ]] && | |
[ $databaseId -gt 0 ] | |
then | |
gh run cancel $databaseId | |
fi | |
env: | |
GH_TOKEN: ${{ github.token }} |