Skip to content

Commit 9c36354

Browse files
authored
Merge pull request #3333 from neuronsimulator/jelic/clean-nmodl-merge
Bring NMODL transpiler under NEURON
2 parents 23a4a0f + 709ab85 commit 9c36354

File tree

536 files changed

+80896
-51
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

536 files changed

+80896
-51
lines changed

.bbp-project.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ tools:
99
ClangFormat:
1010
enable: True
1111
version: == 12.0.1
12+
exclude:
13+
match:
14+
- src/nmodl/language/templates/*
1215
CMakeFormat:
1316
enable: True
1417
version: == 0.6.13
18+
exclude:
19+
match:
20+
- src/nmodl/language/templates/*
21+
- test/nmodl/usecases/*/*

.github/workflows/coverage.yml

-7
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,6 @@ jobs:
7979
with:
8080
fetch-depth: 2
8181

82-
- name: Clone nmodl
83-
working-directory: ${{runner.workspace}}/nrn
84-
run: |
85-
git submodule update --init --recursive --force --depth 1 -- external/nmodl
86-
8782
- name: Set up Python@${{ env.PY_MIN_VERSION }}
8883
uses: actions/setup-python@v5
8984
with:
@@ -92,7 +87,6 @@ jobs:
9287
- name: Install Python@${{ env.PY_MIN_VERSION }} dependencies
9388
working-directory: ${{runner.workspace}}/nrn
9489
run: |
95-
python -m pip install --upgrade -r external/nmodl/requirements.txt
9690
python -m pip install --upgrade -r ci_requirements.txt
9791
python -m pip install --upgrade pip -r nrn_requirements.txt
9892
@@ -109,7 +103,6 @@ jobs:
109103
- name: Install Python@${{ env.PY_MAX_VERSION }} dependencies
110104
working-directory: ${{runner.workspace}}/nrn
111105
run: |
112-
python -m pip install --upgrade -r external/nmodl/requirements.txt
113106
python -m pip install --upgrade -r ci_requirements.txt
114107
python -m pip install --upgrade pip -r nrn_requirements.txt
115108

.github/workflows/neuron-ci.yml

-7
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,6 @@ jobs:
159159
with:
160160
fetch-depth: 2
161161

162-
- name: Clone nmodl
163-
working-directory: ${{runner.workspace}}/nrn
164-
run: |
165-
git submodule update --init --recursive --force --depth 1 -- external/nmodl
166-
167162
- name: Set up Python@${{ env.PY_MIN_VERSION }}
168163
if: ${{matrix.config.python_dynamic == 'ON'}}
169164
uses: actions/setup-python@v5
@@ -174,7 +169,6 @@ jobs:
174169
if: ${{ matrix.config.python_dynamic == 'ON' }}
175170
working-directory: ${{runner.workspace}}/nrn
176171
run: |
177-
python -m pip install --upgrade -r external/nmodl/requirements.txt
178172
python -m pip install --upgrade -r ci_requirements.txt
179173
python -m pip install --upgrade pip -r nrn_requirements.txt
180174
@@ -186,7 +180,6 @@ jobs:
186180
- name: Install Python@${{ env.PY_MAX_VERSION }} dependencies
187181
working-directory: ${{runner.workspace}}/nrn
188182
run: |
189-
python -m pip install --upgrade -r external/nmodl/requirements.txt
190183
python -m pip install --upgrade -r ci_requirements.txt
191184
python -m pip install --upgrade pip -r nrn_requirements.txt
192185

.gitmodules

+9-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
[submodule "external/Random123"]
1717
path = external/Random123
1818
url = https://github.com/BlueBrain/Random123.git
19-
[submodule "external/nmodl"]
20-
path = external/nmodl
21-
url = https://github.com/BlueBrain/nmodl
2219
[submodule "external/CLI11"]
2320
path = external/CLI11
2421
url = https://github.com/CLIUtils/CLI11.git
@@ -31,3 +28,12 @@
3128
[submodule "external/fmt"]
3229
path = external/fmt
3330
url = https://github.com/fmtlib/fmt
31+
[submodule "external/pybind11"]
32+
path = external/pybind11
33+
url = https://github.com/pybind/pybind11.git
34+
[submodule "external/json"]
35+
path = external/json
36+
url = https://github.com/nlohmann/json.git
37+
[submodule "external/spdlog"]
38+
path = external/spdlog
39+
url = https://github.com/gabime/spdlog.git

CMakeLists.txt

+48-4
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,15 @@ set(NRN_PROFILER
209209
"${NRN_PROFILER_DEFAULT}"
210210
CACHE STRING "Set which profiler to build against ('caliper', 'likwid')")
211211

