Skip to content

best practice for including compiler version in abi for dependencies (pybind11/nanobind)Β #2326

Open
@minrk

Description

@minrk

Your question:

The problem

For packages built with pybind11 and nanobind, the major version of the C++ compiler is part of the ABI. That means any package built with nanobind that links to another package via its nanobind API has a runtime requirement that both were built with the same major version of the compiler. This is not currently handled by the pybind11-abi metapackage or other compiler run_exports.

I don't think it comes up very often, but it does in the fenics stack. For fenics, I've added a fenics-basix-nanobind-abi package with a custom version that includes the nanobind and cxx_compiler versions. In the past, I had the same that bundled the pybind11-abi version and compiler version. I've only made one of these because everything in fenics depends on basix, but technically every package build with nanobind (that might be linked against in host) should have one. But this is a general problem, if not a common one. pybind11 has a pybind11-abi package, and nanobind will soon as well. But this is only half a solution, because it doesn't take the build-time compiler version into account, which is also part of the ABI in packages built with either pybind11 or nanobind.

My fenics-basix-nanobind-abi approach also doesn't solve the problem as well as I'd like because downstream packages build just fine since the compiler version is not actually restricted in the build env, but they won't import. that means e.g. cross-compiled outputs pass all CI when they are completely broken, when really the build should have been prevented in the first place due to the compiler version conflict.

Also, I've only dealt with this on linux/mac and don't actually know what needs to be restricted on Windows.

Question

I've struggled to come up with a general solution, but it seems like having nanobind or pybind11 in host dependencies should:

  1. restrict the C++ compiler version at build time when in host requirements, and
  2. restrict install-time packages to those built with the same C++ compiler

One hard part is that pybind11/nanobind packages are host dependencies, so can't easily restrict the cxx compiler version in the build environment. Is there a package in the host env that could be used as a proxy? Or should we be adding a metapackage to the build env to keep things in sync?

Does anyone have a recommendation/experience for a best practice for ensuring ABI compatibility that is sensitive to the compiler version? Is defining one of these abi metapackage outputs for every nanobind-built package really the way to go?

Possible solution

My only idea so far for a general solution is to update the pybind11/nanobind-abi packages (or separately add nanobind-cxx-abi) to generate a version for each compiler version with run_constrains on the compiler version and nanobind and strong run_exports on itself.

so e.g. nanobind-cxx-abi 0.13.12 gxx_* would have:

where:

  • 0 is the versioning scheme (increment when we change how it works)
  • 13 is the nanobind internals version
  • 12 is cxx_compiler_version
  • gxx is cxx_compiler

and would look something like:

run_exports:
  strong:
    - {{ pin_subpackage('nanobind-cxx-abi', max_pin='x.x.x.x') }} {{ cxx_compiler }}_*
run_constrained:
  # constrain compiler version (only works if it's in the build env)
  - {{ cxx_compiler }}_impl_{{ target_platform }} {{ cxx_compiler_version }}.*
  # constrain nanobind abi (host env)
  - nanobind-abi {{ nanobind_internals_version }}
  # another compiler constraint that would work on the host env? libstdcxx_devel?

and then packages make sure this is the same version in both the build and host requirements. But as convoluted as that is, I'm not even sure it would work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions