# \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 _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}/MsgData.py ${MSGUTILS_SCRIPTS_DIR}/MsgCpp.py ${MSGUTILS_SCRIPTS_DIR}/GenerateMsgDefsCpp.py ${MSGUTILS_SCRIPTS_DIR}/templates/MsgDefs_h.jinja ${MSGUTILS_SCRIPTS_DIR}/templates/MsgDefs_cpp.jinja ${${_input_csvs}} OUTPUT ${_header_path} ${_source_path} COMMAND ${Python3_EXECUTABLE} ${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 _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}/MsgData.py ${MSGUTILS_SCRIPTS_DIR}/MsgProtobuf.py ${MSGUTILS_SCRIPTS_DIR}/GenerateProtobuf.py ${MSGUTILS_SCRIPTS_DIR}/templates/MsgDefs_proto.jinja ${${_input_csvs}} OUTPUT ${_protobuf_abs_filename} COMMAND ${Python3_EXECUTABLE} ${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()