Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 215 additions & 0 deletions .github/workflows/build-openmm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# This workflow is based on: https://github.com/openmm/openmm-build-wheels/blob/db996361bca08a147c00f79dd4de8793d721fe34/.github/workflows/BuildWheels.yml
name: Build openmm wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'Version glob to (re)build; empty builds every version of docs/packages/openmm.yaml not released yet'
required: false
default: ''
pull_request:
branches: [main]
paths:
- '.github/workflows/build-openmm.yml'
- 'docs/packages/openmm.yaml'
- 'patches/openmm/**'
push:
branches: [main]
paths:
- '.github/workflows/build-openmm.yml'
- 'docs/packages/openmm.yaml'
- 'patches/openmm/**'

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

permissions:
contents: read

env:
OPENMM_BUILD_WHEELS_REF: db996361bca08a147c00f79dd4de8793d721fe34

jobs:
setup:
uses: $/.github/workflows/_setup.yml
with:
package: openmm
version: ${{ inputs.version }}

build_wheels:
name: Build openmm ${{ matrix.version }} manylinux_riscv64
needs: [setup]
if: needs.setup.outputs.versions != '[]'
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
env:
OPENMM_VERSION: ${{ matrix.version }}
PYTHON_TAGS: cp312 cp313 cp314
runs-on: ubuntu-24.04-riscv
timeout-minutes: 720
container:
image: quay.io/pypa/manylinux_2_39_riscv64

