Skip to content

Fix build system and CI issues#18

Open
corneliusroemer wants to merge 20 commits into
masterfrom
fix-makefile
Open

Fix build system and CI issues#18
corneliusroemer wants to merge 20 commits into
masterfrom
fix-makefile

Conversation

@corneliusroemer

Copy link
Copy Markdown
Member

Summary

This PR resolves build system failures and updates CI infrastructure:

  • Build system fixes: Auto-detect GSL and Boost paths for cross-platform compilation (macOS Homebrew/MacPorts, Ubuntu)
  • SWIG compatibility: Update numpy.i typemaps for SWIG 4.3.1
  • Python extension: Fix setup.py to include required library paths
  • CI improvements: Update GitHub Actions, fix artifact handling, drop EOL Python versions
  • Demo: Add test_ffpopsim.py showing population evolution example

Changes

Build System

  • Update Makefile to use gsl-config for GSL detection
  • Add automatic Boost path detection across platforms
  • Update setup.py with dynamic path detection for Python extensions
  • Fix numpy.i SWIG_Python_AppendOutput calls (3-argument signature for SWIG 4.3+)

CI/CD

  • Update GitHub Actions versions to resolve dependabot warnings
  • Fix artifact upload/download actions
  • Update macOS runner to macos-13
  • Drop Python 3.6-3.9 support (EOL versions)

Testing

  • Add test_ffpopsim.py demonstrating:
    • Population initialization with genetic diversity
    • Evolution under selection
    • Allele frequency tracking
    • Fitness statistics over time

Test Plan

  • Verify C++ library compiles on macOS
  • Verify all test executables build successfully
  • Verify Python extension builds and imports
  • Run test_ffpopsim.py demo successfully
  • CI passes on Ubuntu runners
  • CI passes on macOS runners

Notes

The build system changes are backward compatible and will work on systems with standard GSL/Boost installations via package managers.

🤖 Generated with Claude Code

corneliusroemer and others added 20 commits October 14, 2025 15:01
Updates outdated GitHub Actions to their latest versions:
- actions/checkout v3 → v4
- pypa/cibuildwheel v2.11.1 → v2.21.3
- actions/upload-artifact v3 → v4
- actions/download-artifact v3 → v4

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fixes multiple CI issues:
- Fix artifact upload conflicts by giving each job a unique artifact name
  (dist-{os}-py{version}) to avoid conflicts with actions/upload-artifact@v3
- Update download step to collect all artifacts into dist folder
- Replace deprecated macOS-11 runner with macOS-13

These changes address the artifact conflicts that were causing build failures
and the macOS runner timeout issues.

Note: C++ test failures and Python example test failures still need investigation
as logs are not available from previous runs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Remove Python 3.6 and 3.7 from the build matrix as they are no longer
supported (3.6 EOL: Dec 2021, 3.7 EOL: June 2023).

Current supported versions: 3.8, 3.9, 3.10, 3.11

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Update Makefile to auto-detect GSL and Boost paths using gsl-config
  and common installation directories (macOS Homebrew/MacPorts, Ubuntu)
- Update setup.py to include GSL and Boost paths for Python extension
- Fix numpy.i SWIG typemaps for compatibility with SWIG 4.3.1
  (update SWIG_Python_AppendOutput calls to use 3-argument signature)
- Add test_ffpopsim.py demo showing population evolution with selection

These changes enable successful compilation on macOS and Ubuntu without
hardcoded paths. All targets now build: C++ library, tests, and Python
bindings.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add swig to CI dependencies (both Linux and macOS)
- Drop Python 3.8 and 3.9 from CI matrix (EOL versions)
- Keep only Python 3.10 and 3.11 for wheel builds

The previous CI failures were due to missing swig in the cibuildwheel
environment. SWIG is required to generate Python bindings.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add -std=c++11 to Makefile CXXFLAGS for C++ library compilation
- Add -std=c++11 to setup.py extra_compile_args for Python extension
- Fix run-tests target to run all tests in single shell context

Boost 1.89.0 requires C++11 or later. Without specifying the C++ standard,
the compiler defaulted to C++98/C++03, causing compilation errors with
C++11 features like auto, rvalue references, and variadic templates.

The run-tests target was failing because each cd command ran in a separate
shell, causing "tests: No such file or directory" errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add pre-generated SWIG wrapper (SWIG 4.3.1) to repository
- Add generated FFPopSim.py module
- Update .gitignore to allow SWIG-generated files
- Remove `make swig` step from cibuildwheel.toml
- Remove swig from CI dependencies

