Skip to content

Commit 3d38e42

Browse files
authored
GitHub actions support (#368)
* Initial attempt to port over appveyor logic to GitHub Actions * Refactor GitHub actions config to matrix format
1 parent 48401c1 commit 3d38e42

File tree

3 files changed

+354
-0
lines changed

3 files changed

+354
-0
lines changed
Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
name: Build/Deploy MSVC Windows
2+
3+
on:
4+
push:
5+
branches: [ master, features/github-actions ]
6+
pull_request:
7+
branches: [ master, features/github-actions ]
8+
release:
9+
types: [published]
10+
11+
env:
12+
QT_VERSION: "5.15.0"
13+
14+
jobs:
15+
# Constants to simplify things
16+
17+
build:
18+
name: "Build target: ${{ matrix.linking }} (${{ matrix.arch }})"
19+
runs-on: windows-2019
20+
21+
strategy:
22+
fail-fast: false
23+
matrix:
24+
arch: [x86, x64]
25+
linking: [dynamic, static]
26+
include:
27+
- arch: x86
28+
arch_name: 32-bit
29+
arch_suffix: "32"
30+
arch_qt_msvc: win32_msvc2019
31+
arch_extra_msbuild_args: ""
32+
- arch: x64
33+
arch_name: 64-bit
34+
arch_suffix: "64"
35+
arch_qt_msvc: win64_msvc2019_64
36+
arch_extra_msbuild_args: '/p:Platform="x64"'
37+
38+
- linking: dynamic
39+
linking_name: Dynamic/Shared
40+
linking_suffix: dyn
41+
linking_build_dir_prefix: build
42+
- linking: static
43+
linking_name: Static
44+
linking_suffix: static
45+
linking_build_dir_prefix: build_static
46+
47+
- arch: x86
48+
linking: static
49+
QT5_BIN_DIR: C:\Qt\Qt5.15.0-static\bin
50+
- arch: x64
51+
linking: static
52+
QT5_BIN_DIR: C:\Qt\Qt5.15.0x64-static\bin
53+
54+
env:
55+
VCPKG_PLATFORM_TOOLSET: v141
56+
VC_VARS_VERSION: 14.1
57+
58+
steps:
59+
60+
## Checkout Git repo
61+
- name: Checkout Git Repo
62+
uses: actions/checkout@v2
63+
with:
64+
submodules: 'recursive'
65+
66+
## Install all major library deps
67+
68+
# Setup caches
69+
- name: "Cache shared/dynamic Qt (${{ matrix.arch_name }})"
70+
id: "cache-qt"
71+
uses: actions/cache@v1
72+
if: ${{ matrix.linking == 'dynamic' }}
73+
with:
74+
path: ../QtDyn${{ matrix.arch_suffix }}
75+
key: ${{ runner.os }}-QtCache${{ matrix.arch_suffix }}
76+
77+
# Install Qt (from pre-defined action)
78+
- name: "Install shared/dynamic Qt (v${{ env.QT_VERSION }}, ${{ matrix.arch_name }})"
79+
uses: jurplel/install-qt-action@v2
80+
if: ${{ matrix.linking == 'dynamic' }}
81+
with:
82+
version: ${{ env.QT_VERSION }}
83+
host: 'windows'
84+
target: 'desktop'
85+
arch: ${{ matrix.arch_qt_msvc }}
86+
dir: ${{ runner.workspace }}/QtDyn${{ matrix.arch_suffix }}
87+
cached: ${{ steps.cache-qt.outputs.cache-hit }}
88+
89+
- name: "Set shared/dynamic Qt location (v${{ env.QT_VERSION }}, ${{ matrix.arch_name }})"
90+
if: ${{ matrix.linking == 'dynamic' }}
91+
run: |
92+
echo '::set-env name=QT5_BIN_DIR::${{ env.Qt5_DIR }}/bin'
93+
94+
- name: Set vcpkg's response file path used as part of cache's key.
95+
uses: lukka/set-shell-env@master
96+
with:
97+
VCPKGRESPONSEFILE: ${{ github.workspace }}/.github/workflows/msvc.windows.vcpkg.txt
98+
filter: ^VCPKG.*
99+
100+
# Restore from cache the previously built ports. If cache-miss, download, build vcpkg.
101+
# Then install libarchive + libpng-apng for all targets.
102+
- name: Restore from cache and install vcpkg + libraries (libarchive, libpng-apng)
103+
# Download and build vcpkg, without installing any port. If content is cached already, it is a no-op.
104+
uses: lukka/run-vcpkg@v3
105+
with:
106+
vcpkgArguments: '@${{ env.VCPKGRESPONSEFILE }}'
107+
# This commit ID corresponds to 2020.06
108+
vcpkgGitCommitId: 6185aa76504a5025f36754324abf307cc776f3da
109+
appendedCacheKey: ${{ hashFiles(env.VCPKGRESPONSEFILE) }}
110+
111+
# Install Python modules to run our helper script
112+
- name: Install Python libraries for bootstrap helper script (static linking only)
113+
if: ${{ matrix.linking == 'static' }}
114+
run: |
115+
python -m pip install --upgrade pip
116+
pip install requests jinja2 irc
117+
118+
# Install our static dependencies via helper script
119+
# TODO: get caching working here too
120+
- name: Install static dependencies via bootstrap helper script
121+
if: ${{ matrix.linking == 'static' }}
122+
run: python -u gui\qt\deploy-scripts\appveyor_helper.py install
123+
124+
# TODO: automate this somehow?
125+
- name: Set paths to newly installed static Qt libraries
126+
if: ${{ matrix.linking == 'static' }}
127+
run: |
128+
echo '::set-env name=QT5_BIN_DIR::${{ matrix.QT5_BIN_DIR }}'
129+
130+
## Build time!
131+
132+
# Are we releasing?
133+
- name: Set CEmu version for release (if applicable)
134+
run: |
135+
echo '::set-env name=CEMU_VERSION::${{ github.event.release.tag_name }}'
136+
echo Using tagged version :${{ env.CEMU_VERSION }}
137+
if: "github.event.release.tag_name"
138+
139+
- name: Set CEmu version for development (if applicable)
140+
run: |
141+
echo '::set-env name=CEMU_VERSION::'
142+
echo "No version defined, using empty version '${{ env.CEMU_VERSION }}'"
143+
if: "!github.event.release.tag_name"
144+
145+
# Set dynamic, matrix-controlled env var
146+
- name: Set extra static MSBuild flag, if applicable
147+
run: |
148+
echo '::set-env name=LINKING_EXTRA_MSBUILD_ARGS::/p:VcpkgTriplet=${{ matrix.arch }}-windows-static'
149+
echo "Detected static linking, adding LINKING_EXTRA_MSBUILD_ARGS = '${{ env.LINKING_EXTRA_MSBUILD_ARGS }}'"
150+
if: "matrix.linking == 'static'"
151+
152+
# Setup VS
153+
- name: "Setup MSVC++ paths (${{ matrix.arch_name }} target)"
154+
uses: ilammy/msvc-dev-cmd@v1
155+
with:
156+
arch: ${{ matrix.arch }}
157+
toolset: ${{ env.VC_VARS_VERSION }}
158+
159+
# Install vcpkg integration
160+
- name: Install vcpkg integration (${{ matrix.arch_name }})
161+
run: ${{ env.VCPKG_ROOT }}/vcpkg integrate install
162+
163+
# 32-bit dynamic + static builds
164+
- name: "Build target: ${{ matrix.linking_name }} (Debug, ${{ matrix.arch_name }})"
165+
shell: cmd
166+
run: |
167+
mkdir -p ${{ matrix.linking_build_dir_prefix }}_${{ matrix.arch_suffix }}
168+
cd ${{ matrix.linking_build_dir_prefix }}_${{ matrix.arch_suffix }}
169+
${{ env.QT5_BIN_DIR }}\qmake -spec win32-msvc -tp vc CEMU_VERSION=${{ env.CEMU_VERSION }} LIBPNG_APNG_FROM_VCPKG=1 "..\gui\qt\CEmu.pro" && ^
170+
msbuild CEmu.vcxproj /p:Configuration=Debug ${{ matrix.arch_extra_msbuild_args }} ${{ env.LINKING_EXTRA_MSBUILD_ARGS }}
171+
172+
- name: "Build target: ${{ matrix.linking_name }} (Release, ${{ matrix.arch_name }})"
173+
shell: cmd
174+
run: |
175+
mkdir -p ${{ matrix.linking_build_dir_prefix }}_${{ matrix.arch_suffix }}
176+
cd ${{ matrix.linking_build_dir_prefix }}_${{ matrix.arch_suffix }}
177+
${{ env.QT5_BIN_DIR }}\qmake -spec win32-msvc -tp vc CEMU_VERSION=${{ env.CEMU_VERSION }} LIBPNG_APNG_FROM_VCPKG=1 "..\gui\qt\CEmu.pro" && ^
178+
msbuild CEmu.vcxproj /p:Configuration=Release ${{ matrix.arch_extra_msbuild_args }} ${{ env.LINKING_EXTRA_MSBUILD_ARGS }}
179+
180+
- name: "Upload artifacts: ${{ matrix.linking_name }} (Debug + Release, ${{ matrix.arch_name }})"
181+
uses: actions/upload-artifact@v2
182+
with:
183+
name: build-${{ matrix.linking_suffix }}-${{ matrix.arch_suffix }}
184+
path: ${{ matrix.linking_build_dir_prefix }}_${{ matrix.arch_suffix }}
185+
186+
deploy:
187+
# TODO: maybe find a way to reduce steps req'd to get running here
188+
name: Deploy all built targets
189+
runs-on: windows-2019
190+
191+
strategy:
192+
fail-fast: false
193+
194+
needs: build
195+
196+
steps:
197+
198+
## Checkout Git repo
199+
- name: Checkout Git Repo
200+
uses: actions/checkout@v2
201+
with:
202+
submodules: 'recursive'
203+
204+
## Install all major library deps
205+
206+
# Setup caches
207+
- name: Cache Qt (32-bit)
208+
id: cache-qt-32
209+
uses: actions/cache@v1
210+
with:
211+
path: ../QtDyn32
212+
key: ${{ runner.os }}-QtCache32
213+
214+
- name: Cache Qt (64-bit)
215+
id: cache-qt-64
216+
uses: actions/cache@v1
217+
with:
218+
path: ../QtDyn64
219+
key: ${{ runner.os }}-QtCache64
220+
221+
# Install Qt (from pre-defined action)
222+
- name: Install Qt (v5.15.0, 32-bit)
223+
uses: jurplel/install-qt-action@v2
224+
with:
225+
version: '5.15.0'
226+
host: 'windows'
227+
target: 'desktop'
228+
arch: 'win32_msvc2019'
229+
dir: ${{ runner.workspace }}/QtDyn32
230+
cached: ${{ steps.cache-qt-32.outputs.cache-hit }}
231+
232+
- name: Set Qt location (v5.15.0, 32-bit)
233+
run: |
234+
echo '::set-env name=QT5_BIN_DIR_DYNAMIC_32::${{ env.Qt5_DIR }}/bin'
235+
echo '::set-env name=QT_PLUGIN_PATH_DYNAMIC_32::${{ env.QT_PLUGIN_PATH }}'
236+
echo '::set-env name=QML2_IMPORT_PATH_DYNAMIC_32::${{ env.QML2_IMPORT_PATH }}'
237+
238+
- name: Install Qt (v5.15.0, 64-bit)
239+
uses: jurplel/install-qt-action@v2
240+
with:
241+
version: '5.15.0'
242+
host: 'windows'
243+
target: 'desktop'
244+
arch: 'win64_msvc2019_64'
245+
dir: ${{ runner.workspace }}/QtDyn64
246+
cached: ${{ steps.cache-qt-64.outputs.cache-hit }}
247+
248+
- name: Set Qt location (v5.15.0, 64-bit)
249+
run: |
250+
echo '::set-env name=QT5_BIN_DIR_DYNAMIC_64::${{ env.Qt5_DIR }}/bin'
251+
echo '::set-env name=QT_PLUGIN_PATH_DYNAMIC_64::${{ env.QT_PLUGIN_PATH }}'
252+
echo '::set-env name=QML2_IMPORT_PATH_DYNAMIC_64::${{ env.QML2_IMPORT_PATH }}'
253+
254+
# Install Python + modules to run our helper script
255+
- name: Set up Python 3.8
256+
uses: actions/setup-python@v2
257+
with:
258+
python-version: 3.8
259+
260+
- name: Install Python libraries for bootstrap helper script
261+
run: |
262+
python -m pip install --upgrade pip
263+
pip install requests jinja2 irc
264+
265+
# Install our static dependencies via helper script
266+
# TODO: get caching working here too
267+
- name: Install static dependencies via bootstrap helper script
268+
run: python -u gui\qt\deploy-scripts\appveyor_helper.py install
269+
270+
# TODO: automate this somehow?
271+
- name: Set paths to newly installed static Qt libraries
272+
run: |
273+
echo '::set-env name=QT5_BIN_DIR_STATIC_32::C:\Qt\Qt5.15.0-static\bin'
274+
echo '::set-env name=QT5_BIN_DIR_STATIC_64::C:\Qt\Qt5.15.0x64-static\bin'
275+
276+
- name: "Download artifacts: Dynamic/Shared (Debug + Release, 32-bit)"
277+
uses: actions/download-artifact@v2
278+
with:
279+
name: build-dyn-32
280+
path: build_32
281+
282+
- name: "Download artifacts: Dynamic/Shared (Debug + Release, 64-bit)"
283+
uses: actions/download-artifact@v2
284+
with:
285+
name: build-dyn-64
286+
path: build_64
287+
288+
- name: "Download artifacts: Static (Debug + Release, 32-bit)"
289+
uses: actions/download-artifact@v2
290+
with:
291+
name: build-static-32
292+
path: build_static_32
293+
294+
- name: "Download artifacts: Static (Debug + Release, 64-bit)"
295+
uses: actions/download-artifact@v2
296+
with:
297+
name: build-static-64
298+
path: build_static_64
299+
300+
# This requires the corresponding secrets to be set!
301+
- name: "Upload/deploy artifacts to Artifactory"
302+
run: python -u gui\qt\deploy-scripts\appveyor_helper.py deploy
303+
env:
304+
BINTRAY_API_KEY: ${{ secrets.BINTRAY_API_KEY }}
305+
BINTRAY_API_USERNAME: ${{ secrets.BINTRAY_API_USERNAME }}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
libarchive:x86-windows
2+
libarchive:x64-windows
3+
libarchive:x86-windows-static
4+
libarchive:x64-windows-static
5+
libpng[core,apng]:x86-windows
6+
libpng[core,apng]:x64-windows
7+
libpng[core,apng]:x86-windows-static
8+
libpng[core,apng]:x64-windows-static
9+
--recurse

.github/workflows/yml2jsonvar.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env python
2+
# YAML to (GitHub Actions friendly) JSON
3+
# This reads in a YAML file and returns GitHub Actions friendly JSON to the
4+
# env variable specified. This works by printing this special value:
5+
# ::set-env name=ENV_VAR_NAME::ENV_VAR_VALUE
6+
# Once you have your JSON, you can call fromJSON(value) to parse it.
7+
#
8+
# Usage: yml2jsonvar.py VAR_NAME yml_file
9+
#
10+
# Currently GitHub Actions isn't a fan of multiline strings... see:
11+
# https://github.community/t/set-output-truncates-multiline-strings/16852
12+
# https://github.com/actions/toolkit/issues/403
13+
# https://github.com/actions/toolkit/issues/193
14+
# https://github.com/actions/toolkit/issues/193
15+
16+
import argparse
17+
import json
18+
19+
from yaml import load, dump
20+
try:
21+
from yaml import CLoader as Loader, CDumper as Dumper
22+
except ImportError:
23+
from yaml import Loader, Dumper
24+
25+
def parse_args():
26+
parser = argparse.ArgParser(description="Parse YAML file into a GitHub Actions env var.")
27+
parser.add_argument("var_name", help="variable name to store JSON in")
28+
parser.add_argument("yaml_file", help="YAML file to read from")
29+
return parser.parse_args()
30+
31+
def yaml_to_json(yaml_file):
32+
with open(yaml_file, "r") as yaml_fh:
33+
data = load(yaml_fh, Loader=Loader)
34+
return json.dumps(data)
35+
36+
if __name__ == "__main__":
37+
args = parse_args()
38+
39+
json_out = yaml_to_json(args.yaml_file)
40+
print("::set-env name={var_name}::{json_out}.format(var_name=args.var_name, json_out=json_out)

0 commit comments

Comments
 (0)