NEURON: add v7.8.2, move to CMake and remove all old versions (#20582)

* Update NEURON simulator package
  - update recipe to support autoconf as well as cmake
  - new versions >=7.8 support cmake
  - remove old variants
  - added patch for latest bug fix release 7.8.2

Co-authored-by: Kumbhar Pramod Shivaji <kumbhar@bbpv1.epfl.ch>
Co-authored-by: Kumbhar Pramod Shivaji <kumbhar@bb-c02vf1h0hv2r.epfl.ch>
This commit is contained in:
Pramod Kumbhar 2021-01-19 09:42:50 +01:00 committed by GitHub
parent a92bb5400e
commit 908528f2f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 234 additions and 157 deletions

View file

@ -3,185 +3,123 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
from spack import * from spack import *
class Neuron(Package): class Neuron(CMakePackage):
"""NEURON is a simulation environment for single and networks of neurons. """NEURON is a simulation environment for single and networks of neurons.
NEURON is a simulation environment for modeling individual and networks of NEURON is a simulation environment for modeling individual and networks of
neurons. NEURON models individual neurons via the use of sections that are neurons. NEURON models individual neurons via the use of sections that are
automatically subdivided into individual compartments, instead of automatically subdivided into individual compartments, instead of
requiring the user to manually create compartments. The primary scripting requiring the user to manually create compartments.
language is hoc but a Python interface is also available.
""" """
homepage = "https://www.neuron.yale.edu/" homepage = "https://www.neuron.yale.edu/"
url = "http://www.neuron.yale.edu/ftp/neuron/versions/v7.5/nrn-7.5.tar.gz" url = "https://neuron.yale.edu/ftp/neuron/versions/v7.7/nrn-7.7.tar.gz"
git = "https://github.com/nrnhines/nrn.git" git = "https://github.com/neuronsimulator/nrn"
maintainers = ['pramodk', 'nrnhines', 'iomaganaris', 'alexsavulescu']
version('develop', branch='master') version('develop', branch='master', submodules='True')
version('7.5', sha256='67642216a969fdc844da1bd56643edeed5e9f9ab8c2a3049dcbcbcccba29c336') version("7.8.2", tag="7.8.2", submodules='True')
version('7.4', sha256='1403ba16b2b329d2376f4bf007d96e6bf2992fa850f137f1068ad5b22b432de6') version("7.8.1", tag="7.8.1", submodules='True')
version('7.3', sha256='71cff5962966c5cd5d685d90569598a17b4b579d342126b31e2d431128cc8832')
version('7.2', sha256='c777d73a58ff17a073e8ea25f140cb603b8b5f0df3c361388af7175e44d85b0e')
variant('mpi', default=True, description='Enable MPI parallelism') variant("coreneuron", default=False, description="Enable CoreNEURON as submodule")
variant('python', default=True, description='Enable python') variant("cross-compile", default=False, description="Build for cross-compile environment")
variant('shared', default=False, description='Build shared libraries') variant("interviews", default=False, description="Enable GUI with INTERVIEWS")
variant('cross-compile', default=False, description='Build for cross-compile environment') variant("legacy-unit", default=False, description="Enable legacy units")
variant('multisend', default=True, description="Enable multi-send spike exchange") variant("mpi", default=True, description="Enable MPI parallelism")
variant('rx3d', default=False, description="Enable cython translated 3-d rxd") variant("python", default=True, description="Enable python")
variant("rx3d", default=False, description="Enable cython translated 3-d rxd")
variant("tests", default=False, description="Enable unit tests")
depends_on('flex', type='build') depends_on("bison", type="build")
depends_on('bison', type='build') depends_on("flex", type="build")
depends_on('automake', type='build') depends_on("py-cython", when="+rx3d", type="build")
depends_on('automake', type='build')
depends_on('autoconf', type='build')
depends_on('libtool', type='build')
depends_on('pkgconfig', type='build')
depends_on('mpi', when='+mpi') depends_on("gettext")
depends_on('python@2.6:', when='+python') depends_on("mpi", when="+mpi")
depends_on('ncurses', when='~cross-compile') depends_on("ncurses")
depends_on("python@2.7:", when="+python")
depends_on("py-pytest", when="+python+tests")
depends_on("readline")
conflicts('~shared', when='+python') conflicts("+rx3d", when="~python")
filter_compiler_wrappers('*/bin/nrniv_makefile') patch("patch-v782-git-cmake-avx512.patch", when="@7.8.2")
def get_neuron_archdir(self): def cmake_args(self):
"""Determine the architecture-specific neuron base directory. spec = self.spec
Instead of recreating the logic of the neuron's configure def cmake_options(spec_options):
we dynamically find the architecture-specific directory by value = "TRUE" if spec_options in spec else "FALSE"
looking for a specific binary. cmake_name = spec_options[1:].upper().replace("-", "_")
""" return "-DNRN_ENABLE_" + cmake_name + ":BOOL=" + value
file_list = find(self.prefix, '*/bin/nrniv_makefile')
# check needed as when initially evaluated the prefix is empty args = [cmake_options(variant) for variant in ["+coreneuron",
if file_list: "+interviews",
neuron_archdir = os.path.dirname(os.path.dirname(file_list[0])) "+mpi",
"+python",
"+rx3d",
"+coreneuron",
"+tests"]]
args.append("-DNRN_ENABLE_BINARY_SPECIAL=ON")
if "~mpi" in spec and '+coreneuron' in spec:
args.append("-DCORENRN_ENABLE_MPI=OFF")
if "+python" in spec:
args.append("-DPYTHON_EXECUTABLE:FILEPATH="
+ spec["python"].command.path)
if spec.variants['build_type'].value == 'Debug':
args.append("-DCMAKE_C_FLAGS=-g -O0")
args.append("-DCMAKE_CXX_FLAGS=-g -O0")
args.append("-DCMAKE_BUILD_TYPE=Custom")
if "+legacy-unit" in spec:
args.append('-DNRN_DYNAMIC_UNITS_USE_LEGACY=ON')
return args
@run_after("install")
def filter_compilers(self):
"""run after install to avoid spack compiler wrappers
getting embded into nrnivmodl script"""
spec = self.spec
if "cray" in spec.architecture:
cc_compiler = "cc"
cxx_compiler = "CC"
elif spec.satisfies("+mpi"):
cc_compiler = spec["mpi"].mpicc
cxx_compiler = spec["mpi"].mpicxx
else: else:
neuron_archdir = self.prefix cc_compiler = self.compiler.cc
cxx_compiler = self.compiler.cxx
return neuron_archdir kwargs = {"backup": False, "string": True}
nrnmech_makefile = join_path(self.prefix,
"./bin/nrnmech_makefile")
def patch(self): assign_operator = "?="
# aclocal need complete include path (especially on os x) filter_file("CC {0} {1}".format(assign_operator, env["CC"]),
pkgconf_inc = '-I %s/share/aclocal/' % (self.spec['pkgconfig'].prefix) "CC = {0}".format(cc_compiler),
libtool_inc = '-I %s/share/aclocal/' % (self.spec['libtool'].prefix) nrnmech_makefile,
newpath = 'aclocal -I m4 %s %s' % (pkgconf_inc, libtool_inc) **kwargs)
filter_file(r'aclocal -I m4', r'%s' % newpath, "build.sh") filter_file("CXX {0} {1}".format(assign_operator, env["CXX"]),
"CXX = {0}".format(cxx_compiler),
nrnmech_makefile,
**kwargs)
def get_arch_options(self, spec): if spec.satisfies("+coreneuron"):
options = [] corenrn_makefile = join_path(self.prefix,
"share/coreneuron/nrnivmodl_core_makefile")
if spec.satisfies('+cross-compile'): filter_file(env["CXX"], cxx_compiler, corenrn_makefile, **kwargs)
options.extend(['cross_compiling=yes',
'--without-memacs',
'--without-nmodl'])
# on os-x disable building carbon 'click' utility
if 'darwin' in self.spec.architecture:
options.append('macdarwin=no')
return options
def get_python_options(self, spec):
options = []
if spec.satisfies('+python'):
python_exec = spec['python'].command.path
py_inc = spec['python'].headers.directories[0]
py_lib = spec['python'].prefix.lib
if not os.path.isdir(py_lib):
py_lib = spec['python'].prefix.lib64
options.extend(['--with-nrnpython=%s' % python_exec,
'--disable-pysetup',
'PYINCDIR=%s' % py_inc,
'PYLIBDIR=%s' % py_lib])
if spec.satisfies('~cross-compile'):
options.append('PYTHON_BLD=%s' % python_exec)
else:
options.append('--without-nrnpython')
return options
def get_compiler_options(self, spec):
flags = '-O2 -g'
if self.spec.satisfies('%pgi'):
flags += ' ' + self.compiler.cc_pic_flag
return ['CFLAGS=%s' % flags,
'CXXFLAGS=%s' % flags]
def build_nmodl(self, spec, prefix):
# build components for front-end arch in cross compiling environment
options = ['--prefix=%s' % prefix,
'--with-nmodl-only',
'--without-x']
if 'cray' in self.spec.architecture:
flags = '-target-cpu=x86_64 -target-network=none'
options.extend(['CFLAGS=%s' % flags,
'CXXFLAGS=%s' % flags])
configure = Executable(join_path(self.stage.source_path, 'configure'))
configure(*options)
make()
make('install')
def install(self, spec, prefix):
options = ['--prefix=%s' % prefix,
'--without-iv',
'--without-x',
'--without-readline']
if spec.satisfies('+multisend'):
options.append('--with-multisend')
if spec.satisfies('~rx3d'):
options.append('--disable-rx3d')
if spec.satisfies('+mpi'):
options.extend(['MPICC=%s' % spec['mpi'].mpicc,
'MPICXX=%s' % spec['mpi'].mpicxx,
'--with-paranrn'])
else:
options.append('--without-paranrn')
if spec.satisfies('~shared'):
options.extend(['--disable-shared',
'linux_nrnmech=no'])
options.extend(self.get_arch_options(spec))
options.extend(self.get_python_options(spec))
options.extend(self.get_compiler_options(spec))
build = Executable('./build.sh')
build()
with working_dir('build', create=True):
if spec.satisfies('+cross-compile'):
self.build_nmodl(spec, prefix)
srcpath = self.stage.source_path
configure = Executable(join_path(srcpath, 'configure'))
configure(*options)
make('VERBOSE=1')
make('install')
def setup_run_environment(self, env): def setup_run_environment(self, env):
neuron_archdir = self.get_neuron_archdir() env.prepend_path("PATH", join_path(self.prefix, "bin"))
env.prepend_path('PATH', join_path(neuron_archdir, 'bin')) env.prepend_path("LD_LIBRARY_PATH", join_path(self.prefix, "lib"))
env.prepend_path('LD_LIBRARY_PATH', join_path(neuron_archdir, 'lib')) if self.spec.satisfies("+python"):
env.prepend_path("PYTHONPATH", self.spec.prefix.lib.python)
def setup_dependent_build_environment(self, env, dependent_spec):
neuron_archdir = self.get_neuron_archdir()
env.prepend_path('PATH', join_path(neuron_archdir, 'bin'))
env.prepend_path('LD_LIBRARY_PATH', join_path(neuron_archdir, 'lib'))

