diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..6138cbcdc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.idea +external_dependencies +/python/build +/python/dist +/python/gridpack_hadrec.egg-info \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 90489018e..728215eb6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,4 @@ [submodule "python/pybind11"] path = python/pybind11 url = https://github.com/pybind/pybind11.git + branch = master diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..bb29282d7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,126 @@ +FROM ubuntu:questing + +# Configure dependency versions +ARG boost_version=1.81.0 +ARG ga_version=5.9.1 +ARG petsc_version=3.24.2 + +# Setup environment variables used throughout installation +ENV DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC GNUMAKEFLAGS=--no-print-directory +ENV OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 + +ENV GRIDPACK_ROOT_DIR=/app GP_EXT_DEPS=/deps +ENV GRIDPACK_INSTALL_DIR=${GRIDPACK_ROOT_DIR}/src/install GRIDPACK_BUILD_DIR=${GRIDPACK_ROOT_DIR}/src/build +ENV GRIDPACK_DIR=${GRIDPACK_INSTALL_DIR} + +ENV boost_dir=${GP_EXT_DEPS}/boost-${boost_version} \ + ga_dir=${GP_EXT_DEPS}/ga-${ga_version} \ + petsc_dir=${GP_EXT_DEPS}/petsc + +ENV boost_gp_dir=${boost_dir}/install_for_gridpack \ + ga_gp_dir=${ga_dir}/install_for_gridpack \ + petsc_gp_dir=${petsc_dir}/install_for_gridpack + +ENV PETSC_DIR=${petsc_dir} PETSC_ARCH=build-dir + +ENV LD_LIBRARY_PATH=${boost_gp_dir}/lib:${ga_gp_dir}/lib:${petsc_gp_dir}/lib +ENV DYLD_LIBRARY_PATH=${LD_LIBRARY_PATH} + +# Install required system packages +RUN apt-get update && \ + apt-get install -y --no-install-recommends cmake make wget tzdata git gfortran build-essential pkg-config \ + python3 python3-pip python3-venv python3-dev python-is-python3 \ + openmpi-bin openmpi-common openmpi-doc libopenmpi-dev && \ + apt-get clean + +# Compile/Install Boost +WORKDIR ${GP_EXT_DEPS} +RUN wget "https://github.com/boostorg/boost/releases/download/boost-${boost_version}/boost-${boost_version}.tar.gz" +RUN tar -xf "boost-${boost_version}.tar.gz" +WORKDIR ${boost_dir} +RUN ./bootstrap.sh --prefix=install_for_gridpack --with-libraries=mpi,serialization,random,filesystem,system +RUN echo 'using mpi : mpicxx ; ' >> project-config.jam +RUN ./b2 -a -d+2 link="shared" stage +RUN ./b2 -a -d+2 link="shared" install + +# Compile/Install GA (Global Arrays) +WORKDIR ${GP_EXT_DEPS} +RUN wget "https://github.com/GlobalArrays/ga/releases/download/v${ga_version}/ga-${ga_version}.tar.gz" +RUN tar -xf "ga-${ga_version}.tar.gz" +WORKDIR ${ga_dir} +RUN ./configure --with-mpi-ts --disable-f77 \ + --without-blas --without-lapack --without-scalapack \ + --enable-cxx --enable-i4 \ + --prefix=${ga_gp_dir} \ + CFLAGS="-Wno-implicit-function-declaration -Wno-incompatible-pointer-types -Wno-old-style-definition" \ + CXXFLAGS="-Wno-incompatible-pointer-types" \ + --enable-shared=yes --enable-static=no +RUN make -j 10 install +WORKDIR ${GP_EXT_DEPS} + +# Compile/Install PETSc +RUN git clone https://gitlab.com/petsc/petsc.git +WORKDIR ${petsc_dir} +RUN git checkout "tags/v${petsc_version}" -b "v${petsc_version}" +RUN ./configure \ + --prefix=${PWD}/install_for_gridpack \ + --scalar-type=real \ + --with-fortran-bindings=0 \ + --download-superlu_dist \ + --download-metis \ + --download-parmetis \ + --download-suitesparse \ + --download-f2cblaslapack \ + --download-scalapack \ + --download-mumps \ + --download-cmake=0 \ + --with-sowing=0 \ + --with-debugging=0 \ + --with-shared-libraries=1 +RUN make all +RUN make install +#RUN make PETSC_DIR=${petsc_gp_dir} PETSC_ARCH="" check + +# Copy in GridPACK source code from repository +COPY README.md .gitignore .gitmodules ${GRIDPACK_ROOT_DIR}/ +COPY .git ${GRIDPACK_ROOT_DIR}/.git +COPY docs ${GRIDPACK_ROOT_DIR}/docs +COPY python ${GRIDPACK_ROOT_DIR}/python +COPY src ${GRIDPACK_ROOT_DIR}/src + +# Build GridPACK +WORKDIR ${GRIDPACK_BUILD_DIR} +RUN cmake -Wdev -D GA_DIR:STRING=${ga_gp_dir} \ + -D Boost_ROOT:STRING=${boost_gp_dir} \ + -D Boost_DIR:string=${boost_gp_dir}/lib/cmake/Boost-${boost_version} \ + -D PETSC_DIR:PATH=${petsc_gp_dir} \ + -D MPI_CXX_COMPILER:STRING='mpicxx' \ + -D MPI_C_COMPILER:STRING='mpicc' \ + -D MPIEXEC:STRING='mpiexec' \ + -D MPIEXEC_MAX_NUMPROCS:STRING=2 \ + -D GRIDPACK_TEST_TIMEOUT:STRING=120 \ + -D ENABLE_ENVIRONMENT_FROM_COMM:BOOL=YES \ + -D CMAKE_INSTALL_PREFIX:PATH=${GRIDPACK_INSTALL_DIR} \ + -D CMAKE_BUILD_TYPE:STRING=Debug \ + -D BUILD_SHARED_LIBS=true \ + -D CMAKE_CXX_FLAGS_DEBUG:STRING="-D_GLIBCXX_NO_ASSERTIONS" \ + .. +RUN make install + +# Install Python bindings +WORKDIR ${GRIDPACK_ROOT_DIR} +RUN git submodule update --init +RUN pip config --global set global.break-system-packages true +WORKDIR ${GRIDPACK_ROOT_DIR}/python +RUN pip install --upgrade --prefix=${GRIDPACK_INSTALL_DIR} . + +# Configure Python module search path using .pth file (no environment variables needed) +# Python automatically reads .pth files from its site-packages directories +RUN pyvnum=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') && \ + system_site_packages=$(python3 -c 'import site; print(site.getsitepackages()[0])') && \ + echo "${GRIDPACK_INSTALL_DIR}/lib/python${pyvnum}/site-packages" > ${system_site_packages}/gridpack.pth && \ + echo "${GRIDPACK_INSTALL_DIR}/local/lib/python${pyvnum}/dist-packages" >> ${system_site_packages}/gridpack.pth && \ + echo "Configured Python ${pyvnum} module search path via ${system_site_packages}/gridpack.pth" + +WORKDIR ${GRIDPACK_ROOT_DIR}/workspace +ENV PATH=${GRIDPACK_INSTALL_DIR}/bin:${GRIDPACK_INSTALL_DIR}/local/bin:${PATH} diff --git a/Dockerfile.test b/Dockerfile.test deleted file mode 100644 index b577046e3..000000000 --- a/Dockerfile.test +++ /dev/null @@ -1,10 +0,0 @@ -FROM ubuntu:24.04 - -# Install minimal dependencies -RUN apt-get update && \ - apt-get install -y --no-install-recommends curl ca-certificates && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -# Simple verification command -CMD ["echo", "Multi-arch Docker build pipeline test successful"] diff --git a/README.md b/README.md index 6eaf43687..c39e4955a 100644 --- a/README.md +++ b/README.md @@ -17,12 +17,32 @@ In addition, GridPACK is also a framework to simplify the development of new app ## Installation See the [instructions](docs/markdown/BASIC_INSTALL.md) for installing GridPACK, prerequisite software, and installation notes for different platforms. Formal releases are available [here](https://github.com/GridOPTICS/GridPACK/releases). +### Using Docker (Recommended) + +GridPACK is available as a multi-architecture Docker image with all dependencies pre-installed: + +```bash +# Pull the image +docker pull pnnl/gridpack:latest + +# Run with your files (container starts in /app/workspace) +docker run -it --rm -v $(pwd):/app/workspace pnnl/gridpack:latest bash +``` + +The Docker image supports both AMD64 and ARM64 architectures. See the [Docker usage guide](https://gridpack.readthedocs.io/en/latest/Section2-Docker.html) for more examples. + +### Building from Source + +See the [installation instructions](docs/markdown/BASIC_INSTALL.md) for building GridPACK from source, prerequisite software, and platform-specific installation notes. Formal releases are available [here](https://github.com/GridOPTICS/GridPACK/releases). + ## Usage See the [user manual](https://gridpack.readthedocs.io/en/latest/index.html) for a deep dive on GridPACK internals and/or refer to the [tutorials](docs/markdown/TUTORIALS.md) for more info. - Quick Guide (To do) ## Documentation +- [Docker Usage Guide](https://gridpack.readthedocs.io/en/latest/Section2-Docker.html) +- [CI/CD Pipeline](docs/markdown/CI-CD.md) - [User manual](https://gridpack.readthedocs.io/en/latest/index.html) - [Tutorials](docs/markdown/TUTORIALS.md) - [FAQS](docs/markdown/FAQS.md) diff --git a/docs/markdown/CI-CD.md b/docs/markdown/CI-CD.md new file mode 100644 index 000000000..5536a349b --- /dev/null +++ b/docs/markdown/CI-CD.md @@ -0,0 +1,203 @@ +# CI/CD Pipeline Documentation + +## Overview + +GridPACK uses GitHub Actions to build multi-architecture Docker images that are automatically published to Docker Hub at `pnnl/gridpack`. + +## Pipeline Architecture + +The pipeline uses native ARM64 and AMD64 runners for optimal build performance: + +``` +prepare-metadata → build-native (amd64 + arm64) → merge-manifest → test-native (amd64 + arm64) + ↓ parallel ↓ ↓ ↓ parallel ↓ +``` + +### Jobs + +1. **prepare-metadata**: Generates Docker tags and labels +2. **build-native**: Builds images natively on AMD64 and ARM64 runners in parallel +3. **merge-manifest**: Stitches architecture-specific images into a multi-arch manifest +4. **test-native**: Runs ctest smoke tests on both architectures in parallel + +### Performance + +- **Native ARM64 builds**: 3-10x faster than QEMU emulation +- **Parallel execution**: Both architectures build simultaneously +- **Total build time**: ~20-35 minutes (vs 45-90 minutes with QEMU) + +## Triggers + +### Automatic: Release Published + +When a GitHub release is created, the pipeline automatically builds and publishes: + +```bash +gh release create v3.3.0 --title "Release 3.3.0" --notes "Release notes" +``` + +Generated tags: +- `pnnl/gridpack:3.3.0` +- `pnnl/gridpack:3.3` +- `pnnl/gridpack:latest` + +### Manual: Workflow Dispatch + +Trigger builds manually from the GitHub Actions UI or CLI: + +**Via GitHub UI:** +1. Go to: Actions → Docker Multi-Architecture Build and Publish +2. Click "Run workflow" +3. Configure options: + - **tag**: Custom Docker tag (default: `dev`) + - **skip_tests**: Skip ctest smoke tests (default: `false`) + - **dockerfile**: Dockerfile path (default: `./Dockerfile`) +4. Click "Run workflow" + +**Via GitHub CLI:** + +```bash +# Basic run with defaults +gh workflow run docker-build.yml + +# With custom tag +gh workflow run docker-build.yml -f tag=test-build + +# Skip tests for faster iteration +gh workflow run docker-build.yml -f skip_tests=true + +# Use custom Dockerfile +gh workflow run docker-build.yml -f dockerfile=./Dockerfile.custom +``` + +## Docker Image + +### Repository +- **Location**: `pnnl/gridpack` +- **Registry**: Docker Hub + +### Supported Architectures +- `linux/amd64` (Intel/AMD) +- `linux/arm64` (ARM64/Apple Silicon/AWS Graviton) + +### Usage + +See [Docker Usage Guide](./DOCKER.md) for detailed examples. + +## Testing + +The pipeline runs ctest smoke tests on both architectures after building. Key points: + +- **Non-blocking**: Test failures do NOT prevent image publication (`continue-on-error: true`) +- **Expected pass rate**: ~94% +- **Can be skipped**: Use `skip_tests=true` for faster iteration + +## Secrets Required + +The pipeline requires two GitHub repository secrets: + +| Secret | Description | +|--------|-------------| +| `DOCKERHUB_USERNAME` | Docker Hub username for authentication | +| `DOCKERHUB_TOKEN` | Docker Hub access token (not password!) | + +### Setting Up Secrets + +1. **Generate Docker Hub Access Token:** + - Go to: https://hub.docker.com → Account Settings → Security + - Create token: Name: `gridpack-ci`, Permissions: Read, Write, Delete + - Copy the token (shown only once) + +2. **Add to GitHub:** + - Go to: Repository Settings → Secrets and variables → Actions + - Add both secrets with the values above + +## Monitoring + +### View Workflow Runs + +```bash +# List recent runs +gh run list --workflow=docker-build.yml --limit 5 + +# Watch a specific run +gh run watch + +# View detailed logs +gh run view --log +``` + +### Inspect Published Image + +```bash +# View manifest with both architectures +docker buildx imagetools inspect pnnl/gridpack:latest + +# Expected output shows: +# - linux/amd64 manifest +# - linux/arm64 manifest +``` + +## Caching + +The pipeline uses GitHub Actions cache to speed up builds: + +- Separate cache per architecture (`build-amd64`, `build-arm64`) +- Automatically managed by GitHub +- Improves rebuild times significantly + +## Troubleshooting + +### Build Fails on One Architecture + +The pipeline uses `fail-fast: false`, so if one architecture fails, the other continues. Check job logs for architecture-specific issues. + +### Manifest Merge Fails + +This usually indicates both architecture builds failed. Check that: +- Docker Hub credentials are correct +- Both build jobs completed successfully +- Digest artifacts were uploaded + +### Authentication Issues + +Verify secrets are configured correctly: +```bash +gh secret list +``` + +Should show: +- `DOCKERHUB_USERNAME` +- `DOCKERHUB_TOKEN` + +## Technical Details + +### Push-by-Digest Workflow + +The pipeline uses a digest-based approach: + +1. Each architecture builds and pushes: `pnnl/gridpack@sha256:abc123...` +2. These are content-addressed (by digest), not tagged yet +3. Manifest merge creates tags that reference both digests +4. Docker automatically selects the right image based on client platform + +### Why Native Runners? + +- **Performance**: 3-10x faster ARM64 builds without QEMU +- **Reliability**: No emulation issues or crashes +- **Testing**: Tests run on actual target platforms +- **Cost**: Same GitHub Actions pricing as AMD64 + +## Workflow File + +Location: `.github/workflows/docker-build.yml` + +The workflow definition must be in the default branch to be accessible. Changes to the workflow require merging to the default branch. + +## Future Enhancements + +Potential improvements: +- Additional architectures (RISC-V when runners available) +- Multi-registry support (GitHub Container Registry) +- Build time metrics/reporting +- Automated security scanning per architecture diff --git a/docs/user_manual/sphinx/Section9-Examples.rst b/docs/user_manual/sphinx/Section10-Examples.rst similarity index 100% rename from docs/user_manual/sphinx/Section9-Examples.rst rename to docs/user_manual/sphinx/Section10-Examples.rst diff --git a/docs/user_manual/sphinx/Section2-Docker.rst b/docs/user_manual/sphinx/Section2-Docker.rst new file mode 100644 index 000000000..edc381002 --- /dev/null +++ b/docs/user_manual/sphinx/Section2-Docker.rst @@ -0,0 +1,175 @@ +Using GridPACK with Docker +=========================== + +GridPACK is available as a Docker image with all dependencies pre-installed and ready to use. + +Quick Start +----------- + +Pull the Image +~~~~~~~~~~~~~~ + +.. code-block:: bash + + docker pull pnnl/gridpack:latest + +Run with Your Files +~~~~~~~~~~~~~~~~~~~ + +The container starts in ``/app/workspace`` by default. Mount your current directory to work with your files: + +.. code-block:: bash + + docker run -it --rm -v $(pwd):/app/workspace pnnl/gridpack:latest + +Usage Examples +-------------- + +Interactive Shell +~~~~~~~~~~~~~~~~~ + +.. code-block:: bash + + # Mount your working directory and start an interactive session + docker run -it --rm -v $(pwd):/app/workspace pnnl/gridpack:latest bash + +Run a Specific Command +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: bash + + # Run a GridPACK application directly + docker run --rm -v $(pwd):/app/workspace pnnl/gridpack:latest \ + powerflow.x input.xml + +Python Scripts +~~~~~~~~~~~~~~ + +.. code-block:: bash + + # Execute a Python script using GridPACK Python bindings + docker run --rm -v $(pwd):/app/workspace pnnl/gridpack:latest \ + python3 my_gridpack_script.py + +Run Tests +~~~~~~~~~ + +.. code-block:: bash + + # Run the GridPACK test suite + docker run --rm pnnl/gridpack:latest bash -c "cd /app/src/build && ctest" + +Working Directory +----------------- + +The container is configured with: + +- **Working directory**: ``/app/workspace`` +- **GridPACK installation**: ``/app/src/install`` +- **Build directory**: ``/app/src/build`` + +Mount your data/scripts to ``/app/workspace`` to access them from within the container. + +Environment Variables +--------------------- + +The following environment variables are pre-configured: + +.. code-block:: bash + + GRIDPACK_DIR=/app/src/install + PATH=/app/src/install/bin:$PATH + LD_LIBRARY_PATH=/deps/boost-1.81.0/install_for_gridpack/lib:/deps/ga-5.9.1/install_for_gridpack/lib:/deps/petsc/install_for_gridpack/lib + +Multi-Architecture Support +--------------------------- + +The Docker image supports both AMD64 and ARM64 architectures. Docker automatically pulls the correct image for your platform. + +To explicitly specify an architecture: + +.. code-block:: bash + + # For AMD64 (Intel/AMD processors) + docker pull --platform linux/amd64 pnnl/gridpack:latest + + # For ARM64 (Apple Silicon, AWS Graviton) + docker pull --platform linux/arm64 pnnl/gridpack:latest + +Available Tags +-------------- + +- ``latest`` - Latest stable release +- ``dev`` - Development builds +- ``vX.Y.Z`` - Specific version releases + +Tips +---- + +- Add ``-it`` for interactive terminal access +- Add ``--rm`` to automatically remove the container after exit +- Use ``-v`` to mount local directories into the container +- Increase memory limits for large simulations: ``--memory=8g`` +- Use multiple cores: Set ``OMPI_NUM_PROCS`` or pass to MPI commands + +Example Workflow +---------------- + +.. code-block:: bash + + # 1. Create a project directory + mkdir my-gridpack-project + cd my-gridpack-project + + # 2. Create your input files + cat > input.xml << EOF + + + + + EOF + + # 3. Run GridPACK in the container + docker run -it --rm -v $(pwd):/app/workspace pnnl/gridpack:latest bash + + # Inside container: + # powerflow.x input.xml + # exit + +Troubleshooting +--------------- + +Permission Issues +~~~~~~~~~~~~~~~~~ + +If you encounter permission issues with mounted volumes: + +.. code-block:: bash + + # Run with your user ID + docker run -it --rm -u $(id -u):$(id -g) -v $(pwd):/app/workspace pnnl/gridpack:latest + +MPI Warnings +~~~~~~~~~~~~ + +The container sets ``OMPI_ALLOW_RUN_AS_ROOT=1`` to allow running MPI as root. This is safe for containerized environments. + +Running Applications with MPI +------------------------------ + +GridPACK applications can be run with MPI inside the Docker container. For example: + +.. code-block:: bash + + # Run with 4 MPI processes + docker run --rm -v $(pwd):/app/workspace pnnl/gridpack:latest \ + mpirun -n 4 powerflow.x input.xml + +For detailed information on MPI execution, application arguments, and input file conventions, +see :doc:`Section3-ConfigureBuild` (Running GridPACK Applications section). + +Building from Source +-------------------- + +If you need to build GridPACK from source instead of using Docker, see :doc:`Section3-ConfigureBuild` +for detailed instructions on using build scripts or manual compilation. diff --git a/docs/user_manual/sphinx/Section2-ConfigureBuild.rst b/docs/user_manual/sphinx/Section3-ConfigureBuild.rst similarity index 100% rename from docs/user_manual/sphinx/Section2-ConfigureBuild.rst rename to docs/user_manual/sphinx/Section3-ConfigureBuild.rst diff --git a/docs/user_manual/sphinx/Section3-BuildApplications.rst b/docs/user_manual/sphinx/Section4-BuildApplications.rst similarity index 100% rename from docs/user_manual/sphinx/Section3-BuildApplications.rst rename to docs/user_manual/sphinx/Section4-BuildApplications.rst diff --git a/docs/user_manual/sphinx/Section4-FrameworkComponents.rst b/docs/user_manual/sphinx/Section5-FrameworkComponents.rst similarity index 100% rename from docs/user_manual/sphinx/Section4-FrameworkComponents.rst rename to docs/user_manual/sphinx/Section5-FrameworkComponents.rst diff --git a/docs/user_manual/sphinx/Section5-DevelopingApplications.rst b/docs/user_manual/sphinx/Section6-DevelopingApplications.rst similarity index 100% rename from docs/user_manual/sphinx/Section5-DevelopingApplications.rst rename to docs/user_manual/sphinx/Section6-DevelopingApplications.rst diff --git a/docs/user_manual/sphinx/Section6-AdvancedFunctionality.rst b/docs/user_manual/sphinx/Section7-AdvancedFunctionality.rst similarity index 100% rename from docs/user_manual/sphinx/Section6-AdvancedFunctionality.rst rename to docs/user_manual/sphinx/Section7-AdvancedFunctionality.rst diff --git a/docs/user_manual/sphinx/Section7-GeneralizedMatVecInterface.rst b/docs/user_manual/sphinx/Section8-GeneralizedMatVecInterface.rst similarity index 100% rename from docs/user_manual/sphinx/Section7-GeneralizedMatVecInterface.rst rename to docs/user_manual/sphinx/Section8-GeneralizedMatVecInterface.rst diff --git a/docs/user_manual/sphinx/Section8-ApplicationModules.rst b/docs/user_manual/sphinx/Section9-ApplicationModules.rst similarity index 100% rename from docs/user_manual/sphinx/Section8-ApplicationModules.rst rename to docs/user_manual/sphinx/Section9-ApplicationModules.rst diff --git a/docs/user_manual/sphinx/index.rst b/docs/user_manual/sphinx/index.rst index bf4cd6044..cdd328bf3 100644 --- a/docs/user_manual/sphinx/index.rst +++ b/docs/user_manual/sphinx/index.rst @@ -8,14 +8,15 @@ GridPACK documentation Section0-GridPACK Section1-Introduction - Section2-ConfigureBuild - Section3-BuildApplications - Section4-FrameworkComponents - Section5-DevelopingApplications - Section6-AdvancedFunctionality - Section7-GeneralizedMatVecInterface - Section8-ApplicationModules - Section9-Examples + Section2-Docker + Section3-ConfigureBuild + Section4-BuildApplications + Section5-FrameworkComponents + Section6-DevelopingApplications + Section7-AdvancedFunctionality + Section8-GeneralizedMatVecInterface + Section9-ApplicationModules + Section10-Examples .. toctree:: :maxdepth: 1 diff --git a/python/pybind11 b/python/pybind11 index 80d452484..c761608a2 160000 --- a/python/pybind11 +++ b/python/pybind11 @@ -1 +1 @@ -Subproject commit 80d452484c5409444b0ec19383faa84bb7a4d351 +Subproject commit c761608a22b956e51218f4360661b0135dca3b7f diff --git a/python/pyproject.toml b/python/pyproject.toml new file mode 100644 index 000000000..c66b93789 --- /dev/null +++ b/python/pyproject.toml @@ -0,0 +1,4 @@ +[build-system] +requires = ["setuptools>=40.8.0", "wheel", "mpi4py"] +build-backend = "setuptools.build_meta" +