Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
20ad11d
refactor(tests): link internal tests against cuopt_static
ramakrishnap-nv Jul 16, 2026
de93a4d
refactor(tests): consolidate internal numopt tests into single binary
ramakrishnap-nv Jul 16, 2026
e6589c1
fix(tests): make combined internal test binaries link and run
ramakrishnap-nv Jul 16, 2026
a59bd8c
style(tests): remove stale comments from empty CMakeLists stubs
ramakrishnap-nv Jul 16, 2026
bd27745
refactor(tests): remove empty dual_simplex and socp CMakeLists stubs
ramakrishnap-nv Jul 16, 2026
0e5689a
fix(build): link PSLP directly on cuopt shared target
ramakrishnap-nv Jul 16, 2026
90e5d79
refactor(tests): delete CUOPT_TEST_PROGRAM_MAIN from combined-binary …
ramakrishnap-nv Jul 16, 2026
3e58684
refactor(tests): replace runtime cuSPARSE check with compile-time macro
ramakrishnap-nv Jul 17, 2026
c9476b2
fix(tests): require error when mixed precision is unsupported
ramakrishnap-nv Jul 17, 2026
1f52c5e
fix(tests): fix invalid CSR in problem_test create_problem helper
ramakrishnap-nv Jul 17, 2026
545ce45
fix(test): check runtime cuSPARSE version in pdlp_precision_mixed test
ramakrishnap-nv Jul 17, 2026
0effbce
fix(tests): restore RMM setup in ROUTING_UNIT_TEST
ramakrishnap-nv Jul 20, 2026
755ec5d
fix(tests): fix malformed SPDX block comment in internal/main.cu
ramakrishnap-nv Jul 20, 2026
8f23153
fix(build): add OpenMP::OpenMP_CUDA to cuopt_objs PRIVATE deps
ramakrishnap-nv Jul 20, 2026
c159896
fix(build): add simde::simde to cuopt_objs PRIVATE deps
ramakrishnap-nv Jul 21, 2026
3a55206
fix(tests): add missing symmetric QCMATRIX entry in fast parser edge …
ramakrishnap-nv Jul 21, 2026
5ec9425
Merge branch 'main' into refactor/test-static-link-for-internal-tests
ramakrishnap-nv Jul 22, 2026
6610d44
check symbols script
arhag23 Jul 23, 2026
2ca4e80
Symbol visibility controls and exports
arhag23 Jul 23, 2026
b1644c1
Merge remote-tracking branch 'upstream/main' into fix-symbol-visibili…
ramakrishnap-nv Jul 24, 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
84 changes: 84 additions & 0 deletions ci/check_symbols.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/bin/bash
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

set -eEuo pipefail

echo "checking for symbol visibility issues"

LIBRARY="${1}"

echo ""
echo "Checking exported symbols in '${LIBRARY}'"
symbol_file="$(mktemp)"
match_file="$(mktemp)"
trap 'rm -f "${symbol_file}" "${match_file}"' EXIT

# Ignore WEAK and UNIQUE symbols since UNIQUE symbols should be exported and
# WEAK symbols may come from template instantiations.
# Ignore symbols containing "_error" since these are likely exception types
# and should be exported.

readelf --dyn-syms --wide "${LIBRARY}" \
| awk '$7 != "UND" && $5 != "WEAK" && $5 != "UNIQUE"' \
| c++filt --no-params \
| awk '$0 !~ /_error/' \
> "${symbol_file}"

patterns=(
'cub::'
'thrust::'
'raft::'
'rmm::'
'cuopt::mathematical_optimization::detail'
'cuopt::routing::detail'
'cuopt::detail'
'grpc::'
'google::protobuf'
'tbb::'
'absl::'
'dejavu::'
'papilo::'
'boost::'
)

failed=0

for pattern in "${patterns[@]}"; do
echo "Checking for '${pattern}' symbols..."

awk -v pattern="${pattern}" '
BEGIN { has_trailing_scope = (substr(pattern, length(pattern) - 1) == "::") }
$1 ~ /^[0-9]+:/ {
symbol = ""
for (i = 8; i <= NF; ++i) {
symbol = symbol (i == 8 ? "" : " ") $i
}

sub(/<.*/, "", symbol)
sub(/^.*[[:space:]](for|to)[[:space:]]+/, "", symbol)

if (has_trailing_scope) {
matched = (index(symbol, pattern) == 1)
} else {
matched = (symbol == pattern || index(symbol, pattern "::") == 1)
}

if (matched) { print }
}
' "${symbol_file}" > "${match_file}"

