Skip to content

Vcpkg Windows

Vcpkg Windows #114

Workflow file for this run

# Common notes
# ---
# Queries/uses only SQLite database.
# ccache
# ---
# Uses /ccache_vcpkg folder and the compressed cache size is 80M (after whole workflow finishes)
name: Vcpkg Windows
on: workflow_dispatch
concurrency:
group: tinyorm-windows
# 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-windows:
name: Vcpkg Windows
# Self-hosted runner is Windows 11 (Release Preview channel - 24H2)
runs-on: [ self-hosted, windows ]
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
# 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,tom-example]
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 = Resolve-Path -Path "$env:RUNNER_WORKSPACE/.."
"TinyRunnerWorkPath=$runnerWorkPath" >> $env:GITHUB_ENV
$tinyormPath = Resolve-Path -Path ./main
"TinyORMPath=$tinyormPath" >> $env:GITHUB_ENV
- name: Ninja install latest version
uses: seanmiddleditch/gha-setup-ninja@master
with:
destination: ${{ env.TinyRunnerWorkPath }}/ninja-build
- name: Visual Studio 2022 pwsh shell setup
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
# Must be after the ilammy/msvc-dev-cmd@v1 because vcvars64 overrides the VCPKG_ROOT
# Define the VCPKG_DEFAULT_BINARY_CACHE because it takes ~20G in C:\Windows\ServiceProfiles
- name: vcpkg prepare environment
run: |
"VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT" >> $env:GITHUB_ENV
'VCPKG_DEFAULT_TRIPLET=x64-windows' >> $env:GITHUB_ENV
"VCPKG_MAX_CONCURRENCY=$env:TINY_PARALLEL" >> $env:GITHUB_ENV
$vcpkgArchivesPath = Join-Path -Path $env:RUNNER_WORKSPACE -ChildPath vcpkg_archives
"VCPKG_DEFAULT_BINARY_CACHE=$vcpkgArchivesPath" >> $env:GITHUB_ENV
$vcpkgPath = Resolve-Path -Path "$env:TinyORMPath/cmake/vcpkg"
$portsPath = Join-Path -Path $vcpkgPath -ChildPath 'ports'
"VCPKG_OVERLAY_PORTS=$portsPath" >> $env:GITHUB_ENV
$tripletsPath = Join-Path -Path $vcpkgPath -ChildPath 'triplets'
"VCPKG_OVERLAY_TRIPLETS=$tripletsPath" >> $env:GITHUB_ENV
- name: vcpkg create binary caching folder
run: |
if (-not (Test-Path $env:VCPKG_DEFAULT_BINARY_CACHE)) {
New-Item -Type Directory $env:VCPKG_DEFAULT_BINARY_CACHE
}
- name: Self-hosted runner prepare environment
run: |
'C:\Program Files\CMake\bin' >> $env:GITHUB_PATH
"$env:VCPKG_INSTALLATION_ROOT" >> $env:GITHUB_PATH
- name: vcpkg needs upgrade? (once per day)
run: |
$vcpkgUpgradedAtFilepath = "$env:RUNNER_WORKSPACE/.vcpkg_upgraded_at"
if (-not (Test-Path -Path $vcpkgUpgradedAtFilepath)) {
'TINY_VCPKG_NEEDS_UPGRADE=true' >> $env:GITHUB_ENV
exit 0
}
$datePreviousUpgrade = New-Object System.DateTime
$result = [System.DateTime]::TryParseExact( `
(Get-Content "$env:RUNNER_WORKSPACE/.vcpkg_upgraded_at"), 'yyyyMMdd', `
[cultureinfo]::InvariantCulture, `
[System.Globalization.DateTimeStyles]::None -bor `
[System.Globalization.DateTimeStyles]::AssumeLocal, [ref] $datePreviousUpgrade)
if (-not $result) {
throw "Parsing the '.vcpkg_upgraded_at' failed."
}
$dateToday = Get-Date -Hour 0 -Minute 0 -Second 0 -Millisecond 0
if ($datePreviousUpgrade -lt $dateToday) {
'TINY_VCPKG_NEEDS_UPGRADE=true' >> $env:GITHUB_ENV
}
- name: vcpkg upgrade repository (latest version)
if: env.TINY_VCPKG_NEEDS_UPGRADE == 'true'
run: |
Set-Location -Path $env:VCPKG_INSTALLATION_ROOT
git.exe switch master
git.exe fetch --tags origin
git.exe reset --hard origin/master
.\bootstrap-vcpkg.bat
Get-Date -Format 'yyyyMMdd' > "$env:RUNNER_WORKSPACE/.vcpkg_upgraded_at"
- name: Compiler print version (cl.exe)
run: |
cl.exe
- name: Linker print version (link.exe)
run: |
link.exe | Select-Object -First 1
- name: CMake print version
run: |
cmake.exe --version
- name: Ninja print version
run: |
ninja.exe --version
- name: vcpkg print version
run: |
vcpkg.exe --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: |
& "$env:TINY_QT_ROOT\${{ matrix.qt.version }}\msvc2019_64\bin\qmake.exe" -query QT_VERSION
# Will be used in the classic method (vcpkg install tinyorm) and VcpkgManifest method
- name: vcpkg prepare TinyORM ports (update REF and SHA512)
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.exe 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.exe install ${{ matrix.qt.vcpkg-qt-features }}
- name: vcpkg install ${{ matrix.qt.vcpkg-tinyorm }} (classic mode)
if: matrix.build-type.key == 'debug'
run: |
vcpkg.exe 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: |
Copy-Item -Path ./HelloWorld.sqlite3 -Destination $env:RUNNER_WORKSPACE -Force
# VcpkgManifest method with the VCPKG_APPLOCAL_DEPS (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 with the VCPKG_APPLOCAL_DEPS (no install or deployment) πŸͺ‘
run: |
Write-Output 'no-op'
- name: HelloWorld prepare VcpkgManifest method environment
run: |
$helloWorldVcpkManifestBuildName = 'vcpkgmanifest-msvc-${{ matrix.build-type.key }}'
"HelloWorldVcpkManifestBuildName=$helloWorldVcpkManifestBuildName" >> $env:GITHUB_ENV
$helloWorldVcpkManifestBuildTree = Join-Path -Path $env:RUNNER_WORKSPACE `
HelloWorld-builds-cmake "build-$helloWorldVcpkManifestBuildName"
"HelloWorldVcpkManifestBuildTree=$helloWorldVcpkManifestBuildTree" >> $env:GITHUB_ENV
- name: HelloWorld prepare VcpkgManifest method (vcpkg.json)
working-directory: HelloWorld
run: >-
Copy-Item -Path ./vcpkg.json.VcpkgManifest.${{ matrix.qt.name }}.example
-Destination ./vcpkg.json
# Don't use ccache for the VcpkgManifest method as the vcpkg has its own binary caching
- name: HelloWorld cmake configure (${{ env.HelloWorldVcpkManifestBuildName }})
working-directory: HelloWorld
run: >-
cmake.exe --log-level=DEBUG --log-context
-S .
-B $env:HelloWorldVcpkManifestBuildTree
-G Ninja
-D CMAKE_TOOLCHAIN_FILE:FILEPATH="$env: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=ON
-D RESOLVE_TINYORM:STRING=VcpkgManifest
- name: HelloWorld cmake build ✨ (${{ env.HelloWorldVcpkManifestBuildName }})
working-directory: ${{ env.HelloWorldVcpkManifestBuildTree }}
run: |
cmake.exe --build . --target all --parallel $env:TINY_PARALLEL
- name: HelloWorld print linker version (${{ env.HelloWorldVcpkManifestBuildName }})
working-directory: ${{ env.HelloWorldVcpkManifestBuildTree }}
run: |
dumpbin.exe /HEADERS .\HelloWorld.exe | Select-String -SimpleMatch 'linker version'
# Related issue: https://github.com/microsoft/vcpkg/issues/33539
- name: HelloWorld finish VCPKG_APPLOCAL_DEPS (Debug)
if: matrix.build-type.key == 'debug'
working-directory: ${{ env.HelloWorldVcpkManifestBuildTree }}
run: |
Copy-Item -Path ./vcpkg_installed/x64-windows/debug/bin/sqlite3.dll -Destination .
Copy-Item -Path ./vcpkg_installed/x64-windows/debug/Qt6 -Destination . -Recurse -Force
- name: HelloWorld finish VCPKG_APPLOCAL_DEPS (Release)
if: matrix.build-type.key == 'release'
working-directory: ${{ env.HelloWorldVcpkManifestBuildTree }}
run: |
Copy-Item -Path ./vcpkg_installed/x64-windows/bin/sqlite3.dll -Destination .
Copy-Item -Path ./vcpkg_installed/x64-windows/Qt6 -Destination . -Recurse -Force
- name: HelloWorld execute (SQLite) 🏁
working-directory: ${{ env.HelloWorldVcpkManifestBuildTree }}
run: |
.\HelloWorld.exe
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: |
"$env:TINY_QT_ROOT\${{ matrix.qt.version }}\msvc2019_64\bin" >> $env:GITHUB_PATH
# 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
- name: Ccache prepare environment
run: |
$ccacheDirPath = Join-Path -Path $env:RUNNER_WORKSPACE -ChildPath ccache_vcpkg
"CCACHE_DIR=$ccacheDirPath" >> $env:GITHUB_ENV
- name: Ccache print version and configuration
run: |
Write-Output '::group::Print version'
ccache.exe --version
Write-Output '::endgroup::'
Write-Output '::group::Print ccache config'
ccache.exe --show-config
Write-Output '::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: |
Write-Output 'no-op'
- name: HelloWorld prepare Manual method environment
run: |
$helloWorldManualBuildName = 'manual-msvc-${{ matrix.build-type.key }}'
"HelloWorldManualBuildName=$helloWorldManualBuildName" >> $env:GITHUB_ENV
$tinyormManualBuildTree = Join-Path -Path $env:RUNNER_WORKSPACE `
TinyORM-builds-cmake "build-vcpkg-$helloWorldManualBuildName"
"TinyORMManualBuildTree=$tinyormManualBuildTree" >> $env:GITHUB_ENV
$helloWorldManualBuildTree = Join-Path -Path $env:RUNNER_WORKSPACE `
HelloWorld-builds-cmake "build-$helloWorldManualBuildName"
"HelloWorldManualBuildTree=$helloWorldManualBuildTree" >> $env:GITHUB_ENV
- name: Ccache clear statistics
run: |
ccache.exe --zero-stats
# CMAKE_DISABLE_PRECOMPILE_HEADERS=ON is correct (Windows ccache doesn't work well with PCH)
- name: TinyORM cmake configure (${{ env.HelloWorldManualBuildName }})
working-directory: ${{ env.TinyORMPath }}
run: >-
cmake.exe --log-level=DEBUG --log-context
-S .
-B $env:TinyORMManualBuildTree
-G Ninja
-D CMAKE_CXX_COMPILER_LAUNCHER:FILEPATH=ccache.exe
-D CMAKE_TOOLCHAIN_FILE:FILEPATH="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"
-D CMAKE_DISABLE_PRECOMPILE_HEADERS:BOOL=ON
-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.exe --build . --target all --parallel $env:TINY_PARALLEL
- name: Ccache print statistics
run: |
ccache.exe --show-stats --verbose
- name: TinyOrm print linker version (${{ env.HelloWorldManualBuildName }})
working-directory: ${{ env.TinyORMManualBuildTree }}
run: |
$tinyTinyOrm = '${{ matrix.build-type.key }}' -ceq 'debug' ? 'TinyOrm0d.dll' : 'TinyOrm0.dll'
dumpbin.exe /HEADERS .\$tinyTinyOrm | Select-String -SimpleMatch 'linker version'
# Build and execute the HelloWorld console application
- name: HelloWorld prepare Manual method (vcpkg.json)
working-directory: HelloWorld
run: |
Copy-Item -Path ./vcpkg.json.Manual.example -Destination ./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.exe --log-level=DEBUG --log-context
-S .
-B $env:HelloWorldManualBuildTree
-G Ninja
-D CMAKE_PREFIX_PATH:PATH=$env:TinyORMManualBuildTree
-D CMAKE_TOOLCHAIN_FILE:FILEPATH="$env: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.exe --build . --target all --parallel $env:TINY_PARALLEL
- name: HelloWorld execute (SQLite) 🏁
working-directory: ${{ env.HelloWorldManualBuildTree }}
run: |
$env:Path = "$env:TinyORMManualBuildTree;" + $env:Path
.\HelloWorld.exe
env:
TINYORM_HELLOWORLD_DB_SQLITE_DATABASE: ../../HelloWorld.sqlite3
# FetchContent method (with install or deployment)
# ---
- name: πŸͺ‘ FetchContent method (with install or deployment) πŸͺ‘
run: |
Write-Output 'no-op'
- name: HelloWorld prepare FetchContent method environment
run: |
$helloWorldFetchContentBuildName = 'fetchcontent-msvc-${{ matrix.build-type.key }}'
"HelloWorldFetchContentBuildName=$helloWorldFetchContentBuildName" >> $env:GITHUB_ENV
$helloWorldFetchContentBuildTree = Join-Path -Path $env:RUNNER_WORKSPACE `
HelloWorld-builds-cmake "build-$helloWorldFetchContentBuildName"
"HelloWorldFetchContentBuildTree=$helloWorldFetchContentBuildTree" >> $env:GITHUB_ENV
- name: HelloWorld prepare FetchContent method (vcpkg.json)
working-directory: HelloWorld
run: |
Copy-Item -Path ./vcpkg.json.FetchContent.example -Destination ./vcpkg.json
- name: HelloWorld prepare FetchContent method (update GIT_TAG)
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.exe --zero-stats
# CMAKE_DISABLE_PRECOMPILE_HEADERS=ON is correct (Windows ccache doesn't work well with PCH)
- name: HelloWorld cmake configure (${{ env.HelloWorldFetchContentBuildName }})
working-directory: HelloWorld
run: >-
cmake.exe --log-level=DEBUG --log-context
-S .
-B $env:HelloWorldFetchContentBuildTree
-G Ninja
-D CMAKE_CXX_COMPILER_LAUNCHER:FILEPATH=ccache.exe
-D CMAKE_TOOLCHAIN_FILE:FILEPATH="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"
-D CMAKE_DISABLE_PRECOMPILE_HEADERS:BOOL=ON
-D CMAKE_BUILD_TYPE:STRING=${{ matrix.build-type.name }}
-D CMAKE_CXX_SCAN_FOR_MODULES:BOOL=OFF
-D CMAKE_INSTALL_PREFIX:PATH="$env: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.exe --build . --target install --parallel $env:TINY_PARALLEL
- name: Ccache print statistics
run: |
ccache.exe --show-stats --verbose
- name: HelloWorld print linker version (${{ env.HelloWorldFetchContentBuildName }})
working-directory: ${{ env.HelloWorldFetchContentBuildTree }}
run: |
dumpbin.exe /HEADERS .\HelloWorld.exe | Select-String -SimpleMatch 'linker version'
- name: HelloWorld execute (SQLite) 🏁
working-directory: ../HelloWorld-FetchContent-Install/${{ matrix.build-type.name }}/bin
run: |
.\HelloWorld.exe
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-windows-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-windows-drivers.yml")) | .state'
if ($? -and $workflowState -ceq 'active') {
gh workflow run vcpkg-windows-drivers.yml --ref $env:GITHUB_REF_NAME
}
env:
GH_TOKEN: ${{ github.token }}
- name: Cancel vcpkg-windows-drivers.yml workflow (on failure)
if: ${{ failure() }}
working-directory: ${{ env.TinyORMPath }}
run: |
$databaseId = gh run list --workflow vcpkg-windows-drivers.yml --event workflow_dispatch `
--json databaseId,conclusion,status `
--jq '.[] | select (.status == "pending") | select (.conclusion == "") | .databaseId'
if ($? -and $null -ne $databaseId -and $databaseId -match '^\d+$' -and
[int64] $databaseId -ne 0
) {
gh run cancel $databaseId
}
env:
GH_TOKEN: ${{ github.token }}