diff --git a/packages/build-brainscales/package.py b/packages/build-brainscales/package.py
index a162821d8753e6cb8c9dd17e8e5cea7713ea1c03..a919b94921988b4b76bfe16b3cdeef0c47a8c5fb 100644
--- a/packages/build-brainscales/package.py
+++ b/packages/build-brainscales/package.py
@@ -14,6 +14,10 @@ import spack.build_environment
 class BuildBrainscales(WafPackage):
     """Common stuff for BrainScaleS packages..."""
 
+    # waf setup performs git clone and might query gerrit
+    depends_on('git', type=('build', 'link'))
+    depends_on('py-git-review', type=('build', 'link'))
+
     def do_fetch(self, mirror_only=False):
         """Setup the project."""
 
diff --git a/packages/genpybind/package.py b/packages/genpybind/package.py
index a0a631beff14bf1a6eda836c47e88c8874eb7700..fdca20b64b4a7089ec080aca1da4d907dc7ac6a9 100644
--- a/packages/genpybind/package.py
+++ b/packages/genpybind/package.py
@@ -43,8 +43,8 @@ class Genpybind(WafPackage):
     version('ebrains', tag='ebrains_release-1-rc1', git='https://github.com/electronicvisions/genpybind')
 
     depends_on(
-            'llvm+clang+python+visionary@5.0.0: libcxx=none',
-        type=('build', 'link', 'run'))
+            'llvm+clang+python+visionary@5.0.0:',
+        type=('build', 'link'))
     depends_on('binutils', type='build')
     depends_on('python@2.7:', type=('build', 'run'))
 
@@ -52,6 +52,9 @@ class Genpybind(WafPackage):
 
     patch('v0.2.1-python3.10.patch', when='@:0.2.1 ^python@3.10:')
 
+    # llvm-config needs to be found at build time of packages using genpybind
+    def setup_dependent_build_environment(self, env, dependent_spec):
+        env.prepend_path("PATH", self.spec["llvm"].prefix.bin)
 
     def configure_args(self):
         args = super(Genpybind, self).configure_args()
diff --git a/packages/hxtorch/package.py b/packages/hxtorch/package.py
index f9751d98611bb07b3afb9313834ac6a8680ae5d3..b3201623341980353a78d2442a48bf3b9c7a65f0 100644
--- a/packages/hxtorch/package.py
+++ b/packages/hxtorch/package.py
@@ -23,6 +23,7 @@ class Hxtorch(build_brainscales.BuildBrainscales):
 
     maintainers = ['emuller']
 
+    version('8.0-a4',         tag='hxtorch-8.0-a4')
     version('8.0-a3',         tag='hxtorch-8.0-a3')
     version('8.0-a2',         tag='hxtorch-8.0-a2')
     version('8.0-a1',         tag='hxtorch-8.0-a1')
@@ -30,53 +31,57 @@ class Hxtorch(build_brainscales.BuildBrainscales):
     version('7.0-rc1-fixup2', tag='hxtorch-7.0-rc1-fixup2')
     version('7.0-rc1-fixup1', branch='waf')
 
-    # compiler for the BrainScaleS-2 embedded processor ("PPU"); needed for
-    # building/linking, at runtime and for testing
-    depends_on('oppulance@8.0-a3', when='@8.0-a3', type=('build', 'link', 'run', 'test'))
-    depends_on('oppulance@8.0-a2', when='@8.0-a2', type=('build', 'link', 'run', 'test'))
-    depends_on('oppulance@8.0-a1', when='@8.0-a1', type=('build', 'link', 'run', 'test'))
-    depends_on('oppulance@7.0-rc1-fixup3', when='@7.0-rc1-fixup3', type=('build', 'link', 'run', 'test'))
-    depends_on('oppulance@7.0-rc1-fixup2', when='@7.0-rc1-fixup2', type=('build', 'link', 'run', 'test'))
-    depends_on('oppulance@7.0-rc1-fixup1', when='@7.0-rc1-fixup1', type=('build', 'link', 'run', 'test'))
+    deps_hxtorch_core = [
+        # compiler for the BrainScaleS-2 embedded processor ("PPU"); needed for
+        # building/linking, at runtime and for testing
+        ('oppulance@8.0-a4', { "when":'@8.0-a4', "type": ('build', 'link', 'run', 'test') } ),
+        ('oppulance@8.0-a3', { "when":'@8.0-a3', "type": ('build', 'link', 'run', 'test') } ),
+        ('oppulance@8.0-a2', { "when":'@8.0-a2', "type": ('build', 'link', 'run', 'test') } ),
+        ('oppulance@8.0-a1', { "when":'@8.0-a1', "type": ('build', 'link', 'run', 'test') } ),
+        ('oppulance@7.0-rc1-fixup3', { "when":'@7.0-rc1-fixup3', "type": ('build', 'link', 'run', 'test') } ),
+        ('oppulance@7.0-rc1-fixup2', { "when":'@7.0-rc1-fixup2', "type": ('build', 'link', 'run', 'test') } ),
+        ('oppulance@7.0-rc1-fixup1', { "when":'@7.0-rc1-fixup1', "type": ('build', 'link', 'run', 'test') } ),
+
+        # host software dependencies
+        ('bitsery', { "type": ('build', 'link', 'run', 'test') } ),
+        ('binutils+gold+ld+plugins', { "type": ('build', 'link', 'run') } ), # specialize
+        ('boost@1.69.0: +graph+icu+mpi+numpy+coroutine+context+filesystem+python+serialization+system+thread+program_options cxxstd=17', { "type": ('build', 'link', 'run', 'test') } ),
+        ('cereal', { "type": ('build', 'link', 'run', 'test') } ),
+        ('cppcheck', { "type": ('build', 'link', 'run') } ),
+        ('genpybind@ebrains', { "type": ('build', 'link') } ),
+        ('gflags', { "type": ('build', 'link', 'run') } ),
+        ('googletest@1.11.0:+gmock', { "type": ('build', 'link', 'run') } ), # variadic templates needed
+        ('inja', { "type": ('build', 'link', 'run', 'test')  } ),# template engine for PPU source jit generation
+        ('intel-tbb', { "type": ('build', 'link', 'run') } ), # ppu gdbserver
+        ('libelf', { "type": ('build', 'link', 'run') } ),
+        ('liblockfile', { "type": ('build', 'link', 'run') } ),
+        ('log4cxx@0.12.1:1.0', { "when": "@:8.0-a3", "type": ('build', 'link', 'run') } ),
+        ('log4cxx@1.1: +events_at_exit', { "when": "@8.0-a4:", "type": ('build', 'link', 'run') } ),
+        ('pkgconfig', { "type": ('build', 'link', 'run') } ),
+        ('psmisc', { "type": ('run', 'test') } ),
+        ('python@3.7.0:', { "type": ('build', 'link', 'run') } ), # BrainScaleS-2 only supports Python >= 3.7
+        ('py-h5py', { "type": ('build', 'link', 'run') } ), # PyNN tests need it
+        ('py-matplotlib', { "type": ('build', 'link', 'run') } ),
+        ('py-networkx', { "type": ('build', 'link', 'run') } ),
+        ('py-nose', { "type": ('build', 'link', 'run') } ),
+        ('py-numpy', { "type": ('build', 'link', 'run') } ),
+        ('py-pybind11', { "type": ('build', 'link', 'run') } ),
+        ('py-pybind11-stubgen', { "type": ('build', 'link', 'run') } ),
+        ('py-pycodestyle', { "type": ('build', 'link', 'run') } ),
+        ('py-pyelftools', { "type": ('build', 'link', 'run') } ),
+        ('py-pylint', { "type": ('build', 'link', 'run') } ),
+        ('py-torch@1.9.1:', { "type": ('build', 'link', 'run', 'test') } ),
+        ('py-torchvision', { "type": ('run') } ), # for demos
+        ('py-pyyaml', { "type": ('build', 'link', 'run') } ),
+        ('py-scipy', { "type": ('build', 'link', 'run') } ),
+        ('py-sqlalchemy', { "type": ('build', 'link', 'run') } ),
+        ('util-linux', { "type": ('build', 'link', 'run') } ),
+        ('yaml-cpp+shared', { "type": ('build', 'link', 'run') } ),
+    ]
+
+    for dep, dep_kw in deps_hxtorch_core:
+        depends_on(dep, **dep_kw)
 