steps:
- name: Checkout openmm ${{ env.OPENMM_VERSION }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: openmm/openmm
ref: ${{ env.OPENMM_VERSION }}
path: openmm
persist-credentials: false

- name: Checkout openmm-build-wheels
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: openmm/openmm-build-wheels
ref: ${{ env.OPENMM_BUILD_WHEELS_REF }}
path: openmm-build-wheels
persist-credentials: false

- name: Checkout python-wheels
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: python-wheels
persist-credentials: false

- name: Install dependencies with dnf
run: dnf -y install doxygen zip opencl-headers ocl-icd

- name: Patch openmm source
working-directory: openmm
run: |
git apply "$GITHUB_WORKSPACE"/python-wheels/patches/openmm/"$OPENMM_VERSION"/*.patch
git apply "$GITHUB_WORKSPACE"/openmm-build-wheels/devtools/patches/library_path.patch
git apply "$GITHUB_WORKSPACE"/openmm-build-wheels/devtools/patches/cxx11_abi.patch
git apply "$GITHUB_WORKSPACE"/openmm-build-wheels/devtools/patches/link_args.patch

- name: Configure build with CMake
run: |
set -euxo pipefail
/opt/python/cp312-cp312/bin/python -m pip install --extra-index-url https://pypi.riseproject.dev/simple/ --only-binary=numpy \
swig cython numpy setuptools wheel delocate
export PATH="/opt/python/cp312-cp312/bin:$PATH"
# BUILD_TESTING=OFF: upstream's wheel job compiles the ctest suite but never runs it.
cmake -S openmm -B openmm/build \
-DCMAKE_INSTALL_PREFIX="${HOME}/openmm-install" \
-DCMAKE_CXX_FLAGS='-D_GLIBCXX_USE_CXX11_ABI=1' \
-DOPENMM_BUILD_OPENCL_LIB=ON \
-DOPENCL_INCLUDE_DIR=/usr/include/CL \
-DOPENCL_LIBRARY=/usr/lib64/libOpenCL.so.1 \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DBUILD_TESTING=OFF \
-DPYTHON_EXECUTABLE=/opt/python/cp312-cp312/bin/python

- name: Build OpenMM
working-directory: openmm/build
run: |
export PATH="/opt/python/cp312-cp312/bin:$PATH"
make -j"$(nproc)" install

- name: Build wheels
run: |
set -euxo pipefail
export PATH="/opt/python/cp312-cp312/bin:$PATH"
export LD_LIBRARY_PATH="${HOME}/openmm-install/lib"
mkdir -p wheelhouse
for tag in $PYTHON_TAGS; do
py="/opt/python/${tag}-${tag}/bin/python"
"$py" -m pip install --extra-index-url https://pypi.riseproject.dev/simple/ --only-binary=numpy \
cython numpy setuptools wheel delocate
cmake -S openmm -B openmm/build -DPYTHON_EXECUTABLE="$py"
rm -rf openmm/build/python/dist
make -C openmm/build PythonBdistWheel
(
cd openmm/build/python/dist
ls ./*.whl
"$py" "$GITHUB_WORKSPACE"/openmm-build-wheels/devtools/scripts/add_plugins_and_headers.py "${HOME}/openmm-install" "!CUDA" "!HIP"
)
auditwheel repair -w wheelhouse -L ".libs/lib" --plat manylinux_2_39_riscv64 openmm/build/python/dist/*.whl \
--exclude libOpenMM.so \
--exclude libOpenMMOpenCL.so \
--exclude libOpenMMDrude.so \
--exclude libOpenMMAmoeba.so \
--exclude libOpenMMRPMD.so \
--exclude libOpenCL.so.1
"$py" -m zipfile -l wheelhouse/openmm-*-"${tag}"-*.whl | grep -F licenses/Licenses.txt
done
ls -la wheelhouse

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: openmm-${{ env.OPENMM_VERSION }}-wheels-manylinux_riscv64
path: wheelhouse/*.whl
if-no-files-found: error

test_wheels:
name: Test openmm ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64
needs: [setup, build_wheels]
if: needs.setup.outputs.versions != '[]'
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
python: ["cp312", "cp313", "cp314"]
env:
OPENMM_VERSION: ${{ matrix.version }}
runs-on: ubuntu-24.04-riscv
timeout-minutes: 360
container:
image: quay.io/pypa/manylinux_2_39_riscv64

steps:
- name: Checkout openmm ${{ env.OPENMM_VERSION }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: openmm/openmm
ref: ${{ env.OPENMM_VERSION }}
sparse-checkout: wrappers/python/tests
persist-credentials: false

- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: openmm-${{ env.OPENMM_VERSION }}-wheels-manylinux_riscv64
path: wheelhouse

- name: Install dependencies with dnf
run: dnf -y install ocl-icd

- name: Test the wheel
run: |
set -euxo pipefail
"/opt/python/${{ matrix.python }}-${{ matrix.python }}/bin/python" -m venv "${RUNNER_TEMP}/test_env"
source "${RUNNER_TEMP}/test_env/bin/activate"
pip install --extra-index-url https://pypi.riseproject.dev/simple/ --only-binary=numpy \
wheelhouse/openmm-*-${{ matrix.python }}-*.whl pytest pytest-xdist
python -m openmm.testInstallation
python -c "import openmm as mm; print(mm.version.openmm_library_path)"
python -c "import openmm as mm; print('---Loaded---', *mm.pluginLoadedLibNames, '---Failed---', *mm.Platform.getPluginLoadFailures(), sep='\n')"
python -c "import openmm as mm; mm.Platform.getPlatformByName('CPU')"
cp -r wrappers/python/tests "${RUNNER_TEMP}/tests"
cd "${RUNNER_TEMP}/tests"
python -m pytest -v -n auto

publish:
name: Publish openmm ${{ matrix.version }}
needs: [setup, test_wheels]
if: needs.setup.outputs.versions != '[]'
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
permissions:
contents: write
pull-requests: write
uses: $/.github/workflows/_publish-wheel.yml
secrets:
app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }}
with:
artifact-pattern: openmm-${{ matrix.version }}-*-manylinux_riscv64
6 changes: 6 additions & 0 deletions docs/packages/openmm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package-name: openmm
source-code: https://github.com/openmm/openmm
license: MIT AND LGPL-3.0-or-later
versions:
- version: 8.6.0
patched: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Fri, 2 Oct 2026 23:49:48 +0000
Subject: [PATCH] python: ship the licence texts in the wheel

The Python wheel carries no licence file at all: dist-info has only
METADATA/WHEEL/RECORD/top_level.txt, and OpenMM.libs/ holds the core
libraries and plugins without any notice. The MIT licence covering the
API, Reference and CPU platforms requires the notice to accompany
copies, the OpenCL plugins in the wheel are LGPL, and the bundled
SFMT, Hilbert, irrXML, L-BFGS and VkFFT code carry their own notices --
all of which upstream already collects in docs-source/licenses/.

Stage that directory next to setup.py and list it in license_files, so
Licenses.txt, LGPL.txt and GPL.txt land in dist-info/licenses.

Upstream's own PyPI wheels have the same gap on every platform.

Upstream-Status: To upstream [not submitted from this automated port run; needs a pull request against openmm/openmm]
---
wrappers/python/CMakeLists.txt | 1 +
wrappers/python/setup.py | 1 +
2 files changed, 2 insertions(+)

diff --git a/wrappers/python/CMakeLists.txt b/wrappers/python/CMakeLists.txt
index b7400fa..93d72bf 100644
--- a/wrappers/python/CMakeLists.txt
+++ b/wrappers/python/CMakeLists.txt
@@ -13,6 +13,7 @@ file(MAKE_DIRECTORY ${OPENMM_PYTHON_STAGING_DIR}/simtk/openmm)
file(MAKE_DIRECTORY ${OPENMM_PYTHON_STAGING_DIR}/simtk/unit)
file(MAKE_DIRECTORY ${OPENMM_PYTHON_STAGING_DIR}/src/swig_doxygen/swig_lib/python)
file(MAKE_DIRECTORY ${OPENMM_PYTHON_STAGING_DIR}/tests)
+file(COPY "${CMAKE_SOURCE_DIR}/docs-source/licenses/" DESTINATION "${OPENMM_PYTHON_STAGING_DIR}/licenses")

##############################################################################
### Identify files that need to be copied from source area to staging area ###
diff --git a/wrappers/python/setup.py b/wrappers/python/setup.py
index 356e6de..f008244 100644
--- a/wrappers/python/setup.py
+++ b/wrappers/python/setup.py
@@ -135,6 +135,7 @@ def buildKeywordDictionary(major_version_num=MAJOR_VERSION_NUM,
setupKeywords["author"] = "Peter Eastman"
setupKeywords["license"] = \
"Python Software Foundation License (BSD-like)"
+ setupKeywords["license_files"] = ["licenses/*.txt"]
setupKeywords["url"] = "https://openmm.org"
setupKeywords["download_url"] = "https://openmm.org"
setupKeywords["packages"] = [
--
2.43.0

Loading