# \brief This function adds a custom command to generate message defintions from inputted message conf files # \param[in] _input_confs list of message conf files to use to generate the header # \param[in] _device_name name of device these files are being generated for # \param[in] _header_dir directory where the header file will be outputted # \param[in] _source_dir directory where the source file will be outputted # \param[in] _namespace C++ namespace for the outputted message definitions function(generate_msg_defs_cpp _input_confs _device_name _header_dir _source_dir _namespace) find_package(Python3 COMPONENTS Interpreter Development REQUIRED) # create a variable with the full path output header file get_filename_component(_header_dir ${_header_dir} ABSOLUTE) # cmake < 3.20 # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _header_path) string(JOIN "/" _header_path ${_header_dir} ${_device_name}MsgDefs.h) # create a variable with the full path output header file get_filename_component(_source_dir ${_source_dir} ABSOLUTE) # cmake < 3.20 # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _source_path) string(JOIN "/" _source_path ${_source_dir} ${_device_name}MsgDefs.cpp) # protobuf utility files (struct <-> protobuf conversions) generated alongside the structs string(JOIN "/" _proto_utils_header_path ${_header_dir} ${_device_name}MsgProtoUtils.h) string(JOIN "/" _proto_utils_source_path ${_source_dir} ${_device_name}MsgProtoUtils.cpp) # generate a pretty string containing a list of the relative paths of all csv files foreach(_path ${${_input_confs}}) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _path) get_filename_component(_path ${_path} ABSOLUTE) list(APPEND _files ${_path}) endforeach() list(JOIN _files ", " _file_list) add_custom_command( DEPENDS ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgData.py ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgCpp.py ${MSGUTILS_SCRIPTS_DIR}/GenerateMsgDefsCpp.py ${MSGUTILS_SCRIPTS_DIR}/msgutils/templates/MsgDefs_h.jinja ${MSGUTILS_SCRIPTS_DIR}/msgutils/templates/MsgDefs_cpp.jinja ${MSGUTILS_SCRIPTS_DIR}/msgutils/templates/MsgProtoUtils_h.jinja ${MSGUTILS_SCRIPTS_DIR}/msgutils/templates/MsgProtoUtils_cpp.jinja ${${_input_confs}} OUTPUT ${_header_path} ${_source_path} ${_proto_utils_header_path} ${_proto_utils_source_path} COMMAND ${PROJECT_PYTHON} ${MSGUTILS_SCRIPTS_DIR}/GenerateMsgDefsCpp.py --namespace ${_namespace} --header_dir ${_header_dir} --source_dir ${_source_dir} --proto ${${_input_confs}} ${_device_name} COMMENT "Generating MsgDefs C++ header ${_header_path} and source ${_source_path} from input ${_file_list}" VERBATIM ) endfunction() # \brief This function adds a custom command to generate/update a message handling INI. # \param[in] _input_confs list of message conf files to use to generate the INI # \param[in] _output_ini path to the INI file to create or update # \param[in] _target_name name of the custom target to add function(generate_message_ini _input_confs _output_ini _target_name) find_package(Python3 COMPONENTS Interpreter Development REQUIRED) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _output_ini) get_filename_component(_output_ini ${_output_ini} ABSOLUTE) # cmake < 3.20 # generate a pretty string containing a list of the absolute paths of all conf files foreach(_path ${${_input_confs}}) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _path) get_filename_component(_path ${_path} ABSOLUTE) list(APPEND _files ${_path}) endforeach() list(JOIN _files ", " _file_list) add_custom_command( DEPENDS ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgData.py ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgIni.py ${MSGUTILS_SCRIPTS_DIR}/GenerateMsgIni.py ${MSGUTILS_SCRIPTS_DIR}/msgutils/templates/MsgIni.jinja ${${_input_confs}} OUTPUT ${_output_ini} COMMAND ${PROJECT_PYTHON} ${MSGUTILS_SCRIPTS_DIR}/GenerateMsgIni.py ${${_input_confs}} ${_output_ini} COMMENT "Generating/updating message INI ${_output_ini} from input ${_file_list}" VERBATIM ) add_custom_target(${_target_name} DEPENDS ${_output_ini}) endfunction() # \brief This function adds a custom command to generate a Protobuf file from inputted message conf files # \param[in] _input_confs list of message conf files to use to generate the header # \param[in] _protobuf_filename name of the generated protobuf file # \param[in] _output_path directory where the header file will be outputted # \param[in] _namespace C++ namespace for the outputted message definitions function(generate_protobuf _input_confs _protobuf_filename _output_path _namespace) find_package(Python3 COMPONENTS Interpreter Development REQUIRED) # create a variable with the full path output header file string(JOIN "/" _protobuf_abs_filename ${_output_path} ${_protobuf_filename}) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _protobuf_abs_filename) get_filename_component(_protobuf_abs_filename ${_protobuf_abs_filename} ABSOLUTE) # cmake < 3.20 # generate a pretty string containing a list of the relative paths of all csv files foreach(_path ${${_input_confs}}) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _path) get_filename_component(_path ${_path} ABSOLUTE) # cmake < 3.20 list(APPEND _files ${_path}) endforeach() list(JOIN _files ", " _file_list) add_custom_command( DEPENDS ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgData.py ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgProtobuf.py ${MSGUTILS_SCRIPTS_DIR}/GenerateProtobuf.py ${MSGUTILS_SCRIPTS_DIR}/msgutils/templates/MsgDefs_proto.jinja ${${_input_confs}} OUTPUT ${_protobuf_abs_filename} COMMAND ${PROJECT_PYTHON} ${MSGUTILS_SCRIPTS_DIR}/GenerateProtobuf.py --namespace ${_namespace} --output_dir ${_output_path} ${${_input_confs}} ${_protobuf_filename} COMMENT "Generating Protobuf definitions ${_protobuf_abs_filename} from input ${_file_list}" VERBATIM ) endfunction() # \brief This function adds a custom command to generate message defintions from inputted CSV files # \param[in] _input_csvs list of CSV files to use to generate the header # \param[in] _device_name name of device these files are being generated for # \param[in] _header_dir directory where the header file will be outputted # \param[in] _source_dir directory where the source file will be outputted # \param[in] _namespace C++ namespace for the outputted message definitions function(generate_msg_defs_cpp_csvs _input_csvs _device_name _header_dir _source_dir _namespace) find_package(Python3 COMPONENTS Interpreter Development REQUIRED) # create a variable with the full path output header file get_filename_component(_header_dir ${_header_dir} ABSOLUTE) # cmake < 3.20 # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _header_path) string(JOIN "/" _header_path ${_header_dir} ${_device_name}MsgDefs.h) # create a variable with the full path output header file get_filename_component(_source_dir ${_source_dir} ABSOLUTE) # cmake < 3.20 # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _source_path) string(JOIN "/" _source_path ${_source_dir} ${_device_name}MsgDefs.cpp) # generate a pretty string containing a list of the relative paths of all csv files foreach(_path ${${_input_csvs}}) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _path) get_filename_component(_path ${_path} ABSOLUTE) list(APPEND _files ${_path}) endforeach() list(JOIN _files ", " _file_list) add_custom_command( DEPENDS ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgData.py ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgCpp.py ${MSGUTILS_SCRIPTS_DIR}/GenerateMsgDefsCpp.py ${MSGUTILS_SCRIPTS_DIR}/msgutils/templates/MsgDefs_h.jinja ${MSGUTILS_SCRIPTS_DIR}/msgutils/templates/MsgDefs_cpp.jinja ${${_input_csvs}} OUTPUT ${_header_path} ${_source_path} COMMAND ${PROJECT_PYTHON} ${MSGUTILS_SCRIPTS_DIR}/GenerateMsgDefsCpp.py --namespace ${_namespace} --header_dir ${_header_dir} --source_dir ${_source_dir} ${${_input_csvs}} ${_device_name} COMMENT "Generating MsgDefs C++ header ${_header_path} and source ${_source_path} from input ${_file_list}" VERBATIM ) endfunction() # \brief This function adds a custom command to generate a Protobuf file from inputted CSV files # \param[in] _input_csvs list of CSV files to use to generate the header # \param[in] _protobuf_filename name of the generated protobuf file # \param[in] _output_path directory where the header file will be outputted # \param[in] _namespace C++ namespace for the outputted message definitions function(generate_protobuf_csvs _input_csvs _protobuf_filename _output_path _namespace) find_package(Python3 COMPONENTS Interpreter Development REQUIRED) # create a variable with the full path output header file string(JOIN "/" _protobuf_abs_filename ${_output_path} ${_protobuf_filename}) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _protobuf_abs_filename) get_filename_component(_protobuf_abs_filename ${_protobuf_abs_filename} ABSOLUTE) # cmake < 3.20 # generate a pretty string containing a list of the relative paths of all csv files foreach(_path ${${_input_csvs}}) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _path) get_filename_component(_path ${_path} ABSOLUTE) # cmake < 3.20 list(APPEND _files ${_path}) endforeach() list(JOIN _files ", " _file_list) add_custom_command( DEPENDS ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgData.py ${MSGUTILS_SCRIPTS_DIR}/msgutils/MsgProtobuf.py ${MSGUTILS_SCRIPTS_DIR}/GenerateProtobuf.py ${MSGUTILS_SCRIPTS_DIR}/msgutils/templates/MsgDefs_proto.jinja ${${_input_csvs}} OUTPUT ${_protobuf_abs_filename} COMMAND ${PROJECT_PYTHON} ${MSGUTILS_SCRIPTS_DIR}/GenerateProtobuf.py --namespace ${_namespace} --output_dir ${_output_path} ${${_input_csvs}} ${_protobuf_filename} COMMENT "Generating Protobuf definitions ${_protobuf_abs_filename} from input ${_file_list}" VERBATIM ) endfunction() # \brief This function adds a custom command to generate C++ heder and source files from an inputted Protobuf file # \param[in] _protobuf_filename name of the input Protobuf file # \param[in] _protobuf_path directory containing the input Protobuf file # \param[in] _header_path directory where the generated C++ header file will be outputted # \param[in] _source_path directory where the generated C++ source file will be outputted function(generate_protobuf_cpp _protobuf_filename _protobuf_path _header_path _source_path) find_package(Protobuf REQUIRED) find_program(PROTOBUF_PROTOC protoc REQUIRED) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _protobuf_path) get_filename_component(_protobuf_path ${_protobuf_path} ABSOLUTE) # cmake < 3.20 # cmake >= 3.20: cmake_path(GET _protobuf_filename STEM LAST_ONLY _protobuf_filename_laststem) get_filename_component(_protobuf_filename_laststem ${_protobuf_filename} NAME) string(REGEX REPLACE "\\.[^.]*$" "" _protobuf_filename_laststem ${_protobuf_filename_laststem}) string(JOIN "/" _protobuf_abs_filename ${_protobuf_path} ${_protobuf_filename}) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _protobuf_abs_filename) get_filename_component(_protobuf_abs_filename ${_protobuf_abs_filename} ABSOLUTE) # cmake < 3.20 string(JOIN "/" _header_abs_filename ${_header_path} ${_protobuf_filename_laststem}.pb.h) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _header_abs_filename) get_filename_component(_header_abs_filename ${_header_abs_filename} ABSOLUTE) # cmake < 3.20 string(JOIN "/" _source_abs_filename ${_source_path} ${_protobuf_filename_laststem}.pb.cc) # cmake >= 3.20: cmake_path(ABSOLUTE_PATH _source_abs_filename) get_filename_component(_source_abs_filename ${_source_abs_filename} ABSOLUTE) # cmake < 3.20 # uncomment this line and the _proto_srcs and _proto_hdrs lines in DEPENDS to use the # cmake built-in function to generate the protobuf cpp files # NOTE: the built-in function seems to not realize if the input proto file has changed # and will always force the .h/.cpp files to regenerate and trigger a recompile, # the add_custom_command below, does not trigger a recompile if the proto is unchanged. # protobuf_generate_cpp(_proto_srcs _proto_hdrs ${_protobuf_abs_filename}) add_custom_command( DEPENDS ${_protobuf_abs_filename} # ${_proto_hdrs} # ${_proto_srcs} OUTPUT ${_header_abs_filename} ${_source_abs_filename} COMMAND ${PROTOBUF_PROTOC} --proto_path ${_protobuf_path} --cpp_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_abs_filename} COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_BINARY_DIR}/${_protobuf_filename_laststem}.pb.h ${_header_abs_filename} COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_BINARY_DIR}/${_protobuf_filename_laststem}.pb.cc ${_source_abs_filename} COMMENT "Generating C++ files ${_header_abs_filename} and ${_source_abs_filename} from Protobuf file ${_protobuf_abs_filename}" VERBATIM ) endfunction()