Skip to content

fix(toolkit): populate Python3_SOABI from sysconfig when empty#165

Merged
michaeltryby merged 1 commit intopyswmm:devfrom
cheginit:fix/soabi-fallback
Apr 29, 2026
Merged

fix(toolkit): populate Python3_SOABI from sysconfig when empty#165
michaeltryby merged 1 commit intopyswmm:devfrom
cheginit:fix/soabi-fallback

Conversation

@cheginit
Copy link
Copy Markdown

Summary

Fixes the double-dot extension filename (e.g. _solver..so, _output..so) produced when NO_STABLE_ABI=1 is set and CMake's FindPython3 fails to populate Python3_SOABI. The malformed suffix makes the compiled modules unimportable, which is the likely root cause of #155.

The build does set(SOABI ".${Python3_SOABI}"), so an empty Python3_SOABI collapses the suffix to a single . and the linker emits _solver..so.

What this PR does

  1. Fallback: in swmm-toolkit/src/swmm/toolkit/CMakeLists.txt, when Python3_SOABI is empty under the NO_STABLE_ABI branch, query the interpreter for sysconfig.get_config_var('SOABI') and use that. This is the canonical source of the ABI tag.
  2. Guardrail: add two ctest tests (ExtensionSuffix_output, ExtensionSuffix_solver) that assert each built module exists, has no .. in its basename, and ends with a valid importlib.machinery.EXTENSION_SUFFIXES entry. enable_testing() is added at the project root to support this.
  3. CI regression coverage: add a step to unit_test.yml that performs a direct CMake build with NO_STABLE_ABI=1 and runs ctest on Linux, macOS, and Windows. The existing wheel test only covers the default stable-ABI path, so without this step the fallback has no CI coverage.

Verification (local, macOS arm64, Python 3.14)

Config Extension filenames ctest
NO_STABLE_ABI=1 _output.cpython-314-darwin.so, _solver.cpython-314-darwin.so 2/2 pass
Default (stable ABI) _output.abi3.so, _solver.abi3.so 2/2 pass
Synthetic _solver..so n/a Guardrail correctly fails with Double-dot ABI bug

Test plan

  • Local build + ctest with NO_STABLE_ABI=1
  • Local build + ctest with default (stable ABI)
  • Local negative test proving the guardrail catches a double-dot filename
  • CI: Unit Test workflow passes on Ubuntu, macOS, Windows (including the new regression step)

Refs #155

When NO_STABLE_ABI=1, the build sets SOABI=".${Python3_SOABI}". If
CMake's FindPython3 fails to populate Python3_SOABI, the suffix
collapses to "." and extension modules are linked as `_solver..so` /
`_output..so`, which Python cannot import.

Fall back to `sysconfig.get_config_var('SOABI')` via the interpreter
when the CMake variable is empty.

Also add a ctest guardrail (ExtensionSuffix_output, ExtensionSuffix_solver)
that asserts each built module has no double-dot and ends with a valid
`importlib.machinery.EXTENSION_SUFFIXES` entry, and wire a regression
step into unit_test.yml so the NO_STABLE_ABI path is exercised on
Linux, macOS, and Windows.

Refs pyswmm#155
@cheginit
Copy link
Copy Markdown
Author

@michaeltryby @karosc Let me know if any changes are needed for this PR.

@michaeltryby michaeltryby merged commit 91faab4 into pyswmm:dev Apr 29, 2026
3 checks passed
@cheginit cheginit deleted the fix/soabi-fallback branch April 29, 2026 04:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants