Skip to content

Commit 7bccfef

Browse files
Merge branch 'main' into chore/nvskills-ci-cuopt-routing-api-python
2 parents 22b6e5e + ae0a38a commit 7bccfef

84 files changed

Lines changed: 1428 additions & 450 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ci/check_symbols.sh

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/bin/bash
2+
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
set -eEuo pipefail
6+
7+
echo "checking for symbol visibility issues"
8+
9+
LIBRARY="${1}"
10+
11+
echo ""
12+
echo "Checking exported symbols in '${LIBRARY}'"
13+
symbol_file="$(mktemp)"
14+
match_file="$(mktemp)"
15+
trap 'rm -f "${symbol_file}" "${match_file}"' EXIT
16+
17+
# Ignore WEAK and UNIQUE symbols since UNIQUE symbols should be exported and
18+
# WEAK symbols may come from template instantiations.
19+
# Ignore symbols containing "_error" since these are likely exception types
20+
# and should be exported.
21+
22+
readelf --dyn-syms --wide "${LIBRARY}" \
23+
| awk '$7 != "UND" && $5 != "WEAK" && $5 != "UNIQUE"' \
24+
| c++filt --no-params \
25+
| awk '$0 !~ /_error/' \
26+
> "${symbol_file}"
27+
28+
patterns=(
29+
'cub::'
30+
'thrust::'
31+
'raft::'
32+
'rmm::'
33+
'cuopt::mathematical_optimization::detail'
34+
'cuopt::routing::detail'
35+
'cuopt::detail'
36+
'grpc::'
37+
'google::protobuf'
38+
'tbb::'
39+
'absl::'
40+
'dejavu::'
41+
'papilo::'
42+
'boost::'
43+
)
44+
45+
failed=0
46+
47+
for pattern in "${patterns[@]}"; do
48+
echo "Checking for '${pattern}' symbols..."
49+
50+
awk -v pattern="${pattern}" '
51+
BEGIN { has_trailing_scope = (substr(pattern, length(pattern) - 1) == "::") }
52+
$1 ~ /^[0-9]+:/ {
53+
symbol = ""
54+
for (i = 8; i <= NF; ++i) {
55+
symbol = symbol (i == 8 ? "" : " ") $i
56+
}
57+
58+
sub(/<.*/, "", symbol)
59+
sub(/^.*[[:space:]](for|to)[[:space:]]+/, "", symbol)
60+
61+
if (has_trailing_scope) {
62+
matched = (index(symbol, pattern) == 1)
63+
} else {
64+
matched = (symbol == pattern || index(symbol, pattern "::") == 1)
65+
}
66+
67+
if (matched) { print }
68+
}
69+
' "${symbol_file}" > "${match_file}"
70+
71+
matches=$(awk 'END { print NR }' "${match_file}")
72+
if [[ "${matches}" -ne 0 ]]; then
73+
sed -n '1,20p' "${match_file}"
74+
echo "ERROR: Found exported symbols in ${LIBRARY} matching the pattern ${pattern}."
75+
echo "ERROR: Total matching symbols: ${matches}"
76+
failed=1
77+
fi
78+
done
79+
80+
# Required public API symbols that must stay exported. This is a small stability
81+
# anchor (core C API lifecycle entrypoints), not an exhaustive list: without it,
82+
# a library whose visibility was over-tightened so the public API is entirely
83+
# hidden would still pass the forbidden-symbol checks above while being unusable.
84+
# Keep this set minimal and limited to entrypoints guaranteed to exist.
85+
required_symbols=(
86+
cuOptReadProblem
87+
cuOptCreateProblem
88+
cuOptSolve
89+
cuOptDestroyProblem
90+
)
91+
92+
exported_funcs="$(readelf --dyn-syms --wide "${LIBRARY}" | awk '$7 != "UND" && $4 == "FUNC" { print $8 }')"
93+
94+
for sym in "${required_symbols[@]}"; do
95+
echo "Checking that required symbol '${sym}' is exported..."
96+
if ! grep -qxF "${sym}" <<< "${exported_funcs}"; then
97+
echo "ERROR: Required public API symbol '${sym}' is not exported from ${LIBRARY}."
98+
echo "ERROR: Symbol visibility may be over-restricted and hiding the public API."
99+
failed=1
100+
fi
101+
done
102+
103+
if [[ "${failed}" -ne 0 ]]; then
104+
exit 1
105+
fi
106+
107+
echo "No symbol visibility issues found in ${LIBRARY}"

