[IGNORE] Backport #3093 #9150
This file contains 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: NEURON CI | |
concurrency: | |
group: ${{ github.workflow }}#${{ github.ref }} | |
cancel-in-progress: true | |
on: | |
push: | |
branches: | |
- master | |
- release/** | |
pull_request: | |
branches: | |
- master | |
- release/** | |
# TODO : https://github.com/neuronsimulator/nrn/issues/1063 | |
# paths-ignore: | |
# - '**.md' | |
# - '**.rst' | |
# - 'docs/**' | |
env: | |
BUILD_TYPE: Release | |
DESIRED_CMAKE_VERSION: 3.15.0 | |
PY_MIN_VERSION: '3.7' | |
PY_MAX_VERSION: '3.11' | |
jobs: | |
ci: | |
runs-on: ${{ matrix.os }} | |
name: ${{ matrix.os }} - ${{ matrix.config.build_mode }} (${{ matrix.config.cmake_option }}${{ matrix.config.config_options }}${{ matrix.config.matrix_eval }}) | |
timeout-minutes: 45 | |
env: | |
INSTALL_DIR: install | |
SDK_ROOT: $(xcrun --sdk macosx --show-sdk-path) | |
SKIP_WHEELHOUSE_REPAIR: true | |
BUILD_TYPE: Release | |
DESIRED_CMAKE_VERSION: 3.15.0 | |
PY_MIN_VERSION: ${{ matrix.config.python_min_version || '3.8' }} | |
PY_MAX_VERSION: ${{ matrix.config.python_max_version || '3.11' }} | |
MUSIC_INSTALL_DIR: /opt/MUSIC | |
strategy: | |
matrix: | |
os: [ macOS-12, ubuntu-20.04] | |
config: | |
- { matrix_eval : "CC=gcc-9 CXX=g++-9", build_mode: "setuptools"} | |
- { matrix_eval : "CC=gcc-8 CXX=g++-8", build_mode: "cmake", music: ON} | |
- { matrix_eval : "CC=gcc-9 CXX=g++-9", build_mode: "cmake", python_dynamic: ON} | |
- { matrix_eval : "CC=gcc-7 CXX=g++-7" , build_mode: "cmake", cmake_option: "-DNRN_ENABLE_CORENEURON=ON"} | |
- { matrix_eval : "CC=gcc-7 CXX=g++-7", build_mode: "cmake", cmake_option: "-DNRN_ENABLE_MPI=OFF -DNRN_ENABLE_INTERVIEWS=OFF -DNRN_ENABLE_CORENEURON=ON"} | |
- { matrix_eval : "CC=gcc-10 CXX=g++-10", build_mode: "cmake", cmake_option: "-DNRN_ENABLE_PYTHON=OFF -DNRN_ENABLE_RX3D=OFF -DNRN_ENABLE_CORENEURON=ON"} | |
include: | |
- os: ubuntu-22.04 | |
config: | |
build_mode: cmake | |
# TODO: -DCORENRN_ENABLE_NMODL=ON -DNMODL_SANITIZERS=undefined | |
cmake_option: -DNRN_ENABLE_CORENEURON=ON | |
-DNRN_ENABLE_INTERVIEWS=OFF -DCORENRN_SANITIZERS=undefined | |
flag_warnings: ON | |
sanitizer: undefined | |
- os: ubuntu-22.04 | |
config: | |
build_mode: cmake | |
# TODO: -DCORENRN_ENABLE_NMODL=ON -DNMODL_SANITIZERS=address,leak | |
# TODO: CoreNEURON is only LeakSanitizer-clean if we disable MPI | |
cmake_option: -DNRN_ENABLE_CORENEURON=ON | |
-DNRN_ENABLE_INTERVIEWS=OFF -DCORENRN_SANITIZERS=address | |
# TODO: address-leak is the dream, but there are many problems, | |
# including external ones from the MPI implementations | |
sanitizer: address | |
fail-fast: false | |
steps: | |
- name: Setup cmake | |
uses: jwlawson/actions-setup-cmake@v2 | |
with: | |
cmake-version: ${{ env.DESIRED_CMAKE_VERSION }} | |
- name: Fix kernel mmap rnd bits | |
if: ${{matrix.os == 'ubuntu-22.04'}} | |
# Asan in llvm 14 provided in ubuntu 22.04 is incompatible with | |
# high-entropy ASLR in much newer kernels that GitHub runners are | |
# using leading to random crashes: https://reviews.llvm.org/D148280 | |
run: sudo sysctl vm.mmap_rnd_bits=28 | |
- name: Install homebrew packages | |
if: startsWith(matrix.os, 'macOS') | |
run: | | |
brew install ccache coreutils doxygen flex mpich ninja xz autoconf autoconf automake libtool | |
brew unlink mpich | |
brew install openmpi | |
brew install --cask xquartz | |
echo /usr/local/opt/flex/bin >> $GITHUB_PATH | |
# Core https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources | |
echo CMAKE_BUILD_PARALLEL_LEVEL=3 >> $GITHUB_ENV | |
echo CTEST_PARALLEL_LEVEL=3 >> $GITHUB_ENV | |
echo CI_OS_NAME=osx >> $GITHUB_ENV | |
shell: bash | |
- name: Install apt packages | |
if: startsWith(matrix.os, 'ubuntu') | |
run: | | |
sudo apt-get install build-essential ccache libopenmpi-dev \ | |
libmpich-dev libx11-dev libxcomposite-dev mpich ninja-build \ | |
openmpi-bin patchelf | |
# The sanitizer builds use ubuntu 22.04 | |
if [[ "${{matrix.os}}" == "ubuntu-20.04" ]]; then | |
sudo apt-get install g++-7 g++-8 | |
fi | |
# Core https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources | |
echo CMAKE_BUILD_PARALLEL_LEVEL=2 >> $GITHUB_ENV | |
echo CTEST_PARALLEL_LEVEL=2 >> $GITHUB_ENV | |
echo CI_OS_NAME=linux >> $GITHUB_ENV | |
shell: bash | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 2 | |
- name: Set up Python@${{ env.PY_MIN_VERSION }} | |
if: ${{matrix.config.python_dynamic == 'ON'}} | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ env.PY_MIN_VERSION }} | |
- name: Install Python@${{ env.PY_MIN_VERSION }} dependencies | |
if: ${{ matrix.config.python_dynamic == 'ON' }} | |
working-directory: ${{runner.workspace}}/nrn | |
run: | | |
python -m pip install --upgrade pip -r nrn_requirements.txt | |
- name: Set up Python@${{ env.PY_MAX_VERSION }} | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ env.PY_MAX_VERSION }} | |
- name: Install Python@${{ env.PY_MAX_VERSION }} dependencies | |
working-directory: ${{runner.workspace}}/nrn | |
run: | | |
python -m pip install --upgrade pip -r nrn_requirements.txt | |
- name: Setup MUSIC | |
if: matrix.config.music == 'ON' | |
run: | | |
python3 -m venv music-venv | |
source music-venv/bin/activate | |
python3 -m pip install mpi4py "cython<3" "numpy<2" | |
sudo mkdir -p $MUSIC_INSTALL_DIR | |
sudo chown -R $USER $MUSIC_INSTALL_DIR | |
# Stable build: https://github.com/INCF/MUSIC/archive/refs/heads/switch-to-MPI-C-interface.zip @ f33b66ea9348888eed1761738ab48c23ffc8a0d0 | |
curl -L -o MUSIC.zip https://codeload.github.com/INCF/MUSIC/zip/f33b66ea9348888eed1761738ab48c23ffc8a0d0 | |
unzip MUSIC.zip && mv MUSIC-* MUSIC && cd MUSIC | |
./autogen.sh | |
# workaround for MUSIC on MacOS 12 | |
if [[ "${{matrix.os}}" == "macOS-12" ]]; then | |
MPI_CXXFLAGS="-g" MPI_CFLAGS="-g" MPI_LDFLAGS="-g" CC=mpicc CXX=mpicxx ./configure --with-python-sys-prefix --prefix=$MUSIC_INSTALL_DIR --disable-anysource | |
else | |
./configure --with-python-sys-prefix --prefix=$MUSIC_INSTALL_DIR --disable-anysource | |
fi | |
make -j install | |
deactivate | |
working-directory: ${{runner.temp}} | |
- name: Register gcc problem matcher | |
if: ${{matrix.config.flag_warnings == 'ON'}} | |
run: echo "::add-matcher::.github/problem-matchers/gcc.json" | |
- name: Register sanitizer problem matcher | |
if: ${{matrix.config.sanitizer}} | |
run: echo "::add-matcher::.github/problem-matchers/${{matrix.config.sanitizer}}.json" | |
- name: Hash config dictionary | |
run: | | |
cat << EOF > matrix.json | |
${{toJSON(matrix.config)}} | |
EOF | |
echo matrix.config JSON: | |
cat matrix.json | |
echo ----- | |
- name: Restore compiler cache | |
uses: actions/cache@v4 | |
with: | |
path: ${{runner.workspace}}/ccache | |
save-always: true | |
key: ${{matrix.os}}-${{hashfiles('matrix.json')}}-${{github.ref}}-${{github.sha}} | |
restore-keys: | | |
${{matrix.os}}-${{hashfiles('matrix.json')}}-${{github.ref}}- | |
${{matrix.os}}-${{hashfiles('matrix.json')}}- | |
- name: Build and Test | |
id: build-test | |
shell: bash | |
working-directory: ${{runner.workspace}}/nrn | |
run: | | |
# OS related | |
if [ "$RUNNER_OS" == "Linux" ]; then | |
export ${MATRIX_EVAL}; | |
export SHELL="/bin/bash" | |
else | |
export CXX=${CXX:-g++}; | |
export CC=${CC:-gcc}; | |
fi | |
if [ "$RUNNER_OS" == "macOS" ]; then | |
# TODO - this is a workaround that was implemented for Azure being reported as getting stuck. | |
# However it does not get stuck: neuron module not found and script goes to interpreter, seeming stuck. | |
# This needs to be addressed and SKIP_EMBEDED_PYTHON_TEST logic removed everywhere. | |
export SKIP_EMBEDED_PYTHON_TEST="true" | |
fi | |
# Python setup | |
export PYTHONPATH=$PYTHONPATH:$INSTALL_DIR/lib/python/ | |
# Python setup | |
export PYTHON_MIN=$(command -v $PYTHON_MIN_NAME); | |
export PYTHON_MAX=$(command -v $PYTHON_MAX_NAME); | |
export PYTHON=$PYTHON_MAX | |
if [ "$RUNNER_OS" == "macOS" ]; then | |
# Python is not installed as a framework, so we need to writ 'backend: TkAgg' to `matplotlibrc`. | |
# Since we are in a virtual environment, we cannot use `$HOME/matplotlibrc` | |
# The following solution is generic and relies on `matplotlib.__file__` to know where to append backend setup. | |
$PYTHON -c "import os,matplotlib; f =open(os.path.join(os.path.dirname(matplotlib.__file__), 'mpl-data/matplotlibrc'),'a'); f.write('backend: TkAgg');f.close();" | |
fi; | |
# Some logging | |
echo $LANG | |
echo $LC_ALL | |
python3 -c 'import os,sys; os.set_blocking(sys.stdout.fileno(), True)' | |
cmake --version | |
# different builds with CMake | |
if [[ "$BUILD_MODE" == "cmake" ]]; then | |
cmake_args=(-G Ninja) | |
# Sanitizer-specific setup | |
if [[ -n "${{matrix.config.sanitizer}}" ]]; then | |
CC=$(command -v clang-14) | |
CXX=$(command -v clang++-14) | |
symbolizer_path=$(realpath $(command -v llvm-symbolizer-14)) | |
echo symbolizer_path=${symbolizer_path} | |
cmake_args+=(-DCMAKE_BUILD_TYPE=Custom \ | |
-DCMAKE_C_FLAGS="-O1 -g -Wno-writable-strings" \ | |
-DCMAKE_CXX_FLAGS="-O1 -g -Wno-writable-strings" \ | |
-DLLVM_SYMBOLIZER_PATH="${symbolizer_path}" \ | |
-DNRN_SANITIZERS=$(echo ${{matrix.config.sanitizer}} | sed -e 's/-/,/g')) | |
fi | |
cmake_args+=(-DCMAKE_C_COMPILER="${CC}" \ | |
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ | |
-DCMAKE_CXX_COMPILER="${CXX}" \ | |
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ | |
-DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ | |
-DNRN_ENABLE_TESTS=ON \ | |
${{matrix.config.cmake_option}}) | |
if [[ "$NRN_ENABLE_PYTHON_DYNAMIC" == "ON" ]]; then | |
cmake_args+=(-DNRN_ENABLE_PYTHON=ON \ | |
-DNRN_ENABLE_PYTHON_DYNAMIC=ON \ | |
-DNRN_PYTHON_DYNAMIC="${PYTHON_MIN};${PYTHON_MAX}" \ | |
-DNRN_ENABLE_CORENEURON=ON) | |
else | |
cmake_args+=(-DPYTHON_EXECUTABLE="${PYTHON}") | |
fi | |
if [[ "$NRN_ENABLE_MUSIC" == "ON" ]]; then | |
cmake_args+=(-DNRN_ENABLE_MUSIC=ON \ | |
-DCMAKE_PREFIX_PATH=${MUSIC_INSTALL_DIR} \ | |
-DMUSIC_ROOT=${MUSIC_INSTALL_DIR}) | |
fi | |
# Enable more warnings in the builds whose compiler warnings we | |
# highlight in the GitHub UI | |
if [[ "${{matrix.config.flag_warnings}}" == "ON" ]]; then | |
cmake_args+=(-DNRN_EXTRA_CXX_FLAGS="-Wall \ | |
-Wno-char-subscripts \ | |
-Wno-unknown-pragmas \ | |
-Wno-unused-variable \ | |
-Wno-unused-function \ | |
-Wno-unused-but-set-variable \ | |
-Wno-reorder \ | |
-Wno-sign-compare \ | |
-Wno-strict-aliasing \ | |
-Wno-missing-braces \ | |
-Wno-mismatched-tags" \ | |
-DNRN_EXTRA_MECH_CXX_FLAGS="") | |
fi | |
mkdir build && cd build | |
echo "Building with: ${cmake_args[@]}" | |
cmake .. "${cmake_args[@]}" | |
if ccache --version | grep -E '^ccache version 4\.(4|4\.1)$' | |
then | |
echo "------- Disable ccache direct mode -------" | |
# https://github.com/ccache/ccache/issues/935 | |
export CCACHE_NODIRECT=1 | |
fi | |
ccache -z | |
# Older versions don't support -v (verbose) | |
ccache -vs 2>/dev/null || ccache -s | |
cmake --build . --parallel | |
ccache -vs 2>/dev/null || ccache -s | |
if [ "$RUNNER_OS" == "macOS" ] | |
then | |
echo $'[install]\nprefix='>src/nrnpython/setup.cfg; | |
fi | |
if [[ "$NRN_ENABLE_PYTHON_DYNAMIC" == "ON" ]]; then | |
echo "--RUNNING BASIC TESTS FROM BUILD DIR--" | |
for python in "${PYTHON_MIN}" "${PYTHON_MAX}" | |
do | |
echo "Using ${python}" | |
NEURONHOME="${PWD}/share/nrn" \ | |
PYTHONPATH="${PWD}/lib/python" \ | |
PATH="${PWD}/bin" \ | |
LD_LIBRARY_PATH="${PWD}/lib:${LD_LIBRARY_PATH}" \ | |
DYLD_LIBRARY_PATH="${PWD}/lib:${DYLD_LIBRARY_PATH}" \ | |
"${python}" -c "from neuron import h; import neuron; neuron.test()" | |
done | |
fi | |
ctest --output-on-failure | |
cmake --build . --target install | |
export PATH="${INSTALL_DIR}/bin:${PATH}" | |
if [[ -f "${INSTALL_DIR}/bin/nrn-enable-sanitizer" ]]; then | |
echo --- bin/nrn-enable-sanitizer --- | |
cat bin/nrn-enable-sanitizer | |
echo --- | |
nrn_enable_sanitizer=${INSTALL_DIR}/bin/nrn-enable-sanitizer | |
nrn_enable_sanitizer_preload="${nrn_enable_sanitizer} --preload" | |
else | |
echo nrn-enable-sanitizer not found, not using it | |
fi | |
elif [[ "$BUILD_MODE" == "setuptools" ]]; then | |
./packaging/python/build_wheels.bash CI; | |
fi; | |
# basic test for cmake when python is not disabled | |
if [[ "$BUILD_MODE" == "cmake" && ! "${cmake_args[*]}" =~ "NRN_ENABLE_PYTHON=OFF" ]]; then | |
$PYTHON --version && ${nrn_enable_sanitizer_preload} $PYTHON -c 'import neuron; neuron.test()' | |
fi; | |
# test neurondemo with cmake | |
if [[ "$BUILD_MODE" != "setuptools" ]]; then | |
${nrn_enable_sanitizer} neurondemo -nogui -c 'demo(4)' -c 'run()' -c 'quit()' | |
fi; | |
# with cmake dynamic check python_min and python_max together | |
if [[ "$BUILD_MODE" == "cmake" && "$NRN_ENABLE_PYTHON_DYNAMIC" == "ON" ]]; then | |
${nrn_enable_sanitizer_preload} $PYTHON_MAX -c 'import neuron; neuron.test()' | |
${nrn_enable_sanitizer_preload} $PYTHON_MIN -c 'import neuron; neuron.test()' | |
fi; | |
# run rxd tests manually if rxd is enabled *and CoreNEURON is | |
# disabled -- otherwise hh-related tests fail | |
if [[ "$BUILD_MODE" == "cmake" \ | |
&& ! "${cmake_args[*]}" =~ "NRN_ENABLE_RX3D=OFF" \ | |
&& ! "${cmake_args[*]}" =~ "NRN_ENABLE_CORENEURON=ON" ]]; then | |
${nrn_enable_sanitizer_preload} $PYTHON ../share/lib/python/neuron/rxdtests/run_all.py | |
fi; | |
if [ "$BUILD_MODE" == "setuptools" ]; then | |
neuron_wheel=wheelhouse/NEURON*.whl; | |
# test with virtual environment | |
${nrn_enable_sanitizer_preload} ./packaging/python/test_wheels.sh $PYTHON $neuron_wheel | |
# test with global installation | |
${nrn_enable_sanitizer_preload} ./packaging/python/test_wheels.sh $PYTHON $neuron_wheel false | |
fi; | |
env: | |
BUILD_MODE: ${{ matrix.config.build_mode }} | |
CCACHE_BASEDIR: ${{runner.workspace}}/nrn | |
CCACHE_DIR: ${{runner.workspace}}/ccache | |
NRN_ENABLE_PYTHON_DYNAMIC : ${{ matrix.config.python_dynamic }} | |
NRN_ENABLE_MUSIC: ${{ matrix.config.music }} | |
PYTHON_MIN_NAME: "python${{ env.PY_MIN_VERSION }}" | |
PYTHON_MAX_NAME: "python${{ env.PY_MAX_VERSION }}" | |
INSTALL_DIR : ${{ runner.workspace }}/install | |
MATRIX_EVAL: ${{ matrix.config.matrix_eval }} | |
# This step will set up an SSH connection on tmate.io for live debugging. | |
# To enable it, you have to: | |
# * add 'live-debug-ci' to your PR title | |
# * push something to your PR branch (note that just re-running the pipeline disregards the title update) | |
- name: live debug session on failure (manual steps required, check `.github/neuron-ci.yml`) | |
if: failure() && contains(github.event.pull_request.title, 'live-debug-ci') | |
uses: mxschmitt/action-tmate@v3 | |
# see https://github.com/orgs/community/discussions/26822 | |
final: | |
name: Final CI | |
needs: [ci] | |
if: ${{ always() }} | |
runs-on: ubuntu-latest | |
steps: | |
- name: Check ci matrix all done | |
if: >- | |
${{ | |
contains(needs.*.result, 'failure') | |
|| contains(needs.*.result, 'cancelled') | |
|| contains(needs.*.result, 'skipped') | |
}} | |
run: exit 1 |