Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e54ffe3
build(wheel): split libcuopt into per-component wheels
ramakrishnap-nv Sep 17, 2026
e9220dc
build(wheel): regenerate the component build scripts from current main
ramakrishnap-nv Sep 18, 2026
8655cd2
build(wheel): fix the dependency file keys and cross-wheel library re…
ramakrishnap-nv Sep 18, 2026
df5d1cc
ci(wheel): build and publish the component wheels
ramakrishnap-nv Sep 18, 2026
3b1d771
ci(wheel): teach validate_wheel.sh the component package dirs
ramakrishnap-nv Sep 19, 2026
7571355
review: document and annotate the new public loaders
ramakrishnap-nv Sep 19, 2026
5189588
build(wheel): make libcuopt depend on the component wheels
ramakrishnap-nv Sep 20, 2026
4b3b2f8
ci(wheel): resolve the component wheels wherever libcuopt is installed
ramakrishnap-nv Sep 21, 2026
868560b
build(wheel): keep the libraries in libcuopt for now
ramakrishnap-nv Sep 21, 2026
2335024
review: drop the cross-wheel RPATH entries
ramakrishnap-nv Sep 21, 2026
18079b1
build(wheel): stop setting install.components on the libcuopt wheel
ramakrishnap-nv Sep 21, 2026
a29984c
build(wheel): drop changes this PR no longer needs
ramakrishnap-nv Sep 21, 2026
27fa7ec
ci(wheel): stop serialising wheel-build-cuopt behind the component bu…
ramakrishnap-nv Sep 21, 2026
6202f85
chore: drop a build backup committed by mistake
ramakrishnap-nv Sep 21, 2026
a42cc67
chore: drop more rapids-build-backend output committed by mistake
ramakrishnap-nv Sep 21, 2026
ebbda42
ci(wheel): publish the client wheel before mathopt and routing
ramakrishnap-nv Sep 21, 2026
acc9df4
fix(wheel): restore the unsuffixed project name
ramakrishnap-nv Sep 21, 2026
7773a9d
WIP build(cmake): give each component its own CMake export
ramakrishnap-nv Sep 21, 2026
e189cc9
build(cmake): export each component separately so wheels can resolve …
ramakrishnap-nv Sep 22, 2026
bd1bccb
Merge remote-tracking branch 'origin/main' into feat/split-wheels
ramakrishnap-nv Sep 22, 2026
0bea735
fix(wheel): ship the cuDSS threading layer and let executables find t…
ramakrishnap-nv Sep 22, 2026
e85ad59
fix(cmake): give the build export the same per-component targets files
ramakrishnap-nv Sep 22, 2026
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
126 changes: 126 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,132 @@ jobs:
package-name: libcuopt
package-type: cpp
publish-wheel-search-key: cuopt_wheel_cpp_libcuopt
wheel-build-libcuopt-client:
permissions:
actions: read
contents: read
id-token: write
packages: read
pull-requests: read
needs: [build-details]
secrets: inherit # zizmor: ignore[secrets-inherit]
uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@release/26.10
with:
build_type: ${{ inputs.build_type || 'branch' }}
build-datetime: ${{ needs.build-details.outputs.build-datetime }}
branch: ${{ inputs.branch }}
sha: ${{ inputs.sha }}
date: ${{ inputs.date }}
script: ci/build_wheel_libcuopt_client.sh
package-name: libcuopt_client
package-type: cpp
matrix_filter: group_by([.ARCH, (.CUDA_VER|split(".")|map(tonumber)|.[0])]) | map(max_by(.PY_VER|split(".")|map(tonumber)))
wheel-publish-libcuopt-client:
needs: wheel-build-libcuopt-client
permissions:
actions: read
contents: read
id-token: write
packages: read
pull-requests: read
uses: rapidsai/shared-workflows/.github/workflows/wheels-publish.yaml@release/26.10
secrets:
CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN: ${{ secrets.CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN }}
RAPIDSAI_PYPI_TOKEN: ${{ secrets.RAPIDSAI_PYPI_TOKEN }}
with:
build_type: ${{ inputs.build_type || 'branch' }}
branch: ${{ inputs.branch }}
sha: ${{ inputs.sha }}
date: ${{ inputs.date }}
package-name: libcuopt_client
package-type: cpp
publish-wheel-search-key: cuopt_wheel_cpp_libcuopt_client
wheel-build-libcuopt-mathopt:
permissions:
actions: read
contents: read
id-token: write
packages: read
pull-requests: read
needs: [build-details]
secrets: inherit # zizmor: ignore[secrets-inherit]
uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@release/26.10
with:
build_type: ${{ inputs.build_type || 'branch' }}
build-datetime: ${{ needs.build-details.outputs.build-datetime }}
branch: ${{ inputs.branch }}
sha: ${{ inputs.sha }}
date: ${{ inputs.date }}
script: ci/build_wheel_libcuopt_mathopt.sh
package-name: libcuopt_mathopt
package-type: cpp
matrix_filter: group_by([.ARCH, (.CUDA_VER|split(".")|map(tonumber)|.[0])]) | map(max_by(.PY_VER|split(".")|map(tonumber)))
wheel-publish-libcuopt-mathopt:
# Waits on the client's publication as well: this wheel declares
# libcuopt-client as a dependency, so publishing first would leave a clean
# install unable to resolve it.
needs: [wheel-build-libcuopt-mathopt, wheel-publish-libcuopt-client]
permissions:
actions: read
contents: read
id-token: write
packages: read
pull-requests: read
uses: rapidsai/shared-workflows/.github/workflows/wheels-publish.yaml@release/26.10
secrets:
CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN: ${{ secrets.CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN }}
RAPIDSAI_PYPI_TOKEN: ${{ secrets.RAPIDSAI_PYPI_TOKEN }}
with:
build_type: ${{ inputs.build_type || 'branch' }}
branch: ${{ inputs.branch }}
sha: ${{ inputs.sha }}
date: ${{ inputs.date }}
package-name: libcuopt_mathopt
package-type: cpp
publish-wheel-search-key: cuopt_wheel_cpp_libcuopt_mathopt
wheel-build-libcuopt-routing:
permissions:
actions: read
contents: read
id-token: write
packages: read
pull-requests: read
needs: [build-details]
secrets: inherit # zizmor: ignore[secrets-inherit]
uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@release/26.10
with:
build_type: ${{ inputs.build_type || 'branch' }}
build-datetime: ${{ needs.build-details.outputs.build-datetime }}
branch: ${{ inputs.branch }}
sha: ${{ inputs.sha }}
date: ${{ inputs.date }}
script: ci/build_wheel_libcuopt_routing.sh
package-name: libcuopt_routing
package-type: cpp
matrix_filter: group_by([.ARCH, (.CUDA_VER|split(".")|map(tonumber)|.[0])]) | map(max_by(.PY_VER|split(".")|map(tonumber)))
wheel-publish-libcuopt-routing:
# Waits on the client's publication as well: this wheel declares
# libcuopt-client as a dependency, so publishing first would leave a clean
# install unable to resolve it.
needs: [wheel-build-libcuopt-routing, wheel-publish-libcuopt-client]
permissions:
actions: read
contents: read
id-token: write
packages: read
pull-requests: read
uses: rapidsai/shared-workflows/.github/workflows/wheels-publish.yaml@release/26.10
secrets:
CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN: ${{ secrets.CONDA_RAPIDSAI_WHEELS_NIGHTLY_TOKEN }}
RAPIDSAI_PYPI_TOKEN: ${{ secrets.RAPIDSAI_PYPI_TOKEN }}
with:
build_type: ${{ inputs.build_type || 'branch' }}
branch: ${{ inputs.branch }}
sha: ${{ inputs.sha }}
date: ${{ inputs.date }}
package-name: libcuopt_routing
package-type: cpp
publish-wheel-search-key: cuopt_wheel_cpp_libcuopt_routing
wheel-build-cuopt:
needs: [build-details, wheel-build-libcuopt]
permissions:
Expand Down
60 changes: 60 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ jobs:
- docs-build
- multi-gpu-cpp-tests
- wheel-build-libcuopt
- wheel-build-libcuopt-client
- wheel-build-libcuopt-mathopt
- wheel-build-libcuopt-routing
- wheel-build-cuopt
- wheel-tests-cuopt
- wheel-build-cuopt-server
Expand Down Expand Up @@ -608,6 +611,63 @@ jobs:
build_type: pull-request
build-datetime: ${{ needs.build-details.outputs.build-datetime }}
script: ci/build_wheel_libcuopt.sh
wheel-build-libcuopt-client:
needs: [build-details, compute-matrix-filters, changed-files]
if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels
permissions:
actions: read
contents: read
id-token: write
packages: read
pull-requests: read
secrets: inherit # zizmor: ignore[secrets-inherit]
uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@release/26.10
with:
# Same filter as libcuopt: every arch and CUDA version, latest Python only.
matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }}
package-type: cpp
package-name: libcuopt_client
build_type: pull-request
build-datetime: ${{ needs.build-details.outputs.build-datetime }}
script: ci/build_wheel_libcuopt_client.sh
wheel-build-libcuopt-mathopt:
needs: [build-details, compute-matrix-filters, changed-files]
if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels
permissions:
actions: read
contents: read
id-token: write
packages: read
pull-requests: read
secrets: inherit # zizmor: ignore[secrets-inherit]
uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@release/26.10
with:
# Same filter as libcuopt: every arch and CUDA version, latest Python only.
matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }}
package-type: cpp
package-name: libcuopt_mathopt
build_type: pull-request
build-datetime: ${{ needs.build-details.outputs.build-datetime }}
script: ci/build_wheel_libcuopt_mathopt.sh
wheel-build-libcuopt-routing:
needs: [build-details, compute-matrix-filters, changed-files]
if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels
permissions:
actions: read
contents: read
id-token: write
packages: read
pull-requests: read
secrets: inherit # zizmor: ignore[secrets-inherit]
uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@release/26.10
with:
# Same filter as libcuopt: every arch and CUDA version, latest Python only.
matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }}
package-type: cpp
package-name: libcuopt_routing
build_type: pull-request
build-datetime: ${{ needs.build-details.outputs.build-datetime }}
script: ci/build_wheel_libcuopt_routing.sh
wheel-build-cuopt:
needs: [build-details, wheel-build-libcuopt, compute-matrix-filters, changed-files]
if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels
Expand Down
133 changes: 133 additions & 0 deletions ci/build_wheel_libcuopt_client.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/bin/bash
# SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

