Skip to content
Merged
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
2 changes: 2 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ jobs:
script: ci/build_wheel_cuopt.sh
package-name: cuopt
package-type: python
# Build a wheel for each CUDA x ARCH x minimum supported Python version
matrix_filter: group_by({CUDA_VER, ARCH}) | map(min_by(.PY_VER | split(".") | map(tonumber)))
wheel-publish-cuopt:
needs: wheel-build-cuopt
permissions:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ jobs:
runs-on: ubuntu-latest
outputs:
libcuopt_filter: ${{ steps.set-filters.outputs.libcuopt_filter }}
cuopt_filter: ${{ steps.set-filters.outputs.cuopt_filter }}
cuopt_server_filter: ${{ steps.set-filters.outputs.cuopt_server_filter }}
cuopt_server_test_filter: ${{ steps.set-filters.outputs.cuopt_server_test_filter }}
cuopt_sh_client_filter: ${{ steps.set-filters.outputs.cuopt_sh_client_filter }}
Expand All @@ -56,6 +57,7 @@ jobs:
id: set-filters
run: |
echo "libcuopt_filter=group_by([.ARCH, (.CUDA_VER|split(\".\")|map(tonumber)|.[0])]) | map(max_by(.PY_VER|split(\".\")|map(tonumber)))" >> $GITHUB_OUTPUT
echo "cuopt_filter=group_by({CUDA_VER, ARCH}) | map(min_by(.PY_VER | split(\".\") | map(tonumber)))" >> $GITHUB_OUTPUT
echo "cuopt_server_filter=map(select(.ARCH == \"amd64\")) | group_by(.CUDA_VER|split(\".\")|map(tonumber)|.[0]) | map(max_by([(.PY_VER|split(\".\")|map(tonumber)), (.CUDA_VER|split(\".\")|map(tonumber))]))" >> $GITHUB_OUTPUT
echo "cuopt_server_test_filter=map(select(.ARCH == \"amd64\")) | group_by(.CUDA_VER | split(\".\") | map(tonumber) | .[0]) | map(max_by([(.PY_VER | split(\".\") | map(tonumber)), (.CUDA_VER | split(\".\") | map(tonumber))]))" >> $GITHUB_OUTPUT
echo "cuopt_sh_client_filter=[map(select(.ARCH == \"amd64\")) | min_by((.PY_VER | split(\".\") | map(tonumber)), (.CUDA_VER | split(\".\") | map(-tonumber)))]" >> $GITHUB_OUTPUT
Expand Down Expand Up @@ -479,6 +481,8 @@ jobs:
script: ci/build_wheel_cuopt.sh
package-name: cuopt
package-type: python
# Build a wheel for each CUDA x ARCH x minimum supported Python version
matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_filter }}
wheel-tests-cuopt:
needs: [wheel-build-cuopt, wheel-build-cuopt-sh-client, changed-files]
permissions:
Expand Down
3 changes: 3 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ To build all libraries and tests, simply run
```

- **Note**: if Cython files (`*.pyx` or `*.pxd`) have changed, the Python build must be rerun.
- **Note**: the `cuopt` wheel is built against the CPython Limited API (abi3), so Cython code must
use only APIs the Limited API exposes. An unsupported API fails to compile under
`-DPy_LIMITED_API` rather than failing at runtime.

To run the C++ tests, run

Expand Down
21 changes: 21 additions & 0 deletions ci/build_wheel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ set -euo pipefail

package_name=$1
package_dir=$2
shift 2

# Parse optional flags
stable_abi=false
while [[ $# -gt 0 ]]; do
case "$1" in
--stable)
stable_abi=true
shift
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done

source rapids-configure-sccache
source rapids-datetime-string
Expand All @@ -29,6 +45,11 @@ RAPIDS_PIP_WHEEL_ARGS=(
--disable-pip-version-check
)

# Add py-api setting for stable ABI builds
if [[ "${stable_abi}" == "true" ]] && [[ -n "${RAPIDS_PY_API:-}" ]]; then
RAPIDS_PIP_WHEEL_ARGS+=(--config-settings="skbuild.wheel.py-api=${RAPIDS_PY_API}")
fi

# Only use --build-constraint when build isolation is enabled.
#
# Passing '--build-constraint' and '--no-build-isolation` together results in an error from 'pip',
Expand Down
9 changes: 7 additions & 2 deletions ci/build_wheel_cuopt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,17 @@ EXCLUDE_ARGS=(
--exclude "librmm.so"
)