-    # host software dependencies
-    depends_on('bitsery', type=('build', 'link', 'run', 'test'))
-    depends_on('binutils+gold+ld+plugins', type=('build', 'link', 'run')) # specialize
-    depends_on('boost@1.69.0: +graph+icu+mpi+numpy+coroutine+context+filesystem+python+serialization+system+thread+program_options cxxstd=17', type=('build', 'link', 'run', 'test'))
-    depends_on('cereal', type=('build', 'link', 'run', 'test'))
-    depends_on('cppcheck', type=('build', 'link', 'run'))
-    depends_on('genpybind@ebrains', type=('build', 'link', 'run'))
-    depends_on('gflags', type=('build', 'link', 'run'))
-    depends_on('git', type=('build', 'link'))
-    depends_on('googletest@1.11.0:+gmock', type=('build', 'link', 'run')) # variadic templates needed
-    depends_on('inja', type=('build', 'link', 'run', 'test')) # template engine for PPU source jit generation
-    depends_on('intel-tbb', type=('build', 'link', 'run'))  # ppu gdbserver
-    depends_on('libelf', type=('build', 'link', 'run'))
-    depends_on('liblockfile', type=('build', 'link', 'run'))
-    depends_on('log4cxx@0.12.1:', type=('build', 'link', 'run'))
-    depends_on('pkgconfig', type=('build', 'link', 'run'))
-    depends_on('psmisc', type=('run', 'test'))
-    depends_on('python@3.7.0:', type=('build', 'link', 'run')) # BrainScaleS-2 only supports Python >= 3.7
-    depends_on('py-git-review', type=('build', 'link'))
-    depends_on('py-h5py', type=('build', 'link', 'run')) # PyNN tests need it
-    depends_on('py-jax@0.3.25:', type=('build', 'link', 'run'))
-    depends_on('py-matplotlib', type=('build', 'link', 'run'))
-    depends_on('py-networkx', type=('build', 'link', 'run'))
-    depends_on('py-nose', type=('build', 'link', 'run'))
-    depends_on('py-numpy', type=('build', 'link', 'run'))
-    depends_on('py-pybind11', type=('build', 'link', 'run'))
-    depends_on('py-pybind11-stubgen', type=('build', 'link', 'run'))
-    depends_on('py-pycodestyle', type=('build', 'link', 'run'))
-    depends_on('py-pyelftools', type=('build', 'link', 'run'))
-    depends_on('py-pylint', type=('build', 'link', 'run'))
-    depends_on('py-torch@1.9.1:', type=('build', 'link', 'run', 'test'))
-    depends_on('py-torchvision', type=('run')) # for demos
-    depends_on('py-tree-math', type=('build', 'link', 'run'))
-    depends_on('py-pyyaml', type=('build', 'link', 'run'))
-    depends_on('py-scipy', type=('build', 'link', 'run'))
-    depends_on('py-sqlalchemy', type=('build', 'link', 'run'))
-    depends_on('util-linux', type=('build', 'link', 'run'))
-    depends_on('yaml-cpp+shared', type=('build', 'link', 'run'))
     extends('python')
 
     def install_test(self):
diff --git a/packages/jaxsnn/package.py b/packages/jaxsnn/package.py
index cd66a37746f6c30760e1818e278a51e751fc2709..c6b2021e5801a5d3f934b83e33d3b4f04e515ee7 100644
--- a/packages/jaxsnn/package.py
+++ b/packages/jaxsnn/package.py
@@ -12,7 +12,7 @@ import spack.build_environment
 
 import importlib
 build_brainscales = importlib.import_module("spack.pkg.ebrains-spack-builds.build_brainscales")
