Skip to content

Commit 9c7992a

Browse files
build: add the CUDA-free cuopt_client library
With the host code now separable, this adds the target that makes use of it. cuopt_client holds the host-side problem representation (parsers, data_model_view, mps_data_model, writers), the gRPC wire protocol (generated protos + mappers) and the gRPC clients for both LP/MIP and routing. libcuopt and cuopt_grpc_server both link it, so there is one mapper implementation rather than a client-side fork. Both gRPC arms qualify: the routing mappers added in #1597 reference no raft/rmm/thrust either. solve_remote.cpp stays in libcuopt -- it is the local-vs-remote dispatcher and calls into the GPU solver. Built as an OBJECT library plus a SHARED library, mirroring cuopt_objs/cuopt. cuopt_static embeds the objects directly rather than linking the shared library, because the internal test binaries reach parser internals such as mps_phase_registry_t. Two build details worth knowing: * cuopt_client uses default visibility, deliberately unlike cuopt_objs. libcuopt depends on roughly 214 of its symbols -- essentially the whole host-side API -- because this library was carved out of the internals rather than designed as a curated CUOPT_EXPORT surface. Hiding them makes libcuopt.so fail to load with "undefined symbol: grpc_client_t::solve_mip". * logger.cpp moves into the client sources: both the parsers and the gRPC code include <utilities/logger.hpp>, so without it the library has an unresolved reference to the logger. Result: libcuopt_client.so NEEDED: libgrpc++, libprotobuf, libabseil, librapids_logger, libc, libstdc++, libgomp, libdl -- no libcudart, no rmm, no raft, no cudss ldd -r over libcuopt.so + libcuopt_client.so: 0 unresolved symbols Note that raft/rmm headers are still needed at *build* time (the CPU headers transitively include them), which costs nothing at runtime because the device getters throw. Separating the headers is follow-up work, and is what a standalone client package would additionally require. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
1 parent 907c4d5 commit 9c7992a

6 files changed

Lines changed: 179 additions & 19 deletions

File tree

cpp/CMakeLists.txt

Lines changed: 140 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -550,11 +550,12 @@ if (BUILD_TESTS)
550550
endif ()
551551

552552
set(CUOPT_SRC_FILES)
553+
set(CUOPT_CLIENT_SRC_FILES)
553554
set(MPS_FAST_SRC_FILES)
554555
add_subdirectory(src)
555556

556557
if (HOST_LINEINFO)
557-
set_source_files_properties(${CUOPT_SRC_FILES} DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTIES COMPILE_OPTIONS "-g1")
558+
set_source_files_properties(${CUOPT_SRC_FILES} ${CUOPT_CLIENT_SRC_FILES} DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTIES COMPILE_OPTIONS "-g1")
558559
endif ()
559560

560561
# Needed for the fast MPS parser, available on all x86-64-v3 compliant x86 CPUs (essentially since Haswell ~2013)
@@ -567,11 +568,11 @@ endif ()
567568
# TODO: figure out a set of flags for ARM that fits the range of CPUs we wish to support (neoverse?)
568569
# NEON should be universal on aarch64 and enough for our purposes (parsing) though
569570

570-
# Apply -UNDEBUG only to solver source files (not gRPC infrastructure).
571-
# Must happen before gRPC files are appended to CUOPT_SRC_FILES.
571+
# Apply -UNDEBUG only to solver and parser source files (not gRPC infrastructure).
572+
# Must happen before gRPC files are appended to CUOPT_CLIENT_SRC_FILES.
572573
# Uses APPEND to preserve any existing per-file options (e.g. -g1 from HOST_LINEINFO).
573574
if (DEFINE_ASSERT)
574-
set_property(SOURCE ${CUOPT_SRC_FILES} DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
575+
set_property(SOURCE ${CUOPT_SRC_FILES} ${CUOPT_CLIENT_SRC_FILES} DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
575576
APPEND PROPERTY COMPILE_OPTIONS "-UNDEBUG")
576577
endif ()
577578

@@ -598,9 +599,7 @@ if (NOT SKIP_GRPC_BUILD)
598599
src/grpc/client/grpc_client.cpp
599600
src/grpc/client/grpc_client_env.cpp
600601
src/grpc/client/cython_grpc_client.cpp
601-
src/grpc/client/solve_remote.cpp
602602
)
603-
604603
# Routing (VRP) arm: everything that depends on the routing engine. Kept as
605604
# its own list so a routing-only gRPC client can be split out of the
606605
# cuopt_grpc component without moving code around again.
@@ -616,7 +615,17 @@ if (NOT SKIP_GRPC_BUILD)
616615
if (CUOPT_ENABLE_GRPC_ROUTING)
617616
list(APPEND GRPC_INFRA_FILES ${GRPC_ROUTING_FILES})
618617
endif ()
619-
list(APPEND CUOPT_SRC_FILES ${GRPC_INFRA_FILES})
618+
619+
# Both arms are CUDA-free -- the routing mappers reference no raft/rmm/thrust
620+
# either -- so the wire protocol and clients build into cuopt_client, shared by
621+
# libcuopt, cuopt_grpc_server and the Python client extensions. One mapper
622+
# implementation, not a client-side fork of it.
623+
list(APPEND CUOPT_CLIENT_SRC_FILES ${GRPC_INFRA_FILES})
624+
625+
# solve_remote.cpp is the local-vs-remote dispatcher: it calls into the GPU
626+
# solver, so it stays in cuopt_objs rather than moving down to cuopt_client.
627+
list(APPEND CUOPT_SRC_FILES src/grpc/client/solve_remote.cpp)
628+
list(APPEND GRPC_INFRA_FILES src/grpc/client/solve_remote.cpp)
620629

