diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
new file mode 100644
index 0000000000..5412018400
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1,71 @@
+# syntax=docker/dockerfile:1.5
+# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+
+ARG BASE
+ARG PYTHON_PACKAGE_MANAGER=conda
+
+FROM ${BASE} as pip-base
+
+RUN apt update -y \
+ && DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends \
+ libboost-iostreams-dev \
+ libboost-serialization-dev \
+ libgrpc-dev \
+ libgrpc++-dev \
+ libprotobuf-dev \
+ protobuf-compiler \
+ protobuf-compiler-grpc \
+ libtbb-dev \
+ && rm -rf /tmp/* /var/tmp/* /var/cache/apt/* /var/lib/apt/lists/*;
+
+ENV DEFAULT_VIRTUAL_ENV=rapids
+ENV RAPIDS_LIBUCX_PREFER_SYSTEM_LIBRARY=true
+
+FROM ${BASE} as conda-base
+
+ENV DEFAULT_CONDA_ENV=rapids
+
+FROM ${PYTHON_PACKAGE_MANAGER}-base
+
+ARG TARGETARCH
+
+ARG CUDA
+ENV CUDAARCHS="RAPIDS"
+ENV CUDA_VERSION="${CUDA_VERSION:-${CUDA}}"
+
+ARG PYTHON_PACKAGE_MANAGER
+ENV PYTHON_PACKAGE_MANAGER="${PYTHON_PACKAGE_MANAGER}"
+
+ENV PYTHONSAFEPATH="1"
+ENV PYTHONUNBUFFERED="1"
+ENV PYTHONDONTWRITEBYTECODE="1"
+
+ENV HISTFILE="/home/coder/.cache/._bash_history"
+
+###
+# sccache configuration
+###
+ENV AWS_IDP_URL="https://token.rapids.nvidia.com"
+ENV AWS_ROLE_ARN="arn:aws:iam::279114543810:role/rapids-token-sccache-devs"
+ENV SCCACHE_REGION="us-east-2"
+ENV SCCACHE_BUCKET="rapids-sccache-devs"
+ENV SCCACHE_S3_USE_PREPROCESSOR_CACHE_MODE=true
+ENV SCCACHE_IDLE_TIMEOUT=0
+
+###
+# sccache-dist configuration
+###
+# Enable sccache-dist by default
+ENV DEVCONTAINER_UTILS_ENABLE_SCCACHE_DIST=1
+# Compile locally if max retries exceeded
+ENV SCCACHE_DIST_FALLBACK_TO_LOCAL_COMPILE=true
+# Retry transient errors 4 times (for a total of 5 attempts)
+ENV SCCACHE_DIST_MAX_RETRIES=4
+# 1hr 59min (to accommodate debug builds)
+ENV SCCACHE_DIST_REQUEST_TIMEOUT=7140
+ENV SCCACHE_DIST_URL="https://${TARGETARCH}.linux.sccache.rapids.nvidia.com"
+
+# Build as much in parallel as possible
+ENV INFER_NUM_DEVICE_ARCHITECTURES=1
+ENV MAX_DEVICE_OBJ_TO_COMPILE_IN_PARALLEL=20
diff --git a/.devcontainer/README.md b/.devcontainer/README.md
new file mode 100644
index 0000000000..476cff60f0
--- /dev/null
+++ b/.devcontainer/README.md
@@ -0,0 +1,60 @@
+# cuOpt Development Containers
+
+This directory contains [devcontainer configurations](https://containers.dev/implementors/json_reference/) for using VSCode to [develop in a container](https://code.visualstudio.com/docs/devcontainers/containers) via the `Remote Containers` [extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) or [GitHub Codespaces](https://github.com/codespaces).
+
+This container is a turnkey development environment for building and testing the cuOpt C++ and Python libraries.
+
+## Table of Contents
+
+* [Prerequisites](#prerequisites)
+* [Host bind mounts](#host-bind-mounts)
+* [Launch a Dev Container](#launch-a-dev-container)
+* [Using the devcontainer](#using-the-devcontainer)
+
+## Prerequisites
+
+* [VSCode](https://code.visualstudio.com/download)
+* [VSCode Remote Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
+
+## Host bind mounts
+
+By default, the following directories are bind-mounted into the devcontainer:
+
+* `${repo}:/home/coder/cuopt`
+* `${repo}/../.aws:/home/coder/.aws`
+* `${repo}/../.local:/home/coder/.local`
+* `${repo}/../.cache:/home/coder/.cache`
+* `${repo}/../.conda:/home/coder/.conda`
+* `${repo}/../.config:/home/coder/.config`
+
+This ensures caches, configurations, dependencies, and your commits are persisted on the host across container runs.
+
+## Launch a Dev Container
+
+To launch a devcontainer from VSCode, open the cuOpt repo and select the "Reopen in Container" button in the bottom right:
+
+Alternatively, open the VSCode command palette (typically `cmd/ctrl + shift + P`) and run the "Rebuild and Reopen in Container" command.
+
+## Using the devcontainer
+
+On startup, the devcontainer creates or updates the conda/pip environment using `cuopt/dependencies.yaml`.
+
+The container includes convenience functions to clean, configure, and build the cuOpt components:
+
+```shell
+$ clean-cuopt-cpp # only cleans the C++ build dir
+$ clean-cuopt-python # only cleans the Python build dir
+$ clean-cuopt # cleans both C++ and Python build dirs
+
+$ configure-cuopt-cpp # only configures cuOpt C++ lib
+
+$ build-cuopt-cpp # only builds cuOpt C++ lib
+$ build-cuopt-python # only builds cuOpt Python lib
+$ build-cuopt # builds both C++ and Python libs
+$ build-all # builds all libraries in this repo
+```
+
+* The C++ build script is a small wrapper around `cmake -S ~/cuopt/cpp -B ~/cuopt/cpp/build` and `cmake --build ~/cuopt/cpp/build`
+* The Python build script is a small wrapper around `pip install --editable ~/cuopt/python/cuopt`
+
+Unlike `build.sh`, these convenience scripts do not install the libraries after building them. Instead, they automatically inject the correct arguments to build the C++ libraries from source and use their build dirs as package roots.
diff --git a/.devcontainer/cuda12.9-conda/devcontainer.json b/.devcontainer/cuda12.9-conda/devcontainer.json
new file mode 100644
index 0000000000..534787af14
--- /dev/null
+++ b/.devcontainer/cuda12.9-conda/devcontainer.json
@@ -0,0 +1,44 @@
+{
+ "build": {
+ "context": "${localWorkspaceFolder}/.devcontainer",
+ "dockerfile": "${localWorkspaceFolder}/.devcontainer/Dockerfile",
+ "args": {
+ "CUDA": "12.9",
+ "PYTHON_PACKAGE_MANAGER": "conda",
+ "BASE": "rapidsai/devcontainers:26.06-cpp-mambaforge"
+ }
+ },
+ "runArgs": [
+ "--rm",
+ "--name",
+ "${localEnv:USER:anon}-rapids-${localWorkspaceFolderBasename}-26.06-cuda12.9-conda",
+ "--ulimit",
+ "nofile=500000"
+ ],
+ "hostRequirements": {"gpu": "optional"},
+ "features": {
+ "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils:26.6": {}
+ },
+ "overrideFeatureInstallOrder": [
+ "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils"
+ ],
+ "initializeCommand": ["/bin/bash", "-c", "mkdir -m 0755 -p ${localWorkspaceFolder}/../.{aws,cache,config,conda/pkgs,conda/${localWorkspaceFolderBasename}-cuda12.9-envs}"],
+ "postAttachCommand": ["/bin/bash", "-c", "if [ ${CODESPACES:-false} = 'true' ]; then . devcontainer-utils-post-attach-command; . rapids-post-attach-command; fi"],
+ "workspaceFolder": "/home/coder",
+ "workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/cuopt,type=bind,consistency=consistent",
+ "mounts": [
+ "source=${localWorkspaceFolder}/../.aws,target=/home/coder/.aws,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.cache,target=/home/coder/.cache,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.config,target=/home/coder/.config,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.conda/pkgs,target=/home/coder/.conda/pkgs,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.conda/${localWorkspaceFolderBasename}-cuda12.9-envs,target=/home/coder/.conda/envs,type=bind,consistency=consistent"
+ ],
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "ms-python.flake8",
+ "nvidia.nsight-vscode-edition"
+ ]
+ }
+ }
+}
diff --git a/.devcontainer/cuda12.9-pip/devcontainer.json b/.devcontainer/cuda12.9-pip/devcontainer.json
new file mode 100644
index 0000000000..b0e98ae436
--- /dev/null
+++ b/.devcontainer/cuda12.9-pip/devcontainer.json
@@ -0,0 +1,53 @@
+{
+ "build": {
+ "context": "${localWorkspaceFolder}/.devcontainer",
+ "dockerfile": "${localWorkspaceFolder}/.devcontainer/Dockerfile",
+ "args": {
+ "CUDA": "12.9",
+ "PYTHON_PACKAGE_MANAGER": "pip",
+ "BASE": "rapidsai/devcontainers:26.06-cpp-cuda12.9-ucx1.19.0-openmpi5.0.10"
+ }
+ },
+ "runArgs": [
+ "--rm",
+ "--name",
+ "${localEnv:USER:anon}-rapids-${localWorkspaceFolderBasename}-26.06-cuda12.9-pip",
+ "--ulimit",
+ "nofile=500000"
+ ],
+ "hostRequirements": {"gpu": "optional"},
+ "features": {
+ "ghcr.io/rapidsai/devcontainers/features/cuda:26.6": {
+ "version": "12.9",
+ "installcuBLAS": true,
+ "installcuDSS": true,
+ "installcuSOLVER": true,
+ "installcuRAND": true,
+ "installcuSPARSE": true
+ },
+ "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils:26.6": {}
+ },
+ "overrideFeatureInstallOrder": [
+ "ghcr.io/rapidsai/devcontainers/features/ucx",
+ "ghcr.io/rapidsai/devcontainers/features/cuda",
+ "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils"
+ ],
+ "initializeCommand": ["/bin/bash", "-c", "mkdir -m 0755 -p ${localWorkspaceFolder}/../.{aws,cache,config/pip,local/share/${localWorkspaceFolderBasename}-cuda12.9-venvs}"],
+ "postAttachCommand": ["/bin/bash", "-c", "if [ ${CODESPACES:-false} = 'true' ]; then . devcontainer-utils-post-attach-command; . rapids-post-attach-command; fi"],
+ "workspaceFolder": "/home/coder",
+ "workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/cuopt,type=bind,consistency=consistent",
+ "mounts": [
+ "source=${localWorkspaceFolder}/../.aws,target=/home/coder/.aws,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.cache,target=/home/coder/.cache,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.config,target=/home/coder/.config,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.local/share/${localWorkspaceFolderBasename}-cuda12.9-venvs,target=/home/coder/.local/share/venvs,type=bind,consistency=consistent"
+ ],
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "ms-python.flake8",
+ "nvidia.nsight-vscode-edition"
+ ]
+ }
+ }
+}
diff --git a/.devcontainer/cuda13.2-conda/devcontainer.json b/.devcontainer/cuda13.2-conda/devcontainer.json
new file mode 100644
index 0000000000..7f970ff7f1
--- /dev/null
+++ b/.devcontainer/cuda13.2-conda/devcontainer.json
@@ -0,0 +1,44 @@
+{
+ "build": {
+ "context": "${localWorkspaceFolder}/.devcontainer",
+ "dockerfile": "${localWorkspaceFolder}/.devcontainer/Dockerfile",
+ "args": {
+ "CUDA": "13.2",
+ "PYTHON_PACKAGE_MANAGER": "conda",
+ "BASE": "rapidsai/devcontainers:26.06-cpp-mambaforge"
+ }
+ },
+ "runArgs": [
+ "--rm",
+ "--name",
+ "${localEnv:USER:anon}-rapids-${localWorkspaceFolderBasename}-26.06-cuda13.2-conda",
+ "--ulimit",
+ "nofile=500000"
+ ],
+ "hostRequirements": {"gpu": "optional"},
+ "features": {
+ "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils:26.6": {}
+ },
+ "overrideFeatureInstallOrder": [
+ "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils"
+ ],
+ "initializeCommand": ["/bin/bash", "-c", "mkdir -m 0755 -p ${localWorkspaceFolder}/../.{aws,cache,config,conda/pkgs,conda/${localWorkspaceFolderBasename}-cuda13.2-envs}"],
+ "postAttachCommand": ["/bin/bash", "-c", "if [ ${CODESPACES:-false} = 'true' ]; then . devcontainer-utils-post-attach-command; . rapids-post-attach-command; fi"],
+ "workspaceFolder": "/home/coder",
+ "workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/cuopt,type=bind,consistency=consistent",
+ "mounts": [
+ "source=${localWorkspaceFolder}/../.aws,target=/home/coder/.aws,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.cache,target=/home/coder/.cache,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.config,target=/home/coder/.config,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.conda/pkgs,target=/home/coder/.conda/pkgs,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.conda/${localWorkspaceFolderBasename}-cuda13.2-envs,target=/home/coder/.conda/envs,type=bind,consistency=consistent"
+ ],
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "ms-python.flake8",
+ "nvidia.nsight-vscode-edition"
+ ]
+ }
+ }
+}
diff --git a/.devcontainer/cuda13.2-pip/devcontainer.json b/.devcontainer/cuda13.2-pip/devcontainer.json
new file mode 100644
index 0000000000..b74a649631
--- /dev/null
+++ b/.devcontainer/cuda13.2-pip/devcontainer.json
@@ -0,0 +1,53 @@
+{
+ "build": {
+ "context": "${localWorkspaceFolder}/.devcontainer",
+ "dockerfile": "${localWorkspaceFolder}/.devcontainer/Dockerfile",
+ "args": {
+ "CUDA": "13.2",
+ "PYTHON_PACKAGE_MANAGER": "pip",
+ "BASE": "rapidsai/devcontainers:26.06-cpp-cuda13.2-ucx1.19.0-openmpi5.0.10"
+ }
+ },
+ "runArgs": [
+ "--rm",
+ "--name",
+ "${localEnv:USER:anon}-rapids-${localWorkspaceFolderBasename}-26.06-cuda13.2-pip",
+ "--ulimit",
+ "nofile=500000"
+ ],
+ "hostRequirements": {"gpu": "optional"},
+ "features": {
+ "ghcr.io/rapidsai/devcontainers/features/cuda:26.6": {
+ "version": "13.2",
+ "installcuBLAS": true,
+ "installcuDSS": true,
+ "installcuSOLVER": true,
+ "installcuRAND": true,
+ "installcuSPARSE": true
+ },
+ "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils:26.6": {}
+ },
+ "overrideFeatureInstallOrder": [
+ "ghcr.io/rapidsai/devcontainers/features/ucx",
+ "ghcr.io/rapidsai/devcontainers/features/cuda",
+ "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils"
+ ],
+ "initializeCommand": ["/bin/bash", "-c", "mkdir -m 0755 -p ${localWorkspaceFolder}/../.{aws,cache,config/pip,local/share/${localWorkspaceFolderBasename}-cuda13.2-venvs}"],
+ "postAttachCommand": ["/bin/bash", "-c", "if [ ${CODESPACES:-false} = 'true' ]; then . devcontainer-utils-post-attach-command; . rapids-post-attach-command; fi"],
+ "workspaceFolder": "/home/coder",
+ "workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/cuopt,type=bind,consistency=consistent",
+ "mounts": [
+ "source=${localWorkspaceFolder}/../.aws,target=/home/coder/.aws,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.cache,target=/home/coder/.cache,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.config,target=/home/coder/.config,type=bind,consistency=consistent",
+ "source=${localWorkspaceFolder}/../.local/share/${localWorkspaceFolderBasename}-cuda13.2-venvs,target=/home/coder/.local/share/venvs,type=bind,consistency=consistent"
+ ],
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "ms-python.flake8",
+ "nvidia.nsight-vscode-edition"
+ ]
+ }
+ }
+}
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
index 474f5e2363..f59382060f 100644
--- a/.github/workflows/pr.yaml
+++ b/.github/workflows/pr.yaml
@@ -35,6 +35,7 @@ jobs:
- wheel-build-cuopt-mps-parser
- wheel-build-cuopt-sh-client
- test-self-hosted-server
+ - devcontainer
permissions:
contents: read
uses: rapidsai/shared-workflows/.github/workflows/pr-builder.yaml@main
@@ -159,6 +160,7 @@ jobs:
- '!.github/workflows/test.yaml'
- '!.github/workflows/test_images.yaml'
- '!.github/workflows/trigger-breaking-change-alert.yaml'
+ - '!.devcontainer/**'
- '!.gitignore'
- '!.pre-commit-config.yaml'
- '!AGENTS.md'
@@ -215,6 +217,7 @@ jobs:
- '!.github/workflows/test.yaml'
- '!.github/workflows/test_images.yaml'
- '!.github/workflows/trigger-breaking-change-alert.yaml'
+ - '!.devcontainer/**'
- '!.gitignore'
- '!.pre-commit-config.yaml'
- '!AGENTS.md'
@@ -279,6 +282,7 @@ jobs:
- '!.github/workflows/test.yaml'
- '!.github/workflows/test_images.yaml'
- '!.github/workflows/trigger-breaking-change-alert.yaml'
+ - '!.devcontainer/**'
- '!.gitignore'
- '!.pre-commit-config.yaml'
- '!AGENTS.md'
@@ -340,6 +344,7 @@ jobs:
- '!.github/workflows/test.yaml'
- '!.github/workflows/test_images.yaml'
- '!.github/workflows/trigger-breaking-change-alert.yaml'
+ - '!.devcontainer/**'
- '!.gitignore'
- '!.pre-commit-config.yaml'
- '!AGENTS.md'
@@ -627,3 +632,24 @@ jobs:
with:
build_type: pull-request
script: ci/test_self_hosted_service.sh
+ devcontainer:
+ 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/build-in-devcontainer.yaml@main
+ with:
+ arch: '["amd64", "arm64"]'
+ cuda: '["13.2"]'
+ node_type: "cpu8"
+ env: |
+ SCCACHE_DIST_MAX_RETRIES=inf
+ SCCACHE_SERVER_LOG=sccache=debug
+ SCCACHE_DIST_FALLBACK_TO_LOCAL_COMPILE=false
+ build_command: |
+ sccache --zero-stats;
+ build-all -j0 -DBUILD_MIP_BENCHMARKS=ON -DBUILD_LP_BENCHMARKS=ON --verbose
+ sccache --show-adv-stats
diff --git a/ci/release/update-version.sh b/ci/release/update-version.sh
index 9a67bb65a5..62ee313b72 100755
--- a/ci/release/update-version.sh
+++ b/ci/release/update-version.sh
@@ -143,6 +143,14 @@ for FILE in .github/workflows/*.yaml; do
sed_runner "s/:[0-9]*\\.[0-9]*-/:${NEXT_SHORT_TAG}-/g" "${FILE}"
done
+# .devcontainer files
+find .devcontainer/ -type f -name devcontainer.json -print0 | while IFS= read -r -d '' filename; do
+ sed_runner "s@rapidsai/devcontainers:[0-9.]*@rapidsai/devcontainers:${NEXT_SHORT_TAG}@g" "${filename}"
+ sed_runner "s@rapidsai/devcontainers/features/cuda:[0-9.]*@rapidsai/devcontainers/features/cuda:${NEXT_SHORT_TAG_PEP440}@" "${filename}"
+ sed_runner "s@rapidsai/devcontainers/features/rapids-build-utils:[0-9.]*@rapidsai/devcontainers/features/rapids-build-utils:${NEXT_SHORT_TAG_PEP440}@" "${filename}"
+ sed_runner "s@rapids-\${localWorkspaceFolderBasename}-[0-9.]*@rapids-\${localWorkspaceFolderBasename}-${NEXT_SHORT_TAG}@g" "${filename}"
+done
+
# Documentation references - context-aware
if [[ "${RUN_CONTEXT}" == "main" ]]; then
# In main context, keep external documentation on main (no changes needed)
diff --git a/ci/run_ctests.sh b/ci/run_ctests.sh
index 7cf7b60d03..275dbef87f 100755
--- a/ci/run_ctests.sh
+++ b/ci/run_ctests.sh
@@ -23,15 +23,20 @@ SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
source "${SCRIPT_DIR}/utils/crash_helpers.sh"
# Support customizing the gtests' install location
+script_dir="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
+repo_dir="$(realpath "${script_dir}/..")"
+export RAPIDS_DATASET_ROOT_DIR="${RAPIDS_DATASET_ROOT_DIR:-${repo_dir}/datasets}"
+export CUOPT_HOME="${CUOPT_HOME:-${repo_dir}}"
+
# First, try the installed location (CI/conda environments)
installed_test_location="${INSTALL_PREFIX:-${CONDA_PREFIX:-/usr}}/bin/gtests/libcuopt/"
# Fall back to the build directory (devcontainer environments)
-devcontainers_test_location="${SCRIPT_DIR}/../cpp/build/latest/gtests/libcuopt/"
+devcontainers_test_location="${repo_dir}/cpp/build/latest/gtests/libcuopt/"
if [[ -d "${installed_test_location}" ]]; then
- GTEST_DIR="${installed_test_location}"
+ cd "${installed_test_location}"
elif [[ -d "${devcontainers_test_location}" ]]; then
- GTEST_DIR="${devcontainers_test_location}"
+ cd "${devcontainers_test_location}"
else
echo "Error: Test location not found. Searched:" >&2
echo " - ${installed_test_location}" >&2
diff --git a/conda/environments/all_cuda-131_arch-aarch64.yaml b/conda/environments/all_cuda-132_arch-aarch64.yaml
similarity index 96%
rename from conda/environments/all_cuda-131_arch-aarch64.yaml
rename to conda/environments/all_cuda-132_arch-aarch64.yaml
index b1acfe1c4c..03e77ca5ba 100644
--- a/conda/environments/all_cuda-131_arch-aarch64.yaml
+++ b/conda/environments/all_cuda-132_arch-aarch64.yaml
@@ -18,7 +18,7 @@ dependencies:
- cuda-nvtx-dev
- cuda-python>=13.0.1,<14.0
- cuda-sanitizer-api
-- cuda-version=13.1
+- cuda-version=13.2
- cudf==26.6.*,>=0.0.0a0
- cupy>=13.6.0
- cxx-compiler
@@ -83,4 +83,4 @@ dependencies:
- nvidia-sphinx-theme
- swagger-plugin-for-sphinx
- veroviz
-name: all_cuda-131_arch-aarch64
+name: all_cuda-132_arch-aarch64
diff --git a/conda/environments/all_cuda-131_arch-x86_64.yaml b/conda/environments/all_cuda-132_arch-x86_64.yaml
similarity index 96%
rename from conda/environments/all_cuda-131_arch-x86_64.yaml
rename to conda/environments/all_cuda-132_arch-x86_64.yaml
index 3d4d03c85c..ffc94113e3 100644
--- a/conda/environments/all_cuda-131_arch-x86_64.yaml
+++ b/conda/environments/all_cuda-132_arch-x86_64.yaml
@@ -18,7 +18,7 @@ dependencies:
- cuda-nvtx-dev
- cuda-python>=13.0.1,<14.0
- cuda-sanitizer-api
-- cuda-version=13.1
+- cuda-version=13.2
- cudf==26.6.*,>=0.0.0a0
- cupy>=13.6.0
- cxx-compiler
@@ -83,4 +83,4 @@ dependencies:
- nvidia-sphinx-theme
- swagger-plugin-for-sphinx
- veroviz
-name: all_cuda-131_arch-x86_64
+name: all_cuda-132_arch-x86_64
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 57637bf1e6..cc32a8550d 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -266,11 +266,13 @@ FetchContent_Declare(
)
find_package(TBB REQUIRED)
-set(BUILD_TESTING OFF CACHE BOOL "Disable test build for papilo")
+set(CUOPT_BUILD_TESTING ${BUILD_TESTING})
+set(BUILD_TESTING OFF)
set(PAPILO_NO_BINARIES ON)
option(LUSOL "Disable LUSOL" OFF)
FetchContent_MakeAvailable(papilo)
+set(BUILD_TESTING ${CUOPT_BUILD_TESTING})
# PSLP - Lightweight C presolver for linear programs
# https://github.com/dance858/PSLP
@@ -567,6 +569,7 @@ target_link_libraries(cuopt
# - generate tests --------------------------------------------------------------------------------
if (BUILD_TESTS)
include(CTest)
+ list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure")
add_subdirectory(tests)
endif (BUILD_TESTS)
@@ -743,6 +746,7 @@ if (BUILD_MIP_BENCHMARKS AND NOT BUILD_LP_ONLY)
cuopt
OpenMP::OpenMP_CXX
PRIVATE
+ argparse::argparse
)
if (NOT DEFINED INSTALL_TARGET OR "${INSTALL_TARGET}" STREQUAL "")
target_link_options(solve_MIP PRIVATE -Wl,--enable-new-dtags)
@@ -773,6 +777,7 @@ if (BUILD_LP_BENCHMARKS)
cuopt
OpenMP::OpenMP_CXX
PRIVATE
+ argparse::argparse
)
if (NOT DEFINED INSTALL_TARGET OR "${INSTALL_TARGET}" STREQUAL "")
target_link_options(solve_LP PRIVATE -Wl,--enable-new-dtags)
diff --git a/cpp/libmps_parser/tests/CMakeLists.txt b/cpp/libmps_parser/tests/CMakeLists.txt
index 6d8b5b2ca5..9267787742 100644
--- a/cpp/libmps_parser/tests/CMakeLists.txt
+++ b/cpp/libmps_parser/tests/CMakeLists.txt
@@ -3,6 +3,8 @@
# SPDX-License-Identifier: Apache-2.0
# cmake-format: on
+enable_testing()
+
function(ConfigureTest CMAKE_TEST_NAME)
add_executable(${CMAKE_TEST_NAME} ${ARGN})
diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt
index 2c1aa5be73..5ccd4d1057 100644
--- a/cpp/tests/CMakeLists.txt
+++ b/cpp/tests/CMakeLists.txt
@@ -3,6 +3,11 @@
# SPDX-License-Identifier: Apache-2.0
# cmake-format: on
+enable_testing()
+
+include(rapids-test)
+rapids_test_init()
+
if(BUILD_TESTS)
add_library(cuopttestutils STATIC
routing/utilities/check_constraints.cu
@@ -65,18 +70,11 @@ function(ConfigureTest CMAKE_TEST_NAME)
target_link_options(${CMAKE_TEST_NAME} PRIVATE -Wl,--enable-new-dtags)
endif()
- add_test(NAME ${CMAKE_TEST_NAME} COMMAND ${CMAKE_TEST_NAME})
+ rapids_test_add(NAME ${CMAKE_TEST_NAME} COMMAND ${CMAKE_TEST_NAME} GPUS 1 INSTALL_COMPONENT_SET testing)
if(CT_LABELS)
set_tests_properties(${CMAKE_TEST_NAME} PROPERTIES LABELS "${CT_LABELS}")
endif()
-
- install(
- TARGETS ${CMAKE_TEST_NAME}
- COMPONENT testing
- DESTINATION bin/gtests/libcuopt
- EXCLUDE_FROM_ALL
- )
endfunction()
@@ -104,5 +102,5 @@ if(BUILD_TESTS)
add_subdirectory(qp)
add_subdirectory(utilities)
- enable_testing()
+ rapids_test_install_relocatable(INSTALL_COMPONENT_SET testing DESTINATION bin/gtests/libcuopt)
endif()
diff --git a/cpp/tests/linear_programming/CMakeLists.txt b/cpp/tests/linear_programming/CMakeLists.txt
index a21918590a..f626d7d51e 100644
--- a/cpp/tests/linear_programming/CMakeLists.txt
+++ b/cpp/tests/linear_programming/CMakeLists.txt
@@ -64,14 +64,17 @@ if (NOT SKIP_C_PYTHON_ADAPTERS)
target_link_options(C_API_TEST PRIVATE -Wl,--enable-new-dtags)
endif()
- add_test(NAME C_API_TEST COMMAND C_API_TEST)
+ rapids_test_add(NAME C_API_TEST COMMAND C_API_TEST GPUS 1 INSTALL_COMPONENT_SET testing)
set_tests_properties(C_API_TEST PROPERTIES LABELS "numopt")
-
- install(
- TARGETS C_API_TEST
- COMPONENT testing
- DESTINATION bin/gtests/libcuopt
- EXCLUDE_FROM_ALL
+ rapids_test_add(
+ NAME C_API_TEST_CPU_MEM
+ COMMAND C_API_TEST
+ GPUS 1
+ INSTALL_COMPONENT_SET testing
+ )
+ set_tests_properties(
+ C_API_TEST_CPU_MEM
+ PROPERTIES LABELS "numopt" ENVIRONMENT "CUOPT_USE_CPU_MEM_FOR_LOCAL=1;GTEST_FILTER=-c_api/TimeLimitTestFixture.*"
)
endif()
diff --git a/cpp/tests/linear_programming/grpc/CMakeLists.txt b/cpp/tests/linear_programming/grpc/CMakeLists.txt
index 74f15f5cfa..e640596573 100644
--- a/cpp/tests/linear_programming/grpc/CMakeLists.txt
+++ b/cpp/tests/linear_programming/grpc/CMakeLists.txt
@@ -34,16 +34,9 @@ if(NOT DEFINED INSTALL_TARGET OR "${INSTALL_TARGET}" STREQUAL "")
target_link_options(GRPC_CLIENT_TEST PRIVATE -Wl,--enable-new-dtags)
endif()
-add_test(NAME GRPC_CLIENT_TEST COMMAND GRPC_CLIENT_TEST)
+rapids_test_add(NAME GRPC_CLIENT_TEST COMMAND GRPC_CLIENT_TEST GPUS 1 INSTALL_COMPONENT_SET testing)
set_tests_properties(GRPC_CLIENT_TEST PROPERTIES LABELS "numopt")
-install(
- TARGETS GRPC_CLIENT_TEST
- COMPONENT testing
- DESTINATION bin/gtests/libcuopt
- EXCLUDE_FROM_ALL
-)
-
# ##################################################################################################
# - gRPC Pipe Serialization Unit Tests -------------------------------------------------------------
# These tests verify pipe serialization round-trips using real pipe(2) FDs.
@@ -75,16 +68,9 @@ if(NOT DEFINED INSTALL_TARGET OR "${INSTALL_TARGET}" STREQUAL "")
target_link_options(GRPC_PIPE_SERIALIZATION_TEST PRIVATE -Wl,--enable-new-dtags)
endif()
-add_test(NAME GRPC_PIPE_SERIALIZATION_TEST COMMAND GRPC_PIPE_SERIALIZATION_TEST)
+rapids_test_add(NAME GRPC_PIPE_SERIALIZATION_TEST COMMAND GRPC_PIPE_SERIALIZATION_TEST GPUS 1 INSTALL_COMPONENT_SET testing)
set_tests_properties(GRPC_PIPE_SERIALIZATION_TEST PROPERTIES LABELS "numopt")
-install(
- TARGETS GRPC_PIPE_SERIALIZATION_TEST
- COMPONENT testing
- DESTINATION bin/gtests/libcuopt
- EXCLUDE_FROM_ALL
-)
-
# ##################################################################################################
# - gRPC Integration Tests -------------------------------------------------------------------------
# These tests start a real server process and run end-to-end tests
@@ -118,17 +104,13 @@ endif()
# Integration tests need the server binary to be built first
add_dependencies(GRPC_INTEGRATION_TEST cuopt_grpc_server)
-add_test(
+rapids_test_add(
NAME GRPC_INTEGRATION_TEST
COMMAND ${CMAKE_COMMAND} -E env
"CUOPT_GRPC_SERVER_PATH=$"
$
+ GPUS 1
+ INSTALL_TARGET GRPC_INTEGRATION_TEST
+ INSTALL_COMPONENT_SET testing
)
set_tests_properties(GRPC_INTEGRATION_TEST PROPERTIES LABELS "numopt")
-
-install(
- TARGETS GRPC_INTEGRATION_TEST
- COMPONENT testing
- DESTINATION bin/gtests/libcuopt
- EXCLUDE_FROM_ALL
-)
diff --git a/cpp/tests/mip/doc_example_test.cu b/cpp/tests/mip/doc_example_test.cu
index 648568bd13..2024055eac 100644
--- a/cpp/tests/mip/doc_example_test.cu
+++ b/cpp/tests/mip/doc_example_test.cu
@@ -116,6 +116,7 @@ TEST(docs, user_problem_file)
auto problem = create_doc_example_problem();
const auto user_problem_path = std::filesystem::temp_directory_path() / "user_problem.mps";
+ std::filesystem::remove(user_problem_path);
EXPECT_FALSE(std::filesystem::exists(user_problem_path));
settings.time_limit = test_time_limit;
@@ -134,7 +135,8 @@ TEST(docs, user_problem_file)
EXPECT_EQ(problem2.get_nnz(), problem.get_nnz());
const auto user_problem_path2 = std::filesystem::temp_directory_path() / "user_problem2.mps";
- settings.user_problem_file = user_problem_path2;
+ std::filesystem::remove(user_problem_path2);
+ settings.user_problem_file = user_problem_path2;
mip_solution_t solution = solve_mip(&handle_, problem2, settings);
EXPECT_EQ(solution.get_termination_status(), mip_termination_status_t::Optimal);
diff --git a/cpp/tests/utilities/CMakeLists.txt b/cpp/tests/utilities/CMakeLists.txt
index 8747d47bd0..1c796660ae 100644
--- a/cpp/tests/utilities/CMakeLists.txt
+++ b/cpp/tests/utilities/CMakeLists.txt
@@ -4,4 +4,6 @@
# cmake-format: on
# Add CLI end-to-end test
-ConfigureTest(CLI_TEST test_cli.cpp LABELS numopt)
+ConfigureTest(CLI_TEST test_cli.cpp
+ LABELS numopt)
+set_tests_properties(CLI_TEST PROPERTIES ENVIRONMENT "PATH=$:$ENV{PATH}")
diff --git a/datasets/get_test_data.sh b/datasets/get_test_data.sh
index 472813a003..097635ada6 100755
--- a/datasets/get_test_data.sh
+++ b/datasets/get_test_data.sh
@@ -221,15 +221,19 @@ set +e # Disable exit on error for the entire script
for index in ${!DESTDIRS[*]}; do
tfname=$(basename "${URLS[$index]}")
+ archive="tmp/${tfname}"
- if file --mime-type "tmp/${tfname}" | grep -q gzip$; then
- tar xvzf tmp/"${tfname}" -C "${DESTDIRS[$index]}" || true
- elif file --mime-type "tmp/${tfname}" | grep -q zip$; then
- unzip tmp/"${tfname}" -d "${DESTDIRS[$index]}" || true
- else
- tar xvf tmp/"${tfname}" -C "${DESTDIRS[$index]}" || true
+ if [ ! -f "${archive}" ]; then
+ echo "Missing download: ${archive}"
+ exit 1
fi
+ case "${tfname}" in
+ *.tar.gz|*.tgz) tar xvzf "${archive}" -C "${DESTDIRS[$index]}" || true ;;
+ *.zip) unzip "${archive}" -d "${DESTDIRS[$index]}" || true ;;
+ *) tar xvf "${archive}" -C "${DESTDIRS[$index]}" || true ;;
+ esac
+
if ls "${DESTDIRS[$index]}"/*.gz >/dev/null 2>&1; then
gzip -d "${DESTDIRS[$index]}"/* || true
fi
diff --git a/dependencies.yaml b/dependencies.yaml
index 68afb4f7f5..6e237c687c 100644
--- a/dependencies.yaml
+++ b/dependencies.yaml
@@ -7,7 +7,7 @@ files:
all:
output: conda
matrix:
- cuda: ["12.9", "13.1"]
+ cuda: ["12.9", "13.2"]
arch: [x86_64, aarch64]
includes:
- build_common
@@ -670,6 +670,10 @@ dependencies:
cuda: "13.1"
packages:
- cuda-version=13.1
+ - matrix:
+ cuda: "13.2"
+ packages:
+ - cuda-version=13.2
- output_types: requirements
matrices:
# if use_cuda_wheels=false is provided, do not add dependencies on any CUDA wheels
@@ -715,6 +719,11 @@ dependencies:
use_cuda_wheels: "true"
packages:
- cuda-toolkit==13.1.*
+ - matrix:
+ cuda: "13.2"
+ use_cuda_wheels: "true"
+ packages:
+ - cuda-toolkit==13.2.*
cuda:
common:
- output_types: [conda]
diff --git a/python/cuopt/cuopt/linear_programming/CMakeLists.txt b/python/cuopt/cuopt/linear_programming/CMakeLists.txt
index 84029d2c6e..4ea06a92ef 100644
--- a/python/cuopt/cuopt/linear_programming/CMakeLists.txt
+++ b/python/cuopt/cuopt/linear_programming/CMakeLists.txt
@@ -59,11 +59,13 @@ rapids_cython_init()
add_subdirectory(cuopt_mps_parser)
add_subdirectory(data_model)
-if(DEFINED cython_lib_dir)
+if(TARGET mps_parser AND DEFINED cython_lib_dir)
rapids_cython_add_rpath_entries(TARGET mps_parser PATHS "${cython_lib_dir}")
endif()
set(rpaths
"$ORIGIN/../lib64"
"$ORIGIN/../../rapids_logger/lib64"
)
-set_property(TARGET mps_parser PROPERTY INSTALL_RPATH ${rpaths} APPEND)
+if(TARGET mps_parser)
+ set_property(TARGET mps_parser PROPERTY INSTALL_RPATH ${rpaths} APPEND)
+endif()