Skip to content
This repository was archived by the owner on Mar 20, 2023. It is now read-only.

Commit 6215225

Browse files
authored
Configure sanitizers in CMake, fix issues (#823)
* Use sanitizer helpers from hpc-coding-conventions. * Integrate sanitizer-specific configuration into CMake configuration so less external magic is needed. * Add ASan and UBSan jobs to the GitHub Actions CI. LSan is not currently enabled because of MPI. * Add problem matchers to GitHub Actions CI so that compiler warnings and sanitizer issues are flagged. * Drop two redundant macOS GitHub Actions CI jobs. * Use ccache in GitHub Actions CI. * Add UBSan exclusion file. * Do not pass -undefined dynamic_lookup to vanilla Clang. * Fix signed/unsigned comparison compiler warnings. * Fix struct/class mismatch compiler warnings. * stdindex2ptr: fix bugs when nrn_sav_rhs is too far away from _data in memory. * Fix __restrict__ violation in sprintf.
1 parent 2375eb8 commit 6215225

32 files changed

+253
-108
lines changed

.github/problem-matchers/address.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
{
3+
"problemMatcher": [
4+
{
5+
"owner": "asan-problem-matcher",
6+
"severity": "warning",
7+
"pattern": [
8+
{
9+
"regexp": "^.*AddressSanitizer: (.*)$",
10+
"message": 1
11+
}
12+
]
13+
}
14+
]
15+
}

.github/problem-matchers/gcc.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"__comment": "Taken from vscode-cpptools's Extension/package.json gcc rule",
3+
"problemMatcher": [
4+
{
5+
"owner": "gcc-problem-matcher",
6+
"pattern": [
7+
{
8+
"regexp": "^\\.\\./(.*):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
9+
"file": 1,
10+
"line": 2,
11+
"column": 3,
12+
"severity": 4,
13+
"message": 5
14+
}
15+
]
16+
}
17+
]
18+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"problemMatcher": [
3+
{
4+
"owner": "ubsan-problem-matcher",
5+
"severity": "warning",
6+
"pattern": [
7+
{
8+
"regexp": "^.*\\/(src\\/.*):(\\d+):(\\d+): runtime error: (.*)$",
9+
"file": 1,
10+
"line": 2,
11+
"column": 3,
12+
"message": 4
13+
},
14+
{
15+
"regexp": "^.*UndefinedBehaviorSanitizer:.*$"
16+
}
17+
]
18+
}
19+
]
20+
}

.github/workflows/coreneuron-ci.yml

Lines changed: 112 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ on:
1616

1717
env:
1818
BUILD_TYPE: Release
19-
DEVELOPER_DIR: /Applications/Xcode_11.3.1.app/Contents/Developer
2019
DEFAULT_PY_VERSION: 3.8
20+
MACOSX_DEPLOYMENT_TARGET: 11.0
2121

2222
jobs:
2323
ci:
@@ -26,22 +26,34 @@ jobs:
2626
name: ${{ matrix.os }} - ${{ toJson(matrix.config) }})
2727

2828
env:
29-
INSTALL_DIR: install
3029
SDK_ROOT: $(xcrun --sdk macosx --show-sdk-path)
3130

3231
strategy:
3332
matrix:
34-
os: [ ubuntu-20.04, macOS-10.15 ]
33+
os: [ubuntu-20.04, macOS-11]
3534
config:
3635
# Defaults: CORENRN_ENABLE_MPI=ON
37-
- {cmake_option: "-DCORENRN_ENABLE_MPI=ON -DCORENRN_ENABLE_DEBUG_CODE=ON", documentation: ON}
38-
- {cmake_option: "-DCORENRN_ENABLE_MPI_DYNAMIC=ON"}
36+
- {cmake_option: "-DCORENRN_ENABLE_MPI_DYNAMIC=ON", flag_warnings: ON}
3937
- {cmake_option: "-DCORENRN_ENABLE_MPI_DYNAMIC=ON -DCORENRN_ENABLE_SHARED=OFF"}
4038
- {cmake_option: "-DCORENRN_ENABLE_MPI=OFF"}
4139
- {use_nmodl: ON, py_version: 3.6.7}
4240
- {use_nmodl: ON}
4341
- {use_ispc: ON, py_version: 3.6.7}
44-
- {gcc_version: 9}
42+
include:
43+
- os: ubuntu-20.04
44+
config:
45+
gcc_version: 10
46+
- os: ubuntu-20.04
47+
config:
48+
cmake_option: -DCORENRN_ENABLE_DEBUG_CODE=ON
49+
documentation: ON
50+
- os: ubuntu-22.04
51+
config:
52+
sanitizer: address
53+
- os: ubuntu-22.04
54+
config:
55+
flag_warnings: ON
56+
sanitizer: undefined
4557
fail-fast: false
4658

