Skip to content

Add CI that runs things through valgrind. #226

Add CI that runs things through valgrind.

Add CI that runs things through valgrind. #226

Workflow file for this run

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}}