set -euo pipefail

# Same full C++ configure as every other cuOpt wheel; only the install components
# staged into it differ, set by install.components in this package's pyproject.toml.
# Kept in step with ci/build_wheel_libcuopt.sh -- regenerate all four together.

source rapids-init-pip

package_name="libcuopt_client"
package_dir="python/libcuopt_client"

# Install rockylinux repo
if command -v dnf &> /dev/null; then
bash ci/utils/update_rockylinux_repo.sh
fi

# Install Boost and TBB
bash ci/utils/install_boost_tbb.sh

# Install libuuid (needed by cuopt_grpc_server)
if command -v dnf &> /dev/null; then
dnf install -y libuuid-devel
elif command -v apt-get &> /dev/null; then
apt-get update
apt-get install -y uuid-dev
fi

# Install Protobuf + gRPC (protoc + grpc_cpp_plugin)
bash ci/utils/install_protobuf_grpc.sh

# Compile against a modern GNU libgomp from conda-forge instead of bundled LLVM libomp, to
# unify cuOpt's OpenMP runtime with the one cuDSS's threading layer needs (#1219).
MODERN_LIBGOMP_DIR="$(pwd)/modern_libgomp"
python -m pip install --quiet zstandard
python ci/utils/install_modern_libgomp.py "${MODERN_LIBGOMP_DIR}"