-
+hxtorch = importlib.import_module("spack.pkg.ebrains-spack-builds.hxtorch")
 
 class Jaxsnn(build_brainscales.BuildBrainscales):
     """jaxsnn is an event-based approach to machine-learning-inspired training
@@ -25,14 +25,14 @@ class Jaxsnn(build_brainscales.BuildBrainscales):
 
     maintainers = ['emuller']
 
+    version('8.0-a4', tag='jaxsnn-8.0-a4')
     version('8.0-a3', tag='jaxsnn-8.0-a3')
     version('8.0-a2', tag='jaxsnn-8.0-a2')
     version('8.0-a1', tag='jaxsnn-8.0-a1')
 
-    # for now, this is still "on top" of hxtorch…
-    depends_on('hxtorch@8.0-a3', when='@8.0-a3', type=('build', 'link', 'run', 'test'))
-    depends_on('hxtorch@8.0-a2', when='@8.0-a2', type=('build', 'link', 'run', 'test'))
-    depends_on('hxtorch@8.0-a1', when='@8.0-a1', type=('build', 'link', 'run', 'test'))
+    # dependencies inherited from hxtorch.core
+    for dep, dep_kw in hxtorch.Hxtorch.deps_hxtorch_core:
+        depends_on(dep, **dep_kw)
 
     # main dependencies w/o hxtorch.core dependencies (those come via hxtorch above)
     depends_on('py-jax@0.4.13:', type=('build', 'link', 'run'))
diff --git a/packages/log4cxx/log4cxx-0.10.0-missing_includes.patch b/packages/log4cxx/log4cxx-0.10.0-missing_includes.patch
new file mode 100644
index 0000000000000000000000000000000000000000..6834648d09a826c18cf5755c406006c16accc36d
--- /dev/null
+++ b/packages/log4cxx/log4cxx-0.10.0-missing_includes.patch
@@ -0,0 +1,38 @@
+diff -Naur apache-log4cxx-0.10.0.orig/src/examples/cpp/console.cpp apache-log4cxx-0.10.0/src/examples/cpp/console.cpp
+--- apache-log4cxx-0.10.0.orig/src/examples/cpp/console.cpp	2008-04-01 00:34:52.000000000 +0200
++++ apache-log4cxx-0.10.0/src/examples/cpp/console.cpp	2008-05-06 05:40:52.000000000 +0200
+@@ -15,7 +15,10 @@
+  * limitations under the License.
+  */
+ 
+-#include <stdlib.h>
++#include <cstdio>
++#include <cstdlib>
++#include <cstring>
++#include <stdint.h>
+ #include <log4cxx/logger.h>
+ #include <log4cxx/consoleappender.h>
+ #include <log4cxx/simplelayout.h>
+diff -Naur apache-log4cxx-0.10.0.orig/src/main/cpp/inputstreamreader.cpp apache-log4cxx-0.10.0/src/main/cpp/inputstreamreader.cpp
+--- apache-log4cxx-0.10.0.orig/src/main/cpp/inputstreamreader.cpp	2008-04-01 00:34:09.000000000 +0200
++++ apache-log4cxx-0.10.0/src/main/cpp/inputstreamreader.cpp	2008-05-06 05:32:31.000000000 +0200
+@@ -21,6 +21,8 @@
+ #include <log4cxx/helpers/pool.h>
+ #include <log4cxx/helpers/bytebuffer.h>
+ 
++#include <cstring>
++
+ using namespace log4cxx;
+ using namespace log4cxx::helpers;
+ 
+diff -Naur apache-log4cxx-0.10.0.orig/src/main/cpp/socketoutputstream.cpp apache-log4cxx-0.10.0/src/main/cpp/socketoutputstream.cpp
+--- apache-log4cxx-0.10.0.orig/src/main/cpp/socketoutputstream.cpp	2008-04-01 00:34:09.000000000 +0200
++++ apache-log4cxx-0.10.0/src/main/cpp/socketoutputstream.cpp	2008-05-06 05:35:55.000000000 +0200
+@@ -20,6 +20,8 @@
+ #include <log4cxx/helpers/socket.h>
+ #include <log4cxx/helpers/bytebuffer.h>
+ 
++#include <cstring>
++
+ using namespace log4cxx;
+ using namespace log4cxx::helpers;
\ No newline at end of file
diff --git a/packages/log4cxx/log4cxx-0.10.0-narrowing-fixes-from-upstream.patch b/packages/log4cxx/log4cxx-0.10.0-narrowing-fixes-from-upstream.patch
new file mode 100644
index 0000000000000000000000000000000000000000..e583e7661d1d0adc0650dd3d96f5bf8d77aa6cbf
--- /dev/null
+++ b/packages/log4cxx/log4cxx-0.10.0-narrowing-fixes-from-upstream.patch
@@ -0,0 +1,117 @@
+diff --git a/src/main/cpp/locationinfo.cpp b/src/main/cpp/locationinfo.cpp
+index e76ea29..bd22a1d 100644
+--- a/src/main/cpp/locationinfo.cpp
++++ b/src/main/cpp/locationinfo.cpp
+@@ -149,18 +149,21 @@ void LocationInfo::write(ObjectOutputStream& os, Pool& p) const {
+          os.writeNull(p);
+     } else {
+         char prolog[] = {
+-         0x72, 0x00, 0x21, 0x6F, 0x72, 0x67, 0x2E, 
+-         0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2E, 0x6C, 
+-         0x6F, 0x67, 0x34, 0x6A, 0x2E, 0x73, 0x70, 0x69, 
+-         0x2E, 0x4C, 0x6F, 0x63, 0x61, 0x74, 0x69, 0x6F, 
+-         0x6E, 0x49, 0x6E, 0x66, 0x6F, 0xED, 0x99, 0xBB, 
+-         0xE1, 0x4A, 0x91, 0xA5, 0x7C, 0x02, 0x00, 0x01, 
+-         0x4C, 0x00, 0x08, 0x66, 0x75, 0x6C, 0x6C, 0x49, 
+-         0x6E, 0x66, 0x6F, 
+-            0x74, 0x00, 0x12, 0x4C, 0x6A, 
+-                0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67, 
+-                0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B,
+-         0x78, 0x70 };
++         0x72,
++         0x00,
++         0x21, 0x6F, 0x72, 0x67, 0x2E, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2E,
++         0x6C, 0x6F, 0x67, 0x34, 0x6A, 0x2E, 0x73, 0x70, 0x69, 0x2E, 0x4C, 0x6F,
++         0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x6E, 0x66, 0x6F, static_cast<char>(0xED),
++         static_cast<char>(0x99), static_cast<char>(0xBB), static_cast<char>(0xE1),
++         0x4A, static_cast<char>(0x91), static_cast<char>(0xA5), 0x7C, 0x02,
++         0x00,
++         0x01, 0x4C,
++         0x00,
++         0x08, 0x66, 0x75, 0x6C, 0x6C, 0x49, 0x6E, 0x66, 0x6F, 0x74,
++         0x00,
++         0x12, 0x4C, 0x6A, 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67, 0x2F,
++         0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B, 0x78, 0x70
++        };
+       os.writeProlog("org.apache.log4j.spi.LocationInfo", 2, prolog, sizeof(prolog), p);
+         char* line = p.itoa(lineNumber);
+         //
+diff --git a/src/main/cpp/loggingevent.cpp b/src/main/cpp/loggingevent.cpp
+index 1c0d4be..edbf40b 100644
+--- a/src/main/cpp/loggingevent.cpp
++++ b/src/main/cpp/loggingevent.cpp
+@@ -242,7 +242,7 @@ void LoggingEvent::writeProlog(ObjectOutputStream& os, Pool& p)  {
+         0x68, 0x65, 0x2E, 0x6C, 0x6F, 0x67, 0x34, 0x6A, 
+         0x2E, 0x73, 0x70, 0x69, 0x2E, 0x4C, 0x6F, 0x67, 
+         0x67, 0x69, 0x6E, 0x67, 0x45, 0x76, 0x65, 0x6E, 
+-        0x74, 0xF3, 0xF2, 0xB9, 0x23, 0x74, 0x0B, 0xB5, 
++        0x74, static_cast<char>(0xF3), static_cast<char>(0xF2), static_cast<char>(0xB9), 0x23, 0x74, 0x0B, static_cast<char>(0xB5), 
+         0x3F, 0x03, 0x00, 0x0A, 0x5A, 0x00, 0x15, 0x6D, 
+         0x64, 0x63, 0x43, 0x6F, 0x70, 0x79, 0x4C, 0x6F, 
+         0x6F, 0x6B, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 
+diff --git a/src/main/cpp/objectoutputstream.cpp b/src/main/cpp/objectoutputstream.cpp
+index 7cd696b..5442420 100644
+--- a/src/main/cpp/objectoutputstream.cpp
++++ b/src/main/cpp/objectoutputstream.cpp
+@@ -36,7 +36,7 @@ ObjectOutputStream::ObjectOutputStream(OutputStreamPtr outputStream, Pool& p)
+        objectHandle(0x7E0000),
+        classDescriptions(new ClassDescriptionMap())
+ {
+-   char start[] = { 0xAC, 0xED, 0x00, 0x05 };
++   char start[] = { static_cast<char>(0xAC), static_cast<char>(0xED), 0x00, 0x05 };
+    ByteBuffer buf(start, sizeof(start));
+    os->write(buf, p);
+ }
+@@ -81,15 +81,15 @@ void ObjectOutputStream::writeObject(const MDC::Map& val, Pool& p) {
+     //
+     //  TC_OBJECT and the classDesc for java.util.Hashtable
+     //
+-    char prolog[] = {
+-        0x72, 0x00, 0x13, 0x6A, 0x61, 0x76, 0x61, 
+-        0x2E, 0x75, 0x74, 0x69, 0x6C, 0x2E, 0x48, 0x61, 
+-        0x73, 0x68, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x13, 
+-        0xBB, 0x0F, 0x25, 0x21, 0x4A, 0xE4, 0xB8, 0x03, 
+-        0x00, 0x02, 0x46, 0x00, 0x0A, 0x6C, 0x6F, 0x61, 
+-        0x64, 0x46, 0x61, 0x63, 0x74, 0x6F, 0x72, 0x49, 
+-        0x00, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 
+-        0x6F, 0x6C, 0x64, 0x78, 0x70  };
++	char prolog[] = {
++		0x72, 0x00, 0x13, 0x6A, 0x61, 0x76, 0x61,
++		0x2E, 0x75, 0x74, 0x69, 0x6C, 0x2E, 0x48, 0x61,
++		0x73, 0x68, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x13,
++		static_cast<char>(0xBB), 0x0F, 0x25, 0x21, 0x4A, static_cast<char>(0xE4), static_cast<char>(0xB8), 0x03,
++		0x00, 0x02, 0x46, 0x00, 0x0A, 0x6C, 0x6F, 0x61,
++		0x64, 0x46, 0x61, 0x63, 0x74, 0x6F, 0x72, 0x49,
++		0x00, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68,
++		0x6F, 0x6C, 0x64, 0x78, 0x70  };
+     writeProlog("java.util.Hashtable", 1, prolog, sizeof(prolog), p);
+     //
+     //   loadFactor = 0.75, threshold = 5, blockdata start, buckets.size = 7
+diff --git a/src/test/cpp/xml/domtestcase.cpp b/src/test/cpp/xml/domtestcase.cpp
+index a500628..29d67dd 100644
+--- a/src/test/cpp/xml/domtestcase.cpp
++++ b/src/test/cpp/xml/domtestcase.cpp
+@@ -190,9 +190,9 @@ public:
+                 DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMTestCase3.xml"));
+                 LOG4CXX_INFO(logger, "File name is expected to end with a superscript 3");
+ #if LOG4CXX_LOGCHAR_IS_UTF8
+-                const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, 0xC2, 0xB3, 0 };
++                const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, static_cast<logchar>(0xC2), static_cast<logchar>(0xB3), 0 };
+ #else
+-                const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, 0xB3, 0 };
++                const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, static_cast<logchar>(0xB3), 0 };
+ #endif
+                 File file;
+                 file.setPath(fname);
+@@ -209,9 +209,9 @@ public:
+                 DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMTestCase4.xml"));
+                 LOG4CXX_INFO(logger, "File name is expected to end with an ideographic 4");
+ #if LOG4CXX_LOGCHAR_IS_UTF8
+-                const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, 0xE3, 0x86, 0x95, 0 };
++                const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, static_cast<logchar>(0xE3), static_cast<logchar>(0x86), static_cast<logchar>(0x95), 0 };
+ #else
+-                const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, 0x3195, 0 };
++                const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, static_cast<logchar>(0x3195), 0 };
+ #endif
+                 File file;
+                 file.setPath(fname);
\ No newline at end of file
diff --git a/packages/log4cxx/package.py b/packages/log4cxx/package.py
new file mode 100644
index 0000000000000000000000000000000000000000..e792947a5330a3515799f6b502ea09720f378ba1
--- /dev/null
+++ b/packages/log4cxx/package.py
@@ -0,0 +1,43 @@
+# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+from spack.package import *
+
+
+class Log4cxx(CMakePackage):
+    """A C++ port of Log4j"""
+
+    homepage = "https://logging.apache.org/log4cxx/latest_stable/"
+    url = "https://dlcdn.apache.org/logging/log4cxx/0.12.0/apache-log4cxx-0.12.0.tar.gz"
+
+    maintainers("nicmcd")
+
+    # begin EBRAINS (added): bring upstream (ref. spack@0.21.2)
+    version("1.2.0",  sha256="09f4748aa5675ef5c0770bedbf5e00488668933c5a935a43ac5b85be2436c48a")
+    version("1.1.0",  sha256="1fc7d82697534184bc0f757348d969d24852b948f63d6b17283fd1ee29c2c28a")
+    # end EBRAINS
+    version("0.12.1", sha256="7bea5cb477f0e31c838f0e1f4f498cc3b30c2eae74703ddda923e7e8c2268d22")
+    version("0.12.0", sha256="bd5b5009ca914c8fa7944b92ea6b4ca6fb7d146f65d526f21bf8b3c6a0520e44")
+
+    variant("cxxstd", default="17", description="C++ standard", values=("11", "17"), multi=False)
+    variant("events_at_exit",
+            default=False,
+            description="Enable to use logging during the application termination"
+            )
+
+    depends_on("cmake@3.13:", type="build")
+
+    depends_on("apr-util")
+    depends_on("apr")
+    depends_on("boost+thread+system", when="cxxstd=11")
+    depends_on("zlib-api")
+    depends_on("zip")
+
+    def cmake_args(self):
+        return [
+            self.define_from_variant("CMAKE_CXX_STANDARD", "cxxstd"),
+            self.define("BUILD_TESTING", "off"),
+            self.define_from_variant("LOG4CXX_EVENTS_AT_EXIT", "events_at_exit"),
+        ]
diff --git a/packages/nanoflann/package.py b/packages/nanoflann/package.py
new file mode 100644
index 0000000000000000000000000000000000000000..387c139610fbfa4fd95653dbe1e03a6adc951e23
--- /dev/null
+++ b/packages/nanoflann/package.py
@@ -0,0 +1,27 @@
+# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+from spack.package import *
+
+
+class Nanoflann(CMakePackage):
+    """a C++ header-only library for Nearest Neighbor (NN) search wih KD-trees."""
+
+    homepage = "https://github.com/jlblancoc/nanoflann"
+    url = "https://github.com/jlblancoc/nanoflann/archive/v1.2.3.tar.gz"
+
+    # begine EBRAINS: add version
+    version("1.5.4", sha256="a7f64d0bdff42614c561e52680b16de46c0edac9719f21f935c5e1f8b0654afc")
+    # end EBRAINS
+    version("1.4.3", sha256="cbcecf22bec528a8673a113ee9b0e134f91f1f96be57e913fa1f74e98e4449fa")
+    version("1.2.3", sha256="5ef4dfb23872379fe9eb306aabd19c9df4cae852b72a923af01aea5e8d7a59c3")
+
+    def patch(self):
+        filter_file("-mtune=native", "", "CMakeLists.txt")
+
+    def cmake_args(self):
+        args = ["-DBUILD_SHARED_LIBS=ON"]
+        return args
+
diff --git a/packages/open3d/glew-no-glu.patch b/packages/open3d/glew-no-glu.patch
new file mode 100644
index 0000000000000000000000000000000000000000..84baf0ecd3f5c2cfb403c2142d85427d9e64ee43
--- /dev/null
+++ b/packages/open3d/glew-no-glu.patch
@@ -0,0 +1,15 @@
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index a87d542b5..509a50633 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -41,6 +41,10 @@ endif()
+ include(CMakeDependentOption)
+ 
+ # Open3D build options
++option(DEFINE_GLEW_NO_GLU         "Glew without GLU"                         OFF)
++if(DEFINE_GLEW_NO_GLU)
++    add_definitions(-DGLEW_NO_GLU)
++endif(DEFINE_GLEW_NO_GLU)
+ option(BUILD_SHARED_LIBS          "Build shared libraries"                   OFF)
+ option(BUILD_EXAMPLES             "Build Open3D examples programs"           ON )
+ option(BUILD_UNIT_TESTS           "Build Open3D unit tests"                  OFF)
diff --git a/packages/open3d/package.py b/packages/open3d/package.py
new file mode 100644
index 0000000000000000000000000000000000000000..d97a7e03bc066c7204f28cd2309c59e0bc4a3efc
--- /dev/null
+++ b/packages/open3d/package.py
@@ -0,0 +1,196 @@
+# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+import os
+
+from llnl.util import filesystem
+
+from spack.package import *
+
+
+# begin EBRAINS: modified (based on spack/0.21.2)
+class Open3d(CMakePackage, CudaPackage):
+    """Open3D: A Modern Library for 3D Data Processing."""
+
+    homepage = "http://www.open3d.org/"
+    url = "https://github.com/isl-org/Open3D/archive/refs/tags/v0.13.0.tar.gz"
+    git = "https://github.com/isl-org/Open3D.git"
+
+    # begin EBRAINS: added v0.18.0
+    version("0.18.0", tag="v0.18.0", submodules=True)
+    # end EBRAINS
+    version("0.13.0", tag="v0.13.0", submodules=True)
+
+    variant("python", default=False, description="Build the Python module")
+
+    # http://www.open3d.org/docs/latest/compilation.html
+
+    depends_on("cmake@3.19:", type="build")
+    # https://github.com/isl-org/Open3D/issues/3762
+    # https://github.com/isl-org/Open3D/issues/4570
+    depends_on("llvm@7:+clang")
+    # begin EBRAINS: modified
+    depends_on("eigen", type=("build"))
+    depends_on("flann", when="@:0.13")
+    # https://github.com/isl-org/Open3D/issues/4360
+    # https://github.com/isl-org/Open3D/pull/5303
+    depends_on("fmt@:7", when="@:0.16")
+    depends_on("fmt@:9", when="@0.17:")
+    depends_on("googletest")
+    depends_on("glew")
+    depends_on("glfw")
+    # depends_on('imgui')
+    depends_on("jpeg")
+    # depends_on('liblzf')
+    # depends_on("libpng")
+    depends_on("nanoflann@:1.4", when="@0.15:0.17")
+    depends_on("nanoflann@1.5:", when="@0.18:")
+    depends_on("py-pybind11", type=("build"))
+    # end EBRAINS
+    depends_on("qhull")
+    # depends_on('tinygltf')
+    # depends_on('tinyobjloader')
+
+    # begin EBRAINS: added
+    depends_on("assimp", when="@0.15:")
+    depends_on("jsoncpp", when="@0.15:")
+    depends_on("msgpack-c", when="@0.15:")
+    # depends_on("tbb", when="@0.15:")
+    depends_on("cppzmq", when="@0.15:")
+    depends_on("curl", when="@0.17:")
+    depends_on("openssl", when="@0.17:")
+    # depends_on("vtk", when="@0.17:")
+    depends_on("embree@:3", when="@0.18:")
+    # end EBRAINS
+
+    extends("python", when="+python", type=("build", "link", "run"))
+    depends_on("python@3.6:", when="+python", type=("build", "link", "run"))
+    depends_on("py-pip", when="+python", type="build")
+    depends_on("py-setuptools@40.8:", when="+python", type="build")
+    depends_on("py-wheel@0.36:", when="+python", type="build")
+    depends_on("py-numpy@1.18:", when="+python", type=("build", "run"))
+    depends_on("py-dash@2.6.0:", when="+python", type=("build", "run"))
+    depends_on("py-nbformat@5.7.0:", when="+python", type=("build", "run"))
+    depends_on("py-werkzeug@2.2.3:", when="+python", type=("build", "run"))
+    depends_on("py-configargparse", when="+python", type=("build", "run"))
+    depends_on("py-pytest", when="+python", type="test")
+    depends_on("cuda@10.1:", when="+cuda")
+
+    # C++14 compiler required
+    conflicts("%gcc@:4")
+    conflicts("%clang@:6")
+
+    # LLVM must be built with the C++ library
+    conflicts("^llvm libcxx=none")
+
+    patch("glew-no-glu.patch")
+
+    def patch(self):
+        # Force Python libraries to be installed to self.prefix
+        args = std_pip_args + ["--prefix=" + self.prefix]
+        filter_file(
+            "pip install",
+            "pip " + " ".join(args),
+            os.path.join("cpp", "pybind", "make_install_pip_package.cmake"),
+        )
+
+    def cmake_args(self):
+        # begin EBRAINS: modified
+        libcxx_paths = filesystem.find_libraries(
+            "libc++", self.spec["llvm"].prefix, shared=True, recursive=True
+        )
+        if len(libcxx_paths) > 1:
+            raise InstallError(
+                "concretized llvm dependency must provide a "
+                "unique directory containing libc++.so, "
+                "found: {0}".format(libcxx_paths)
+            )
+        args = [
+            self.define("BUILD_UNIT_TESTS", self.run_tests),
+            self.define_from_variant("BUILD_PYTHON_MODULE", "python"),
+            self.define_from_variant("BUILD_CUDA_MODULE", "cuda"),
+            # https://github.com/isl-org/Open3D/issues/4570
+            # self.define('BUILD_FILAMENT_FROM_SOURCE', 'ON'),
+            # Use Spack-installed dependencies instead of vendored dependencies
+            # Numerous issues with using externally installed dependencies:
+            # https://github.com/isl-org/Open3D/issues/4333
+            # https://github.com/isl-org/Open3D/issues/4360
+            self.define("USE_SYSTEM_EIGEN3", True),
+            self.define("USE_SYSTEM_FMT", True),
+            self.define("USE_SYSTEM_GOOGLETEST", True),
+            self.define("USE_SYSTEM_GLEW", True),
+            self.define("USE_SYSTEM_GLFW", True),
+            # self.define('USE_SYSTEM_IMGUI', True),
+            self.define("USE_SYSTEM_JPEG", True),
+            # self.define('USE_SYSTEM_LIBLZF', True),
+            # https://github.com/isl-org/Open3D/issues/4883
+            # self.define("USE_SYSTEM_PNG", True),
+            self.define("USE_SYSTEM_PYBIND11", True),
+            # self.define('USE_SYSTEM_TINYGLTF', True),
+            # self.define('USE_SYSTEM_TINYOBJLOADER', True),
+            self.define("CLANG_LIBDIR", os.path.dirname(libcxx_paths[0])),
+        ]
+        if self.spec.satisfies("@:0.13"):
+            args.append(self.define("USE_SYSTEM_FLANN", True))
+            args.append(self.define("USE_SYSTEM_QHULL", True))
+        if self.spec.satisfies("@0.14:"):
+            args.append(self.define("USE_SYSTEM_QHULLCPP", True))
+        if self.spec.satisfies("@0.15:"):
+            args.append(self.define("USE_SYSTEM_ASSIMP", True))
+            args.append(self.define("USE_SYSTEM_JSONCPP", True))
+            args.append(self.define("USE_SYSTEM_MSGPACK", True))
+            args.append(self.define("USE_SYSTEM_NANOFLANN", True))
+            # args.append(self.define("USE_SYSTEM_TBB", True))
+            args.append(self.define("USE_SYSTEM_ZEROMQ", True))
+        if self.spec.satisfies("@0.17:"):
+            args.append(self.define("USE_SYSTEM_CURL", True))
+            args.append(self.define("USE_SYSTEM_OPENSSL", True))
+            # args.append(self.define("USE_SYSTEM_VTK", True))
+        if self.spec.satisfies("@0.18:"):
+           args.append(self.define("USE_SYSTEM_EMBREE", True))
+        # cf. https://github.com/spack/spack/issues/42839
+        args.append(self.define("DEFINE_GLEW_NO_GLU", True))
+        # end EBRAINS
+
+        if "+python" in self.spec:
+            args.append(self.define("PYTHON_EXECUTABLE", self.spec["python"].command.path))
+
+        return args
+
+    def check(self):
+        # begin EBRAINS: modified
+        with working_dir(self.builder.build_directory):
+        # end EBRAINS
+            tests = Executable(os.path.join("bin", "tests"))
+            tests()
+
+    def install(self, spec, prefix):
+        # begin EBRAINS: modified
+        with working_dir(self.builder.build_directory):
+        # end EBRAINS
+            make("install")
+            if "+python" in spec:
+                make("install-pip-package")
+
+    # Tests don't pass unless all optional features are compiled, including PyTorch
+    # @run_after('install')
+    # @on_package_attributes(run_tests=True)
+    # def unit_test(self):
+    #     if '+python' in self.spec:
+    #         pytest = which('pytest')
+    #         pytest(os.path.join('python', 'test'))
+
+    @run_after("install")
+    @on_package_attributes(run_tests=True)
+    def test(self):
+        if "+python" in self.spec:
+            self.run_test(
+                self.spec["python"].command.path,
+                ["-c", "import open3d"],
+                purpose="checking import of open3d",
+                work_dir="spack-test",
+            )
+# end EBRAINS
+
diff --git a/packages/oppulance/package.py b/packages/oppulance/package.py
index 6db434fdf3d0509d8584df847ee8e3785046a98e..d917e96c38ed0c5737beb2cc0cbffe7515614736 100644
--- a/packages/oppulance/package.py
+++ b/packages/oppulance/package.py
@@ -21,6 +21,10 @@ class Oppulance(Package):
     depends_on('gmp')
 
     releases = [
+        {
+            'version': '8.0-a4',
+            'tag': 'ebrains-8.0-a4'
+        },
         {
             'version': '8.0-a3',
             'tag': 'ebrains-8.0-a3'
diff --git a/packages/py-dash/package.py b/packages/py-dash/package.py
new file mode 100644
index 0000000000000000000000000000000000000000..ab410d2f142c9f57525588ddc573d7129815e111
--- /dev/null
+++ b/packages/py-dash/package.py
@@ -0,0 +1,29 @@
+# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+from spack.package import *
+
+
+class PyDash(PythonPackage):
+    """Python framework for building ML & data science web apps"""
+
+    homepage = "https://dash.plotly.com/"
+    pypi = "dash/dash-2.16.1.tar.gz"
+
+    version("2.16.1", sha256="b2871d6b8d4c9dfd0a64f89f22d001c93292910b41d92d9ff2bb424a28283976")
+    version("2.15.0", sha256="d38891337fc855d5673f75e5346354daa063c4ff45a8a6a21f25e858fcae41c2")
+
+    depends_on("python@3.8:", type=("build", "run"))
+    depends_on("py-setuptools", type="build")
+    
+    depends_on("py-flask@1.0.4:3.0", type=("build", "run"))
+    depends_on("py-werkzeug@:3.0", type=("build", "run"))
+    depends_on("py-plotly@5:", type=("build", "run"))
+    depends_on("py-importlib-metadata", type=("build", "run"))
+    depends_on("py-typing-extensions@4.1.1:", type=("build", "run"))
+    depends_on("py-requests", type=("build", "run"))
+    depends_on("py-retrying", type=("build", "run"))
+    depends_on("py-nest-asyncio", type=("build", "run"))
+
diff --git a/packages/py-nestml/package.py b/packages/py-nestml/package.py
index 91c71307eb57577f63fab1fcb4b185690ac9da38..f071ca2228111fbaafe3cdaee42b79687b4d32ff 100644
--- a/packages/py-nestml/package.py
+++ b/packages/py-nestml/package.py
@@ -13,11 +13,12 @@ class PyNestml(PythonPackage):
     """
 
     homepage = 'https://nestml.readthedocs.org/'