matches=$(awk 'END { print NR }' "${match_file}")
if [[ "${matches}" -ne 0 ]]; then
sed -n '1,20p' "${match_file}"
echo "ERROR: Found exported symbols in ${LIBRARY} matching the pattern ${pattern}."
echo "ERROR: Total matching symbols: ${matches}"
failed=1
fi
done

if [[ "${failed}" -ne 0 ]]; then
exit 1
fi

echo "No symbol visibility issues found in ${LIBRARY}"
4 changes: 3 additions & 1 deletion conda/recipes/libcuopt/recipe.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION.
# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
schema_version: 1

Expand Down Expand Up @@ -107,6 +107,7 @@ outputs:
script:
content: |
cmake --install cpp/build
./ci/check_symbols.sh cpp/build/libcuopt.so
dynamic_linking:
overlinking_behavior: "error"
prefix_detection:
Expand All @@ -118,6 +119,7 @@ outputs:
build:
- cmake ${{ cmake_version }}
- ${{ stdlib("c") }}
- binutils
host:
- libboost-devel
- cuda-version =${{ cuda_version }}
Expand Down
148 changes: 115 additions & 33 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -510,58 +510,48 @@ if (NOT SKIP_GRPC_BUILD)
# at runtime with "undefined symbol: absl::…::Mutex::Dtor".
set_property(SOURCE ${GRPC_INFRA_FILES} DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
APPEND PROPERTY COMPILE_OPTIONS "-DNDEBUG")
set_property(SOURCE ${PROTO_SRCS} ${GRPC_PROTO_SRCS} ${GRPC_SERVICE_SRCS} ${DATA_PROTO_SRCS} DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
APPEND PROPERTY COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:CXX>:-fvisibility=default>")
endif (NOT SKIP_GRPC_BUILD)

add_library(cuopt SHARED
add_library(cuopt_objs OBJECT
${CUOPT_SRC_FILES}
)

set_target_properties(cuopt
PROPERTIES BUILD_RPATH "\$ORIGIN"
INSTALL_RPATH "\$ORIGIN"
INTERFACE_POSITION_INDEPENDENT_CODE ON
set_target_properties(cuopt_objs
PROPERTIES POSITION_INDEPENDENT_CODE ON
CXX_VISIBILITY_PRESET hidden
CUDA_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
CXX_SCAN_FOR_MODULES OFF
)

target_compile_definitions(cuopt
PUBLIC "CUOPT_LOG_ACTIVE_LEVEL=RAPIDS_LOGGER_LOG_LEVEL_${LIBCUOPT_LOGGING_LEVEL}"
PUBLIC CUSPARSE_ENABLE_EXPERIMENTAL_API
target_compile_definitions(cuopt_objs
PUBLIC "CUOPT_LOG_ACTIVE_LEVEL=RAPIDS_LOGGER_LOG_LEVEL_${LIBCUOPT_LOGGING_LEVEL}"
PUBLIC CUSPARSE_ENABLE_EXPERIMENTAL_API
)

target_compile_options(cuopt
target_compile_options(cuopt_objs
PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${CUOPT_CXX_FLAGS}>"
"$<$<COMPILE_LANGUAGE:CUDA>:${CUOPT_CUDA_FLAGS}>"
)

if (WRITE_FATBIN)
file(WRITE "${CUOPT_BINARY_DIR}/fatbin.ld"
[=[
SECTIONS
{
.nvFatBinSegment : { *(.nvFatBinSegment) }
.nv_fatbin : { *(.nv_fatbin) }
}
]=])
target_link_options(cuopt PRIVATE "${CUOPT_BINARY_DIR}/fatbin.ld")
endif ()

add_library(cuopt::cuopt ALIAS cuopt)
# ##################################################################################################
# - include paths ---------------------------------------------------------------------------------
message(STATUS "target include directories CUDSS_INCLUDES = ${CUDSS_INCLUDE}")

# Adding Papilo as a system include messes up clang's include resolution if papilo is already installed as a conda package
target_include_directories(cuopt PRIVATE
target_include_directories(cuopt_objs PRIVATE
"${papilo_SOURCE_DIR}/src"
"${papilo_BINARY_DIR}"
)

target_include_directories(cuopt SYSTEM PRIVATE
"${pslp_SOURCE_DIR}/include"
"${dejavu_SOURCE_DIR}"
target_include_directories(cuopt_objs SYSTEM PRIVATE
"${pslp_SOURCE_DIR}/include"
"${dejavu_SOURCE_DIR}"
)

target_include_directories(cuopt
target_include_directories(cuopt_objs
PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty"
"${CMAKE_CURRENT_SOURCE_DIR}/src"
Expand All @@ -581,8 +571,8 @@ target_include_directories(cuopt
)

# Link PSLP by file to avoid export dependency tracking
target_link_libraries(cuopt PRIVATE $<TARGET_FILE:PSLP>)
add_dependencies(cuopt PSLP)
target_link_libraries(cuopt_objs PRIVATE $<TARGET_FILE:PSLP>)
add_dependencies(cuopt_objs PSLP)

# ##################################################################################################
# - link libraries --------------------------------------------------------------------------------
Expand All @@ -597,7 +587,7 @@ list(PREPEND CUOPT_PRIVATE_CUDA_LIBS CUDA::cublasLt)

# Pass CUDSS_MT_LIB_FILE_NAME as a compile definition
get_filename_component(CUDSS_MT_LIB_FILE_NAME "${CUDSS_MT_LIB_FILE}" NAME)
target_compile_definitions(cuopt PRIVATE CUDSS_MT_LIB_FILE_NAME="${CUDSS_MT_LIB_FILE_NAME}")
target_compile_definitions(cuopt_objs PRIVATE CUDSS_MT_LIB_FILE_NAME="${CUDSS_MT_LIB_FILE_NAME}")

execute_process(
COMMAND git rev-parse --short HEAD
Expand All @@ -616,14 +606,14 @@ configure_file(
)

# Add the generated include directory
target_include_directories(cuopt PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include)
target_include_directories(cuopt_objs PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include)

list(JOIN CMAKE_CUDA_ARCHITECTURES "," JOINED_CUDA_ARCHITECTURES)
target_compile_definitions(cuopt PUBLIC
target_compile_definitions(cuopt_objs PUBLIC
CUOPT_CUDA_ARCHITECTURES="${JOINED_CUDA_ARCHITECTURES}"
CUOPT_CPU_ARCHITECTURE="${CMAKE_SYSTEM_PROCESSOR}")

target_link_libraries(cuopt
target_link_libraries(cuopt_objs
PUBLIC
CUDA::cublas
CUDA::cusparse
Expand All @@ -645,9 +635,101 @@ target_link_libraries(cuopt
# - generate tests --------------------------------------------------------------------------------
if (BUILD_TESTS)
include(CTest)
add_library(cuopt_static STATIC $<TARGET_OBJECTS:cuopt_objs>)
target_link_libraries(cuopt_static
PUBLIC
CUDA::cublas
CUDA::cusparse
rmm::rmm
rapids_logger::rapids_logger
CCCL::CCCL
raft::raft
${CUDSS_LIB_FILE}
OpenMP::OpenMP_CXX
PRIVATE
${CUOPT_PRIVATE_CUDA_LIBS}
$<$<BOOL:${CUOPT_ENABLE_GRPC}>:protobuf::libprotobuf>
$<$<BOOL:${CUOPT_ENABLE_GRPC}>:gRPC::grpc++>
)
# Internal test sources include OMP-dependent headers (omp_helpers.hpp, omp_atomic_t).
# Propagate -fopenmp for CUDA TUs since OpenMP::OpenMP_CXX only covers CXX.
target_compile_options(cuopt_static INTERFACE
"$<$<COMPILE_LANGUAGE:CUDA>:-fopenmp>"
)
target_include_directories(cuopt_static
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
"$<INSTALL_INTERFACE:include>"
)
target_compile_definitions(cuopt_static PUBLIC
CUOPT_CUDA_ARCHITECTURES="${JOINED_CUDA_ARCHITECTURES}"
CUOPT_CPU_ARCHITECTURE="${CMAKE_SYSTEM_PROCESSOR}"
"CUOPT_LOG_ACTIVE_LEVEL=RAPIDS_LOGGER_LOG_LEVEL_${LIBCUOPT_LOGGING_LEVEL}"
CUSPARSE_ENABLE_EXPERIMENTAL_API
)
target_link_libraries(cuopt_static PRIVATE $<TARGET_FILE:PSLP>)
add_dependencies(cuopt_static PSLP)
add_subdirectory(tests)
endif (BUILD_TESTS)

add_library(cuopt SHARED $<TARGET_OBJECTS:cuopt_objs>)
add_library(cuopt::cuopt ALIAS cuopt)
set_target_properties(cuopt
PROPERTIES BUILD_RPATH "\$ORIGIN"
INSTALL_RPATH "\$ORIGIN"
INTERFACE_POSITION_INDEPENDENT_CODE ON
CXX_SCAN_FOR_MODULES OFF
LINKER_LANGUAGE CUDA
)
# cuopt needs PUBLIC interface for consumers
target_include_directories(cuopt
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
INTERFACE
"$<INSTALL_INTERFACE:include>"
)
target_link_libraries(cuopt
PUBLIC
CUDA::cublas
CUDA::cusparse
rmm::rmm
rapids_logger::rapids_logger
CCCL::CCCL
raft::raft
${CUDSS_LIB_FILE}
PRIVATE
${CUOPT_PRIVATE_CUDA_LIBS}
simde::simde
OpenMP::OpenMP_CXX
OpenMP::OpenMP_CUDA
$<$<BOOL:${CUOPT_ENABLE_GRPC}>:protobuf::libprotobuf>
$<$<BOOL:${CUOPT_ENABLE_GRPC}>:gRPC::grpc++>
)
target_link_libraries(cuopt PRIVATE $<TARGET_FILE:PSLP>)
add_dependencies(cuopt PSLP)
# Propagate compile definitions that consumers need when including cuopt headers.
# These were on cuopt directly before the cuopt_objs refactor; $<TARGET_OBJECTS:...>
# does not carry INTERFACE properties, so we restore them explicitly.
target_compile_definitions(cuopt
PUBLIC
"CUOPT_LOG_ACTIVE_LEVEL=RAPIDS_LOGGER_LOG_LEVEL_${LIBCUOPT_LOGGING_LEVEL}"
CUSPARSE_ENABLE_EXPERIMENTAL_API
)

if (WRITE_FATBIN)
file(WRITE "${CUOPT_BINARY_DIR}/fatbin.ld"
[=[
SECTIONS
{
.nvFatBinSegment : { *(.nvFatBinSegment) }
.nv_fatbin : { *(.nv_fatbin) }
}
]=])
target_link_options(cuopt PRIVATE "${CUOPT_BINARY_DIR}/fatbin.ld")
endif ()

# ##################################################################################################
# - install targets -------------------------------------------------------------------------------

Expand Down
5 changes: 3 additions & 2 deletions cpp/include/cuopt/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
/* clang-format on */
#pragma once

#include <cuopt/export.hpp>
#include "cuopt/mathematical_optimization/constants.h"

#include <stdarg.h>

#include <raft/core/error.hpp>

namespace cuopt {
namespace CUOPT_EXPORT cuopt {

/**
* @brief Indicates different type of exceptions which cuOpt might throw
Expand Down Expand Up @@ -168,4 +169,4 @@ void execute_cuopt_fail(Args... args)
throw cuopt::logic_error(msg, error_type_t::RuntimeError);
}

} // namespace cuopt
} // namespace CUOPT_EXPORT cuopt
14 changes: 14 additions & 0 deletions cpp/include/cuopt/export.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */

#pragma once

#if defined(__GNUC__) || defined(__clang__)
#define CUOPT_EXPORT __attribute__((visibility("default")))
#else
#define CUOPT_EXPORT
#endif
7 changes: 5 additions & 2 deletions cpp/include/cuopt/grpc/cython_grpc_client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#pragma once

#include <cuopt/export.hpp>
#include <cuopt/mathematical_optimization/utilities/cython_solve.hpp>

#include <cstddef>
Expand All @@ -22,7 +23,8 @@ class data_model_view_t;
} // namespace io
} // namespace cuopt::mathematical_optimization

namespace cuopt::cython {
namespace cuopt {
namespace CUOPT_EXPORT cython {

/** Mirrors cuopt::mathematical_optimization::job_status_t for the Python bindings. */
enum class grpc_job_status_t : int {
Expand Down Expand Up @@ -166,4 +168,5 @@ class grpc_python_client_t {
std::unique_ptr<impl_t> impl_;
};

} // namespace cuopt::cython
} // namespace CUOPT_EXPORT cython
} // namespace cuopt
Loading
Loading