212+
# =============================================================================
213+
# Build options for NMODL
214+
# =============================================================================
215+
option(NMODL_ENABLE_PYTHON_BINDINGS "Enable pybind11 based python bindings" ON)
216+
set(NMODL_EXTRA_CXX_FLAGS
217+
""
218+
CACHE STRING "Add extra compile flags for NMODL sources")
219+
separate_arguments(NMODL_EXTRA_CXX_FLAGS)
220+
212221
# =============================================================================
213222
# Include cmake modules
214223
# =============================================================================
@@ -507,22 +516,50 @@ cpp_cc_git_submodule(CLI11 BUILD PACKAGE CLI11 REQUIRED)
507516
# Enable NMODL code-generator support
508517
# =============================================================================
509518
if(NRN_ENABLE_NMODL OR NRN_ENABLE_CORENEURON)
519+
# NMODL Python build dependencies
520+
nrn_find_python_module(MODULE jinja2 REQUIRED)
521+
# N.B. `nrn_find_python_module` uses the _importable_ name of the package to find it, _not_ the
522+
# actual package name. In this case, `pip install pyyaml` actually installs an importable package
523+
# called `yaml`
524+
nrn_find_python_module(MODULE yaml REQUIRED)
525+
526+
# NMODL non-Python build dependencies
527+
cpp_cc_git_submodule(json BUILD PACKAGE nlohmann_json REQUIRED)
528+
cpp_cc_git_submodule(pybind11 BUILD PACKAGE pybind11 REQUIRED)
529+
530+
option(SPDLOG_FMT_EXTERNAL "Force to use an external {{fmt}}" ON)
531+
option(SPDLOG_SYSTEM_INCLUDE "Include spdlog as a system lib" ON)
532+
cpp_cc_git_submodule(spdlog BUILD PACKAGE spdlog REQUIRED)
533+
if(${CODING_CONV_PREFIX}_3RDPARTY_USE_SPDLOG)
534+
# See above, same logic as fmt
535+
set_target_properties(spdlog PROPERTIES POSITION_INDEPENDENT_CODE ON)
536+
endif()
510537

511538
set(NMODL_ENABLE_PYTHON_BINDINGS
512539
OFF
513540
CACHE BOOL "Enable NMODL python bindings")
514-
nrn_add_external_project(nmodl)
541+
542+
include(${PROJECT_SOURCE_DIR}/cmake/nmodl/PythonLinkHelper.cmake)
543+
544+
# where the platform-specific sources are located
545+
set(NMODL_PROJECT_PLATLIB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/nmodl)
546+
set(NMODL_PROJECT_PLATLIB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/src/nmodl)
547+
# where the platform-independent sources are located
548+
set(NMODL_PROJECT_PURELIB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/share/lib/python/neuron/nmodl)
549+
set(NMODL_PROJECT_PURELIB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/lib/python/neuron/nmodl)
550+
551+
add_subdirectory(src/nmodl)
515552
set(CORENRN_NMODL_BINARY ${CMAKE_BINARY_DIR}/bin/nmodl${CMAKE_EXECUTABLE_SUFFIX})
516553
set(NMODL_TARGET_TO_DEPEND nmodl)
517-
set(NMODL_PROJECT_BINARY_DIR ${CMAKE_BINARY_DIR}/external/nmodl)
554+
set(NMODL_PROJECT_PLATLIB_BINARY_DIR ${CMAKE_BINARY_DIR}/src/nmodl)
518555
# install nrnunits.lib and libpywrapper.so from external/nmodl
519556
install(
520-
FILES ${NMODL_PROJECT_BINARY_DIR}/lib/libpywrapper${CMAKE_SHARED_LIBRARY_SUFFIX}
557+
FILES ${NMODL_PROJECT_PLATLIB_BINARY_DIR}/lib/libpywrapper${CMAKE_SHARED_LIBRARY_SUFFIX}
521558
DESTINATION lib
522559
COMPONENT pywrapper
523560
OPTIONAL)
524561
install(
525-
FILES ${NMODL_PROJECT_BINARY_DIR}/share/nmodl/nrnunits.lib
562+
FILES ${NMODL_PROJECT_PLATLIB_BINARY_DIR}/share/nmodl/nrnunits.lib
526563
DESTINATION share/nmodl
527564
COMPONENT nrnunits)
528565