-    url      = 'https://pypi.org/packages/py3/N/NESTML/NESTML-7.0.0-py3-none-any.whl'
+    url      = 'https://pypi.org/packages/py3/N/NESTML/NESTML-7.0.1rc1-py3-none-any.whl'
     git      = 'https://github.com/nest/nestml/'
 
     maintainers = ['clinssen', 'pnbabu', 'jougs']
 
+    version('7.0.1rc1', sha256='80a0d66b747424a1f8ee88496c8bb3954db20be570d0dc2d58988b63794a6491', expand=False)
     version('7.0.0', sha256='4e271048b4a9ad2c161dda98d3ee25e143537649a264d521deb0ff5543020d73', expand=False)
     version('6.0.0', sha256='224993f175b9599a3662e65afdaf57e355246c0eab5f88b795fdb089ea28b39e', expand=False)
     version('5.3.0', sha256='8de543d7d3a166cd4d6a0d536a2d4e769513bbf8d7aeaf64458e9d9c21fe546e', expand=False)
diff --git a/packages/py-snudda/package.py b/packages/py-snudda/package.py
index 1678b1a00577884b791be5c8087e00339c26502f..67db0a32742399ae8a8a96835a7c722b0386f516 100644
--- a/packages/py-snudda/package.py
+++ b/packages/py-snudda/package.py
@@ -5,11 +5,12 @@ class PySnudda(PythonPackage):
     """Snudda creates the connectivity for realistic networks of simulated neurons in silico in a bottom up fashion that can then be simulated using the NEURON software."""
 
     homepage = "https://pypi.org/project/snudda/"
