Skip to content

Commit 4c05418

Browse files
feat: add c++ common code (#24)
1 parent 07382e5 commit 4c05418

21 files changed

Lines changed: 1442 additions & 4 deletions

File tree

.github/workflows/ci.yml

Lines changed: 326 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ concurrency:
1414
cancel-in-progress: true
1515

1616
env:
17+
OPENCPPCOVERAGE_VERSION: '0.9.9.0'
1718
PYTHON_VERSION: '3.14'
1819

1920
jobs:
@@ -88,7 +89,7 @@ jobs:
8889
disable_search: true
8990
fail_ci_if_error: true
9091
files: ./coverage/python-coverage.xml
91-
flags: ${{ runner.os }}
92+
flags: ${{ runner.os }}-python
9293
report_type: coverage
9394
token: ${{ secrets.CODECOV_TOKEN }}
9495
verbose: true
@@ -104,7 +105,329 @@ jobs:
104105
disable_search: true
105106
fail_ci_if_error: true
106107
files: ./junit-python.xml
107-
flags: ${{ runner.os }}
108+
flags: ${{ runner.os }}-python
109+
report_type: test_results
110+
token: ${{ secrets.CODECOV_TOKEN }}
111+
verbose: true
112+
113+
build:
114+
name: Build (${{ matrix.name }})
115+
needs:
116+
- release-setup
117+
permissions:
118+
contents: read
119+
runs-on: ${{ matrix.os }}
120+
defaults:
121+
run:
122+
shell: ${{ matrix.shell }}
123+
strategy:
124+
fail-fast: false
125+
matrix:
126+
include:
127+
- name: Linux-GCC
128+
os: ubuntu-latest
129+
shell: bash
130+
kind: unix
131+
cc: gcc
132+
cxx: g++
133+
gcov_executable: gcov
134+
- name: Linux-Clang
135+
os: ubuntu-latest
136+
shell: bash
137+
kind: unix
138+
cc: clang
139+
cxx: clang++
140+
# Clang writes LLVM coverage notes, so gcovr needs llvm-cov's gcov compatibility mode.
141+
gcov_executable: llvm-cov gcov
142+
- name: macOS
143+
os: macos-latest
144+
shell: bash
145+
kind: unix
146+
cc: clang
147+
cxx: clang++
148+
gcov_executable: gcov
149+
- name: Windows-MinGW-UCRT64
150+
os: windows-latest
151+
shell: msys2 {0}
152+
kind: msys2
153+
cc: gcc
154+
cxx: g++
155+
msystem: ucrt64
156+
toolchain: ucrt-x86_64
157+
gcov_executable: gcov
158+
- name: Windows-MSVC
159+
os: windows-2022
160+
shell: pwsh
161+
kind: msvc
162+
steps:
163+
- name: Checkout
164+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
165+
with:
166+
submodules: recursive
167+
168+
- name: Setup Dependencies Linux
169+
if: runner.os == 'Linux'
170+
run: |
171+
sudo apt-get update
172+
sudo apt-get install -y \
173+
build-essential \
174+
clang \
175+
cmake \
176+
llvm \
177+
ninja-build
178+
179+
- name: Setup Dependencies macOS
180+
if: runner.os == 'macOS'
181+
run: |
182+
brew install \
183+
cmake \
184+
ninja
185+
186+
- name: Setup Dependencies Windows MinGW
187+
if: matrix.kind == 'msys2'
188+
uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0
189+
with:
190+
msystem: ${{ matrix.msystem }}
191+
update: true
192+
install: >-
193+
mingw-w64-${{ matrix.toolchain }}-cmake
194+
mingw-w64-${{ matrix.toolchain }}-ninja
195+
mingw-w64-${{ matrix.toolchain }}-toolchain
196+
197+
- name: Setup Dependencies Windows MSVC
198+
if: matrix.kind == 'msvc'
199+
run: |
200+
choco install opencppcoverage --version=${{ env.OPENCPPCOVERAGE_VERSION }} --yes --no-progress
201+
202+
$openCppCoverageDir = "${env:ProgramFiles}\OpenCppCoverage"
203+
if (!(Test-Path (Join-Path $openCppCoverageDir "OpenCppCoverage.exe"))) {
204+
$openCppCoverageDir = "${env:ProgramFiles(x86)}\OpenCppCoverage"
205+
}
206+
if (!(Test-Path (Join-Path $openCppCoverageDir "OpenCppCoverage.exe"))) {
207+
throw "OpenCppCoverage.exe was not found after Chocolatey install."
208+
}
209+
210+
$openCppCoverageDir | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
211+
212+
- name: Set up Python
213+
id: setup-python
214+
if: matrix.kind != 'msvc'
215+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
216+
with:
217+
python-version: ${{ env.PYTHON_VERSION }}
218+
219+
- name: Set up uv
220+
if: matrix.kind != 'msvc'
221+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
222+
with:
223+
enable-cache: true
224+
225+
- name: Sync Python tools
226+
if: matrix.kind != 'msvc'
227+
env:
228+
MSYS2_PATH_TYPE: inherit
229+
UV_PYTHON: ${{ steps.setup-python.outputs.python-path }}
230+
run: |
231+
uv sync --locked --only-group test-c \
232+
--no-python-downloads \
233+
--no-install-project
234+
235+
- name: Configure
236+
if: matrix.kind != 'msvc'
237+
env:
238+
CC: ${{ matrix.cc }}
239+
CXX: ${{ matrix.cxx }}
240+
run: |
241+
cmake \
242+
-DBUILD_DOCS=OFF \
243+
-DBUILD_TESTS=ON \
244+
-DCMAKE_BUILD_TYPE:STRING=Debug \
245+
-B cmake-build-ci \
246+
-G Ninja \
247+
-S .
248+
249+
- name: Configure MSVC
250+
if: matrix.kind == 'msvc'
251+
run: |
252+
cmake `
253+
-DBUILD_DOCS=OFF `
254+
-DBUILD_TESTS=ON `
255+
-A x64 `
256+
-B cmake-build-ci `
257+
-G "Visual Studio 17 2022" `
258+
-S .
259+
260+
- name: Build
261+
if: matrix.kind != 'msvc'
262+
run: cmake --build cmake-build-ci -- -j2
263+
264+
- name: Build MSVC
265+
if: matrix.kind == 'msvc'
266+
run: cmake --build cmake-build-ci --config Debug --parallel 2
267+
268+
- name: Prepare report directory
269+
run: cmake -E make_directory cmake-build-ci/reports
270+
271+
- name: Run tests
272+
id: test
273+
if: matrix.kind != 'msvc'
274+
working-directory: cmake-build-ci/tests
275+
run: ./test_lizardbyte_common --gtest_color=yes --gtest_output=xml:../reports/junit.xml
276+
277+
- name: Run tests MSVC
278+
id: test_msvc
279+
if: matrix.kind == 'msvc'
280+
run: |
281+
$openCppCoverage = (Get-Command OpenCppCoverage.exe -ErrorAction SilentlyContinue).Source
282+
if (!$openCppCoverage) {
283+
$candidates = @(
284+
"${env:ProgramFiles}\OpenCppCoverage\OpenCppCoverage.exe",
285+
"${env:ProgramFiles(x86)}\OpenCppCoverage\OpenCppCoverage.exe"
286+
)
287+
$openCppCoverage = $candidates | Where-Object { Test-Path $_ } | Select-Object -First 1
288+
}
289+
if (!$openCppCoverage) {
290+
throw "OpenCppCoverage.exe was not found."
291+
}
292+
293+
& $openCppCoverage `
294+
--sources "$env:GITHUB_WORKSPACE\src" `
295+
--sources "$env:GITHUB_WORKSPACE\tests\support" `
296+
"--export_type=cobertura:$env:GITHUB_WORKSPACE\cmake-build-ci\reports\coverage.xml" `
297+
--working_dir "$env:GITHUB_WORKSPACE\cmake-build-ci\tests" `
298+
-- `
299+
"$env:GITHUB_WORKSPACE\cmake-build-ci\tests\Debug\test_lizardbyte_common.exe" `
300+
--gtest_color=yes `
301+
"--gtest_output=xml:$env:GITHUB_WORKSPACE\cmake-build-ci\reports\junit.xml"
302+
303+
- name: Normalize MSVC coverage paths
304+
if: >-
305+
always() &&
306+
matrix.kind == 'msvc' &&
307+
(steps.test_msvc.outcome == 'success' || steps.test_msvc.outcome == 'failure')
308+
run: |
309+
$coveragePath = Join-Path $env:GITHUB_WORKSPACE "cmake-build-ci\reports\coverage.xml"
310+
if (!(Test-Path $coveragePath)) {
311+
return
312+
}
313+
314+
[xml] $coverage = Get-Content $coveragePath
315+
$workspace = $env:GITHUB_WORKSPACE.Replace('\', '/')
316+
foreach ($node in $coverage.SelectNodes('//*[@filename]')) {
317+
$filename = $node.GetAttribute('filename').Replace('\', '/')
318+
if ($filename.StartsWith("${workspace}/")) {
319+
$filename = $filename.Substring($workspace.Length + 1)
320+
}
321+
322+
$node.SetAttribute('filename', $filename)
323+
}
324+
325+
foreach ($source in $coverage.SelectNodes('//source')) {
326+
$source.InnerText = '.'
327+
}
328+
329+
$coverage.Save($coveragePath)
330+
331+
- name: Generate gcov report
332+
id: test_report
333+
if: >-
334+
always() &&
335+
matrix.kind != 'msvc' &&
336+
(steps.test.outcome == 'success' || steps.test.outcome == 'failure')
337+
working-directory: cmake-build-ci
338+
env:
339+
GCOV_EXECUTABLE: ${{ matrix.gcov_executable }}
340+
MSYS2_PATH_TYPE: inherit
341+
run: |
342+
uv run --project .. --locked --no-sync gcovr . -r .. \
343+
--filter ../src \
344+
--filter ../tests/support \
345+
--gcov-executable "${GCOV_EXECUTABLE}" \
346+
--exclude-noncode-lines \
347+
--exclude-throw-branches \
348+
--exclude-unreachable-branches \
349+
--verbose \
350+
--xml-pretty \
351+
-o reports/coverage.xml
352+
353+
- name: Install
354+
if: matrix.kind != 'msvc'
355+
run: cmake --install cmake-build-ci --prefix cmake-build-ci/install
356+
357+
- name: Install MSVC
358+
if: matrix.kind == 'msvc'
359+
run: cmake --install cmake-build-ci --config Debug --prefix cmake-build-ci/install
360+
361+
- name: Upload report artifact
362+
if: >-
363+
always() &&
364+
(
365+
steps.test_report.outcome == 'success' ||
366+
steps.test_msvc.outcome == 'success' ||
367+
steps.test_msvc.outcome == 'failure'
368+
)
369+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
370+
with:
371+
name: reports-${{ matrix.name }}
372+
path: cmake-build-ci/reports
373+
if-no-files-found: error
374+
375+
codecov:
376+
name: Codecov (${{ matrix.flag }})
377+
if: >-
378+
always() &&
379+
(needs.build.result == 'success' || needs.build.result == 'failure') &&
380+
startsWith(github.repository, 'LizardByte/')
381+
needs:
382+
- build
383+
permissions:
384+
contents: read
385+
runs-on: ubuntu-latest
386+
strategy:
387+
fail-fast: false
388+
matrix:
389+
include:
390+
- build_name: Linux-GCC
391+
flag: Linux-GCC
392+
- build_name: Linux-Clang
393+
flag: Linux-Clang
394+
- build_name: macOS
395+
flag: macOS
396+
- build_name: Windows-MinGW-UCRT64
397+
flag: Windows-MinGW-UCRT64
398+
- build_name: Windows-MSVC
399+
flag: Windows-MSVC
400+
steps:
401+
- name: Checkout
402+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
403+
404+
- name: Download report artifact
405+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
406+
with:
407+
name: reports-${{ matrix.build_name }}
408+
path: _reports
409+
410+
- name: Debug coverage file
411+
run: cat _reports/coverage.xml
412+
413+
- name: Upload test coverage
414+
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
415+
with:
416+
disable_search: true
417+
fail_ci_if_error: true
418+
files: ./_reports/coverage.xml
419+
flags: ${{ matrix.flag }}
420+
report_type: coverage
421+
token: ${{ secrets.CODECOV_TOKEN }}
422+
verbose: true
423+
424+
- name: Upload test results
425+
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
426+
with:
427+
disable_search: true
428+
fail_ci_if_error: true
429+
files: ./_reports/junit.xml
430+
flags: ${{ matrix.flag }}
108431
report_type: test_results
109432
token: ${{ secrets.CODECOV_TOKEN }}
110433
verbose: true
@@ -115,6 +438,7 @@ jobs:
115438
(github.event_name == 'push' && github.ref == 'refs/heads/master') &&
116439
needs.release-setup.outputs.publish_release == 'true'
117440
needs:
441+
- build
118442
- release-setup
119443
- pytest
120444
permissions: {}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
build/
4747
Build/
4848
build-*/
49+
cmake-build-*/
4950

5051
# CMake generated files
5152
CMakeFiles/

.gitmodules

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[submodule "third-party/doxyconfig"]
2+
path = third-party/doxyconfig
3+
url = https://github.com/LizardByte/doxyconfig.git
4+
branch = master
5+
[submodule "third-party/googletest"]
6+
path = third-party/googletest
7+
url = https://github.com/google/googletest.git

0 commit comments

Comments
 (0)