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)
import os
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 modeling individual and networks of
neurons. NEURON models individual neurons via the use of sections that are
automatically subdivided into individual compartments, instead of
requiring the user to manually create compartments. The primary scripting
language is hoc but a Python interface is also available.
requiring the user to manually create compartments.
"""
homepage = "https://www.neuron.yale.edu/"
url = "http://www.neuron.yale.edu/ftp/neuron/versions/v7.5/nrn-7.5.tar.gz"
git = "https://github.com/nrnhines/nrn.git"
url = "https://neuron.yale.edu/ftp/neuron/versions/v7.7/nrn-7.7.tar.gz"
git = "https://github.com/neuronsimulator/nrn"
maintainers = ['pramodk', 'nrnhines', 'iomaganaris', 'alexsavulescu']
version('develop', branch='master')
version('7.5', sha256='67642216a969fdc844da1bd56643edeed5e9f9ab8c2a3049dcbcbcccba29c336')
version('7.4', sha256='1403ba16b2b329d2376f4bf007d96e6bf2992fa850f137f1068ad5b22b432de6')
version('7.3', sha256='71cff5962966c5cd5d685d90569598a17b4b579d342126b31e2d431128cc8832')
version('7.2', sha256='c777d73a58ff17a073e8ea25f140cb603b8b5f0df3c361388af7175e44d85b0e')
version('develop', branch='master', submodules='True')
version("7.8.2", tag="7.8.2", submodules='True')
version("7.8.1", tag="7.8.1", submodules='True')
variant('mpi', default=True, description='Enable MPI parallelism')
variant('python', default=True, description='Enable python')
variant('shared', default=False, description='Build shared libraries')
variant('cross-compile', default=False, description='Build for cross-compile environment')
variant('multisend', default=True, description="Enable multi-send spike exchange")
variant('rx3d', default=False, description="Enable cython translated 3-d rxd")
variant("coreneuron", default=False, description="Enable CoreNEURON as submodule")
variant("cross-compile", default=False, description="Build for cross-compile environment")
variant("interviews", default=False, description="Enable GUI with INTERVIEWS")
variant("legacy-unit", default=False, description="Enable legacy units")
variant("mpi", default=True, description="Enable MPI parallelism")
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('automake', type='build')
depends_on('automake', type='build')
depends_on('autoconf', type='build')
depends_on('libtool', type='build')
depends_on('pkgconfig', type='build')
depends_on("bison", type="build")
depends_on("flex", type="build")
depends_on("py-cython", when="+rx3d", type="build")
depends_on('mpi', when='+mpi')
depends_on('python@2.6:', when='+python')
depends_on('ncurses', when='~cross-compile')
depends_on("gettext")
depends_on("mpi", when="+mpi")
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):
"""Determine the architecture-specific neuron base directory.
def cmake_args(self):
spec = self.spec
Instead of recreating the logic of the neuron's configure
we dynamically find the architecture-specific directory by
looking for a specific binary.
"""
file_list = find(self.prefix, '*/bin/nrniv_makefile')
# check needed as when initially evaluated the prefix is empty
if file_list:
neuron_archdir = os.path.dirname(os.path.dirname(file_list[0]))
def cmake_options(spec_options):
value = "TRUE" if spec_options in spec else "FALSE"
cmake_name = spec_options[1:].upper().replace("-", "_")
return "-DNRN_ENABLE_" + cmake_name + ":BOOL=" + value
args = [cmake_options(variant) for variant in ["+coreneuron",
"+interviews",
"+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:
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):
# aclocal need complete include path (especially on os x)
pkgconf_inc = '-I %s/share/aclocal/' % (self.spec['pkgconfig'].prefix)
libtool_inc = '-I %s/share/aclocal/' % (self.spec['libtool'].prefix)
newpath = 'aclocal -I m4 %s %s' % (pkgconf_inc, libtool_inc)
filter_file(r'aclocal -I m4', r'%s' % newpath, "build.sh")
assign_operator = "?="
filter_file("CC {0} {1}".format(assign_operator, env["CC"]),
"CC = {0}".format(cc_compiler),
nrnmech_makefile,
**kwargs)
filter_file("CXX {0} {1}".format(assign_operator, env["CXX"]),
"CXX = {0}".format(cxx_compiler),
nrnmech_makefile,
**kwargs)
def get_arch_options(self, spec):
options = []
if spec.satisfies('+cross-compile'):
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')
if spec.satisfies("+coreneuron"):
corenrn_makefile = join_path(self.prefix,
"share/coreneuron/nrnivmodl_core_makefile")
filter_file(env["CXX"], cxx_compiler, corenrn_makefile, **kwargs)
def setup_run_environment(self, env):
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'))
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'))
env.prepend_path("PATH", join_path(self.prefix, "bin"))
env.prepend_path("LD_LIBRARY_PATH", join_path(self.prefix, "lib"))
if self.spec.satisfies("+python"):
env.prepend_path("PYTHONPATH", self.spec.prefix.lib.python)

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)