-    pypi     = "snudda/snudda-1.4.71.tar.gz"
+    pypi     = "snudda/snudda-2.0.1.tar.gz"
 
     maintainers = ["hjorth"]
     
-    version("1.4.71", "563fcd816ad8a5c44b3185759e179c68", url="https://files.pythonhosted.org/packages/f7/d2/3f7b50f01f4d18578e15fb15deee9de0abebaa2006d0738714241d0359a5/snudda-1.4.71-py3-none-any.whl", expand=False)
+    version("2.0.1", "0d78f5ca2cfe728b216f980078d8558a")
+    version("1.4.71", "5871e4af5e1a011d26a22d7dc384638a")
     version("1.4.0", "55f9b398b01b34bf3cec28c8a3aebc78")
     version("1.3.2", "2306ec50acead5fd4f988ec373f19718", url="https://files.pythonhosted.org/packages/py3/s/snudda/snudda-1.2.9-py3-none-any.whl", expand=False)
 
@@ -31,6 +32,8 @@ class PySnudda(PythonPackage):
     depends_on("py-psutil",             type=("build","run"))
     depends_on("py-cython",             type=("build","run"))
     depends_on("py-numba@0.53.1:",      type=("build","run"))
+    depends_on("open3d+python",         type=("build","run"), when="@2:")
+
 
     # snudda tarballs in pypi do not include the tests/ dir: just use default spack tests for now
     # @run_after('install')
