Skip to content

Vcpkg Linux

Vcpkg Linux #100

Workflow file for this run

# Common notes
# ---
# Queries/uses only SQLite database.
# OS settings notes
# ---
# Set time zone to 'Etc/UTC' (this was the default)
# ccache
# ---
# Uses /ccache_vcpkg folder and the compressed cache size is 330M (after whole workflow finishes)
# This /ccache_vcpkg folder is common for analyzers.yml and vcpkg-linux.yml workflows
name: Vcpkg Linux
# 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:
vcpkg-linux:
name: Vcpkg Linux
# Self-hosted runner is Fedora 40
runs-on: [ self-hosted, linux ]
env:
# Settings (constant variables)
TINY_PARALLEL: 10
# State variables
TINY_VCPKG_NEEDS_UPGRADE: false
strategy:
matrix:
build-type:
- key: debug
name: Debug
- key: release
name: Release
qt:
- key: qt6
name: Qt6
version: 6.7.2
apt: [ qt6-base-dev, libqt6sql6-sqlite ]
# For vcpkg classic mode (install tests)
vcpkg-qt: qtbase
vcpkg-qt-features: qtbase[core,sql-sqlite]
vcpkg-tinyorm: tinyorm
vcpkg-tinyorm-features: tinyorm[core,sql-sqlite]
steps:
- uses: actions/checkout@v4
with:
path: main
# I don't install everything to the TinyRunnerWorkPath as in all other workflows, I leave it
# this way because I tried to refactor it to the env.TinyRunnerWorkPath and it looks terrible
- name: TinyORM prepare environment
run: |
runnerWorkPath=$(realpath "$RUNNER_WORKSPACE/..")
echo "TinyRunnerWorkPath=$runnerWorkPath" >> $GITHUB_ENV
tinyormPath=$(realpath ./main)
echo "TinyORMPath=$tinyormPath" >> $GITHUB_ENV
# 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 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
# The x64-linux is correct
echo 'VCPKG_DEFAULT_TRIPLET=x64-linux' >> $GITHUB_ENV
echo "VCPKG_MAX_CONCURRENCY=$TINY_PARALLEL" >> $GITHUB_ENV
vcpkgPath=$(realpath "$TinyORMPath/cmake/vcpkg")
portsPath="$vcpkgPath/ports"
echo "VCPKG_OVERLAY_PORTS=$portsPath" >> $GITHUB_ENV
tripletsPath="$vcpkgPath/triplets"
echo "VCPKG_OVERLAY_TRIPLETS=$tripletsPath" >> $GITHUB_ENV
- name: vcpkg add on the $PATH
run: |
echo "$VCPKG_INSTALLATION_ROOT" >> $GITHUB_PATH
- 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"
# I'm not setting the CMAKE_CXX_COMPILER so query the /usr/bin/c++
- name: Compiler print version (c++)
run: |
c++ --version
- name: Linker print version (ld)
run: |
ld --version
- name: CMake print version
run: |
cmake --version
- name: Ninja print version
run: |
ninja --version
- name: Print SQLite database version
run: |
sqlite3 --version
- name: vcpkg print version
run: |
vcpkg --version
# Used full path to qmake because I don't want to move the Qt prepare environment
# section up, to avoid interfering with the Vcpkg Manifest method
- name: Qt print version
run: |
/opt/Qt/${{ matrix.qt.version }}/gcc_64/bin/qmake -query QT_VERSION
# Will be used in the classic method (vcpkg install tinyorm) and VcpkgManifest method
# I will not write bash scripts for this, would be a pain 🫤
- name: vcpkg prepare TinyORM ports (update REF and SHA512)
shell: pwsh -NoProfile -Command "& '{0}'"
working-directory: ${{ env.TinyORMPath }}
run: |
. ./tools/private/Common-Deploy.ps1
$portfileQt6Path = Resolve-Path -Path './cmake/vcpkg/ports/tinyorm/portfile.cmake'
$vcpkgRef = $env:GITHUB_SHA
Edit-VcpkgRefAndHash -Project $env:GITHUB_REPOSITORY -Ref $vcpkgRef `
-PortFile $portfileQt6Path -EnableRetries
# The following two steps (vcpkg install) are not needed below they only test if the vcpkg
# classic mode works correctly. The Release and Debug build types are build at once so invoke
# these two steps for the debug matrix only.
# This should reliably remove the qtbase and tinyorm with all dependencies.
# It's much faster to do it this way like removing the whole vcpkg folder and then the binary
# caching should kick in.
- name: vcpkg remove ${{ matrix.qt.vcpkg-qt }} and ${{ matrix.qt.vcpkg-tinyorm }} (classic mode)
if: matrix.build-type.key == 'debug'
run: >-
vcpkg remove --recurse vcpkg-cmake vcpkg-cmake-config zlib ${{ matrix.qt.vcpkg-qt }}
${{ matrix.qt.vcpkg-tinyorm }}
- name: vcpkg install ${{ matrix.qt.vcpkg-qt }} (classic mode)
if: matrix.build-type.key == 'debug'
run: |
vcpkg install ${{ matrix.qt.vcpkg-qt-features }}
- name: vcpkg install ${{ matrix.qt.vcpkg-tinyorm }} (classic mode)
if: matrix.build-type.key == 'debug'
run: |
vcpkg install ${{ matrix.qt.vcpkg-tinyorm-features }} --clean-after-build
# Prepare TinyORM-HelloWorld project
- name: HelloWorld checkout
uses: actions/checkout@v4
with:
repository: silverqx/TinyORM-HelloWorld
path: HelloWorld
- name: HelloWorld move HelloWorld.sqlite3 (to parent folder)
working-directory: HelloWorld
run: |
cp --target-directory="$RUNNER_WORKSPACE" ./HelloWorld.sqlite3
# VcpkgManifest method (no install or deployment)
# ---
# I don't need to use set(VCPKG_USE_HEAD_VERSION ON) and set HEAD_REF because I'm using
# Edit-VcpkgRefAndHash a few steps above to correctly set REF and SHA512.
- name: 🪡 VcpkgManifest method (no install or deployment) 🪡
run: |
echo 'no-op'
- name: HelloWorld prepare VcpkgManifest method environment
run: |
helloWorldVcpkgManifestBuildName='vcpkgmanifest-gcc-${{ matrix.build-type.key }}'
echo "HelloWorldVcpkgManifestBuildName=$helloWorldVcpkgManifestBuildName" >> $GITHUB_ENV
helloWoldVcpkgManifestBuildTree="$RUNNER_WORKSPACE/HelloWorld-builds-cmake/build-$helloWorldVcpkgManifestBuildName"
echo "HelloWorldVcpkgManifestBuildTree=$helloWoldVcpkgManifestBuildTree" >> $GITHUB_ENV
- name: HelloWorld prepare VcpkgManifest method (vcpkg.json)
working-directory: HelloWorld
run: |
cp ./vcpkg.json.VcpkgManifest.${{ matrix.qt.name }}.example ./vcpkg.json
# CMAKE_DISABLE_PRECOMPILE_HEADERS=ON is correct (no need to use PCH for one TU)
# VCPKG_APPLOCAL_DEPS=OFF is correct as everything is linked statically on Linux
# Don't use ccache for the VcpkgManifest method as the vcpkg has its own binary caching
- name: HelloWorld cmake configure (${{ env.HelloWorldVcpkgManifestBuildName }})
working-directory: HelloWorld
run: >-
cmake --log-level=DEBUG --log-context
-S .
-B "$HelloWorldVcpkgManifestBuildTree"
-G Ninja
-D CMAKE_TOOLCHAIN_FILE:FILEPATH="$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"
-D CMAKE_DISABLE_PRECOMPILE_HEADERS:BOOL=ON
-D CMAKE_BUILD_TYPE:STRING=${{ matrix.build-type.name }}
-D VCPKG_APPLOCAL_DEPS:BOOL=OFF
-D RESOLVE_TINYORM:STRING=VcpkgManifest
- name: HelloWorld cmake build ✨ (${{ env.HelloWorldVcpkgManifestBuildName }})
working-directory: ${{ env.HelloWorldVcpkgManifestBuildTree }}
run: |
cmake --build . --target all --parallel $TINY_PARALLEL
- name: HelloWorld print .comment section (${{ env.HelloWorldVcpkgManifestBuildName }})
working-directory: ${{ env.HelloWorldVcpkgManifestBuildTree }}
run: |
readelf --string-dump .comment ./HelloWorld
- name: HelloWorld execute (SQLite) 🏁
working-directory: ${{ env.HelloWorldVcpkgManifestBuildTree }}
run: |
./HelloWorld
env:
TINYORM_HELLOWORLD_DB_SQLITE_DATABASE: ../../HelloWorld.sqlite3
# The FetchContent and Manual methods below need Qt installed and to be accessible on the system
- name: ${{ matrix.qt.name }} prepare environment
run: |
echo '/opt/Qt/${{ matrix.qt.version }}/gcc_64/bin' >> $GITHUB_PATH
echo "LD_LIBRARY_PATH=/opt/Qt/${{ matrix.qt.version }}/gcc_64/lib${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH" >> $GITHUB_ENV
# Prepare ccache
#
# The TinyORM build in the Manual method and the FetchContent method are using the ccache,
# packages build through the FetchContent CMake module are also using the ccache, they respect
# the CMAKE_CXX_COMPILER_LAUNCHER option.
# Don't use the default CCACHE_DIR path on self-hosted runners
# vcpkg-linux.yml and analyzers.yml use the same /ccache_vcpkg folder
- name: Ccache prepare environment
run: |
ccacheDirPath=$(realpath "$RUNNER_WORKSPACE/ccache_vcpkg")
echo "CCACHE_DIR=$ccacheDirPath" >> $GITHUB_ENV
- 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::'
# Manual method linking against the TinyORM build tree (no install or deployment)
# ---
- name: 🪡 Manual method linking against the TinyORM build tree (no install or deployment) 🪡
run: |
echo 'no-op'
- name: HelloWorld prepare Manual method environment
run: |
helloWorldManualBuildName='manual-gcc-${{ matrix.build-type.key }}'
echo "HelloWorldManualBuildName=$helloWorldManualBuildName" >> $GITHUB_ENV
tinyormManualBuildTree="$RUNNER_WORKSPACE/TinyORM-builds-cmake/build-vcpkg-$helloWorldManualBuildName"
echo "TinyORMManualBuildTree=$tinyormManualBuildTree" >> $GITHUB_ENV
helloWoldManualBuildTree="$RUNNER_WORKSPACE/HelloWorld-builds-cmake/build-$helloWorldManualBuildName"
echo "HelloWorldManualBuildTree=$helloWoldManualBuildTree" >> $GITHUB_ENV
- name: Ccache clear statistics
run: |
ccache --zero-stats
# CMAKE_DISABLE_PRECOMPILE_HEADERS=OFF is correct (I want to use PCH here)
- name: TinyORM cmake configure (${{ env.HelloWorldManualBuildName }})
working-directory: ${{ env.TinyORMPath }}
run: >-
cmake --log-level=DEBUG --log-context
-S .
-B "$TinyORMManualBuildTree"
-G Ninja
-D CMAKE_CXX_COMPILER_LAUNCHER:FILEPATH=ccache
-D CMAKE_TOOLCHAIN_FILE:FILEPATH="$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"
-D CMAKE_DISABLE_PRECOMPILE_HEADERS:BOOL=OFF
-D CMAKE_BUILD_TYPE:STRING=${{ matrix.build-type.name }}
-D CMAKE_EXPORT_PACKAGE_REGISTRY:BOOL=OFF
-D CMAKE_CXX_SCAN_FOR_MODULES:BOOL=OFF
-D VCPKG_APPLOCAL_DEPS:BOOL=OFF
-D VERBOSE_CONFIGURE:BOOL=ON
-D BUILD_TREE_DEPLOY:BOOL=OFF
-D STRICT_MODE:BOOL=OFF
-D MYSQL_PING:BOOL=OFF
-D BUILD_TESTS:BOOL=OFF
-D ORM:BOOL=ON
-D TOM:BOOL=OFF
-D TOM_EXAMPLE:BOOL=OFF
-D BUILD_DRIVERS:BOOL=OFF
- name: TinyORM cmake build ✨ (${{ env.HelloWorldManualBuildName }})
working-directory: ${{ env.TinyORMManualBuildTree }}
run: |
cmake --build . --target all --parallel $TINY_PARALLEL
- name: Ccache print statistics
run: |
ccache --show-stats --verbose
- name: libTinyOrm print .comment section (${{ env.HelloWorldManualBuildName }})
working-directory: ${{ env.TinyORMManualBuildTree }}
run: >-
[[ '${{ matrix.build-type.key }}' == 'debug' ]] &&
tinyLibTinyOrm='libTinyOrmd.so' ||
tinyLibTinyOrm='libTinyOrm.so'
readelf --string-dump .comment "./$tinyLibTinyOrm"
# Build and execute the HelloWorld console application
- name: HelloWorld prepare Manual method (vcpkg.json)
working-directory: HelloWorld
run: |
cp ./vcpkg.json.Manual.example ./vcpkg.json
# CMAKE_DISABLE_PRECOMPILE_HEADERS=ON is correct (no need to use PCH for one TU)
- name: HelloWorld cmake configure (${{ env.HelloWorldManualBuildName }})
working-directory: HelloWorld
run: >-
cmake --log-level=DEBUG --log-context
-S .
-B "$HelloWorldManualBuildTree"
-G Ninja
-D CMAKE_PREFIX_PATH:PATH="$TinyORMManualBuildTree"
-D CMAKE_TOOLCHAIN_FILE:FILEPATH="$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"
-D CMAKE_DISABLE_PRECOMPILE_HEADERS:BOOL=ON
-D CMAKE_BUILD_TYPE:STRING=${{ matrix.build-type.name }}
-D VCPKG_APPLOCAL_DEPS:BOOL=OFF
-D RESOLVE_TINYORM:STRING=Manual
- name: HelloWorld cmake build ✨ (${{ env.HelloWorldManualBuildName }})
working-directory: ${{ env.HelloWorldManualBuildTree }}
run: |
cmake --build . --target all --parallel $TINY_PARALLEL
- name: HelloWorld execute (SQLite) 🏁
working-directory: ${{ env.HelloWorldManualBuildTree }}
run: |
export LD_LIBRARY_PATH="$TinyORMManualBuildTree"${LD_LIBRARY_PATH:+:}"$LD_LIBRARY_PATH"
./HelloWorld
env:
TINYORM_HELLOWORLD_DB_SQLITE_DATABASE: ../../HelloWorld.sqlite3
# FetchContent method (with install or deployment)
# ---
- name: 🪡 FetchContent method (with install or deployment) 🪡
run: |
echo 'no-op'
- name: HelloWorld prepare FetchContent method environment
run: |
helloWorldFetchContentBuildName='fetchcontent-gcc-${{ matrix.build-type.key }}'
echo "HelloWorldFetchContentBuildName=$helloWorldFetchContentBuildName" >> $GITHUB_ENV
helloWoldFetchContentBuildTree="$RUNNER_WORKSPACE/HelloWorld-builds-cmake/build-$helloWorldFetchContentBuildName"
echo "HelloWorldFetchContentBuildTree=$helloWoldFetchContentBuildTree" >> $GITHUB_ENV
- name: HelloWorld prepare FetchContent method (vcpkg.json)
working-directory: HelloWorld
run: |
cp ./vcpkg.json.FetchContent.example ./vcpkg.json
# I will not write bash scripts for this, would be a pain 🫤
- name: HelloWorld prepare FetchContent method (update GIT_TAG)
shell: pwsh -NoProfile -Command "& '{0}'"
working-directory: HelloWorld
run: |
$toolsPath = Resolve-Path -Path "$env:TinyORMPath/tools/private"
$gitTag = $env:GITHUB_SHA
& "$toolsPath/Edit-FetchContentGitTag.ps1" -CMakeLists ./CMakeLists.txt -GitTag $gitTag
- name: Ccache clear statistics
run: |
ccache --zero-stats
# CMAKE_DISABLE_PRECOMPILE_HEADERS=OFF is correct (I want to use PCH here)
- name: HelloWorld cmake configure (${{ env.HelloWorldFetchContentBuildName }})
working-directory: HelloWorld
run: >-
cmake --log-level=DEBUG --log-context
-S .
-B "$HelloWorldFetchContentBuildTree"
-G Ninja
-D CMAKE_CXX_COMPILER_LAUNCHER:FILEPATH=ccache
-D CMAKE_TOOLCHAIN_FILE:FILEPATH="$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"
-D CMAKE_DISABLE_PRECOMPILE_HEADERS:BOOL=OFF
-D CMAKE_BUILD_TYPE:STRING=${{ matrix.build-type.name }}
-D CMAKE_CXX_SCAN_FOR_MODULES:BOOL=OFF
-D CMAKE_INSTALL_PREFIX:PATH="$RUNNER_WORKSPACE/HelloWorld-FetchContent-Install/${{ matrix.build-type.name }}"
-D CMAKE_EXPORT_PACKAGE_REGISTRY:BOOL=OFF
-D VCPKG_APPLOCAL_DEPS:BOOL=OFF
-D VERBOSE_CONFIGURE:BOOL=ON
-D BUILD_TREE_DEPLOY:BOOL=OFF
-D STRICT_MODE:BOOL=OFF
-D MYSQL_PING:BOOL=OFF
-D BUILD_TESTS:BOOL=OFF
-D ORM:BOOL=ON
-D TOM:BOOL=OFF
-D TOM_EXAMPLE:BOOL=OFF
-D BUILD_DRIVERS:BOOL=OFF
-D RESOLVE_TINYORM:STRING=FetchContent
# Also install it, to test the deployment process
- name: HelloWorld cmake build and install ✨ (${{ env.HelloWorldFetchContentBuildName }})
working-directory: ${{ env.HelloWorldFetchContentBuildTree }}
run: |
cmake --build . --target install --parallel $TINY_PARALLEL
- name: Ccache print statistics
run: |
ccache --show-stats --verbose
- name: HelloWorld print .comment section (${{ env.HelloWorldFetchContentBuildName }})
working-directory: >-
../HelloWorld-FetchContent-Install/${{ matrix.build-type.name }}/bin
run: |
readelf --string-dump .comment ./HelloWorld
- name: HelloWorld execute (SQLite) 🏁
working-directory: >-
../HelloWorld-FetchContent-Install/${{ matrix.build-type.name }}/bin
run: |
# This is enough for us to distinguish between Ubuntu, Fedora, or Gentoo
[ -r /etc/debian_version ] && libFolder='lib' || libFolder='lib64'
export LD_LIBRARY_PATH="../$libFolder"${LD_LIBRARY_PATH:+:}"$LD_LIBRARY_PATH"
./HelloWorld
env:
TINYORM_HELLOWORLD_DB_SQLITE_DATABASE: ../../../HelloWorld.sqlite3
# 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-drivers.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-drivers.yml")) | .state')
if [ $? -eq 0 ] && [[ "$workflowState" == 'active' ]]; then
gh workflow run vcpkg-linux-drivers.yml --ref "$GITHUB_REF_NAME"
fi
env:
GH_TOKEN: ${{ github.token }}
- name: Cancel vcpkg-linux-drivers.yml workflow (on failure)
if: ${{ failure() }}
working-directory: ${{ env.TinyORMPath }}
run: |
databaseId=$(gh run list --workflow vcpkg-linux-drivers.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 }}