11file (MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} /protos_gen)
2+ file (MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} /protos_gen_py)
23
34file (GLOB_RECURSE intrinsic_proto_SRCS "${intrinsic_sdk_SOURCE_DIR} /**/*.proto" )
45list (FILTER intrinsic_proto_SRCS EXCLUDE REGEX "_test\\ .proto$" )
56
67set (exclude_SRCS
7- intrinsic/icon/proto/service.proto
8+ intrinsic/icon/proto/service.proto
89 third_party/ros2/ros_interfaces/jazzy/diagnostic_msgs/srv/self_test.proto
910 third_party/ros2/ros_interfaces/jazzy/diagnostic_msgs/srv/add_diagnostics.proto
1011 third_party/ros2/ros_interfaces/jazzy/rcl_interfaces/srv/set_parameters.proto
@@ -77,22 +78,28 @@ set(grpc_gateway_SRCS
7778 ${grpc_gateway_SOURCE_DIR} /protoc-gen-openapiv2/options /openapiv2.proto
7879)
7980
80- # Generate code from protos and build into a library.
81- add_library (intrinsic_sdk_protos STATIC
81+ set (sdk_protos
8282 ${intrinsic_proto_SRCS}
8383 ${googleapis_SRCS}
8484 ${grpc_gateway_SRCS}
8585 ${grpc_SRCS}
8686)
87+ set (sdk_proto_import_dirs
88+ ${intrinsic_sdk_SOURCE_DIR}
89+ ${googleapis_SOURCE_DIR}
90+ ${grpc_gateway_SOURCE_DIR}
91+ ${grpc_SOURCE_DIR}
92+ )
93+
94+ # Generate code from protos and build into a library.
95+ add_library (intrinsic_sdk_protos STATIC
96+ ${sdk_protos}
97+ )
8798set_property (TARGET intrinsic_sdk_protos PROPERTY POSITION_INDEPENDENT_CODE ON )
8899protobuf_generate(
89100 TARGET intrinsic_sdk_protos
90101 LANGUAGE cpp
91- IMPORT_DIRS
92- ${intrinsic_sdk_SOURCE_DIR}
93- ${googleapis_SOURCE_DIR}
94- ${grpc_gateway_SOURCE_DIR}
95- ${grpc_SOURCE_DIR}
102+ IMPORT_DIRS ${sdk_proto_import_dirs}
96103 PROTOC_OPTIONS --experimental_editions
97104 PROTOC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR} /protos_gen
98105)
@@ -114,11 +121,7 @@ protobuf_generate(
114121 TARGET intrinsic_sdk_services
115122 LANGUAGE grpc
116123 PLUGIN protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>
117- IMPORT_DIRS
118- ${intrinsic_sdk_SOURCE_DIR}
119- ${googleapis_SOURCE_DIR}
120- ${grpc_gateway_SOURCE_DIR}
121- ${grpc_SOURCE_DIR}
124+ IMPORT_DIRS ${sdk_proto_import_dirs}
122125 PROTOC_OPTIONS --experimental_editions
123126 PROTOC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR} /protos_gen
124127 GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc
@@ -131,6 +134,158 @@ target_include_directories(intrinsic_sdk_services
131134target_link_libraries (intrinsic_sdk_services PUBLIC intrinsic_sdk_protos)
132135set_property (TARGET intrinsic_sdk_services PROPERTY POSITION_INDEPENDENT_CODE ON )
133136
137+ # Generate Python code from the protos.
138+ # add_custom_target(intrinsic_sdk_protos_python ALL DEPENDS ${sdk_protos})
139+ # protobuf_generate(
140+ # TARGET intrinsic_sdk_protos_python
141+ # PLUGIN protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_python_plugin>
142+ # LANGUAGE python
143+ # PROTOS ${sdk_protos}
144+ # IMPORT_DIRS ${sdk_proto_import_dirs}
145+ # PROTOC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/protos_gen_py
146+ # OUT_VAR sdk_protos_python_sources_maybe_hyphens
147+ # )
148+ # Use the protoc from the grpcio-tools Python package to generate _pb2.py and _pb2_grpc.py files.
149+ set (venv_dir "${CMAKE_CURRENT_BINARY_DIR} /grpc_venv" )
150+ if (NOT EXISTS "${venv_dir} " )
151+ execute_process (
152+ COMMAND "${Python3_EXECUTABLE} " -m venv "${venv_dir} "
153+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR} "
154+ RESULT_VARIABLE VENV_CREATE_RESULT
155+ OUTPUT_VARIABLE VENV_CREATE_OUTPUT
156+ ERROR_VARIABLE VENV_CREATE_ERROR
157+ )
158+ if (NOT VENV_CREATE_RESULT EQUAL 0)
159+ message (FATAL_ERROR "Failed to create virtual environment: ${VENV_CREATE_ERROR} " )
160+ endif ()
161+
162+ execute_process (
163+ COMMAND "${venv_dir} /bin/pip" install -U grpcio-tools
164+ WORKING_DIRECTORY "${CMAKE_BINARY_DIR} "
165+ RESULT_VARIABLE PIP_INSTALL_RESULT
166+ OUTPUT_VARIABLE PIP_INSTALL_OUTPUT
167+ ERROR_VARIABLE PIP_INSTALL_ERROR
168+ )
169+ if (NOT PIP_INSTALL_RESULT EQUAL 0)
170+ message (FATAL_ERROR "Failed to install Python dependencies: ${PIP_INSTALL_ERROR} " )
171+ endif ()
172+ endif ()
173+ set (protoc_include_flags)
174+ foreach (sdk_proto_import_dir ${sdk_proto_import_dirs} )
175+ list (APPEND protoc_include_flags -I "${sdk_proto_import_dir} " )
176+ endforeach ()
177+ set (protoc_generated_files)
178+ foreach (sdk_proto ${sdk_protos} )
179+ set (_proto ${sdk_proto} )
180+ get_filename_component (_abs_file ${_proto} ABSOLUTE )
181+ get_filename_component (_abs_dir ${_abs_file} DIRECTORY )
182+ get_filename_component (_file_full_name ${_proto} NAME )
183+ string (FIND "${_file_full_name} " "." _file_last_ext_pos REVERSE )
184+ string (SUBSTRING "${_file_full_name} " 0 ${_file_last_ext_pos} _basename)
185+ set (_suitable_include_found FALSE )
186+ foreach (DIR ${sdk_proto_import_dirs} )
187+ if (NOT DIR STREQUAL "-I" )
188+ file (RELATIVE_PATH _rel_dir ${DIR} ${_abs_dir} )
189+ if (_rel_dir STREQUAL _abs_dir)
190+ # When there is no relative path from DIR to _abs_dir (e.g. due to
191+ # different drive letters on Windows), _rel_dir is equal to _abs_dir.
192+ # Therefore, DIR is not a suitable include path and must be skipped.
193+ continue ()
194+ endif ()
195+ string (FIND "${_rel_dir} " "../" _is_in_parent_folder)
196+ if (NOT ${_is_in_parent_folder} EQUAL 0)
197+ set (_suitable_include_found TRUE )
198+ break ()
199+ endif ()
200+ endif ()
201+ endforeach ()
202+ if (NOT _suitable_include_found)
203+ message (FATAL_ERROR "Error: could not find any correct proto include directory: ${_proto} " )
204+ endif ()
205+ set (_proto_generated_files)
206+ list (APPEND _proto_generated_files
207+ "${CMAKE_CURRENT_BINARY_DIR} /protos_gen_py/${_rel_dir} /${_basename} _pb2.py" )
208+ list (APPEND _proto_generated_files
209+ "${CMAKE_CURRENT_BINARY_DIR} /protos_gen_py/${_rel_dir} /${_basename} _pb2_grpc.py" )
210+ list (APPEND protoc_generated_files ${_proto_generated_files} )
211+ add_custom_command (
212+ OUTPUT ${_proto_generated_files}
213+ DEPENDS "${sdk_proto} "
214+ COMMAND
215+ "${venv_dir} /bin/python3"
216+ -m grpc_tools.protoc
217+ ${protoc_include_flags}
218+ --python_out="${CMAKE_CURRENT_BINARY_DIR} /protos_gen_py"
219+ --grpc_python_out="${CMAKE_CURRENT_BINARY_DIR} /protos_gen_py"
220+ "${sdk_proto} "
221+ COMMENT "Using 'grpc_tools.protoc' to generate Python code for '${sdk_proto} '..."
222+ )
223+ endforeach ()
224+ add_custom_target (intrinsic_sdk_protos_python ALL DEPENDS ${sdk_protos} ${protoc_generated_files} )
225+ set (sdk_protos_python_sources_maybe_hyphens ${protoc_generated_files} )
226+ # Create empty __init__.py files for each python package generated by protoc.
227+ set (sdk_protos_python_sources "" )
228+ set (python_package_directories "" )
229+ foreach (generated_python_file_maybe_hyphen ${sdk_protos_python_sources_maybe_hyphens} )
230+ file (RELATIVE_PATH rel_generated_python_file_maybe_hyphen
231+ "${CMAKE_CURRENT_BINARY_DIR} /protos_gen_py"
232+ "${generated_python_file_maybe_hyphen} "
233+ )
234+ string (REPLACE "-" "_" rel_generated_python_file "${rel_generated_python_file_maybe_hyphen} " )
235+ set (generated_python_file "${CMAKE_CURRENT_BINARY_DIR} /protos_gen_py/${rel_generated_python_file} " )
236+ list (APPEND sdk_protos_python_sources "${generated_python_file} " )
237+ get_filename_component (generated_python_file_dir "${generated_python_file} " DIRECTORY )
238+ list (APPEND python_package_directories "${generated_python_file_dir} " )
239+ endforeach ()
240+ list (REMOVE_DUPLICATES python_package_directories)
241+ set (python_init_py_files "" )
242+ # add __init__.py to "leaf" directories
243+ foreach (python_package_directory ${python_package_directories} )
244+ file (MAKE_DIRECTORY "${python_package_directory} " )
245+ set (python_init_py_file "${python_package_directory} /__init__.py" )
246+ list (APPEND python_init_py_files "${python_init_py_file} " )
247+ file (TOUCH "${python_init_py_file} " )
248+ endforeach ()
249+ # second pass to add __init__.py to intermediate directories now that the folder structure exists.
250+ file (GLOB_RECURSE leaf_python_init_files_and_dirs
251+ LIST_DIRECTORIES true
252+ RELATIVE "${CMAKE_CURRENT_BINARY_DIR} /protos_gen_py/"
253+ "${CMAKE_CURRENT_BINARY_DIR} /protos_gen_py/*/__init__.py"
254+ )
255+ foreach (leaf_python_init_file_or_dir ${leaf_python_init_files_and_dirs} )
256+ if (IS_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR} /protos_gen_py/${leaf_python_init_file_or_dir} " )
257+ set (python_init_py_file "${CMAKE_CURRENT_BINARY_DIR} /protos_gen_py/${leaf_python_init_file_or_dir} /__init__.py" )
258+ list (APPEND python_init_py_files "${python_init_py_file} " )
259+ file (TOUCH "${python_init_py_file} " )
260+ endif ()
261+ endforeach ()
262+ # final pass because glob doesn't get the root folders correctly.
263+ file (GLOB root_directories
264+ LIST_DIRECTORIES true
265+ "${CMAKE_CURRENT_BINARY_DIR} /protos_gen_py/*"
266+ )
267+ foreach (root_directory ${root_directories} )
268+ if (IS_DIRECTORY "${root_directory} " )
269+ set (python_init_py_file "${root_directory} /__init__.py" )
270+ list (APPEND python_init_py_files "${python_init_py_file} " )
271+ file (TOUCH "${python_init_py_file} " )
272+ endif ()
273+ endforeach ()
274+ list (REMOVE_DUPLICATES python_init_py_files)
275+
276+ # add_custom_target(intrinsic_sdk_protos_python_grpc ALL DEPENDS ${sdk_protos})
277+ # foreach(sdk_protos_python_source ${sdk_protos_python_sources})
278+ # string(REPLACE "_pb2.py" "_pb2_grpc.py" grpc_version "${sdk_protos_python_source}")
279+ # add_custom_command(
280+ # TARGET intrinsic_sdk_protos_python_grpc POST_BUILD
281+ # DEPENDS "${sdk_protos_python_source}" intrinsic_sdk_protos_python
282+ # COMMAND ${CMAKE_COMMAND} -E copy "${sdk_protos_python_source}" "${grpc_version}"
283+ # COMMENT "Duplicating '${sdk_protos_python_source}' as '${grpc_version}'..."
284+ # )
285+ # endforeach()
286+
287+ # Generated Python code is installed with the Python sdk files later.
288+
134289# Generate a descriptor set.
135290add_custom_command (
136291 OUTPUT ${CMAKE_CURRENT_BINARY_DIR} /intrinsic_proto.desc
0 commit comments