diff --git a/packages/pynn-brainscales/package.py b/packages/pynn-brainscales/package.py
index 39f07d8129ee0c8d0b8f151cceb746d0dd762dc1..ee737581afebbd95bfaf56852fcd2052b74dfd69 100644
--- a/packages/pynn-brainscales/package.py
+++ b/packages/pynn-brainscales/package.py
@@ -23,6 +23,7 @@ class PynnBrainscales(build_brainscales.BuildBrainscales):
 
     maintainers = ['emuller']
 
+    version('8.0-a4',         tag='pynn-brainscales-8.0-a4')
     version('8.0-a3',         tag='pynn-brainscales-8.0-a3')
     version('8.0-a2',         tag='pynn-brainscales-8.0-a2')
     version('8.0-a1',         tag='pynn-brainscales-8.0-a1')
@@ -32,6 +33,7 @@ class PynnBrainscales(build_brainscales.BuildBrainscales):
 
     # compiler for the BrainScaleS-2 embedded processor ("PPU"); needed for
     # building/linking, at runtime and for testing
+    depends_on('oppulance@8.0-a4', when='@8.0-a4', type=('build', 'link', 'run', 'test'))
     depends_on('oppulance@8.0-a3', when='@8.0-a3', type=('build', 'link', 'run', 'test'))
     depends_on('oppulance@8.0-a2', when='@8.0-a2', type=('build', 'link', 'run', 'test'))
     depends_on('oppulance@8.0-a1', when='@8.0-a1', type=('build', 'link', 'run', 'test'))