4759
steps:
@@ -50,29 +62,31 @@ jobs:
5062
if: startsWith(matrix.os, 'macOS')
5163
run: |
5264
brew update
53-
brew install coreutils bison flex boost openmpi
65+
brew install bison boost ccache coreutils flex ninja openmpi
66+
echo /usr/local/opt/flex/bin:/usr/local/opt/bison/bin >> $GITHUB_PATH
5467
shell: bash
5568

5669
- name: Install apt packages
5770
if: startsWith(matrix.os, 'ubuntu')
5871
run: |
59-
sudo apt-get install doxygen bison flex libboost-all-dev libopenmpi-dev openmpi-bin python3-dev python3-pip libfl-dev
72+
sudo apt-get install bison ccache doxygen flex libboost-all-dev \
73+
libfl-dev libopenmpi-dev ninja-build openmpi-bin
6074
shell: bash
6175

6276
- name: Install specific apt packages
6377
if: startsWith(matrix.os, 'ubuntu') && matrix.config.gcc_version
6478
run: |
65-
sudo apt-get install g++-${GCC_VERSION}
79+
sudo apt-get install gcc-${{matrix.config.gcc_version}}
80+
echo CC="gcc-${{matrix.config.gcc_version}}" >> $GITHUB_ENV
81+
echo CXX="g++-${{matrix.config.gcc_version}}" >> $GITHUB_ENV
6682
shell: bash
67-
env:
68-
GCC_VERSION: ${{ matrix.config.gcc_version }}
6983

7084
- name: Set up Python3
7185
uses: actions/setup-python@v3
7286
with:
7387
python-version: ${{ env.PYTHON_VERSION }}
7488
env:
75-
PYTHON_VERSION: ${{ matrix.config.py_version || env.DEFAULT_PY_VERSION }}
89+
PYTHON_VERSION: ${{matrix.config.py_version || env.DEFAULT_PY_VERSION}}
7690

7791
- name: Install ISPC
7892
if: ${{ matrix.config.use_ispc == 'ON' }}
@@ -89,56 +103,116 @@ jobs:
89103
url="https://github.com/ispc/ispc/releases/download/${ispc_version}/ispc-${ispc_version}${ispc_version_suffix}-${url_os}.tar.gz";
90104
wget -O ispc.tar.gz $url;
91105
mkdir ispc && tar -xvzf ispc.tar.gz -C ispc --strip 1;
106+
92107
- name: Install NMODL dependencies
93108
if: ${{ matrix.config.use_nmodl == 'ON' || matrix.config.use_ispc == 'ON' }}
94109
run: |
95110
python3 -m pip install --upgrade pip jinja2 pyyaml pytest sympy
96111
97112
- uses: actions/checkout@v3
98113

