Repository navigation
Conversation
Build wntr's SWIG C++ extensions with cibuildwheel from the 1.5.0 tag, mirroring upstream's build_test_wheels.yml. Upstream ships x86_64-only EPANET 2.0/2.2 and EPANET-MSX shared libraries for Linux; compile them for riscv64 from the sources they were built from (OpenWaterAnalytics EPANET v2.1 and v2.2, USEPA EPANETMSX with its EPANET2.2 submodule) and patch the ctypes loader to pick them up from libepanet/linux-riscv64.
luhenry
added a commit
that referenced
this pull request
Nov 2, 2026
GCC14 compiles EPANET-2.1's sources under strict -std=c99 and treats the resulting implicit-declaration of mkstemp() (a POSIX function, not visible under plain c99 without _DEFAULT_SOURCE/_POSIX_C_SOURCE) as a hard error. Reproduce the Makefile's own CFLAGS on the command line (it replaces rather than appends) and add the missing macro. See gotcha 226/525.
EPANET v2.2 declares cmake_minimum_required(VERSION 2.8.8), which the CMake 4 shipped in manylinux_2_39_riscv64 rejects. Pass CMAKE_POLICY_VERSION_MINIMUM=3.5 to its configure step.
EPANET-MSX's msxout.c only includes <stdlib.h> on Apple, so on Linux calloc() and free() are implicitly declared, which GCC 14 rejects. Force-include the header through CMAKE_C_FLAGS.
wntr/epanet/io.py does an unconditional `import six` but setup.py never lists six in DEPENDENCIES or any extra, so installing the wheel does not guarantee it. Reproduces as ModuleNotFoundError: No module named 'six' on cp312/cp313 riscv64 CI, the first legs to get past dependency resolution far enough to import wntr.
All four riscv64 build legs of PR #4277 were failing: - cp310 failed during the build step itself: PIP_ONLY_BINARY=numpy blocks pip from falling back to an sdist build, and our registry's cp310 numpy riscv64 wheels stop at 2.2.2, below wntr's pyproject.toml build requirement numpy>=2.2.6. Drop numpy from PIP_ONLY_BINARY for cp310 only so pip builds it from source there; cp311-cp313 keep the fast prebuilt wheel since our registry already satisfies them. - cp311 failed installing the wheel's [optional,test] test extras: rasterio/shapely/pyproj have no riscv64 wheel on our registry for cp310/cp311 (geopandas pulls them in transitively). The affected tests (test_gis.py) already guard those imports with try/except, so skip the 'optional' extra there and keep it for cp312/cp313 where the registry has every wheel the extra needs. - cp312/cp313 got past both of the above and failed at pytest collection on the missing six dependency fixed in the previous commit.
_publish-wheel.yml now requires a matrix input (main's "publish: Validate effective wheel targets"), but this PR branch forked before that landed and wntr has never been merged to main, so build-wntr.yml never picked up the matching one-line update every already-published package's workflow got. The merge ref combines the new required-input _publish-wheel.yml with this branch's old build-wntr.yml, so any run has failed startup with "Input matrix is required, but not provided". Pass it the same way the mass-update commit did for every other package's publish job.
wntr/tests/conftest.py os.chdir()s to a temp dir at import time, and pyproject.toml's addopts=--doctest-modules then re-resolves the relative --ignore=wntr/tests/test_demos.py (and test_examples.py) against that new cwd, so they silently stop matching. pytest ends up importing test_demos.py twice (as a regular test module and again for doctest scanning), both failing with ModuleNotFoundError: No module named 'geopandas', since geopandas is deliberately not installed for cp310/cp311 (CIBW_TEST_EXTRAS only installs the 'test' extra there). Resolving the ignore paths with $PWD before cibuildwheel's test command runs keeps them absolute and immune to the later chdir.
…ests cp310/cp311's Build wheels step kept failing after narrowing CIBW_TEST_EXTRAS to 'test' (dropping 'optional') to dodge rasterio/shapely/ pyproj/geopandas, which have no riscv64 wheel on our registry below cp312: FAILED wntr/tests/test_graphics.py::TestGraphics::test_plot_interactive_network1 FAILED wntr/tests/test_graphics.py::TestGraphics::test_plot_leaflet_network1 FAILED wntr/tests/test_graphics.py::TestGraphics::test_plot_leaflet_network_popup FAILED wntr/tests/test_graphics.py::TestGraphics::test_plot_valve_layer_gpd FAILED wntr/tests/test_graphics.py::TestGraphics::test_plot_valve_layer_with_attribute FAILED wntr/tests/test_morph.py::TestMorph::test_UTM_to_longlat_to_UTM FAILED wntr/tests/test_morph.py::TestMorph::test_convert_node_coordinates_to_longlat Five of these seven only need plotly or the utm package (both pure-Python, with no riscv64-specific wheel problem of their own - they were simply never installed once the whole 'optional' extra was dropped). Only the last two, test_plot_valve_layer_gpd and test_plot_valve_layer_with_attribute, actually exercise the geopandas/shapely-backed gpd plotting backend that the registry gap blocks. Install plotly and utm directly via CIBW_TEST_REQUIRES on cp310/cp311 instead of losing their tests along with the rest of 'optional', and deselect only the two tests that genuinely need geopandas/shapely.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
wntr1.5.0Compiles wntr's SWIG C++ extensions (
_evaluator,_network_isolation) and the EPANET 2.0/2.2 and EPANET-MSX libraries it loads through ctypes. Upstream publishes no riscv64 wheel.Mirrors upstream's
build_test_wheels.yml.Differs from upstream
linuxtomanylinux2014Matrix: cp312, cp313 - upstream builds cp310-cp313 only.
Testing
wntr/tests,examplesandpyproject.tomlstaged viatest-sources- upstream sparse-checks them out in a separate jobLicense: Wheel bundles EPANET and EPANET-MSX (MIT) and the image's libgomp (GPL-3.0 with GCC Runtime Library Exception); upstream ships no licence text for EPANET, so the build adds it.
Patches
0001-epanet-load-EPANET-libraries-from-linux-riscv64-on-riscv64.patch- To upstream [not yet submitted]. Without it the loader always openslibepanet/linux-x64, so EpanetSimulator and MSX fail to load. Reproduces on any non-x86_64 Linux.First riscv64 CI run pending.