@@ -45,20 +47,19 @@ class PynnBrainscales(build_brainscales.BuildBrainscales):
     depends_on('boost@1.69.0: +graph+icu+mpi+numpy+coroutine+context+filesystem+python+serialization+system+thread+program_options cxxstd=17', type=('build', 'link', 'run', 'test'))
     depends_on('cereal', type=('build', 'link', 'run', 'test'))
     depends_on('cppcheck', type=('build', 'link', 'run'))
-    depends_on('genpybind@ebrains', type=('build', 'link', 'run'))
+    depends_on('genpybind@ebrains', type=('build', 'link'))
     depends_on('gflags', type=('build', 'link', 'run'))
-    depends_on('git', type=('build', 'link'))
     depends_on('googletest@1.11.0:+gmock', type=('build', 'link', 'run')) # variadic templates needed
     depends_on('inja', type=('build', 'link', 'run', 'test')) # template engine for PPU source jit generation
     depends_on('intel-tbb', type=('build', 'link', 'run'))  # ppu gdbserver
     depends_on('libelf', type=('build', 'link', 'run'))
     depends_on('liblockfile', type=('build', 'link', 'run'))
-    depends_on('log4cxx@0.12.1:', type=('build', 'link', 'run'))
+    depends_on('log4cxx@0.12.1:1.0', when="@:8.0-a3", type=('build', 'link', 'run'))
+    depends_on('log4cxx@1.1: +events_at_exit', when="@8.0-a4:", type=('build', 'link', 'run'))
     depends_on('pkgconfig', type=('build', 'link', 'run'))
     depends_on('psmisc', type=('run', 'test'))
     depends_on('python@3.7.0:', type=('build', 'link', 'run')) # BrainScaleS-2 only supports Python >= 3.7
     depends_on('py-deap@1.3.1:', type=('build', 'link', 'run'))