99-
- name: Install Python3 documentation dependencies
100-
if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.config.documentation == 'ON' }}
114+
- name: Install documentation dependencies
115+
if: ${{matrix.config.documentation == 'ON'}}
101116
working-directory: ${{runner.workspace}}/CoreNeuron
102117
run: |
118+
sudo apt-get install doxygen
103119
python3 -m pip install --upgrade pip
104120
python3 -m pip install --upgrade -r docs/docs_requirements.txt
105121
122+
- name: Register compiler warning problem matcher
123+
if: ${{matrix.config.flag_warnings == 'ON'}}
124+
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
125+
126+
- name: Register sanitizer problem matcher
127+
if: ${{matrix.config.sanitizer}}
128+
run: echo "::add-matcher::.github/problem-matchers/${{matrix.config.sanitizer}}.json"
129+
130+
- name: Hash config dictionary
131+
run: |
132+
cat << EOF > matrix.json
133+
${{toJSON(matrix.config)}}
134+
EOF
135+
echo matrix.config JSON:
136+
cat matrix.json
137+
echo -----
138+
139+
- name: Restore compiler cache
140+
uses: pat-s/always-upload-cache@v3
141+
with:
142+
path: |
143+
${{runner.workspace}}/ccache
144+
key: ${{matrix.os}}-${{hashfiles('matrix.json')}}-${{github.ref}}-${{github.sha}}
145+
restore-keys: |
146+
${{matrix.os}}-${{hashfiles('matrix.json')}}-${{github.ref}}-
147+
${{matrix.os}}-${{hashfiles('matrix.json')}}-
148+
106149
- name: Build and Test
107150
id: build-test
108151
shell: bash
109152
working-directory: ${{runner.workspace}}/CoreNeuron
110153
run: |
111-
if [ -n "$GCC_VERSION" ]; then
112-
export CXX="g++-${GCC_VERSION}" CC="gcc-${GCC_VERSION}";
113-
fi
114-
115-
openmp=" -DCORENRN_ENABLE_OPENMP=ON"
154+
cmake_args=(${{matrix.config.cmake_option}})
116155
if [[ "${{ startsWith(matrix.os, 'macOS') }}" = "true" ]]; then
117-
export PATH=/usr/local/opt/flex/bin:/usr/local/opt/bison/bin:$PATH;
118-
export CXX=g++;
119-
export CC=gcc;
120-
openmp=" -DCORENRN_ENABLE_OPENMP=OFF";
156+
cmake_args+=(-DCORENRN_ENABLE_OPENMP=OFF)
157+
else
158+
cmake_args+=(-DCORENRN_ENABLE_OPENMP=ON)
159+
fi
160+
161+
if [[ "${{matrix.config.flag_warnings}}" == "ON" ]]; then
162+
cmake_args+=(-DCORENRN_EXTRA_CXX_FLAGS="-Wall")
163+
fi
164+
165+
if [[ -n "${{matrix.config.sanitizer}}" ]]; then
166+
CC=$(command -v clang-14)
167+
CXX=$(command -v clang++-14)
168+
symbolizer_path=$(realpath $(command -v llvm-symbolizer-14))
169+
cmake_args+=(-DCMAKE_BUILD_TYPE=Custom \
170+
-DCMAKE_C_FLAGS="-O1 -g -Wno-writable-strings" \
171+
-DCMAKE_CXX_FLAGS="-O1 -g -Wno-writable-strings" \
172+
-DLLVM_SYMBOLIZER_PATH="${symbolizer_path}" \
173+
-DCORENRN_SANITIZERS=$(echo ${{matrix.config.sanitizer}} | sed -e 's/-/,/g'))
174+
else
175+
CC=${CC:-gcc}
176+
CXX=${CXX:-g++}
121177
fi
122178
123179
echo "------- Build, Test and Install -------"
124180
mkdir build && cd build
125181
if [[ "$USE_ISPC" == "ON" ]]; then
126-
cmake ${openmp} -DCORENRN_ENABLE_ISPC=ON -DCMAKE_ISPC_COMPILER=${{runner.workspace}}/ispc/bin/ispc -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR -DPYTHON_EXECUTABLE=$(which python3) ..;
182+
cmake_args+=(-DCORENRN_ENABLE_ISPC=ON -DCMAKE_ISPC_COMPILER=${{runner.workspace}}/ispc/bin/ispc)
127183
elif [[ "$USE_NMODL" == "ON" ]]; then
128-
cmake ${openmp} -DCORENRN_ENABLE_NMODL=ON -DCORENRN_NMODL_FLAGS="sympy --analytic" -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR -DPYTHON_EXECUTABLE=$(which python3) ..;
129-
else
130-
cmake ${cmake_option} ${openmp} -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR -DPYTHON_EXECUTABLE=$(which python3) ..;
184+
cmake_args+=(-DCORENRN_ENABLE_NMODL=ON "-DCORENRN_NMODL_FLAGS=sympy --analytic")
185+
fi
186+
cmake .. -G Ninja "${cmake_args[@]}" \
187+
-DCMAKE_C_COMPILER="${CC}" \
188+
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
189+
-DCMAKE_CXX_COMPILER="${CXX}" \
190+
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
191+
"-DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/install" \
192+
-DPYTHON_EXECUTABLE=$(command -v python3)
193+
if ccache --version | grep -E '^ccache version 4\.(4|4\.1)$'
194+
then
195+
echo "------- Disable ccache direct mode -------"
196+
# https://github.com/ccache/ccache/issues/935
197+
export CCACHE_NODIRECT=1
131198
fi
132-
make
133-
ctest --output-on-failure
134-
make install
199+
ccache -z
200+
# Older versions don't support -v (verbose)
201+
ccache -vs 2>/dev/null || ccache -s
202+
cmake --build . --parallel
203+
ccache -vs 2>/dev/null || ccache -s
204+
ctest -T Test --output-on-failure
205+
cmake --build . --target install
135206
env:
136-
cmake_option: ${{ matrix.config.cmake_option }}
137-
USE_ISPC: ${{ matrix.config.use_ispc }}
138-
USE_NMODL: ${{ matrix.config.use_nmodl }}
139-
INSTALL_DIR: ${{ runner.workspace }}/install
140-
GCC_VERSION: ${{ matrix.config.gcc_version }}
141-
PYTHON_VERSION: ${{ matrix.config.py_version || env.DEFAULT_PY_VERSION }}
207+
CCACHE_BASEDIR: ${{runner.workspace}}/CoreNeuron
208+
CCACHE_DIR: ${{runner.workspace}}/ccache
209+
USE_ISPC: ${{matrix.config.use_ispc}}
210+
USE_NMODL: ${{matrix.config.use_nmodl}}
211+
212+
- uses: actions/upload-artifact@v3
213+
with:
214+
name: ctest-results-${{hashfiles('matrix.json')}}-sanitizer
215+
path: ${{runner.workspace}}/CoreNeuron/build/Testing/*/Test.xml
142216

143217
# This step will set up an SSH connection on tmate.io for live debugging.
144218
# To enable it, you have to:
@@ -151,11 +225,10 @@ jobs:
151225
- name: Documentation
152226
if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.config.documentation == 'ON' }}
153227
id: documentation
154-
working-directory: ${{runner.workspace}}/CoreNeuron
228+
working-directory: ${{runner.workspace}}/CoreNeuron/build
155229
run: |
156230
echo "------- Build Doxygen Documentation -------";
157-
pushd build;
158-
make docs;
231+
cmake --build . --target docs
159232
echo "-------- Disable jekyll --------";
160233
pushd docs;
161234
touch .nojekyll;

.sanitizers/undefined.supp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
unsigned-integer-overflow:_philox4x32bumpkey(r123array2x32)

CMake/AddCLI11Submodule.cmake

Lines changed: 0 additions & 27 deletions
This file was deleted.

CMake/MakefileBuildOptions.cmake

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ endif()
4848
# ~~~
4949
list(REMOVE_ITEM CORENRN_LINK_LIBS "Threads::Threads")
5050

51+
string(JOIN " " CORENRN_COMMON_LDFLAGS ${CORENRN_EXTRA_LINK_FLAGS})
52+
if(CORENRN_SANITIZER_LIBRARY_DIR)
53+
string(APPEND CORENRN_COMMON_LDFLAGS " -Wl,-rpath,${CORENRN_SANITIZER_LIBRARY_DIR}")
54+
endif()
55+
string(JOIN " " CORENRN_SANITIZER_ENABLE_ENVIRONMENT_STRING ${CORENRN_SANITIZER_ENABLE_ENVIRONMENT})
56+
5157
# replicate CMake magic to transform system libs to -l<libname>
5258
foreach(link_lib ${CORENRN_LINK_LIBS})
5359
if(${link_lib} MATCHES "\-l.*")
@@ -82,7 +88,8 @@ string(
8288
${CXX14_STD_FLAGS}
8389
${NVHPC_ACC_COMP_FLAGS}
8490
${NVHPC_CXX_INLINE_FLAGS}
85-
${CORENRN_COMPILE_DEF_FLAGS})
91+
${CORENRN_COMPILE_DEF_FLAGS}
92+
${CORENRN_EXTRA_MECH_CXX_FLAGS})
8693

8794
# =============================================================================
8895
# nmodl/mod2c related options : TODO

CMake/config/CompilerFlagsHelpers.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ endforeach()
147147
# ===============================================================================
148148
# Allow undefined reference in shared library as mod files will be linked later
149149
# ===============================================================================
150-
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
150+
if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang" OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
151151
set(UNDEFINED_SYMBOLS_IGNORE_FLAG "-undefined dynamic_lookup")
152152
string(APPEND CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS " ${UNDEFINED_SYMBOLS_IGNORE_FLAG}")
153153
string(APPEND CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS " ${UNDEFINED_SYMBOLS_IGNORE_FLAG}")

0 commit comments

Comments
 (0)