Hi team , So I'm a contributor to Brian2 and maintain an experimental cppyy code-generation backend for it, a simulator for spiking neural networks (brian-team/brian2#1769, still a draft , we have been working on it for over an year now ).
I had also discussed the platform-support side of this work earlier with Wim Lavrijsen (wlav) in the cppyy repository, wlav/cppyy#311
A bit of context on why I'm asking. Brian2 generates C++ for simulations and currently runs it through Cython. That means compiling and importing each generated code object before it can run. On a cold cache, startup can take tens of seconds, which is especially noticeable for the short, exploratory simulations people tend to run repeatedly.
Replacing that path was the focus of my Google Summer of Code 2025 project (https://brian.discourse.group/t/gsoc-2025-replacing-brians-just-in-time-compilation-mechanism/1450/9 ), Replacing Brian's just-in-time compilation mechanism,
with the Brian2 maintainers (@mstimberg ).
We ended up using cppyy because it gives us an actual in-process JIT instead of doing AOT compilation at runtime. It also lets us keep hot data structures on the C++ side rather than repeatedly crossing the Python/C++ boundary in inner loops.
On Linux and macOS, the backend now does what we wanted it to do and we see a huge performance boost there too. The remaining problem is less about the backend itself and more about whether we can actually ship it to Brian2 users.
Our cppyy surface area is fairly small: cppdef, include, add_include_path, gbl, and the buffer protocol for exposing NumPy arrays to C++ as raw pointers.
I've only recently caught up with the fact that wlav/cppyy is frozen, the three compiler-research forks were archived on August 4, and CppJIT is now the successor. Before we decide how to land our PR, I'd like to understand where CppJIT is heading, particularly around packaging and platform support.
1. Wheels and platform coverage
So I checked and It's good to see #32 and #33 moving toward wheels that bundle LLVM. For Brian2, that would solve one of the biggest problems with the current cppyy stack.
The part I'm less clear on is the intended platform coverage.
Brian2 currently tests on Linux x86-64, Windows x86-64, macOS Intel, and macOS arm64. We publish wheels for manylinux x86-64/aarch64, musllinux x86-64, Windows, and both macOS architectures. Python support follows SPEC-0, so we're on 3.12–3.14 today, which happens to line up exactly with CppJIT's cp312/cp313/cp314 build list.
The important constraint for us is that most Brian2 users are neuroscientists installing through pip or conda. We can't really make a backend the default if installing it means building LLVM locally.
As #22 currently stands, [tool.cibuildwheel] has no Windows section, Linux only builds x86_64, macOS only builds arm64, and musllinux is skipped. That would leave Windows, Linux aarch64, macOS Intel, and musllinux uncovered relative to Brian2.
Are those platforms intended for the first release, or something you'd expect to add later?
A few related questions:
- What macOS deployment target are you aiming for?
MACOSX_DEPLOYMENT_TARGET = "26.0" in the PR would be a fairly high floor for Brian2 users.
- Is conda-forge part of the plan?
- I assume a LICENSE will land before the first release. Do you already know which license CppJIT will use?
2. Windows
This is probably the question that matters most for us, and it is also something I had discussed with wlav while working on the original cppyy-based backend.
From the outside, most of the underlying pieces seem to exist already. CppInterOp's win2025-msvc-llvm22 and win2025-msvc-cling jobs are green, ci-workflows' setup-llvm knows about windows-2025, CppJIT still has the IS_WINDOWS handling inherited from cppyy, and conda-forge has llvmdev 20–22 for win-64.
What I can't find is anything connecting those pieces yet. The reusable cppjit.yml installs dependencies only for Linux and macOS, neither ci.yml nor nightly.yml has a Windows job, and none of CppInterOp's Windows jobs enable cppyy: On.
Is Windows simply work that hasn't been reached yet, or is there a known technical blocker?
Also, do you expect to support a particular range of MSVC toolsets?
I'd be happy to help here. I already have a reproducible GitHub Actions workflow that drives a JIT backend end-to-end on Windows runners, so I can put together a Windows CI job if that would be useful.
3. What happens to the frozen cppyy stack?
Should downstream projects treat cppyy 3.5.0 / cppyy-cling 6.32.8 as effectively final?
So actually all four packages were last released on 2024-12-17, and three of the four are still sdist-only across platforms, so even Linux users need a compiler for a normal install today.
There's also the unreleased Windows linker fix from wlav/cppyy#282:
LNK2001: Cppyy::GetNumBasesLongestBranch
As I understand it, CPyCppyy 1.13.0 build-requires cppyy-backend==1.15.2, while its setup.py run-requires 1.15.3. That's fixed on master but was never released.
Is there any chance of one final cppyy release containing fixes like that, or should downstreams assume there won't be another release and work around them?
4. Migration from cppyy to CppJIT
wheel.packages currently lists only cppjit and cppjit_backend, so I'm assuming there won't be a cppyy compatibility alias and downstream projects should migrate imports themselves. Is that the intended path?
Beyond the rename, how much API drift do you expect from cppyy 3.5?
Our usage is deliberately narrow, so most of it looks straightforward. The bit I'm most interested in is the buffer/pointer path, since we rely on passing NumPy-backed memory into generated C++ without copying it.
One smaller question: the README currently asks for LLVM 21, while CMakeLists.txt accepts LLVM 20–22. Which version would you recommend downstream projects target?
5. What would you recommend we do?
This is ultimately the decision we're trying to make.
We have about a year of work behind this backend. It works and gives us the behavior we were aiming for on Linux and macOS, but packaging and Windows support are what stand between an experimental backend and something Brian2 can actually put in front of users.
Would you recommend that we:
- land against the existing cppyy stack now, document the Windows limitation, and migrate to CppJIT later; or
- wait for the first CppJIT release and target it directly?
If the second path makes more sense, even a rough idea of the release/platform timeline would help us plan the Brian2 side.
Thanks for taking this project on. I'm also happy to help with testing or CI rather than just asking about the roadmap :) .
Brian2 should be a pretty good real-world test case for this too. We generate C++ heavily, pass NumPy-backed memory across the boundary, JIT repeatedly, and already have CI across Linux, Windows, and both macOS architectures.
Hi team , So I'm a contributor to Brian2 and maintain an experimental cppyy code-generation backend for it, a simulator for spiking neural networks (brian-team/brian2#1769, still a draft , we have been working on it for over an year now ).
I had also discussed the platform-support side of this work earlier with Wim Lavrijsen (
wlav) in the cppyy repository, wlav/cppyy#311A bit of context on why I'm asking. Brian2 generates C++ for simulations and currently runs it through Cython. That means compiling and importing each generated code object before it can run. On a cold cache, startup can take tens of seconds, which is especially noticeable for the short, exploratory simulations people tend to run repeatedly.
Replacing that path was the focus of my Google Summer of Code 2025 project (https://brian.discourse.group/t/gsoc-2025-replacing-brians-just-in-time-compilation-mechanism/1450/9 ), Replacing Brian's just-in-time compilation mechanism,
with the Brian2 maintainers (@mstimberg ).
We ended up using cppyy because it gives us an actual in-process JIT instead of doing AOT compilation at runtime. It also lets us keep hot data structures on the C++ side rather than repeatedly crossing the Python/C++ boundary in inner loops.
On Linux and macOS, the backend now does what we wanted it to do and we see a huge performance boost there too. The remaining problem is less about the backend itself and more about whether we can actually ship it to Brian2 users.
Our cppyy surface area is fairly small:
cppdef,include,add_include_path,gbl, and the buffer protocol for exposing NumPy arrays to C++ as raw pointers.I've only recently caught up with the fact that wlav/cppyy is frozen, the three compiler-research forks were archived on August 4, and CppJIT is now the successor. Before we decide how to land our PR, I'd like to understand where CppJIT is heading, particularly around packaging and platform support.
1. Wheels and platform coverage
So I checked and It's good to see #32 and #33 moving toward wheels that bundle LLVM. For Brian2, that would solve one of the biggest problems with the current cppyy stack.
The part I'm less clear on is the intended platform coverage.
Brian2 currently tests on Linux x86-64, Windows x86-64, macOS Intel, and macOS arm64. We publish wheels for manylinux x86-64/aarch64, musllinux x86-64, Windows, and both macOS architectures. Python support follows SPEC-0, so we're on 3.12–3.14 today, which happens to line up exactly with CppJIT's cp312/cp313/cp314 build list.
The important constraint for us is that most Brian2 users are neuroscientists installing through pip or conda. We can't really make a backend the default if installing it means building LLVM locally.
As #22 currently stands,
[tool.cibuildwheel]has no Windows section, Linux only buildsx86_64, macOS only buildsarm64, and musllinux is skipped. That would leave Windows, Linux aarch64, macOS Intel, and musllinux uncovered relative to Brian2.Are those platforms intended for the first release, or something you'd expect to add later?
A few related questions:
MACOSX_DEPLOYMENT_TARGET = "26.0"in the PR would be a fairly high floor for Brian2 users.2. Windows
This is probably the question that matters most for us, and it is also something I had discussed with
wlavwhile working on the original cppyy-based backend.From the outside, most of the underlying pieces seem to exist already. CppInterOp's
win2025-msvc-llvm22andwin2025-msvc-clingjobs are green,ci-workflows'setup-llvmknows aboutwindows-2025, CppJIT still has theIS_WINDOWShandling inherited from cppyy, and conda-forge hasllvmdev20–22 for win-64.What I can't find is anything connecting those pieces yet. The reusable
cppjit.ymlinstalls dependencies only for Linux and macOS, neitherci.ymlnornightly.ymlhas a Windows job, and none of CppInterOp's Windows jobs enablecppyy: On.Is Windows simply work that hasn't been reached yet, or is there a known technical blocker?
Also, do you expect to support a particular range of MSVC toolsets?
I'd be happy to help here. I already have a reproducible GitHub Actions workflow that drives a JIT backend end-to-end on Windows runners, so I can put together a Windows CI job if that would be useful.
3. What happens to the frozen cppyy stack?
Should downstream projects treat cppyy 3.5.0 / cppyy-cling 6.32.8 as effectively final?
So actually all four packages were last released on 2024-12-17, and three of the four are still sdist-only across platforms, so even Linux users need a compiler for a normal install today.
There's also the unreleased Windows linker fix from wlav/cppyy#282:
LNK2001: Cppyy::GetNumBasesLongestBranchAs I understand it, CPyCppyy 1.13.0 build-requires
cppyy-backend==1.15.2, while itssetup.pyrun-requires1.15.3. That's fixed on master but was never released.Is there any chance of one final cppyy release containing fixes like that, or should downstreams assume there won't be another release and work around them?
4. Migration from cppyy to CppJIT
wheel.packagescurrently lists onlycppjitandcppjit_backend, so I'm assuming there won't be acppyycompatibility alias and downstream projects should migrate imports themselves. Is that the intended path?Beyond the rename, how much API drift do you expect from cppyy 3.5?
Our usage is deliberately narrow, so most of it looks straightforward. The bit I'm most interested in is the buffer/pointer path, since we rely on passing NumPy-backed memory into generated C++ without copying it.
One smaller question: the README currently asks for LLVM 21, while
CMakeLists.txtaccepts LLVM 20–22. Which version would you recommend downstream projects target?5. What would you recommend we do?
This is ultimately the decision we're trying to make.
We have about a year of work behind this backend. It works and gives us the behavior we were aiming for on Linux and macOS, but packaging and Windows support are what stand between an experimental backend and something Brian2 can actually put in front of users.
Would you recommend that we:
If the second path makes more sense, even a rough idea of the release/platform timeline would help us plan the Brian2 side.
Thanks for taking this project on. I'm also happy to help with testing or CI rather than just asking about the roadmap :) .
Brian2 should be a pretty good real-world test case for this too. We generate C++ heavily, pass NumPy-backed memory across the boundary, JIT repeatedly, and already have CI across Linux, Windows, and both macOS architectures.