-    depends_on('py-git-review', type=('build', 'link'))
     depends_on('py-h5py', type=('build', 'link', 'run')) # PyNN tests need it
     depends_on('py-matplotlib', type=('build', 'link', 'run'))
     depends_on('py-nose', type=('build', 'link', 'run'))
diff --git a/packages/wf-custom-python/package.py b/packages/wf-custom-python/package.py
new file mode 100644
index 0000000000000000000000000000000000000000..84ebe4ccde56d79e8ad7ac85243744905f82c485
--- /dev/null
+++ b/packages/wf-custom-python/package.py
@@ -0,0 +1,16 @@
+# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+from spack import *
+
+
+class WfCustomPython(BundlePackage):
+    """Meta-package to represent a use case where users install additional
+    (on top of the ESD) Python packages."""
+
+    version("0.1")
+    
+    depends_on("py-pip")
+    depends_on("py-virtualenv")
diff --git a/spack.yaml b/spack.yaml
index 9fc9e2c3f6737948b11f1ce1e7bfa127eb2be5f5..0bdb1d1bc3fd436aa5765fb3a441df74c2154f21 100644
--- a/spack.yaml
+++ b/spack.yaml
@@ -12,10 +12,10 @@ spack:
     - biobb-model@4.0.0
     - biobb-structure-checking@3.12.1
     - biobb-structure-utils@4.0.0
-    - hxtorch@8.0-a3
+    - hxtorch@8.0-a4
     - nest@3.7_rc1 +sonata
     - neuron@8.2.3 +mpi
-    - jaxsnn@8.0-a3
+    - jaxsnn@8.0-a4
     - py-bluepyefe@2.2.18
     - py-bluepymm@0.7.65
     - py-bluepyopt@1.13.86
@@ -35,7 +35,7 @@ spack:
     - py-libneuroml@0.4.1
     - py-libsonata@0.1.23
     - py-neo@0.12.0
-    - py-nestml@7.0.0
+    - py-nestml@7.0.1rc1
     - py-netpyne@1.0.5
     - py-neurom@3.2.2
     - py-neuror@1.6.4
@@ -44,7 +44,7 @@ spack:
     - py-quantities-scidash@0.12.4.3
     - py-quantities@0.15.0
     - py-siibra@0.4a66
-    - py-snudda@1.4.71
+    - py-snudda@2.0.1
     - py-spynnaker@7.0.0
     - py-tvb-contrib@2.8.2
     - py-tvb-data@2.8
@@ -54,7 +54,7 @@ spack:
     - py-tvb-multiscale@2.1.0.ebrains
     - py-tvb-storage@2.8.1
     - py-viziphant@0.4.0
-    - pynn-brainscales@8.0-a3
+    - pynn-brainscales@8.0-a4
     - r-rgsl@0.1.1
     - r-sbtabvfgen@0.1
     - r-uqsa@2.2
@@ -65,6 +65,7 @@ spack:
     - wf-protein-association-rates@0.1
     - wf-multi-area-model@1.1.1
     - wf-uq-akar4@0.1
+    - wf-custom-python@0.1
     #- py-cerebstats
     #- py-cerebunit
     #- py-morphounit@1.0.4