Skip to content

hope

hope #30

Workflow file for this run

name: C++ CI
on:
push:
branches: ['*'] # NOTE: replace/update with appropriate branch name(s)
tags: ['*']
pull_request:
branches: ['*'] # NOTE: replace/update with appropriate branch name(s)
workflow_dispatch:
inputs:
build_type:
description: Build type
required: false
default: 'Debug'
type: choice
options:
- Debug
- Release
- RelWithDebInfo
- MinSizeRel
env:
BUILD_TYPE: ${{ inputs.build_type || 'Debug' }}
# NOTE: update executable name if it is changed in CMakeLists.txt
EXECUTABLE_NAME: "oop"
INPUT_FILENAME: "tastatura.txt"
BUILD_DIR: "build"
EXT_DIR: "ext"
BIN_DIR: "bin"
GEN_DIR: "generated"
defaults:
run:
# Use a bash shell, so we can use the same syntax for environment variable
# access regardless of the host operating system
# https://github.com/saxbophone/CPP20-Cross-Platform-Template
shell: bash
jobs:
cppcheck:
name: "Cppcheck"
runs-on: ubuntu-22.04
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Install cppcheck
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends cppcheck
# The flag CMAKE_EXPORT_COMPILE_COMMANDS generates compile_commands.json
# which is used by cppcheck and clang-tidy
- name: Configure CMake
uses: ./.github/actions/configure-cmake
with:
custom_flags: '-DCMAKE_EXPORT_COMPILE_COMMANDS=ON'
- name: Cppcheck
run: |
cppcheck --enable=all \
--inline-suppr \
--project="${BUILD_DIR}"/compile_commands.json \
-i"${BUILD_DIR}" --suppress='*:"${BUILD_DIR}"/*' \
-i"${EXT_DIR}" --suppress='*:"${EXT_DIR}"/*' \
-i"${GEN_DIR}" --suppress='*:"${GEN_DIR}"/*' \
--suppress=missingIncludeSystem \
--suppress=unmatchedSuppression \
--suppress=useStlAlgorithm \
--error-exitcode=1
# - uses: lukka/get-cmake@latest
# - name: List $RUNNER_WORKSPACE before vcpkg is setup
# run: find $RUNNER_WORKSPACE
# shell: bash
#
# - name: Setup anew (or from cache) vcpkg (and does not build any package)
# uses: lukka/run-vcpkg@v11
#
# - name: Run CMake consuming CMakePreset.json and run vcpkg to build packages
# uses: lukka/run-cmake@v10
# with:
# configurePreset: 'ninja-multi-vcpkg'
clang-tidy:
name: "Clang-Tidy"
runs-on: ubuntu-22.04
env:
CC: clang-17
CXX: clang++-17
steps:
- name: Checkout repo
uses: actions/checkout@v4
# Also see https://github.com/actions/runner-images/discussions/9446#discussioncomment-8668538
- name: Install Clang 17
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x ./llvm.sh
sudo ./llvm.sh 17
- name: Install clang-tidy
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends clang-tidy-17 libc++-17-dev libc++abi-17-dev
# - name: Install Protoc
# uses: arduino/setup-protoc@v3
# with:
# version: "23.x"
- name: Configure CMake
uses: ./.github/actions/configure-cmake
with:
custom_flags: '-DCMAKE_EXPORT_COMPILE_COMMANDS=ON'
- name: Clang-Tidy
continue-on-error: true
# clang-tidy is not able to follow symbolic links: https://bugs.llvm.org/show_bug.cgi?id=47460
# need to use | as sed separator because / is used in paths
run: |
sed -i "s|$(which ${CXX})|$(realpath $(which ${CXX}))|g" "${BUILD_DIR}"/compile_commands.json
cat "${BUILD_DIR}"/compile_commands.json |
jq -r '.[] | .file' | # select source file paths from CMake project; -r to strip quotes
grep -v "/${BUILD_DIR}/_deps/" | # ignore external dependencies
xargs clang-tidy-17 -p "${BUILD_DIR}"
build:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
timeout-minutes: 10
permissions:
contents: write
env:
CC: ${{ matrix.c }}
CXX: ${{ matrix.cxx }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
c: clang-17
cxx: clang++-17
name: "MSan: Ubuntu 22.04 Clang 17"
# cmake_flags:
cmake_generator: Ninja
# This env runs memory sanitizers
runs_msan: true
- os: ubuntu-22.04
c: gcc-12
cxx: g++-12
name: "ASan: Ubuntu 22.04 GCC 12"
# cmake_flags:
cmake_generator: Ninja
# This env runs address sanitizers
runs_asan: true
- os: ubuntu-22.04
c: gcc-11
cxx: g++-11
name: "Valgrind: Ubuntu 22.04 GCC 11"
# cmake_flags:
cmake_generator: Ninja
# This env runs valgrind
runs_valgrind: true
- os: macos-12
c: clang
cxx: clang++
name: "ASan: macOS 12 Apple Clang 14"
# cmake_flags:
# cmake_generator:
# This env runs address sanitizers
runs_asan: true
- os: macos-12
c: gcc-12
cxx: g++-12
name: "macOS 12 GCC 12"
# cmake_flags:
# cmake_generator: Ninja
- os: windows-2022
c: cl
cxx: cl
name: "ASan: Windows 2022 MSVC 19.38"
# cmake_flags:
# cmake_generator: Ninja
# This env runs address sanitizers
runs_asan: true
- os: windows-2022
c: gcc
cxx: g++
name: "Windows 2022 MinGW GCC 12"
# cmake_flags:
cmake_generator: Ninja
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Prepare env
run: |
echo ${GITHUB_WORKSPACE}
mkdir ${GITHUB_WORKSPACE}/artifacts
- name: Set timestamp and zip name
run: |
echo "TIMESTAMP=$(date +%Y-%m-%d-%H-%M-%S)" >> ${GITHUB_ENV}
# use the full name as prefix: {user_name}_{repo_name} (replace / with _)
echo "ZIP_NAME=$(echo "${GITHUB_REPOSITORY}_${{ env.BUILD_TYPE }}_${{ matrix.os }}_${{ matrix.cxx }}" | sed 's|/|_|')" >> ${GITHUB_ENV}
# or use only the repo name (github does not have a predefined environment variable for this)
# the regex splits by / and keeps everything after / without the / character
# echo "ZIP_NAME=$(echo "${GITHUB_REPOSITORY}_${{ env.BUILD_TYPE }}_${{ matrix.os }}_${{ matrix.cxx }}" | sed -E 's|.+/(.+)|\1|')" >> ${GITHUB_ENV}
# Common Linux dependencies
- name: Install Linux Dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install ninja-build
# Also see https://github.com/actions/runner-images/discussions/9446#discussioncomment-8668538
- name: Install Clang 17
if: runner.os == 'Linux' && matrix.runs_msan == true
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x ./llvm.sh
sudo ./llvm.sh 17
- name: Install libc++ (Linux Clang 17)
if: runner.os == 'Linux' && matrix.runs_msan == true
run: |
# sudo apt-get update
sudo apt-get install --no-install-recommends libc++-17-dev libc++abi-17-dev
- name: Install ninja (Windows)
if: runner.os == 'Windows'
run: |
choco install ninja
- name: Install valgrind
if: runner.os == 'Linux' && matrix.runs_valgrind == true
run: |
# sudo apt-get update
sudo apt-get install --no-install-recommends valgrind
- name: Cache tools
uses: actions/cache@v4
if: runner.os == 'Linux' && matrix.runs_msan == true
id: cache-tools
with:
path: tools
key: tools-clang-stdlib-msan
- name: Configure CMake
uses: ./.github/actions/configure-cmake
with:
custom_flags: ${{ matrix.cmake_flags }}
warnings_as_errors: 'ON'
- name: Build
# Execute the build using N jobs (-jN)
run: cmake --build "${BUILD_DIR}" --config ${BUILD_TYPE} -j6
- name: Install
# Use CMake to "install" build artifacts (only interested in CMake registered targets) to our custom artifacts directory
run: cmake --install "${BUILD_DIR}" --config ${BUILD_TYPE} --prefix artifacts
- name: Move artifacts
run: |
mkdir ${{ env.ZIP_NAME }}
mv artifacts/${{ env.BIN_DIR }}/* ${{ env.ZIP_NAME }}
ls -la ${{ env.ZIP_NAME }}
cp "${INPUT_FILENAME}" ${{ env.ZIP_NAME }}
- name: Patch macOS launcher
if: runner.os == 'macOS'
run: |
sed -i '' -e "s/oop/${EXECUTABLE_NAME}/" "${{ env.ZIP_NAME }}/launcher.command"
chmod +x "${{ env.ZIP_NAME }}/launcher.command"
- name: Copy missing dylibs
if: runner.os == 'macOS' && matrix.cxx == 'clang++'
run: |
mkdir lib
cp /Library/Developer/CommandLineTools/usr/lib/clang/14.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib lib
install_name_tool -change @rpath/libclang_rt.asan_osx_dynamic.dylib @executable_path/lib/libclang_rt.asan_osx_dynamic.dylib ${{ env.ZIP_NAME }}/${{ env.EXECUTABLE_NAME }}
mv lib ${{ env.ZIP_NAME }}/
- name: Copy missing dylibs (g++)
if: runner.os == 'macOS' && startsWith(matrix.cxx, 'g++')
run: |
mkdir lib
cp /usr/local/opt/gcc@12/lib/gcc/12/libstdc++.6.dylib /usr/local/opt/gcc@12/lib/gcc/12/libgcc_s.1.1.dylib lib
install_name_tool -change /usr/local/opt/gcc@12/lib/gcc/12/libstdc++.6.dylib @executable_path/lib/libstdc++.6.dylib ${{ env.ZIP_NAME }}/${{ env.EXECUTABLE_NAME }}
install_name_tool -change /usr/local/opt/gcc@12/lib/gcc/12/libgcc_s.1.1.dylib @executable_path/lib/libgcc_s.1.1.dylib ${{ env.ZIP_NAME }}/${{ env.EXECUTABLE_NAME }}
mv lib ${{ env.ZIP_NAME }}/
- name: Copy missing dlls
if: runner.os == 'Windows' && matrix.cxx == 'cl'
run: |
if [[ "${BUILD_TYPE}" =~ "Deb" ]]; then
# runtime debug DLLs
cp "$(which ucrtbased.dll)" \
"$(which VCRUNTIME140_1D.dll)" \
"$(which MSVCP140D.dll)" \
"$(which VCRUNTIME140D.dll)" \
${GITHUB_WORKSPACE}/${{ env.ZIP_NAME }}
# sanitizers DLLs
vcver=$(cat "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt")
vcbindir="C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/MSVC/${vcver}/bin/Hostx64/x64/"
cp "${vcbindir}/clang_rt.asan_dynamic-x86_64.dll" \
"${vcbindir}/clang_rt.asan_dbg_dynamic-x86_64.dll" \
${GITHUB_WORKSPACE}/${{ env.ZIP_NAME }}
fi
# runtime release DLLs
if [[ "${BUILD_TYPE}" =~ "Rel" ]]; then
cp "$(which ucrtbase.dll)" \
"$(which VCRUNTIME140_1.dll)" \
"$(which MSVCP140.dll)" \
"$(which VCRUNTIME140.dll)" \
${GITHUB_WORKSPACE}/${{ env.ZIP_NAME }}
fi
- name: Copy stdlib (MinGW)
if: runner.os == 'Windows' && matrix.cxx == 'g++'
# static linking might not work with MinGW, might be easier this way
run: |
cp $(which libstdc++-6.dll) \
$(which libgcc_s_seh-1.dll) \
$(which libwinpthread-1.dll) \
${GITHUB_WORKSPACE}/${{ env.ZIP_NAME }}
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ env.ZIP_NAME }}_${{ env.TIMESTAMP }}
path: ${{ env.ZIP_NAME }}
retention-days: 30
- name: Setup memory sanitizer
if: runner.os == 'Linux' && matrix.runs_msan == true && steps.cache-tools.outputs.cache-hit != 'true'
run: |
mkdir -p tools
cd tools
git clone --depth=1 --branch=llvmorg-17.0.6 https://github.com/llvm/llvm-project
cd llvm-project
# mkdir build; cd build
sudo ln -s -f /usr/bin/$CC /usr/bin/clang
sudo ln -s -f /usr/bin/$CXX /usr/bin/clang++
cmake -G Ninja -S runtimes -B build \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DLLVM_USE_SANITIZER=MemoryWithOrigins \
-DCMAKE_BUILD_WITH_INSTALL_RPATH=true
cmake --build build -j6 -- cxx cxxabi
- name: Sanitizers
# run one sanitizer for each env to avoid building extra binaries on one env
if: (matrix.runs_asan == true || matrix.runs_msan == true) && runner.os != 'Windows'
# detect_leaks is not supported on macOS
# env:
# ASAN_OPTIONS: detect_leaks=1
run: |
cat "${INPUT_FILENAME}" | tr -d '\r' | ./${{ env.ZIP_NAME }}/"${EXECUTABLE_NAME}"
- name: Sanitizers (Windows MSVC)
# run one sanitizer for each OS to avoid building extra binaries
if: matrix.cxx == 'cl' && matrix.runs_asan == true
continue-on-error: true
run: |
cat "${INPUT_FILENAME}" | ./${{ env.ZIP_NAME }}/"${EXECUTABLE_NAME}".exe
- name: Valgrind
if: runner.os == 'Linux' && matrix.runs_valgrind == true
run: |
# remove --show-leak-kinds=all (and --track-origins=yes) if there are many leaks in external libs
cat "${INPUT_FILENAME}" | tr -d '\r' | valgrind \
--leak-check=full --show-leak-kinds=all --track-origins=yes \
--error-exitcode=1 \
./${{ env.ZIP_NAME }}/"${EXECUTABLE_NAME}"
- name: Set Tag Name
if: startsWith(github.ref, 'refs/tags/')
# trim prefix from ref to get tag name
run: echo "TAG_NAME=${GITHUB_REF#'refs/tags/'}" >> ${GITHUB_ENV}
- name: Add tag to folder name
if: startsWith(github.ref, 'refs/tags/')
run: |
mv ${{ env.ZIP_NAME }} ${{ env.ZIP_NAME }}_${{ env.TAG_NAME }}
- name: Archive Release
uses: thedoctor0/zip-release@master
if: startsWith(github.ref, 'refs/tags/')
with:
type: 'zip'
path: ${{ env.ZIP_NAME }}_${{ env.TAG_NAME }}
filename: ${{ env.ZIP_NAME }}_${{ env.TAG_NAME }}.zip
- name: Release
uses: softprops/action-gh-release@master
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
${{ env.ZIP_NAME }}_${{ env.TAG_NAME }}.zip