@@ -648,6 +685,13 @@ function(prepend_to_var var new_path)
648685
endfunction()
649686
set(NRN_RUN_FROM_BUILD_DIR_ENV "NEURONHOME=${PROJECT_BINARY_DIR}/share/nrn"
650687
"NRNHOME=${PROJECT_BINARY_DIR}")
688+
689+
# if we do not link against Python, NMODL will complain that some of the env variables are missing
690+
# when building coreNEURON mod files
691+
if(NOT NRN_LINK_AGAINST_PYTHON)
692+
set(NRN_RUN_FROM_BUILD_DIR_ENV "${NRN_RUN_FROM_BUILD_DIR_ENV}" "NMODLHOME=${PROJECT_BINARY_DIR}"
693+
"NMODL_PYLIB=${PYTHON_LIBRARY}")
694+
endif()
651695
prepend_to_var(PATH "${PROJECT_BINARY_DIR}/bin")
652696
if(APPLE)
653697
prepend_to_var(DYLD_LIBRARY_PATH "${PROJECT_BINARY_DIR}/lib")

cmake/CompilerHelper.cmake

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
# Compiler specific settings
33
# =============================================================================
44
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR NRN_MACOS_BUILD)
5-
set(UNDEFINED_SYMBOLS_IGNORE_FLAG "-undefined dynamic_lookup")
5+
set(UNDEFINED_SYMBOLS_IGNORE_FLAG "-Wl,-undefined,dynamic_lookup")
66
string(APPEND CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS " ${UNDEFINED_SYMBOLS_IGNORE_FLAG}")
77
string(APPEND CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS " ${UNDEFINED_SYMBOLS_IGNORE_FLAG}")
88
else()
9-
set(UNDEFINED_SYMBOLS_IGNORE_FLAG "--unresolved-symbols=ignore-all")
9+
set(UNDEFINED_SYMBOLS_IGNORE_FLAG "-Wl,--unresolved-symbols=ignore-all")
1010
endif()
1111

1212
if(CMAKE_C_COMPILER_ID MATCHES "PGI" OR CMAKE_C_COMPILER_ID MATCHES "NVHPC")

cmake/MacroHelper.cmake

+1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ macro(nocmodl_mod_to_cpp modfile_basename modfile_compat)
169169
OUTPUT ${CPPFILE_OUTPUT_PATH}
170170
COMMAND
171171
${CMAKE_COMMAND} -E env "MODLUNIT=${PROJECT_BINARY_DIR}/share/nrn/lib/nrnunits.lib"
172+
"NMODL_PYLIB=${PYTHON_LIBRARY}" "NMODLHOME=${PROJECT_BINARY_DIR}"
172173
${NRN_NOCMODL_SANITIZER_ENVIRONMENT} $<TARGET_FILE:${NRN_CODEGENERATOR_TARGET}>
173174
${MODFILE_OUTPUT_PATH} ${NRN_NMODL_--neuron} -o ${modfile_output_dir}
174175
COMMAND sed ${NOCMODL_SED_EXPR} ${CPPFILE_OUTPUT_PATH} > ${CPPFILE_OUTPUT_PATH}.tmp

cmake/nmodl/ClangTidyHelper.cmake

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
set(ENABLE_CLANG_TIDY
2+
OFF
3+
CACHE BOOL "Add clang-tidy automatically to builds")
4+
if(ENABLE_CLANG_TIDY)
5+
find_program(CLANG_TIDY_EXE NAMES "clang-tidy")
6+
if(CLANG_TIDY_EXE)
7+
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
8+
set(CLANG_TIDY_CHECKS
9+
"-*,modernize-*,readability-*,performance-*,cppcoreguidelines-*,clang-analyzer-core*,google-*"
10+
)
11+
set(CMAKE_CXX_CLANG_TIDY
12+
"${CLANG_TIDY_EXE};-checks=${CLANG_TIDY_CHECKS};-fix;-header-filter='${CMAKE_SOURCE_DIR}/*'"
13+
CACHE STRING "" FORCE)
14+
else()
15+
message(AUTHOR_WARNING "clang-tidy not found!")
16+
set(CMAKE_CXX_CLANG_TIDY
17+
""
18+
CACHE STRING "" FORCE) # delete it
19+
endif()
20+
endif()