ci/build_wheel.sh cuopt ${package_dir}
# TODO: move this variable into `ci-wheel`
# Format Python limited API version string
RAPIDS_PY_API="cp${RAPIDS_PY_VERSION//./}"
export RAPIDS_PY_API

ci/build_wheel.sh cuopt ${package_dir} --stable

# repair wheels and write to the location that artifact-uploading code expects to find them
python -m auditwheel repair "${EXCLUDE_ARGS[@]}" -w ${RAPIDS_WHEEL_BLD_OUTPUT_DIR} ${package_dir}/dist/*

ci/validate_wheel.sh "${package_dir}" "${RAPIDS_WHEEL_BLD_OUTPUT_DIR}"

RAPIDS_PACKAGE_NAME="$(rapids-artifact-name wheel_python cuopt cuopt --py "$RAPIDS_PY_VERSION" --cuda "$RAPIDS_CUDA_VERSION")"
RAPIDS_PACKAGE_NAME="$(rapids-artifact-name wheel_python cuopt cuopt --stable --cuda "$RAPIDS_CUDA_VERSION")"
export RAPIDS_PACKAGE_NAME
2 changes: 1 addition & 1 deletion ci/test_self_hosted_service.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ source rapids-init-pip

# Download the cuopt built in the previous step
LIBCUOPT_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_cpp libcuopt cuopt --cuda "$RAPIDS_CUDA_VERSION")")
CUOPT_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_python cuopt cuopt --py "$RAPIDS_PY_VERSION" --cuda "$RAPIDS_CUDA_VERSION")")
CUOPT_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_python cuopt cuopt --stable --cuda "$RAPIDS_CUDA_VERSION")")
CUOPT_SERVER_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_python cuopt-server cuopt --pure --arch any --cuda "$RAPIDS_CUDA_VERSION")")

# generate constraints (possibly pinning to oldest support versions of dependencies)
Expand Down
2 changes: 1 addition & 1 deletion ci/test_wheel_cuopt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ bash "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/utils/install_openssl3_runtim
# Download the packages built in the previous step
RAPIDS_PY_CUDA_SUFFIX="$(rapids-wheel-ctk-name-gen "${RAPIDS_CUDA_VERSION}")"
LIBCUOPT_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_cpp libcuopt cuopt --cuda "$RAPIDS_CUDA_VERSION")")
CUOPT_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_python cuopt cuopt --py "$RAPIDS_PY_VERSION" --cuda "$RAPIDS_CUDA_VERSION")")
CUOPT_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_python cuopt cuopt --stable --cuda "$RAPIDS_CUDA_VERSION")")
CUOPT_SH_CLIENT_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_python cuopt-sh-client cuopt --pure --arch any)")

# update pip constraints.txt to ensure all future 'pip install' (including those in ci/thirdparty-testing)
Expand Down
2 changes: 1 addition & 1 deletion ci/test_wheel_cuopt_server.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ bash "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/utils/install_openssl3_runtim

# Download the packages built in the previous step
LIBCUOPT_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_cpp libcuopt cuopt --cuda "$RAPIDS_CUDA_VERSION")")
CUOPT_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_python cuopt cuopt --py "$RAPIDS_PY_VERSION" --cuda "$RAPIDS_CUDA_VERSION")")
CUOPT_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_python cuopt cuopt --stable --cuda "$RAPIDS_CUDA_VERSION")")
CUOPT_SERVER_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_python cuopt-server cuopt --pure --arch any --cuda "$RAPIDS_CUDA_VERSION")")
CUOPT_SH_CLIENT_WHEELHOUSE=$(rapids-download-from-github "$(rapids-artifact-name wheel_python cuopt-sh-client cuopt --pure --arch any)")

Expand Down
10 changes: 10 additions & 0 deletions ci/validate_wheel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,13 @@ rapids-logger "validate packages with 'twine'"
twine check \
--strict \
"$(echo "${wheel_dir_relative_path}"/*.whl)"

rapids-logger "validate packages with 'abi3audit'"

# 'abi3audit' fails on wheels with DSOs that lack an ABI tag (e.g. 'lib*' wheels).
# Filtering by '*abi*' avoids those.
find \
"${wheel_dir_relative_path}" \
-type f \
-name '*abi*' \
-exec abi3audit --strict --summary --verbose '{}' \+
2 changes: 1 addition & 1 deletion conda/environments/all_cuda-129_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies:
- cudf==26.10.*,>=0.0.0a0
- cupy>=14.0.1,!=14.1.0
- cxx-compiler
- cython>=3.0.3
- cython>=3.2.2,<3.3.0a0
- docutils>=0.21
- doxygen=1.9.1
- fastapi
Expand Down
2 changes: 1 addition & 1 deletion conda/environments/all_cuda-129_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies:
- cudf==26.10.*,>=0.0.0a0
- cupy>=14.0.1,!=14.1.0
- cxx-compiler
- cython>=3.0.3
- cython>=3.2.2,<3.3.0a0
- docutils>=0.21
- doxygen=1.9.1
- fastapi
Expand Down
2 changes: 1 addition & 1 deletion conda/environments/all_cuda-133_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies:
- cudf==26.10.*,>=0.0.0a0
- cupy>=14.0.1,!=14.1.0
- cxx-compiler
- cython>=3.0.3
- cython>=3.2.2,<3.3.0a0
- docutils>=0.21
- doxygen=1.9.1
- fastapi
Expand Down
2 changes: 1 addition & 1 deletion conda/environments/all_cuda-133_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies:
- cudf==26.10.*,>=0.0.0a0
- cupy>=14.0.1,!=14.1.0
- cxx-compiler
- cython>=3.0.3
- cython>=3.2.2,<3.3.0a0
- docutils>=0.21
- doxygen=1.9.1
- fastapi
Expand Down
2 changes: 1 addition & 1 deletion dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ dependencies:
common:
- output_types: [conda, requirements, pyproject]
packages:
- cython>=3.0.3
- cython>=3.2.2,<3.3.0a0
test_python_common:
common:
- output_types: [conda, requirements, pyproject]
Expand Down
3 changes: 2 additions & 1 deletion python/cuopt/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ minimum-version = "build-system.requires"
ninja.make-fallback = false
sdist.reproducible = true
wheel.packages = ["cuopt"]
wheel.py-api = "cp311" # overridden in CI builds by arguments from `ci/build_wheel_cuopt.sh`

[tool.scikit-build.metadata.version]
provider = "scikit_build_core.metadata.regex"
Expand All @@ -102,7 +103,7 @@ matrix-entry = "cuda_suffixed=true;use_cuda_wheels=true"
requires = [
"cmake>=4.0",
"cupy-cuda13x[ctk]>=14.0.1,!=14.1.0",
"cython>=3.0.3",
"cython>=3.2.2,<3.3.0a0",
"libcuopt==26.10.*,>=0.0.0a0",
"ninja",
"pylibraft==26.10.*,>=0.0.0a0",
Expand Down
1 change: 1 addition & 0 deletions skills/cuopt-developer/references/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ Follow YAGNI strictly here — flags, fallbacks, env-var overrides, and config k
A few non-YAGNI points worth keeping in mind:

- Prefer extending an existing script over adding a new one.
- For build/CI conventions shared across RAPIDS (wheel packaging, artifact naming, matrix filters), read the reference implementation in `rapidsai/rmm` or `NVIDIA/cudf` on `main` before writing anything. cuOpt's `ci/` scripts and shared-workflow inputs are near-copies of theirs, and gha-tools expects exact conventions — an equivalent-but-different local invention silently breaks the download side, which looks for the name the build side wrote.
- Validate inputs at the top, before any expensive work.
- One shell command per line over chained `&&`; no comments that restate the next line.
- Keep informational CI jobs (reporting, dashboards, comment posting) out of any required-checks list.
Expand Down
Loading