621630
# Always keep NDEBUG defined for gRPC infrastructure files so that abseil
622631
# headers inline Mutex::Dtor() instead of emitting an external call.
@@ -631,6 +640,120 @@ if (NOT SKIP_GRPC_BUILD)
631640
APPEND PROPERTY COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:CXX>:-fvisibility=default>")
632641
endif (NOT SKIP_GRPC_BUILD)
633642

643+
# ##################################################################################################
644+
# - cuopt_client - CPU-only support library ----------------------------------------------------------
645+
#
646+
# Holds the host-side problem representation (parsers, data_model_view, mps_data_model,
647+
# writers), the gRPC wire protocol (generated protos + mappers), and the gRPC client.
648+
# None of it touches CUDA, so this library links no CUDA runtime.
649+
#
650+
# It exists so the Python extension modules that never call into the GPU -- data_model,
651+
# solver_settings, io, and the gRPC client -- can link something other than libcuopt.so,
652+
# which is what makes a GPU-free client install possible. libcuopt and cuopt_grpc_server
653+
# both link it, so there is exactly one implementation of the mappers, not a client fork.
654+
#
655+
# LANGUAGES is deliberately not CUDA here: adding a .cu file to CUOPT_CLIENT_SRC_FILES
656+
# should fail loudly rather than quietly reintroduce a CUDA dependency.
657+
# Built as an OBJECT library first, mirroring cuopt_objs/cuopt. The shared library below
658+
# keeps hidden visibility and exports only the curated CUOPT_EXPORT surface, while
659+
# cuopt_static (for internal tests) links the objects directly -- internal symbols such as
660+
# the fast MPS parser's mps_phase_registry_t are not exported, and the internal test
661+
# binaries need them.
662+
add_library(cuopt_client_objs OBJECT ${CUOPT_CLIENT_SRC_FILES})
663+
# NOTE: default visibility, deliberately unlike cuopt_objs.
664+
#
665+
# cuopt_objs can hide everything not marked CUOPT_EXPORT because libcuopt has a curated
666+
# public C++ API. cuopt_client is different: it was carved out of the *internals*, so
667+
# libcuopt itself depends on ~214 of its symbols (the whole cpu_optimization_problem_t /
668+
# data_model_view_t / mps_data_model_t / grpc_client_t surface). Those are internal
669+
# cross-library references, not a public API, and hiding them makes libcuopt.so fail to
670+
# load with e.g. "undefined symbol: grpc_client_t::solve_mip".
671+
#
672+
# Curating them behind CUOPT_EXPORT would mean annotating essentially every host-side
673+
# method, so default visibility is the right trade here.
674+
set_target_properties(cuopt_client_objs
675+
PROPERTIES POSITION_INDEPENDENT_CODE ON
676+
CXX_SCAN_FOR_MODULES OFF
677+
)
678+
679+
add_library(cuopt_client SHARED $<TARGET_OBJECTS:cuopt_client_objs>)
680+
add_library(cuopt::cuopt_client ALIAS cuopt_client)
681+
682+
target_include_directories(cuopt_client
683+
PUBLIC
684+
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
685+
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
686+
INTERFACE
687+
"$<INSTALL_INTERFACE:include>"
688+
)
689+
690+
target_compile_definitions(cuopt_client
691+
PUBLIC "CUOPT_LOG_ACTIVE_LEVEL=RAPIDS_LOGGER_LOG_LEVEL_${LIBCUOPT_LOGGING_LEVEL}"
692+
)
693+
694+
set_target_properties(cuopt_client
695+
PROPERTIES POSITION_INDEPENDENT_CODE ON
696+
CXX_SCAN_FOR_MODULES OFF
697+
BUILD_RPATH "\$ORIGIN"
698+
INSTALL_RPATH "\$ORIGIN"
699+
LINKER_LANGUAGE CXX
700+
)
701+
702+
target_compile_definitions(cuopt_client_objs
703+
PUBLIC "CUOPT_LOG_ACTIVE_LEVEL=RAPIDS_LOGGER_LOG_LEVEL_${LIBCUOPT_LOGGING_LEVEL}"
704+
)
705+
706+
target_compile_options(cuopt_client_objs
707+
PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${CUOPT_CXX_FLAGS}>"
708+
)
709+
710+
target_include_directories(cuopt_client_objs
711+
PRIVATE
712+
"${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty"
713+
"${CMAKE_CURRENT_SOURCE_DIR}/src"
714+
"${CMAKE_CURRENT_SOURCE_DIR}/src/io"
715+
"${CMAKE_CURRENT_SOURCE_DIR}/src/grpc"
716+
"${CMAKE_CURRENT_SOURCE_DIR}/src/grpc/client"
717+
"${CMAKE_CURRENT_SOURCE_DIR}/src/grpc/codegen/generated"
718+
"${CMAKE_CURRENT_BINARY_DIR}"
719+
"${CMAKE_CURRENT_BINARY_DIR}/include"
720+
$<$<BOOL:${CUOPT_PARSER_WITH_BZIP2}>:${BZIP2_INCLUDE_DIRS}>
721+
$<$<BOOL:${CUOPT_PARSER_WITH_ZLIB}>:${ZLIB_INCLUDE_DIRS}>
722+
PUBLIC
723+
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
724+
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
725+
INTERFACE
726+
"$<INSTALL_INTERFACE:include>"
727+
)
728+
729+
# CCCL is a compile-time (header-only) dependency here: the fast MPS parser uses
730+
# host helpers from <cuda/cmath> (ceil_div, round_up). It pulls in no CUDA runtime.
731+
# bzip2 / zlib / lz4 are dlopen'd at runtime by file_to_string.cpp, so they are
732+
# header-only here too and deliberately absent from the link line.
733+
# The OBJECT library needs these for their INTERFACE include dirs / defines at compile time.
734+
target_link_libraries(cuopt_client_objs
735+
PUBLIC
736+
rapids_logger::rapids_logger
737+
CCCL::CCCL
738+
PRIVATE
739+
simde::simde
740+
OpenMP::OpenMP_CXX
741+
$<$<BOOL:${CUOPT_ENABLE_GRPC}>:protobuf::libprotobuf>
742+
$<$<BOOL:${CUOPT_ENABLE_GRPC}>:gRPC::grpc++>
743+
)
744+
745+
target_link_libraries(cuopt_client
746+
PUBLIC
747+
rapids_logger::rapids_logger
748+
CCCL::CCCL
749+
PRIVATE
750+
simde::simde
751+
OpenMP::OpenMP_CXX
752+
${CMAKE_DL_LIBS}
753+
$<$<BOOL:${CUOPT_ENABLE_GRPC}>:protobuf::libprotobuf>
754+
$<$<BOOL:${CUOPT_ENABLE_GRPC}>:gRPC::grpc++>
755+
)
756+
634757
add_library(cuopt_objs OBJECT
635758
${CUOPT_SRC_FILES}
636759
)
@@ -757,6 +880,7 @@ target_compile_definitions(cuopt_objs PUBLIC
757880

758881
target_link_libraries(cuopt_objs
759882
PUBLIC
883+
cuopt::cuopt_client
760884
CUDA::cublas
761885
CUDA::cusparse
762886
rmm::rmm
@@ -777,7 +901,10 @@ target_link_libraries(cuopt_objs
777901
# - generate tests --------------------------------------------------------------------------------
778902
if (BUILD_TESTS)
779903
include(CTest)
780-
add_library(cuopt_static STATIC $<TARGET_OBJECTS:cuopt_objs>)
904+
# Embeds cuopt_client_objs directly rather than linking libcuopt_client.so: the internal
905+
# test binaries reach parser internals that the shared library deliberately does not
906+
# export. Do not also link cuopt::cuopt_client here -- that would duplicate every symbol.
907+
add_library(cuopt_static STATIC $<TARGET_OBJECTS:cuopt_objs> $<TARGET_OBJECTS:cuopt_client_objs>)
781908
target_link_libraries(cuopt_static
782909
PUBLIC
783910
CUDA::cublas
@@ -839,6 +966,7 @@ target_include_directories(cuopt
839966
)
840967
target_link_libraries(cuopt
841968
PUBLIC
969+
cuopt::cuopt_client
842970
CUDA::cublas
843971
CUDA::cusparse
844972
rmm::rmm
@@ -904,14 +1032,14 @@ else ()
9041032
endif ()
9051033

9061034
# adds the .so files to the runtime deb package
907-
install(TARGETS cuopt
1035+
install(TARGETS cuopt cuopt_client
9081036
DESTINATION ${_LIB_DEST}
9091037
COMPONENT runtime
9101038
EXPORT cuopt-exports
9111039
)
9121040

9131041
# adds the .so files to the development deb package
914-
install(TARGETS cuopt
1042+
install(TARGETS cuopt cuopt_client
9151043
DESTINATION ${_LIB_DEST}
9161044
COMPONENT dev
9171045
)
@@ -939,7 +1067,7 @@ cuOpt library is a collection of GPU accelerated combinatorial optimization algo
9391067

9401068
rapids_export(INSTALL cuopt
9411069
EXPORT_SET cuopt-exports
942-
GLOBAL_TARGETS cuopt
1070+
GLOBAL_TARGETS cuopt cuopt_client
9431071
NAMESPACE cuopt::
9441072
DOCUMENTATION doc_string
9451073
)
@@ -948,7 +1076,7 @@ rapids_export(INSTALL cuopt
9481076
# - build export -------------------------------------------------------------------------------
9491077
rapids_export(BUILD cuopt
9501078
EXPORT_SET cuopt-exports
951-
GLOBAL_TARGETS cuopt
1079+
GLOBAL_TARGETS cuopt cuopt_client
9521080
NAMESPACE cuopt::
9531081
DOCUMENTATION doc_string
9541082
)

cpp/src/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
# cmake-format: on
55

66
set(UTIL_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/utilities/seed_generator.cu
7-
${CMAKE_CURRENT_SOURCE_DIR}/utilities/logger.cpp
87
${CMAKE_CURRENT_SOURCE_DIR}/utilities/version_info.cpp
98
${CMAKE_CURRENT_SOURCE_DIR}/utilities/timestamp_utils.cpp
109
${CMAKE_CURRENT_SOURCE_DIR}/utilities/work_unit_scheduler.cpp)
1110

11+
# logger.cpp backs <utilities/logger.hpp>, which both the parsers and the gRPC
12+
# sources include, so it belongs to the CPU library. Without this, cuopt_client would
13+
# have an undefined reference to the logger.
14+
set(UTIL_CLIENT_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/utilities/logger.cpp)
15+
1216
add_subdirectory(linear_algebra)
1317
add_subdirectory(pdlp)
1418
add_subdirectory(math_optimization)
@@ -26,4 +30,5 @@ add_subdirectory(branch_and_bound)
2630
add_subdirectory(cuts)
2731

2832
set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} ${UTIL_SRC_FILES} PARENT_SCOPE)
33+
set(CUOPT_CLIENT_SRC_FILES ${CUOPT_CLIENT_SRC_FILES} ${UTIL_CLIENT_SRC_FILES} PARENT_SCOPE)
2934
set(MPS_FAST_SRC_FILES ${MPS_FAST_SRC_FILES} PARENT_SCOPE)

cpp/src/io/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,10 @@ set(PARSERS_SRC_FILES
2323
${MPS_FAST_SRC_FILES}
2424
)
2525

26-
set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} ${PARSERS_SRC_FILES} PARENT_SCOPE)
26+
# The parsers and the host-side problem representation are CUDA-free (the only
27+
# `cuda::` uses are host integer helpers from header-only libcu++), so they build
28+
# into the CPU-only cuopt_client library rather than into cuopt_objs. That is what
29+
# lets the Python data_model / solver_settings / io extension modules link a
30+
# library with no CUDA runtime dependency.
31+
set(CUOPT_CLIENT_SRC_FILES ${CUOPT_CLIENT_SRC_FILES} ${PARSERS_SRC_FILES} PARENT_SCOPE)
2732
set(MPS_FAST_SRC_FILES ${MPS_FAST_SRC_FILES} PARENT_SCOPE)

cpp/src/math_optimization/CMakeLists.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@
55

66
list(PREPEND
77
MATH_OPT_SRC_FILES
8-
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cpp
98
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings_gpu.cu
109
${CMAKE_CURRENT_SOURCE_DIR}/solution_reader.cu
1110
${CMAKE_CURRENT_SOURCE_DIR}/solution_writer.cu
1211
${CMAKE_CURRENT_SOURCE_DIR}/tic_toc.cpp
1312
)
1413

14+
# solver_settings_t is host-only apart from the device members in solver_settings_gpu.cu,
15+
# so the bulk of it builds into cuopt_client. The gRPC client takes a solver_settings_t
16+
# in its public API, so this is required for the client library to resolve standalone.
17+
set(MATH_OPT_CLIENT_SRC_FILES
18+
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cpp
19+
)
20+
1521
set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES}
1622
${MATH_OPT_SRC_FILES} PARENT_SCOPE)
23+
set(CUOPT_CLIENT_SRC_FILES ${CUOPT_CLIENT_SRC_FILES}
24+
${MATH_OPT_CLIENT_SRC_FILES} PARENT_SCOPE)

cpp/src/mip_heuristics/CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ set(MIP_LP_NECESSARY_FILES
99
${CMAKE_CURRENT_SOURCE_DIR}/problem/problem.cu
1010
${CMAKE_CURRENT_SOURCE_DIR}/problem/presolve_data.cu
1111
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cu
12-
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cpp
1312
${CMAKE_CURRENT_SOURCE_DIR}/solver_solution.cu
1413
${CMAKE_CURRENT_SOURCE_DIR}/local_search/rounding/simple_rounding.cu
1514
${CMAKE_CURRENT_SOURCE_DIR}/presolve/third_party_presolve.cpp
@@ -55,5 +54,13 @@ else()
5554
set(MIP_SRC_FILES ${MIP_LP_NECESSARY_FILES} ${MIP_NON_LP_FILES})
5655
endif()
5756

57+
# Host-only members of mip_solver_settings_t (callbacks, tolerances). The gRPC client
58+
# needs them, so they build into cuopt_client; add_initial_solution stays in the .cu.
59+
set(MIP_CLIENT_SRC_FILES
60+
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cpp
61+
)
62+
5863
set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES}
5964
${MIP_SRC_FILES} PARENT_SCOPE)
65+
set(CUOPT_CLIENT_SRC_FILES ${CUOPT_CLIENT_SRC_FILES}
66+
${MIP_CLIENT_SRC_FILES} PARENT_SCOPE)

cpp/src/pdlp/CMakeLists.txt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
# Core LP files always included
77
set(LP_CORE_FILES
88
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cu
9-
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings_accessors.cpp
109
${CMAKE_CURRENT_SOURCE_DIR}/optimization_problem.cu
11-
${CMAKE_CURRENT_SOURCE_DIR}/cpu_optimization_problem.cpp
1210
${CMAKE_CURRENT_SOURCE_DIR}/cpu_optimization_problem_to_gpu.cpp
1311
${CMAKE_CURRENT_SOURCE_DIR}/backend_selection.cpp
1412
${CMAKE_CURRENT_SOURCE_DIR}/utilities/problem_checking.cu
@@ -17,7 +15,6 @@ set(LP_CORE_FILES
1715
${CMAKE_CURRENT_SOURCE_DIR}/pdhg.cu
1816
${CMAKE_CURRENT_SOURCE_DIR}/solver_solution.cu
1917
${CMAKE_CURRENT_SOURCE_DIR}/solution_conversion.cu
20-
${CMAKE_CURRENT_SOURCE_DIR}/solution_conversion_cpu.cpp
2118
${CMAKE_CURRENT_SOURCE_DIR}/saddle_point.cu
2219
${CMAKE_CURRENT_SOURCE_DIR}/cusparse_view.cu
2320
${CMAKE_CURRENT_SOURCE_DIR}/pdlp_warm_start_data.cu
@@ -52,4 +49,14 @@ else()
5249
set(LP_SRC_FILES ${LP_CORE_FILES} ${LP_ADAPTER_FILES})
5350
endif()
5451

52+
# Host-only LP sources that the gRPC client needs. These build into cuopt_client so the
53+
# client library resolves standalone, without libcuopt.so. Their GPU-facing members were
54+
# split into separate CUDA translation units above (e.g. cpu_optimization_problem_to_gpu.cpp).
55+
set(LP_CLIENT_FILES
56+
${CMAKE_CURRENT_SOURCE_DIR}/cpu_optimization_problem.cpp
57+
${CMAKE_CURRENT_SOURCE_DIR}/solution_conversion_cpu.cpp
58+
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings_accessors.cpp
59+
)
60+
5561
set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} ${LP_SRC_FILES} PARENT_SCOPE)
62+
set(CUOPT_CLIENT_SRC_FILES ${CUOPT_CLIENT_SRC_FILES} ${LP_CLIENT_FILES} PARENT_SCOPE)

0 commit comments

Comments
 (0)