# Also build our own cuDSS threading layer against this same libgomp (see cpp/CMakeLists.txt,
# cpp/src/barrier/cudss_mtlayer_cuopt.cpp), instead of cuDSS's prebuilt one, so both actually
# share one instance, not just the same flavor. Conda keeps cuDSS's default (#1219 discussion).
export SKBUILD_CMAKE_ARGS="-DOpenMP_gomp_LIBRARY:FILEPATH=${MODERN_LIBGOMP_DIR}/libgomp.so.1.0.0;-DCUOPT_BUILD_CUSTOM_CUDSS_MTLAYER=ON"

# auditwheel repair does its own dependency resolution separately from the compiler; without
# this it can't see our fetched copy and silently vendors the old Rocky 8 system one instead.
export LD_LIBRARY_PATH="${MODERN_LIBGOMP_DIR}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"

# OpenSSL 3 hints for libcuopt's own find_package(OpenSSL).
#
# install_protobuf_grpc.sh links gRPC against OpenSSL 3 (see that script for
# rationale). libcuopt then re-resolves OpenSSL via find_package because
# gRPC's imported targets propagate it transitively. On Rocky/RHEL 8 the
# EPEL openssl3-devel package installs in non-default paths, so we have to
# point CMake at them; on Rocky/RHEL 9+ and Ubuntu 22.04+ the default
# OpenSSL is already 3.x and no hints are needed.
if [ -f /etc/os-release ]; then
. /etc/os-release
if [[ "$ID" == "rocky" || "$ID" == "centos" || "$ID" == "rhel" || "$ID" == "fedora" ]] && \
[[ "${VERSION_ID%%.*}" == "8" ]]; then
SKBUILD_CMAKE_ARGS="${SKBUILD_CMAKE_ARGS};-DOPENSSL_INCLUDE_DIR=/usr/include/openssl3;-DOPENSSL_SSL_LIBRARY=/usr/lib64/openssl3/libssl.so;-DOPENSSL_CRYPTO_LIBRARY=/usr/lib64/openssl3/libcrypto.so"
fi
fi