The manylinux container has SWIG 3.x which generates incompatible
SWIG_Python_AppendOutput signatures. By committing the wrapper generated
with SWIG 4.3.1, we ensure consistent builds across all platforms.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The GSL libraries installed via Homebrew on macOS-13 have a minimum
deployment target of macOS 13.0. Set MACOSX_DEPLOYMENT_TARGET=13.0
to match the GSL library requirements and fix delocate-wheel errors.

Error was:
  libgsl.28.dylib has a minimum target of 13.0
  libgslcblas.0.dylib has a minimum target of 13.0

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Pin numpy<2 in test dependencies to avoid numpy 2.0 compatibility issues
- Make macOS run full test suite (./run-examples --skip-slow) for consistency with Linux

The numpy 2.0 changes to array creation are stricter and cause test failures
in examples like genetic_drift.py. Pinning to numpy v1 allows tests to pass
while we address numpy v2 compatibility in a future PR.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Change is_void parameter from 0 to 1 in SWIG_Python_AppendOutput calls
in numpy.i. For void functions that output arrays via ARGOUT parameters,
is_void=1 ensures the array is returned directly instead of as a tuple.

The bug caused functions like get_allele_frequencies() to return (None, array)
tuples instead of just the array, leading to numpy errors when examples tried
to create arrays from these results.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Replace macOS-13 with latest runners:
- macos-15 (ARM64/Apple Silicon)
- macos-15-intel (Intel x86_64)

This provides better architecture coverage and future-proofs the CI
as Apple discontinues Intel support.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Update MACOSX_DEPLOYMENT_TARGET from 13.0 to 14.0 to fix build failures
on macOS 15 runners (both Intel and ARM64).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
On macos-15 (ARM): skip x86_64 wheel tests (prevents brew/Rosetta issues)
On macos-15-intel: skip arm64 wheel tests (not runnable on Intel)

Each runner now only tests wheels for its native architecture.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Configuration:
- macos-14: ARM64 runner with GSL 14.0
- macos-15-intel: Intel runner
- MACOSX_DEPLOYMENT_TARGET: 14.0 across all macOS runners

This avoids the GSL minimum target mismatch that occurred with
macos-15 ARM runners where GSL requires 15.0.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The free_mem() function was not releasing several allocated arrays,
causing significant memory leaks during evolution simulations with
CROSSOVERS recombination model.

Fixed by adding deletion of:
- genome array (auxiliary array for crossover points)
- crossovers array (crossover points storage)
- trait_stat array (trait statistics)
- trait_covariance matrix (2D array)
- trait_weights array
- gsl_rng generator (via gsl_rng_free)

This reduces memory growth during evolution, though further
investigation is needed for remaining accumulation during evolve().

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
When available_clones.size() > n, the subtraction (n - available_clones.size())
caused unsigned arithmetic underflow, wrapping to INT_MAX (2^31-1). This made
the code try to allocate 2 billion clones, causing catastrophic memory growth.

The fix checks if we already have enough available clones before performing
the arithmetic. This prevents the underflow and keeps memory usage reasonable.

Before: decay_of_LD_highd.py would hit 12GB after 5 generations
After: Completes all 250 generations with <1GB memory

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- speed_highd.py: Cast float to int for evolve() argument
- genealogies_with_selection.py: Use integer division (//) instead of
  float division (/) for locus index

In Python 3, `/` always returns float, while `//` returns int.
Functions expecting integer arguments now get the correct type.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Remove parallel dependency and run examples in a simple bash loop
instead. This ensures truly serial execution to avoid any potential
memory pressure in CI environments.

Changes:
- Removed parallel from before-test dependencies
- Replaced ./run-examples script call with direct bash loop
- Still skip slow examples for CI efficiency
- Use MPLBACKEND=Agg to avoid interactive matplotlib

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Previously cibuildwheel was configured to build both x86_64 and arm64
wheels on BOTH runners, causing unnecessary cross-compilation:
- macos-14 (ARM) was cross-compiling x86_64 via Rosetta
- macos-15-intel (x86) was cross-compiling arm64

This was slower, less reliable, and produced duplicate wheels.

Changes:
- Set CIBW_ARCHS_MACOS per-runner: arm64 on macos-14, x86_64 on macos-15-intel
- Removed macos.archs from cibuildwheel.toml (now set in workflow)
- Removed test-skip config (no longer needed without cross-arch builds)
- Each runner now builds only its native architecture

Benefits:
- Faster builds (no cross-compilation overhead)
- More reliable (no Rosetta issues)
- Cleaner artifact naming (no duplicates)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
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.

1 participant