View file

@ -0,0 +1,139 @@
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 391d4daa..20b8b571 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -98,7 +98,7 @@ Currently we have enabled CMake code formatting using [cmake-format](https://git
* Make sure to install cmake-format utility with Python version you are using:
```
-pip3.7 install cmake-format==0.6.0 --user
+pip3.7 install cmake-format==0.6.0 pyyaml --user
```
Now you should have `cmake-format` command available.
diff --git a/cmake/ExternalProjectHelper.cmake b/cmake/ExternalProjectHelper.cmake
index 57094e7e..eeb6dfc2 100644
--- a/cmake/ExternalProjectHelper.cmake
+++ b/cmake/ExternalProjectHelper.cmake
@@ -1,5 +1,15 @@
find_package(Git QUIET)
+if(${GIT_FOUND} AND EXISTS ${CMAKE_SOURCE_DIR}/.git)
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} --git-dir=.git describe --all
+ RESULT_VARIABLE NOT_A_GIT_REPO
+ ERROR_QUIET
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
+else()
+ set(NOT_A_GIT_REPO "NotAGitRepo")
+endif()
+
# initialize submodule with given path
function(initialize_submodule path)
if(NOT ${GIT_FOUND})
@@ -9,7 +19,7 @@ function(initialize_submodule path)
message(STATUS "Sub-module : missing ${path} : running git submodule update --init --recursive")
execute_process(
COMMAND
- git submodule update --init --recursive -- ${path}
+ ${GIT_EXECUTABLE} submodule update --init --recursive -- ${path}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
endfunction()
@@ -20,6 +30,9 @@ function(add_external_project name)
NAMES CMakeLists.txt
PATHS "${PROJECT_SOURCE_DIR}/external/${name}")
if(NOT EXISTS ${${name}_PATH})
+ if(NOT_A_GIT_REPO)
+ message(FATAL_ERROR "Looks like you are building from source. Git needed for ${name} feature.")
+ endif()
initialize_submodule(external/${name})
else()
message(STATUS "Sub-project : using ${name} from from external/${name}")
diff --git a/git2nrnversion_h.sh b/git2nrnversion_h.sh
index d62b7410..4d8e4015 100755
--- a/git2nrnversion_h.sh
+++ b/git2nrnversion_h.sh
@@ -20,10 +20,9 @@ if git log > /dev/null && test -d .git ; then
elif test -f src/nrnoc/nrnversion.h ; then
sed -n '1,$p' src/nrnoc/nrnversion.h
else
- echo "#define GIT_DATE \"1999-12-31\""
- echo "#define GIT_BRANCH \"?\""
- echo "#define GIT_CHANGESET \"?\""
- echo "#define GIT_DESCRIBE \"?\""
- exit 1
+ echo "#define GIT_DATE \"Build Time: $(date "+%Y-%m-%d-%H:%M:%S")\""
+ echo "#define GIT_BRANCH \"unknown branch\""
+ echo "#define GIT_CHANGESET \"unknown commit id\""
+ echo "#define GIT_DESCRIBE \"${PROJECT_VERSION}.dev0\""
fi
diff --git a/src/ivoc/ivocvect.cpp b/src/ivoc/ivocvect.cpp
index 4884614a..4da9e17e 100644
--- a/src/ivoc/ivocvect.cpp
+++ b/src/ivoc/ivocvect.cpp
@@ -67,7 +67,26 @@ extern "C" {
#define FRead(arg1,arg2,arg3,arg4) if (fread(arg1,arg2,arg3,arg4) != arg3) {}
#endif
-static double dmaxint_;
+/**
+ * As all parameters are passed from hoc as double, we need
+ * to calculate max integer that can fit into double variable.
+ *
+ * With IEEE 64-bit double has 52 bits of mantissa, so it's 2^53.
+ * calculating it with approach `while (dbl + 1 != dbl) dbl++;`
+ * has issues with SSE and other 32 bits platform. So we are using
+ * direct value here.
+ *
+ * The maximum mantissa 0xFFFFFFFFFFFFF which is 52 bits all 1.
+ * In Python it's:
+ *
+ * >>> (2.**53).hex()
+ * '0x1.0000000000000p+53'
+ * >>> (2.**53)
+ * 9007199254740992.0
+ *
+ * See https://stackoverflow.com/questions/1848700/biggest-integer-that-can-be-stored-in-a-double
+ */
+static double dmaxint_ = 9007199254740992;
// Definitions allow machine independent write and read
// note that must include BYTEHEADER at head of routine
@@ -3776,20 +3795,7 @@ static void steer_x(void* v) {
}
void Vector_reg() {
- dmaxint_ = 1073741824.;
- for(;;) {
- if (dmaxint_*2. == double(int(dmaxint_*2.))) {
- dmaxint_ *= 2.;
- }else{
- if (dmaxint_*2. - 1. == double(int(dmaxint_*2. - 1.))) {
- dmaxint_ = 2.*dmaxint_ - 1.;
- }
- break;
- }
- }
- //printf("dmaxint=%30.20g %d\n", dmaxint_, (long)dmaxint_);
- class2oc("Vector", v_cons, v_destruct, v_members, NULL, v_retobj_members,
- v_retstr_members);
+ class2oc("Vector", v_cons, v_destruct, v_members, NULL, v_retobj_members, v_retstr_members);
svec_ = hoc_lookup("Vector");
// now make the x variable an actual double
Symbol* sv = hoc_lookup("Vector");
diff --git a/src/nrniv/CMakeLists.txt b/src/nrniv/CMakeLists.txt
index 30024d6e..26f76a98 100644
--- a/src/nrniv/CMakeLists.txt
+++ b/src/nrniv/CMakeLists.txt
@@ -139,7 +139,8 @@ set(NRN_INCLUDE_DIRS
# is different from the contents of nrnversion.h
# ~~~
add_custom_target(
- nrnversion_h ${PROJECT_SOURCE_DIR}/git2nrnversion_h.sh ${PROJECT_SOURCE_DIR} > nrnversion.h.tmp
+ nrnversion_h
+ COMMAND ${CMAKE_COMMAND} -E env PROJECT_VERSION=${PROJECT_VERSION} $ENV{SHELL} ${PROJECT_SOURCE_DIR}/git2nrnversion_h.sh ${PROJECT_SOURCE_DIR} > nrnversion.h.tmp
COMMAND ${CMAKE_COMMAND} -E copy_if_different nrnversion.h.tmp ${NRN_NRNOC_SRC_DIR}/nrnversion.h
DEPENDS ${PROJECT_SOURCE_DIR}/git2nrnversion_h.sh)