conda/recipes/libcuopt/recipe.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ outputs:
108108
script:
109109
content: |
110110
cmake --install cpp/build
111+
./ci/check_symbols.sh cpp/build/libcuopt.so
111112
dynamic_linking:
112113
overlinking_behavior: "error"
113114
prefix_detection:
@@ -119,6 +120,7 @@ outputs:
119120
build:
120121
- cmake ${{ cmake_version }}
121122
- ${{ stdlib("c") }}
123+
- binutils
122124
host:
123125
- libboost-devel
124126
- cuda-version =${{ cuda_version }}

cpp/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,8 @@ if (NOT SKIP_GRPC_BUILD)
548548
# at runtime with "undefined symbol: absl::…::Mutex::Dtor".
549549
set_property(SOURCE ${GRPC_INFRA_FILES} DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
550550
APPEND PROPERTY COMPILE_OPTIONS "-DNDEBUG")
551+
set_property(SOURCE ${PROTO_SRCS} ${GRPC_PROTO_SRCS} ${GRPC_SERVICE_SRCS} ${DATA_PROTO_SRCS} DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
552+
APPEND PROPERTY COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:CXX>:-fvisibility=default>")
551553
endif (NOT SKIP_GRPC_BUILD)
552554

553555
add_library(cuopt_objs OBJECT
@@ -556,6 +558,9 @@ add_library(cuopt_objs OBJECT
556558

557559
set_target_properties(cuopt_objs
558560
PROPERTIES POSITION_INDEPENDENT_CODE ON
561+
CXX_VISIBILITY_PRESET hidden
562+
CUDA_VISIBILITY_PRESET hidden
563+
VISIBILITY_INLINES_HIDDEN ON
559564
CXX_SCAN_FOR_MODULES OFF
560565
)
561566

@@ -683,6 +688,7 @@ target_link_libraries(cuopt_objs
683688
PRIVATE
684689
${CUOPT_PRIVATE_CUDA_LIBS}
685690
simde::simde
691+
OpenMP::OpenMP_CXX
686692
OpenMP::OpenMP_CUDA
687693
$<$<BOOL:${CUOPT_ENABLE_GRPC}>:protobuf::libprotobuf>
688694
$<$<BOOL:${CUOPT_ENABLE_GRPC}>:gRPC::grpc++>

cpp/include/cuopt/error.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
/* clang-format on */
77
#pragma once
88

9+
#include <cuopt/export.hpp>
910
#include "cuopt/mathematical_optimization/constants.h"
1011

1112
#include <stdarg.h>
1213

1314
#include <raft/core/error.hpp>
1415

15-
namespace cuopt {
16+
namespace CUOPT_EXPORT cuopt {
1617

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

171-
} // namespace cuopt
172+
} // namespace CUOPT_EXPORT cuopt

cpp/include/cuopt/export.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* clang-format off */
2+
/*
3+
* SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
/* clang-format on */
7+
8+
#pragma once
9+
10+
#if defined(__GNUC__) || defined(__clang__)
11+
#define CUOPT_EXPORT __attribute__((visibility("default")))
12+
#else
13+
#define CUOPT_EXPORT
14+
#endif

cpp/include/cuopt/grpc/cython_grpc_client.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#pragma once
77

8+
#include <cuopt/export.hpp>
89
#include <cuopt/mathematical_optimization/utilities/cython_solve.hpp>
910

1011
#include <cstddef>
@@ -22,7 +23,8 @@ class data_model_view_t;
2223
} // namespace io
2324
} // namespace cuopt::mathematical_optimization
2425

25-
namespace cuopt::cython {
26+
namespace cuopt {
27+
namespace CUOPT_EXPORT cython {
2628

2729
/** Mirrors cuopt::mathematical_optimization::job_status_t for the Python bindings. */
2830
enum class grpc_job_status_t : int {
@@ -167,4 +169,5 @@ class grpc_python_client_t {
167169
std::unique_ptr<impl_t> impl_;
168170
};
169171

170-
} // namespace cuopt::cython
172+
} // namespace CUOPT_EXPORT cython
173+
} // namespace cuopt

cpp/include/cuopt/grpc/grpc_client_env.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55

66
#pragma once
77

8+
#include <cuopt/export.hpp>
89
#include "grpc_client.hpp"
910

10-
namespace cuopt::mathematical_optimization {
11+
namespace cuopt {
12+
namespace CUOPT_EXPORT mathematical_optimization {
1113

1214
/** How TLS is chosen when building a grpc_client_config_t. */
1315
enum class grpc_tls_mode_t {
@@ -49,4 +51,5 @@ grpc_client_config_t make_grpc_client_config(const std::string& host,
4951
grpc_tls_mode_t tls_mode,
5052
const grpc_explicit_tls_t* explicit_tls = nullptr);
5153

52-
} // namespace cuopt::mathematical_optimization
54+
} // namespace CUOPT_EXPORT mathematical_optimization
55+
} // namespace cuopt

cpp/include/cuopt/mathematical_optimization/backend_selection.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77

88
#pragma once
99

10-
namespace cuopt::mathematical_optimization {
10+
#include <cuopt/export.hpp>
11+
12+
namespace cuopt {
13+
namespace CUOPT_EXPORT mathematical_optimization {
1114

1215
/**
1316
* @brief Enum for execution mode (local vs remote solve)
@@ -51,4 +54,5 @@ execution_mode_t get_execution_mode();
5154
*/
5255
memory_backend_t get_memory_backend_type();
5356

54-
} // namespace cuopt::mathematical_optimization
57+
} // namespace CUOPT_EXPORT mathematical_optimization
58+
} // namespace cuopt

cpp/include/cuopt/mathematical_optimization/cpu_optimization_problem.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#pragma once
99

10+
#include <cuopt/export.hpp>
1011
#include <cuopt/mathematical_optimization/optimization_problem_interface.hpp>
1112

1213
#include <raft/core/handle.hpp>
@@ -18,7 +19,8 @@
1819
#include <string>
1920
#include <vector>
2021

21-
namespace cuopt::mathematical_optimization {
22+
namespace cuopt {
23+
namespace CUOPT_EXPORT mathematical_optimization {
2224

2325
namespace io {
2426
template <typename i_t, typename f_t>
@@ -238,4 +240,5 @@ class cpu_optimization_problem_t : public optimization_problem_interface_t<i_t,
238240
std::vector<std::string> row_names_{};
239241
};
240242

241-
} // namespace cuopt::mathematical_optimization
243+
} // namespace CUOPT_EXPORT mathematical_optimization
244+
} // namespace cuopt

cpp/include/cuopt/mathematical_optimization/cpu_optimization_problem_solution.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#pragma once
99

10+
#include <cuopt/export.hpp>
1011
#include <cuopt/mathematical_optimization/cpu_pdlp_warm_start_data.hpp>
1112
#include <cuopt/mathematical_optimization/mip/solver_solution.hpp>
1213
#include <cuopt/mathematical_optimization/mip/solver_stats.hpp>
@@ -18,7 +19,8 @@
1819

1920
#include <vector>
2021

21-
namespace cuopt::mathematical_optimization {
22+
namespace cuopt {
23+
namespace CUOPT_EXPORT mathematical_optimization {
2224

2325
/**
2426
* @brief CPU-backed LP solution (uses std::vector instead of rmm::device_uvector)
@@ -389,4 +391,5 @@ class cpu_mip_solution_t : public mip_solution_interface_t<i_t, f_t> {
389391
i_t num_simplex_iterations_;
390392
};
391393

392-
} // namespace cuopt::mathematical_optimization
394+
} // namespace CUOPT_EXPORT mathematical_optimization
395+
} // namespace cuopt

0 commit comments

Comments
 (0)