Add CI that runs things through valgrind. #226
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: BuildAntimony | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true' #for seanmiddleditch/gha-setup-ninja and ilammy/msvc-dev-cmd. | |
| on: | |
| push: | |
| branches: | |
| - develop | |
| pull_request: | |
| branches: | |
| - '**' | |
| jobs: | |
| build_on_OSs: | |
| name: Build Antimony on ${{ matrix.platform.name }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| platform: | |
| - name: macos-15-intel-release | |
| os_type: macos | |
| os_name: macos-15-intel | |
| build_type: Release | |
| build_python: ON | |
| build_qt_antimony: ON | |
| - name: macos-15-intel-debug | |
| os_type: macos | |
| os_name: macos-15-intel | |
| build_type: Debug | |
| build_python: ON | |
| build_qt_antimony: OFF | |
| - name: macos-14-release | |
| os_type: macos | |
| os_name: macos-14 | |
| build_type: Release | |
| build_python: ON | |
| build_qt_antimony: OFF | |
| - name: macos-14-debug | |
| os_type: macos | |
| os_name: macos-14 | |
| build_type: Debug | |
| build_python: ON | |
| build_qt_antimony: OFF | |
| - name: ubuntu-latest-release | |
| os_type: ubuntu | |
| os_name: ubuntu-latest | |
| build_type: Release | |
| build_python: ON | |
| build_qt_antimony: ON | |
| - name: ubuntu-latest-debug | |
| os_type: ubuntu | |
| os_name: ubuntu-latest | |
| build_type: Debug | |
| build_python: ON | |
| build_qt_antimony: OFF | |
| - name: windows-latest-release | |
| os_type: windows | |
| os_name: windows-latest | |
| expat_lib_name: libexpatmd.lib | |
| build_type: Release | |
| build_python: ON | |
| build_qt_antimony: ON | |
| - name: windows-latest-debug | |
| os_type: windows | |
| os_name: windows-latest | |
| expat_lib_name: libexpatdMD.lib | |
| build_type: Debug | |
| build_python: OFF | |
| build_qt_antimony: OFF | |
| - name: manylinux_2_28-release | |
| os_type: manylinux | |
| os_name: ubuntu-latest | |
| container_image: quay.io/pypa/manylinux_2_28_x86_64 | |
| build_type: Release | |
| build_python: ON | |
| build_qt_antimony: OFF | |
| - name: manylinux_2_28-debug | |
| os_type: manylinux | |
| os_name: ubuntu-latest | |
| container_image: quay.io/pypa/manylinux_2_28_x86_64 | |
| build_type: Debug | |
| build_python: ON | |
| build_qt_antimony: OFF | |
| libroadrunner_deps_owner: [ "sys-bio" ] | |
| libroadrunner_deps_repo: [ "libroadrunner-deps" ] | |
| libroadrunner_deps_name: [ "libroadrunner-deps" ] | |
| libroadrunner_deps_release_version: [ "v2.3.3" ] | |
| python_version: [ "3.13" ] | |
| runs-on: ${{ matrix.platform.os_name }} | |
| container: | |
| image: ${{ matrix.platform.container_image || '' }} | |
| steps: | |
| - name: Checkout Antimony | |
| uses: actions/checkout@main | |
| - name: Set MSVC as the default compiler on Windows | |
| if: matrix.platform.os_type == 'windows' | |
| uses: ilammy/msvc-dev-cmd@v1 | |
| - name: Upgrade gcc on Linux | |
| if: matrix.platform.os_type == 'manylinux' | |
| shell: bash | |
| run: | | |
| if [ "${{ matrix.platform.os_type }}" == 'ubuntu' ]; then | |
| apt-get update | |
| apt-get install -y software-properties-common | |
| add-apt-repository -y ppa:ubuntu-toolchain-r/test | |
| apt-get update | |
| apt-get install -y gcc-11 g++-11 | |
| update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 90 | |
| update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 90 | |
| elif [ "${{ matrix.platform.os_type }}" == 'manylinux' ]; then | |
| dnf install -y gcc-toolset-11 | |
| scl enable gcc-toolset-11 bash | |
| echo "/opt/rh/gcc-toolset-11/root/usr/bin" >> "${GITHUB_PATH}" | |
| fi | |
| - name: Setup Ninja | |
| if: matrix.platform.os_type == 'manylinux' | |
| uses: seanmiddleditch/gha-setup-ninja@master | |
| - name: Get Host Architecture | |
| shell: bash | |
| run: | | |
| architecture=$(uname -m) | |
| echo "host_architecture=$architecture" >> "${GITHUB_ENV}" | |
| if [ "${{ matrix.platform.os_type }}" == 'macos' ]; then | |
| echo "OSX_ARCHITECTURES=$architecture" >> "${GITHUB_ENV}" | |
| fi | |
| - name: Install ccache | |
| shell: bash | |
| run: | | |
| cd ${RUNNER_WORKSPACE} | |
| if [ "${{ matrix.platform.os_type }}" == 'macos' ]; then | |
| brew install ccache | |
| elif [ "${{ matrix.platform.os_type }}" == 'ubuntu' ]; then | |
| sudo apt-get update | |
| sudo apt-get install -y ccache | |
| if [ "${{ matrix.platform.name }}" == 'ubuntu-latest-release' ]; then | |
| # Needed for the "Run Antimony tests under valgrind" step below. | |
| # (The debug-build valgrind run lives in a separate, | |
| # manually-triggered workflow -- see | |
| # .github/workflows/valgrind-debug-memcheck.yml.) | |
| sudo apt-get install -y valgrind | |
| fi | |
| elif [ "${{ matrix.platform.os_type }}" == 'manylinux' ]; then | |
| mkdir -p ccache | |
| cd ccache | |
| curl -L https://github.com/ccache/ccache/releases/download/v4.9.1/ccache-4.9.1.tar.gz > ccache.tar.gz | |
| tar -zxf ccache.tar.gz | |
| rm ccache.tar.gz | |
| mkdir -p build-ccache | |
| mkdir -p install-ccache | |
| cd build-ccache | |
| cmake -DCMAKE_INSTALL_PREFIX="$RUNNER_WORKSPACE/ccache/install-ccache" -DCMAKE_BUILD_TYPE=Release ../ccache-4.9.1 | |
| cmake --build . --target install | |
| echo "$RUNNER_WORKSPACE/ccache/install-ccache/bin" >> $GITHUB_PATH | |
| fi | |
| - name: Prepare ccache timestamp on non-Windows platforms | |
| if: matrix.platform.os_type != 'windows' | |
| id: ccache_cache_timestamp | |
| shell: cmake -P {0} | |
| run: | | |
| string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC) | |
| message("timestamp=${current_date}" >> $GITHUB_OUTPUT) | |
| - name: Set ccache cache directory on non-Windows | |
| if: matrix.platform.os_type != 'windows' | |
| shell: bash | |
| run: | | |
| cd ${RUNNER_WORKSPACE} | |
| echo "CCACHE_DIR=${RUNNER_WORKSPACE}/.ccache" >> "${GITHUB_ENV}" | |
| echo "COMPILER_LAUNCHER=ccache" >> "${GITHUB_ENV}" | |
| - name: Cache ccache files on non-Windows | |
| if: matrix.platform.os_type != 'windows' | |
| uses: actions/cache@main | |
| with: | |
| path: ${RUNNER_WORKSPACE}/.ccache | |
| key: | |
| ${{ runner.os }}-${{ steps.ccache_cache_timestamp.outputs.timestamp | |
| }} | |
| restore-keys: | | |
| ${{ runner.os }}-${{ steps.ccache_cache_timestamp.outputs.timestamp }} | |
| ${{ runner.os }}- | |
| - name: Setup Python for non-Manylinux platforms | |
| if: matrix.platform.build_python == 'ON' && matrix.platform.os_type != 'manylinux' | |
| uses: actions/setup-python@main | |
| with: | |
| python-version: ${{ matrix.python_version }} | |
| - name: Setup Python for Manylinux platforms | |
| if: matrix.platform.build_python == 'ON' && matrix.platform.os_type == 'manylinux' | |
| shell: bash | |
| run: | | |
| dnf install -y wget | |
| wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh | |
| bash Miniconda3-latest-Linux-x86_64.sh -b -p /Miniconda3 | |
| /Miniconda3/bin/conda create -y --name py3 python=${{ matrix.python_version }} | |
| /Miniconda3/bin/conda init && bash ~/.bashrc && . ~/.bashrc cd ${RUNNER_WORKSPACE} | |
| # sed -i 's/PKG_CONFIG openssl /PKG_CONFIG openssl11 /g' configure | |
| echo "python_exe=/Miniconda3/envs/py3/bin/python" >> $GITHUB_ENV | |
| echo "python_dir=/Miniconda3/envs/py3" >> $GITHUB_ENV | |
| - name: Save Python executable for Windows | |
| if: matrix.platform.build_python == 'ON' && matrix.platform.os_type == 'windows' | |
| run: | | |
| cd ${{ env.pythonLocation }} | |
| $pattern = '[\\]' | |
| $pythonWinExecutable = "${{env.pythonLocation }}" -replace $pattern, '/' | |
| echo "python_exe=$pythonWinExecutable/python.exe" | Out-File -FilePath $env:GITHUB_ENV -Append | |
| echo "python_v1_dir=$pythonWinExecutable" | Out-File -FilePath $env:GITHUB_ENV -Append | |
| - name: Download dependencies binaries | |
| shell: bash | |
| run: | | |
| cd ${RUNNER_WORKSPACE} | |
| mkdir -p ${{ matrix.libroadrunner_deps_name }}-binaries | |
| cd ${{ matrix.libroadrunner_deps_name }}-binaries | |
| if [ "${{ matrix.platform.os_type }}" == 'windows' ]; then | |
| compiler_version=$(ls "C:\Program Files\Microsoft Visual Studio") | |
| binary_file_name=${{ matrix.libroadrunner_deps_name }}-${{ matrix.platform.os_type }}-msvc${compiler_version}-${host_architecture}-${{ matrix.platform.build_type }} | |
| elif [ "${{ matrix.platform.os_type }}" == 'macos' ]; then | |
| os_version=$(sw_vers -productVersion | cut -d '.' -f 1) | |
| binary_file_name=${{ matrix.libroadrunner_deps_name }}-${{ matrix.platform.os_type }}-${os_version}-${host_architecture}-${{ matrix.platform.build_type }} | |
| elif [ "${{ matrix.platform.os_type }}" == 'ubuntu' ]; then | |
| os_version=$(lsb_release -rs | cut -d '.' -f 1) | |
| binary_file_name=${{ matrix.libroadrunner_deps_name }}-${{ matrix.platform.os_type }}-${os_version}-${host_architecture}-${{ matrix.platform.build_type }} | |
| elif [ "${{ matrix.platform.os_type }}" == 'manylinux' ]; then | |
| os_name="${{ matrix.platform.name }}" | |
| os_name_without_build_type="${os_name%%-*}" | |
| binary_file_name=${{ matrix.libroadrunner_deps_name }}-${os_name_without_build_type}-${host_architecture}-${{ matrix.platform.build_type }} | |
| fi | |
| curl -LO "https://github.com/${{ matrix.libroadrunner_deps_owner }}/${{ matrix.libroadrunner_deps_repo }}/releases/download/${{ matrix.libroadrunner_deps_release_version }}/$binary_file_name.zip" | |
| unzip -q $binary_file_name.zip | |
| rm $binary_file_name.zip | |
| echo ANT_DEPENDENCIES_INSTALL_PREFIX="-DANT_DEPENDENCIES_INSTALL_PREFIX=${RUNNER_WORKSPACE}/${{ matrix.libroadrunner_deps_name }}-binaries" >> "${GITHUB_ENV}" | |
| #if [ "${{ matrix.platform.os_type }}" == 'windows' ]; then | |
| # echo EXPAT_LIBRARY="-DEXPAT_LIBRARY=${RUNNER_WORKSPACE}/${{ matrix.libroadrunner_deps_name }}-binaries/lib/${{ matrix.platform.expat_lib_name }}" >> "${GITHUB_ENV}" | |
| #fi | |
| - name: Install Qt | |
| if : matrix.platform.build_qt_antimony == 'ON' | |
| uses: jurplel/install-qt-action@v4 | |
| with: | |
| version: '5.15.2' | |
| #extra: '--base https://mirrors.dotsrc.org/qtproject --UNSAFE-ignore-hash' | |
| #aqtsource: 'git+https://github.com/Kidev/aqtinstall.git@fix_linux_version' | |
| #aqtsource: 'git+https://github.com/miurahr/aqtinstall.git@master' | |
| - name: Create build directory | |
| shell: bash | |
| run: mkdir -p ${RUNNER_WORKSPACE}/build-antimony | |
| - name: Configure CMake for Antimony | |
| shell: bash | |
| run: | | |
| cd ${RUNNER_WORKSPACE}/build-antimony | |
| EXTRA_CMAKE_ARGS=() | |
| if [ "${{ matrix.platform.name }}" == 'ubuntu-latest-release' ]; then | |
| # This is the leg the automatic valgrind memcheck step runs | |
| # against (see "Run Antimony tests under valgrind" below). Keep | |
| # full -O3 Release optimization (so it stays fast) but add -g | |
| # so leak reports have real stack traces instead of bare | |
| # addresses. | |
| EXTRA_CMAKE_ARGS+=("-DCMAKE_CXX_FLAGS_RELEASE=-O3 -DNDEBUG -g") | |
| EXTRA_CMAKE_ARGS+=("-DCMAKE_C_FLAGS_RELEASE=-O3 -DNDEBUG -g") | |
| fi | |
| cmake $GITHUB_WORKSPACE \ | |
| -G "Ninja" \ | |
| -DCMAKE_C_COMPILER_LAUNCHER=${COMPILER_LAUNCHER} \ | |
| -DCMAKE_CXX_COMPILER_LAUNCHER=${COMPILER_LAUNCHER} \ | |
| -DCMAKE_BUILD_TYPE=${{ matrix.platform.build_type }} \ | |
| -DUSE_UNIVERSAL_BINARIES=OFF \ | |
| -DCMAKE_OSX_ARCHITECTURES=${{ matrix.platform.arch }} \ | |
| -DCMAKE_INSTALL_PREFIX="${RUNNER_WORKSPACE}/install-antimony" \ | |
| ${ANT_DEPENDENCIES_INSTALL_PREFIX} \ | |
| -DWITH_QTANTIMONY=${{ matrix.platform.build_qt_antimony }} \ | |
| -DWITH_GTEST=ON \ | |
| -DWITH_PYTHON=${{ matrix.platform.build_python }} \ | |
| "${EXTRA_CMAKE_ARGS[@]}" | |
| - name: Build and install Antimony | |
| shell: bash | |
| run: | | |
| cd ${RUNNER_WORKSPACE}/build-antimony | |
| cmake --build . --target install --config ${{ matrix.platform.build_type }} | |
| - name: Run Antimony tests | |
| if : matrix.platform.build_type == 'Release' | |
| shell: bash | |
| run: | | |
| cd ${RUNNER_WORKSPACE}/build-antimony | |
| ctest -C ${{ matrix.platform.build_type }} --output-on-failure --verbose --extra-verbose --progress | |
| # Valgrind is Linux-only (no Windows support, weak/no Apple Silicon | |
| # support), so this only runs on one leg of the matrix rather than | |
| # across every platform/config combination. See MEMORYCHECK_* in the | |
| # root CMakeLists.txt and valgrind.supp for the suppressions file. | |
| # | |
| # This runs automatically on every push/PR, against the release build | |
| # (which has -g added just for this leg -- see "Configure CMake for | |
| # Antimony" above -- so it's still symbol-rich) so it's much faster | |
| # than a full debug-build run and still gives usable stack traces, at | |
| # the cost of somewhat less precise line numbers due to optimization | |
| # (inlining etc.), and a small risk that -O3 could eliminate a | |
| # provably-dead allocation an unoptimized debug build wouldn't. | |
| # | |
| # For a slower but fully accurate debug-build memcheck run (e.g. to | |
| # dig into something this one flagged), trigger | |
| # .github/workflows/valgrind-debug-memcheck.yml manually from the | |
| # Actions tab -- see the comment at the top of that file for why it's | |
| # a separate workflow rather than another leg here. | |
| # | |
| # `ctest -T memcheck` only prints a per-test defect *count* to the | |
| # console -- the actual valgrind report (stack traces, "definitely | |
| # lost" byte counts, etc.) goes to a per-test log file instead: | |
| # Testing/Temporary/MemoryChecker.<test-id>.log, one per test. Rather | |
| # than running every test as one opaque block and only finding out | |
| # what broke at the very end, run them in numbered chunks (via | |
| # `ctest -I <start>,<end>`) and print any defects from each chunk | |
| # immediately after it finishes, so problems surface within minutes | |
| # rather than at the end of the whole run. | |
| - name: Run Antimony tests under valgrind (memcheck), in chunks | |
| if : matrix.platform.name == 'ubuntu-latest-release' | |
| shell: bash | |
| run: | | |
| cd ${RUNNER_WORKSPACE}/build-antimony | |
| chunk_size=20 | |
| total=$(ctest -N -C ${{ matrix.platform.build_type }} | grep "Total Tests:" | awk '{print $NF}') | |
| echo "Running $total tests under valgrind, $chunk_size at a time" | |
| overall_exit=0 | |
| start=1 | |
| while [ "$start" -le "$total" ]; do | |
| end=$((start + chunk_size - 1)) | |
| if [ "$end" -gt "$total" ]; then | |
| end=$total | |
| fi | |
| echo "::group::Running tests $start-$end of $total under valgrind" | |
| ctest -T memcheck -C ${{ matrix.platform.build_type }} -I ${start},${end} --output-on-failure || overall_exit=1 | |
| echo "::endgroup::" | |
| found_any=0 | |
| for i in $(seq $start $end); do | |
| f="Testing/Temporary/MemoryChecker.$i.log" | |
| [ -f "$f" ] || continue | |
| if grep -qE "ERROR SUMMARY: [1-9]|(definitely|indirectly|possibly) lost: [1-9]|still reachable: [1-9]" "$f"; then | |
| found_any=1 | |
| echo "::group::Valgrind defect: $f" | |
| cat "$f" | |
| echo "::endgroup::" | |
| fi | |
| done | |
| if [ "$found_any" -eq 0 ]; then | |
| echo "No valgrind defects in tests $start-$end." | |
| fi | |
| start=$((end + 1)) | |
| done | |
| exit $overall_exit | |
| - name: Upload memcheck logs | |
| if: always() | |
| uses: actions/upload-artifact@main | |
| with: | |
| name: valgrind-release-memcheck-logs | |
| path: ${{ runner.workspace }}/build-antimony/Testing/Temporary/ | |
| - name: Set artifacts path and name | |
| shell: bash | |
| run: | | |
| cd ${RUNNER_WORKSPACE} | |
| echo "artifacts_name=antimony-${{ matrix.platform.name }}" >> "${GITHUB_ENV}" | |
| # we need to use relative path as actions/upload-artifact@v1 cannot find it on containerized runners | |
| echo "artifacts_path=${RUNNER_WORKSPACE}/install-antimony" >> "${GITHUB_ENV}" | |
| - name: Upload Antimony binaries | |
| uses: actions/upload-artifact@main | |
| with: | |
| name: ${{env.artifacts_name}} | |
| path: ${{env.artifacts_path}} | |
| - name: Create Python wheel artifacts | |
| if: matrix.platform.build_type == 'Release' && matrix.platform.build_python == 'ON' | |
| shell: bash | |
| run: | | |
| cd ${RUNNER_WORKSPACE}/install-antimony/bindings/python | |
| if [ "${{ matrix.platform.os_type }}" == 'windows' ]; then | |
| ${{env.python_exe}} -m pip install setuptools wheel | |
| ${{env.python_exe}} setup.py bdist_wheel | |
| elif [ "${{ matrix.platform.os_type }}" == 'manylinux' ]; then | |
| python${{ matrix.python_version }} -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org setuptools wheel | |
| python${{ matrix.python_version }} setup.py bdist_wheel | |
| else | |
| python${{ matrix.python_version }} -m pip install setuptools wheel | |
| python${{ matrix.python_version }} setup.py bdist_wheel | |
| fi | |
| - name: Rename Python wheel artifacts | |
| if: matrix.platform.build_type == 'Release' && matrix.platform.build_python == 'ON' | |
| shell: bash | |
| run: | | |
| cd ${RUNNER_WORKSPACE}/install-antimony/bindings/python/dist | |
| if [ "${{ matrix.platform.os_type }}" == 'macos' ]; then | |
| mv antimony*.whl $(echo antimony*.whl | sed "s/universal2/${host_architecture}/g") | |
| elif [ "${{ matrix.platform.os_type }}" == 'manylinux' ]; then | |
| mv antimony*.whl $(echo antimony*.whl | sed "s/linux/manylinux_2_28/g") | |
| elif [ "${{ matrix.platform.os_type }}" == 'ubuntu' ]; then | |
| mv antimony*.whl $(echo antimony*.whl | sed "s/linux/ubuntu/g") | |
| fi | |
| python_version_number=$(echo "${{ matrix.python_version }}" | tr -d '.') | |
| mv antimony*.whl $(echo antimony*.whl | sed "s/cp${python_version_number}-cp${python_version_number}/py3-none/g") | |
| - name: Set Python wheel artifacts path and name | |
| if: matrix.platform.build_type == 'Release' && matrix.platform.build_python == 'ON' | |
| shell: bash | |
| run: | | |
| cd ${RUNNER_WORKSPACE} | |
| python_wheel_file_name=$(ls install-antimony/bindings/python/dist | grep '^antimony') | |
| echo "python_wheel_artifacts_name=${python_wheel_file_name}" >> "${GITHUB_ENV}" | |
| echo "python_wheel_artifacts_file=${RUNNER_WORKSPACE}/install-antimony/bindings/python/dist/$python_wheel_file_name" >> "${GITHUB_ENV}" | |
| - name: Upload Python wheel artifacts | |
| if: matrix.platform.build_type == 'Release' && matrix.platform.build_python == 'ON' | |
| uses: actions/upload-artifact@main | |
| with: | |
| name: ${{env.python_wheel_artifacts_name}} | |
| path: ${{env.python_wheel_artifacts_file}} |