@@ -255,6 +255,92 @@ create_logger_macros(CUOPT "cuopt::default_logger()" include/cuopt)
255255
256256find_package (CUDSS REQUIRED )
257257
258+ # ##################################################################################################
259+ # - gRPC and Protobuf setup (REQUIRED) ------------------------------------------------------------
260+
261+ # gRPC is required for this branch - it provides remote execution features
262+ # gRPC can come from either:
263+ # - an installed CMake package (gRPCConfig.cmake), or
264+ # - an in-tree build (e.g. python/libcuopt uses FetchContent(grpc), which defines gRPC::grpc++).
265+ if (NOT TARGET gRPC::grpc++)
266+ find_package (gRPC CONFIG REQUIRED )
267+ endif ()
268+
269+ # Find Protobuf (should come with gRPC, but verify)
270+ if (NOT TARGET protobuf::libprotobuf)
271+ find_package (protobuf CONFIG REQUIRED )
272+ endif ()
273+
274+ set (CUOPT_ENABLE_GRPC ON )
275+ add_compile_definitions (CUOPT_ENABLE_GRPC )
276+ message (STATUS "gRPC enabled (target gRPC::grpc++ is available)" )
277+
278+ # Find protoc compiler (provided by config package or target)
279+ if (TARGET protobuf::protoc)
280+ get_target_property (_PROTOBUF_PROTOC protobuf::protoc IMPORTED_LOCATION_RELEASE )
281+ if (NOT _PROTOBUF_PROTOC)
282+ get_target_property (_PROTOBUF_PROTOC protobuf::protoc IMPORTED_LOCATION )
283+ endif ()
284+ else ()
285+ find_package (protobuf CONFIG REQUIRED )
286+ get_target_property (_PROTOBUF_PROTOC protobuf::protoc IMPORTED_LOCATION_RELEASE )
287+ if (NOT _PROTOBUF_PROTOC)
288+ get_target_property (_PROTOBUF_PROTOC protobuf::protoc IMPORTED_LOCATION )
289+ endif ()
290+ endif ()
291+
292+ if (NOT _PROTOBUF_PROTOC)
293+ message (FATAL_ERROR "protoc not found (Protobuf_PROTOC_EXECUTABLE is empty)" )
294+ endif ()
295+
296+ # Find grpc_cpp_plugin
297+ if (TARGET grpc_cpp_plugin)
298+ set (_GRPC_CPP_PLUGIN_EXECUTABLE "$<TARGET_FILE :grpc_cpp_plugin >" )
299+ else ()
300+ find_program (_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin )
301+ if (NOT _GRPC_CPP_PLUGIN_EXECUTABLE)
302+ message (FATAL_ERROR "grpc_cpp_plugin not found" )
303+ endif ()
304+ endif ()
305+
306+ # Generate C++ code from cuopt_remote.proto (base message definitions)
307+ set (PROTO_FILE "${CMAKE_CURRENT_SOURCE_DIR} /src/grpc/cuopt_remote.proto" )
308+ set (PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR} /cuopt_remote.pb.cc" )
309+ set (PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR} /cuopt_remote.pb.h" )
310+
311+ add_custom_command (
312+ OUTPUT "${PROTO_SRCS} " "${PROTO_HDRS} "
313+ COMMAND ${_PROTOBUF_PROTOC}
314+ ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR}
315+ --proto_path ${CMAKE_CURRENT_SOURCE_DIR} /src/grpc
316+ ${PROTO_FILE}
317+ DEPENDS ${PROTO_FILE}
318+ COMMENT "Generating C++ code from cuopt_remote.proto"
319+ VERBATIM
320+ )
321+
322+ # Generate gRPC service code from cuopt_remote_service.proto
323+ set (GRPC_PROTO_FILE "${CMAKE_CURRENT_SOURCE_DIR} /src/grpc/cuopt_remote_service.proto" )
324+ set (GRPC_PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR} /cuopt_remote_service.pb.cc" )
325+ set (GRPC_PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR} /cuopt_remote_service.pb.h" )
326+ set (GRPC_SERVICE_SRCS "${CMAKE_CURRENT_BINARY_DIR} /cuopt_remote_service.grpc.pb.cc" )
327+ set (GRPC_SERVICE_HDRS "${CMAKE_CURRENT_BINARY_DIR} /cuopt_remote_service.grpc.pb.h" )
328+
329+ add_custom_command (
330+ OUTPUT "${GRPC_PROTO_SRCS} " "${GRPC_PROTO_HDRS} " "${GRPC_SERVICE_SRCS} " "${GRPC_SERVICE_HDRS} "
331+ COMMAND ${_PROTOBUF_PROTOC}
332+ ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR}
333+ --grpc_out ${CMAKE_CURRENT_BINARY_DIR}
334+ --plugin=protoc-gen-grpc=${_GRPC_CPP_PLUGIN_EXECUTABLE}
335+ --proto_path ${CMAKE_CURRENT_SOURCE_DIR} /src/grpc
336+ ${GRPC_PROTO_FILE}
337+ DEPENDS ${GRPC_PROTO_FILE} ${PROTO_FILE}
338+ COMMENT "Generating gRPC C++ code from cuopt_remote_service.proto"
339+ VERBATIM
340+ )
341+
342+ message (STATUS "gRPC protobuf code generation configured" )
343+
258344if (BUILD_TESTS)
259345 include (cmake/thirdparty/get_gtest.cmake )
260346endif ()
@@ -264,6 +350,20 @@ add_subdirectory(src)
264350if (HOST_LINEINFO)
265351 set_source_files_properties (${CUOPT_SRC_FILES} DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTIES COMPILE_OPTIONS "-g1" )
266352endif ()
353+
354+ # Add gRPC mapper files and generated protobuf sources
355+ list (APPEND CUOPT_SRC_FILES
356+ ${PROTO_SRCS}
357+ ${GRPC_PROTO_SRCS}
358+ ${GRPC_SERVICE_SRCS}
359+ src/grpc/grpc_problem_mapper.cu
360+ src/grpc/grpc_solution_mapper.cu
361+ src/grpc/grpc_settings_mapper.cu
362+ src/grpc/grpc_service_mapper.cu
363+ src/grpc/client/grpc_client.cu
364+ src/grpc/client/solve_remote.cu
365+ )
366+
267367add_library (cuopt SHARED
268368 ${CUOPT_SRC_FILES}
269369)
@@ -315,6 +415,9 @@ target_include_directories(cuopt
315415 PRIVATE
316416 "${CMAKE_CURRENT_SOURCE_DIR} /../thirdparty"
317417 "${CMAKE_CURRENT_SOURCE_DIR} /src"
418+ "${CMAKE_CURRENT_SOURCE_DIR} /src/grpc"
419+ "${CMAKE_CURRENT_SOURCE_DIR} /src/grpc/client"
420+ "${CMAKE_CURRENT_BINARY_DIR} "
318421 "${CUDSS_INCLUDE} "
319422 PUBLIC
320423 "$<BUILD_INTERFACE :${CMAKE_CURRENT_SOURCE_DIR} /include >"
@@ -384,6 +487,8 @@ target_link_libraries(cuopt
384487 ${CUDSS_LIB_FILE}
385488 PRIVATE
386489 ${CUOPT_PRIVATE_CUDA_LIBS}
490+ protobuf::libprotobuf
491+ gRPC::grpc++
387492 )
388493
389494
@@ -606,6 +711,109 @@ if(BUILD_LP_BENCHMARKS)
606711 endif ()
607712endif ()
608713
714+ # ##################################################################################################
715+ # - cuopt_grpc_server - gRPC-based remote server --------------------------------------------------
716+
717+ add_executable (cuopt_grpc_server
718+ src/grpc/server/grpc_server_main.cpp
719+ src/grpc/server/grpc_worker.cpp
720+ src/grpc/server/grpc_worker_infra.cpp
721+ src/grpc/server/grpc_server_threads.cpp
722+ src/grpc/server/grpc_job_management.cpp
723+ src/grpc/server/grpc_service_impl.cpp
724+ )
725+
726+ set_target_properties (cuopt_grpc_server
727+ PROPERTIES
728+ CXX_STANDARD 20
729+ CXX_STANDARD_REQUIRED ON
730+ CXX_SCAN_FOR_MODULES OFF
731+ )
732+
733+ target_compile_options (cuopt_grpc_server
734+ PRIVATE "$<$<COMPILE_LANGUAGE :CXX >:${CUOPT_CXX_FLAGS} >"
735+ )
736+
737+ target_include_directories (cuopt_grpc_server
738+ PRIVATE
739+ "${CMAKE_CURRENT_SOURCE_DIR} /src"
740+ "${CMAKE_CURRENT_SOURCE_DIR} /src/grpc"
741+ "${CMAKE_CURRENT_SOURCE_DIR} /src/grpc/server"
742+ "${CMAKE_CURRENT_SOURCE_DIR} /include"
743+ "${CMAKE_CURRENT_SOURCE_DIR} /libmps_parser/include"
744+ "${CMAKE_CURRENT_BINARY_DIR} "
745+ PUBLIC
746+ "$<BUILD_INTERFACE :${CMAKE_CURRENT_SOURCE_DIR} /include >"
747+ "$<BUILD_INTERFACE :${CMAKE_CURRENT_BINARY_DIR} /include >"
748+ )
749+
750+ find_library (UUID_LIBRARY uuid REQUIRED )
751+
752+ target_link_libraries (cuopt_grpc_server
753+ PUBLIC
754+ cuopt
755+ OpenMP::OpenMP_CXX
756+ PRIVATE
757+ protobuf::libprotobuf
758+ gRPC::grpc++
759+ ${UUID_LIBRARY}
760+ )
761+
762+ # Use RUNPATH when building locally
763+ target_link_options (cuopt_grpc_server PRIVATE -Wl,--enable-new-dtags )
764+ set_property (TARGET cuopt_grpc_server PROPERTY INSTALL_RPATH "$ORIGIN/../${lib_dir} " )
765+
766+ # Install the grpc server executable
767+ install (TARGETS cuopt_grpc_server
768+ COMPONENT runtime
769+ RUNTIME DESTINATION ${_BIN_DEST}
770+ )
771+
772+ message (STATUS "Building cuopt_grpc_server (gRPC-based remote solve server)" )
773+
774+ # ##################################################################################################
775+ # - test_grpc_client - Simple test client for cuopt_grpc_server -----------------------------------
776+
777+ add_executable (test_grpc_client src/grpc/client/test_grpc_client.cpp )
778+
779+ set_target_properties (test_grpc_client
780+ PROPERTIES
781+ CXX_STANDARD 20
782+ CXX_STANDARD_REQUIRED ON
783+ CXX_SCAN_FOR_MODULES OFF
784+ )
785+
786+ target_compile_options (test_grpc_client
787+ PRIVATE "$<$<COMPILE_LANGUAGE :CXX >:${CUOPT_CXX_FLAGS} >"
788+ )
789+
790+ target_include_directories (test_grpc_client
791+ PRIVATE
792+ "${CMAKE_CURRENT_SOURCE_DIR} /src"
793+ "${CMAKE_CURRENT_SOURCE_DIR} /src/grpc"
794+ "${CMAKE_CURRENT_SOURCE_DIR} /src/grpc/client"
795+ "${CMAKE_CURRENT_SOURCE_DIR} /include"
796+ "${CMAKE_CURRENT_SOURCE_DIR} /libmps_parser/include"
797+ "${CMAKE_CURRENT_BINARY_DIR} "
798+ PUBLIC
799+ "$<BUILD_INTERFACE :${CMAKE_CURRENT_SOURCE_DIR} /include >"
800+ "$<BUILD_INTERFACE :${CMAKE_CURRENT_BINARY_DIR} /include >"
801+ )
802+
803+ target_link_libraries (test_grpc_client
804+ PUBLIC
805+ cuopt
806+ PRIVATE
807+ protobuf::libprotobuf
808+ gRPC::grpc++
809+ )
810+
811+ # Use RUNPATH when building locally
812+ target_link_options (test_grpc_client PRIVATE -Wl,--enable-new-dtags )
813+ set_property (TARGET test_grpc_client PROPERTY INSTALL_RPATH "$ORIGIN/../${lib_dir} " )
814+
815+ message (STATUS "Building test_grpc_client (simple gRPC client for testing)" )
816+
609817
610818# ##################################################################################################
611819# - CPack has to be the last item in the cmake file-------------------------------------------------
0 commit comments