cmake/nmodl/CompilerHelper.cmake

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
if(CMAKE_CXX_COMPILER_ID MATCHES "PGI" OR CMAKE_CXX_COMPILER_ID MATCHES "NVHPC")
2+
set(NMODL_PGI_COMPILER TRUE)
3+
4+
# CMake adds standard complaint PGI flag "-A" which breaks compilation of of spdlog and fmt
5+
set(CMAKE_CXX14_STANDARD_COMPILE_OPTION --c++14)
6+
7+
# Avoid errors related to "excessive recursion at instantiation of function ...", Eigen-related
8+
# (in accelerated regions), e.g., transposeInPlace()
9+
list(APPEND NMODL_EXTRA_CXX_FLAGS "-Wc,--pending_instantiations=0")
10+
11+
# ~~~
12+
# PGI enables number of diagnostic messages by default classes which results into thousands of
13+
# messages specifically for AST. Disable these verbose warnings for now.
14+
# TODO : fix these warnings from template modification (#272)
15+
# ~~~
16+
if(${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 20.7)
17+
set(NMODL_COMPILER_WARNING_SUPPRESSIONS --diag_suppress=1,82,111,115,177,186,611,997,1097,1625)
18+
else()
19+
# https://forums.developer.nvidia.com/t/many-all-diagnostic-numbers-increased-by-1-from-previous-values/146268/3
20+
# changed the numbering scheme in newer versions. The following list is from a clean start 13
21+
# August 2021. It would clearly be nicer to apply these suppressions only to relevant files.
22+
# Examples of the suppressed warnings are given below.
23+
# ~~~
24+
# "ext/spdlog/include/spdlog/fmt/fmt.h", warning #1-D: last line of file ends without a newline
25+
# "ext/fmt/include/fmt/format.h", warning #111-D: statement is unreachable
26+
# "ext/fmt/include/fmt/format.h", warning #128-D: loop is not reachable
27+
# "ext/spdlog/include/spdlog/fmt/bundled/format.h", warning #185-D: dynamic initialization in unreachable code
28+
# "ext/json/json.hpp", warning #186-D: pointless comparison of unsigned integer with zero
29+
# "src/ast/all.hpp", warning #998-D: function "..." is hidden by "..." -- virtual function override intended?
30+
# "ext/spdlog/include/spdlog/fmt/bundled/format.h", warning #1098-D: unknown attribute "fallthrough"
31+
# "ext/pybind11/include/pybind11/detail/common.h", warning #1626-D: routine is both "inline" and "noinline"
32+
# "ext/spdlog/include/spdlog/fmt/bundled/core.h", warning #1676-D: unrecognized GCC pragma
33+
# ~~~
34+
# The following warnings do not seem to be suppressible with --diag_suppress:
35+
# ~~~
36+
# "src/codegen/codegen_cuda_visitor.cpp", NVC++-W-0277-Cannot inline function - data type mismatch
37+
# "nvc++IkWUbMugiSgNH.s: Warning: stand-alone `data16' prefix
38+
# ~~~
39+
# The situation may be better once https://github.com/fmtlib/fmt/pull/2582 is included in a
40+
# release.
41+
set(NMODL_COMPILER_WARNING_SUPPRESSIONS --diag_suppress=1,111,128,185,186,998,1098,1626,1676)
42+
# There are a few more warnings produced by the unit test infrastructure.
43+
# ~~~
44+
# "test/unit/visitor/constant_folder.cpp", warning #177-D: variable "..." was declared but never referenced
45+
# ~~~
46+
set(NMODL_TESTS_COMPILER_WARNING_SUPPRESSIONS --diag_suppress=177)
47+
endif()
48+
endif()

cmake/nmodl/Config.cmake.in

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@PACKAGE_INIT@
2+
3+
include("${CMAKE_CURRENT_LIST_DIR}/nmodlTargets.cmake")
4+
5+
set(nmodl_BINARY ${PACKAGE_PREFIX_DIR}/@nmodl_BINARY@)
6+
7+
check_required_components(nmodl)
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
find_package(Git QUIET)
2+
3+
# initialize submodule with given path
4+
function(initialize_submodule path)
5+
if(NOT ${GIT_FOUND})
6+
message(
7+
FATAL_ERROR "git not found and ${path} sub-module not cloned (use git clone --recursive)")
8+
endif()
9+
message(STATUS "Sub-module : missing ${path}: running git submodule update --init")
10+
execute_process(COMMAND git submodule update --init -- ${path}
11+
WORKING_DIRECTORY ${NMODL_PROJECT_PLATLIB_SOURCE_DIR})
12+
endfunction()

cmake/nmodl/FlexHelper.cmake

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Often older version of flex is available in /usr. Even we set PATH for newer flex, CMake will set
2+
# FLEX_INCLUDE_DIRS to /usr/include. This will result in compilation errors. Hence we check for flex
3+
# include directory for the corresponding FLEX_EXECUTABLE. If found, we add that first and then we
4+
# include include path from CMake.
5+
6+
get_filename_component(FLEX_BIN_DIR ${FLEX_EXECUTABLE} DIRECTORY)
7+
8+
if(NOT FLEX_BIN_DIR MATCHES "/usr/bin")
9+
if(NOT FLEX_INCLUDE_PATH)
10+
get_filename_component(FLEX_INCLUDE_PATH ${FLEX_BIN_DIR} PATH)
11+
set(FLEX_INCLUDE_PATH ${FLEX_INCLUDE_PATH}/include/)
12+
endif()
13+
if(EXISTS "${FLEX_INCLUDE_PATH}/FlexLexer.h")
14+
message(STATUS " Adding Flex include path as : ${FLEX_INCLUDE_PATH}")
15+
include_directories(${FLEX_INCLUDE_PATH})
16+
endif()
17+
endif()

cmake/nmodl/GitRevision.cmake

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# For now use simple approach to get version information as git is always avaialble on the machine
2+
# where we are building
3+
4+
find_package(Git)
5+
6+
if(GIT_FOUND)
7+
8+
# get last commit sha1
9+
execute_process(
10+
COMMAND ${GIT_EXECUTABLE} log -1 --format=%h
11+
WORKING_DIRECTORY ${NMODL_PROJECT_PLATLIB_SOURCE_DIR}
12+
OUTPUT_VARIABLE NMODL_GIT_REVISION_SHA1
13+
RESULT_VARIABLE NMODL_GIT_STATUS
14+
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
15+
if(NOT NMODL_GIT_STATUS EQUAL 0)
16+
set(NMODL_GIT_REVISION_SHA1 "git-error")
17+
endif()
18+
19+
# get last commit date
20+
execute_process(
21+
COMMAND ${GIT_EXECUTABLE} show -s --format=%ci
22+
WORKING_DIRECTORY ${NMODL_PROJECT_PLATLIB_SOURCE_DIR}
23+
OUTPUT_VARIABLE NMODL_GIT_REVISION_DATE
24+
RESULT_VARIABLE NMODL_GIT_STATUS
25+
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
26+
if(NOT NMODL_GIT_STATUS EQUAL 0)
27+
set(NMODL_GIT_REVISION_SHA1 "git-error")
28+
endif()
29+
30+
# remove extra double quotes
31+
string(REGEX REPLACE "\"" "" NMODL_GIT_REVISION_DATE "${NMODL_GIT_REVISION_DATE}")
32+
set(NMODL_GIT_REVISION "${NMODL_GIT_REVISION_SHA1} ${NMODL_GIT_REVISION_DATE}")
33+
34+
# get the last version tag from git
35+
execute_process(
36+
COMMAND ${GIT_EXECUTABLE} describe --abbrev=0 --tags
37+
WORKING_DIRECTORY ${NMODL_PROJECT_PLATLIB_SOURCE_DIR}
38+
OUTPUT_VARIABLE NMODL_GIT_LAST_TAG
39+
RESULT_VARIABLE NMODL_GIT_STATUS
40+
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
41+
if(NOT NMODL_GIT_STATUS EQUAL 0)
42+
# Must be a valid version from CMake's perspective.
43+
set(NMODL_GIT_LAST_TAG "0.0")
44+
endif()
45+
else()
46+
set(NMODL_GIT_REVISION "unknown")
47+
# Must be a valid version from CMake's perspective.
48+
set(NMODL_GIT_LAST_TAG "0.0")
49+
endif()

cmake/nmodl/PythonLinkHelper.cmake

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# =============================================================================
2+
# Support for building NMODL without python library
3+
# =============================================================================
4+
# ~~~
5+
# When NMODL is built under environment (e.g. manylinux) without python-dev
6+
# package i.e. libpython.so, we have to build extension and binaries by
7+
# ignoring undefned symbols. The python library will be loaded later on target
8+
# system.
9+
# ~~~
10+
11+
# use same variable name as NEURON as it won't be user option
12+
set(NRN_LINK_AGAINST_PYTHON
13+
TRUE
14+
CACHE BOOL "Disable linking to python library")
15+
16+
mark_as_advanced(NRN_LINK_AGAINST_PYTHON)
17+
18+
if(NOT NRN_LINK_AGAINST_PYTHON)
19+
string(APPEND CMAKE_EXE_LINKER_FLAGS " ${UNDEFINED_SYMBOLS_IGNORE_FLAG}")
20+
set(NMODL_WRAPPER_LIBS pyembed dl)
21+
else()
22+
set(NMODL_WRAPPER_LIBS pyembed pywrapper dl)
23+
endif()

0 commit comments

Comments
 (0)