# For pull requests we are enabling assert mode.
if [ "$RAPIDS_BUILD_TYPE" = "pull-request" ]; then
echo "Building in assert mode"
export SKBUILD_CMAKE_ARGS="${SKBUILD_CMAKE_ARGS};-DDEFINE_ASSERT=True"
else
echo "Building in release mode"
fi

# Install cudss
bash ci/utils/install_cudss.sh

rapids-logger "Generating build requirements"

rapids-dependency-file-generator \
--output requirements \
--file-key "py_build_${package_name}" \
--file-key "py_rapids_build_${package_name}" \
--matrix "cuda=${RAPIDS_CUDA_VERSION%.*};arch=$(arch);py=${RAPIDS_PY_VERSION};cuda_suffixed=true;use_cuda_wheels=true" \
| tee /tmp/requirements-build.txt

rapids-logger "Installing build requirements"
rapids-pip-retry install \
-v \
--prefer-binary \
-r /tmp/requirements-build.txt

# build with '--no-build-isolation', for better sccache hit rate
# 0 really means "add --no-build-isolation" (ref: https://github.com/pypa/pip/issues/5735)
export PIP_NO_BUILD_ISOLATION=0


EXCLUDE_ARGS=(
--exclude "libraft.so"
--exclude "libcublas.so.*"
--exclude "libcublasLt.so.*"
--exclude "libcuda.so.1"
--exclude "libcudss.so.*"
--exclude "libcurand.so.*"
--exclude "libcusolver.so.*"
--exclude "libcusparse.so.*"
--exclude "libnccl.so.*"
--exclude "libnvJitLink.so*"
--exclude "librapids_logger.so"
--exclude "librmm.so"
# Provided by the sibling libcuopt-* wheels, so they must not be vendored here: doing so
# would ship several copies of each engine and defeat the split. RPATH resolves them.
--exclude "libcuopt_client.so"
--exclude "libcuopt_mathopt.so"
--exclude "libcuopt_routing.so"
# OpenSSL 3 is intentionally NOT bundled. Resolving libssl.so.3 / libcrypto.so.3
# at runtime via the host (or container image) keeps libcrypto and the FIPS
# provider (system or mounted) byte-version-matched, which is required for
# the FIPS provider's HMAC integrity check and avoids loading two libcrypto.so.3
# in the same process. Hosts must provide libssl.so.3 / libcrypto.so.3 (Ubuntu
# 22.04+, RHEL/Rocky 9+, manylinux_2_28+ with openssl3, Debian 12+).
--exclude "libssl.so.3"
--exclude "libcrypto.so.3"
)

ci/build_wheel.sh ${package_name} ${package_dir}

mkdir -p final_dist
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_cpp libcuopt_client cuopt --cuda "$RAPIDS_CUDA_VERSION")"
export RAPIDS_PACKAGE_NAME
Loading
Loading