Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore message generation pipeline and generate message libraries #368

Merged
merged 23 commits into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ build_*
.DS_Store
*.swp
*.orig

# Python generated files
__pycache__
29 changes: 19 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ find_package(gz-cmake3 REQUIRED)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

gz_configure_project(VERSION_SUFFIX)
gz_configure_project(VERSION_SUFFIX
CONFIG_EXTRAS "gz-msgs-extras.cmake.in")

if (UNIX AND NOT APPLE)
set (EXTRA_TEST_LIB_DEPS stdc++fs)
else()
set (EXTRA_TEST_LIB_DEPS)
endif()
# Install cmake support files
install(
DIRECTORY cmake/
DESTINATION "${PROJECT_CMAKE_EXTRAS_INSTALL_DIR}"
)

#============================================================================
# Set project-specific options
Expand Down Expand Up @@ -80,11 +81,18 @@ gz_find_package(GzProtobuf
COMPONENTS all
PRETTY Protobuf)

#--------------------------------------
# Find gz-utils
gz_find_package(gz-utils2 REQUIRED)
set(GZ_UTILS_VER ${gz-utils2_VERSION_MAJOR})

#--------------------------------------
# Find gz-math
gz_find_package(gz-math7 REQUIRED)
set(GZ_MATH_VER ${gz-math7_VERSION_MAJOR})

find_package(Python3 REQUIRED COMPONENTS Interpreter)

#--------------------------------------
# Find if command is available. This is used to enable tests.
# Note that CLI files are installed regardless of whether the dependency is
Expand All @@ -96,6 +104,11 @@ set(GZ_TOOLS_VER 1)
# Find Tinyxml2
gz_find_package(TINYXML2 REQUIRED PRIVATE PRETTY tinyxml2)

#--------------------------------------
# Find DL
# Required for properly doing relocatable installation
gz_find_package(DL REQUIRED)
mjcarroll marked this conversation as resolved.
Show resolved Hide resolved

#--------------------------------------
# Find Python
find_package(Python3 REQUIRED COMPONENTS Interpreter)
Expand Down Expand Up @@ -129,10 +142,6 @@ add_subdirectory(tools)
#============================================================================
# Install proto files
#============================================================================
# TODO: Consider tweaking gz_configure_build() to call add_subdirectory(proto)
# whenever a proto subdirectory exists. This could be used alongside
# gz_msgs_protoc to get uniform support for proto messages across all Gazebo
# projects.
add_subdirectory(proto)

# Generate python
Expand Down
8 changes: 8 additions & 0 deletions Migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ Deprecated code produces compile-time warnings. These warning serve as
notification to users that their code should be upgraded. The next major
release will remove the deprecated code.

## Gazebo Msgs 9.X to 10.X

### Modifications

1. Th message generation pipeline is now accessible in downstream packages .
* For more information, consult the `using_gz_msgs` example.
* Note that there will no longer be Ruby generated messages, this support will be restored as-needed.

## Gazebo Msgs 8.X to 9.X

1. **SuppressWarnings.hh** is deprecated and isn't part of `msgs.hh` anymore.
Expand Down
71 changes: 71 additions & 0 deletions cmake/gz_msgs_factory.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
##################################################
# A function that generates factory methods for generated gz-msgs
# The output of this is are a header and source file that can be used as part of your library
# for the gz::msgs::Factory
# Options:
# One value arguments:
# FACTORY_GEN_SCRIPT - Location of the factory generator script
# PROTO_PACKAGE - Protobuf package the file belongs to (e.g. "gz.msgs")
# PROTOC_EXEC - Path to protoc
# OUTPUT_CPP_DIR - Path where C++ files are saved
# OUTPUT_CPP_HH_VAR - A CMake variable name containing a list that the C++ headers should be appended to
# OUTPUT_CPP_CC_VAR - A Cmake variable name containing a list that the C++ sources should be appended to
# Multi value arguments
# INPUT_PROTOS - List of input proto files
# PROTO_PATH - Base directory of the proto files
function(gz_msgs_factory)
set(options "")
set(oneValueArgs
FACTORY_GEN_SCRIPT
PROTO_PACKAGE
OUTPUT_CPP_DIR
OUTPUT_CPP_HH_VAR
OUTPUT_CPP_CC_VAR)
set(multiValueArgs INPUT_PROTOS PROTO_PATH)

cmake_parse_arguments(gz_msgs_factory "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

_gz_msgs_proto_pkg_to_path(${gz_msgs_factory_PROTO_PACKAGE} proto_package_dir)

set(output_header "${gz_msgs_factory_OUTPUT_CPP_DIR}/${proto_package_dir}/MessageTypes.hh")
set(output_source "${gz_msgs_factory_OUTPUT_CPP_DIR}/${proto_package_dir}/register.cc")

list(APPEND ${gz_msgs_factory_OUTPUT_CPP_HH_VAR} ${output_header})
list(APPEND ${gz_msgs_factory_OUTPUT_CPP_CC_VAR} ${output_source})

list(APPEND output_files ${output_header})
list(APPEND output_files ${output_source})

set(${gz_msgs_factory_OUTPUT_CPP_HH_VAR} ${${gz_msgs_factory_OUTPUT_CPP_HH_VAR}} PARENT_SCOPE)
set(${gz_msgs_factory_OUTPUT_CPP_CC_VAR} ${${gz_msgs_factory_OUTPUT_CPP_CC_VAR}} PARENT_SCOPE)

set(depends_index)
# Full path to an index file, which contains all defined message types for that proto file
foreach(proto_file ${gz_msgs_factory_INPUT_PROTOS})
# Get a unique path (gz.msgs.foo -> gz_msgs_foo) for naming the index
_gz_msgs_proto_to_unique(${proto_file} ${gz_msgs_factory_PROTO_PACKAGE} UNIQUE_NAME)
set(input_index "${gz_msgs_factory_OUTPUT_CPP_DIR}/${UNIQUE_NAME}.pb_index")
list(APPEND depends_index ${input_index})
endforeach()

set(GENERATE_ARGS
--output-cpp-path "${gz_msgs_factory_OUTPUT_CPP_DIR}"
--proto-package "${gz_msgs_factory_PROTO_PACKAGE}"
--proto-path "${gz_msgs_factory_PROTO_PATH}"
--protos "${gz_msgs_factory_INPUT_PROTOS}"
)

add_custom_command(
OUTPUT ${output_files}
COMMAND Python3::Interpreter
ARGS ${gz_msgs_factory_FACTORY_GEN_SCRIPT} ${GENERATE_ARGS}
DEPENDS
${depends_index}
# While the script is executed in the source directory, it does not write
# to the source tree. All outputs are stored in the build directory.
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Running factory generator"
VERBATIM
)

endfunction()
186 changes: 186 additions & 0 deletions cmake/gz_msgs_generate.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
##################################################
# The implementation of gz_msgs_generate_messages
# Options:
# One value arguments:
# MSGS_GEN_SCRIPT - Location of the messge generator script
# FACTORY_GEN_SCRIPT - Location of the factory generator script
# GZ_PROTOC_PLUGIN - Location of the gazebo generator plugin
# PROTO_PATH - Base directory of the proto files
# PROTO_PACKAGE - Protobuf package the file belongs to (e.g. "gz.msgs")
# MSGS_LIB - gz-msgs library to link to
# TARGET - Target (static library) to create
# Multi value arguments
# INPUT_PROTOS - List of input proto files
# DEPENDENCIES - List of generated messages targets that these messages depend on
# Primarily used when generating new custom messages downstream
# that depend on gz-msgs
function(gz_msgs_generate_messages_impl)
set(options "")
set(oneValueArgs TARGET PROTO_PACKAGE MSGS_GEN_SCRIPT GZ_PROTOC_PLUGIN FACTORY_GEN_SCRIPT MSGS_LIB PROTO_PATH)
set(multiValueArgs INPUT_PROTOS DEPENDENCIES)

cmake_parse_arguments(generate_messages "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
_gz_msgs_proto_pkg_to_string(${generate_messages_PROTO_PACKAGE} gen_dir)
_gz_msgs_proto_pkg_to_path(${generate_messages_PROTO_PACKAGE} proto_package_dir)

# Extract dependency information from targets
set(depends_proto_paths)
set(depends_includes)

set(target_name ${PROJECT_NAME}-${generate_messages_TARGET})

set(output_directory ${PROJECT_BINARY_DIR}/${target_name}_genmsg)
file(MAKE_DIRECTORY ${output_directory})

foreach(dep ${generate_messages_DEPENDENCIES})
get_target_property(msgs_desc_file ${dep} GZ_MSGS_DESC_FILE)
list(APPEND depends_msgs_desc ${msgs_desc_file})
endforeach()

foreach(proto_file ${generate_messages_INPUT_PROTOS})
gz_msgs_protoc(
MSGS_GEN_SCRIPT
${generate_messages_MSGS_GEN_SCRIPT}
PROTO_PACKAGE
${generate_messages_PROTO_PACKAGE}
INPUT_PROTO
${proto_file}
PROTOC_EXEC
protobuf::protoc
GZ_PROTOC_PLUGIN
${generate_messages_GZ_PROTOC_PLUGIN}
PROTO_PATH
${generate_messages_PROTO_PATH}
DEPENDENCY_PROTO_DESCS
${depends_msgs_desc}

# Cpp Specific arguments
GENERATE_CPP
OUTPUT_INCLUDES
gen_includes
OUTPUT_CPP_HH_VAR
gen_headers
OUTPUT_DETAIL_CPP_HH_VAR
gen_detail_headers
OUTPUT_CPP_CC_VAR
gen_sources
OUTPUT_CPP_DIR
${output_directory}

# Python Specific arguments
GENERATE_PYTHON
OUTPUT_PYTHON_VAR
gen_sources_py
OUTPUT_PYTHON_DIR
${output_directory}/python/
)
endforeach()

gz_msgs_factory(
FACTORY_GEN_SCRIPT
${generate_messages_FACTORY_GEN_SCRIPT}
PROTO_PACKAGE
${generate_messages_PROTO_PACKAGE}
INPUT_PROTOS
${generate_messages_INPUT_PROTOS}
OUTPUT_CPP_DIR
${output_directory}
OUTPUT_CPP_HH_VAR
gen_factory_headers
OUTPUT_CPP_CC_VAR
gen_factory_sources
PROTO_PATH
${generate_messages_PROTO_PATH}
)

set_source_files_properties(
${gen_headers}
${gen_detail_headers}
${gen_sources}
${gen_factory_headers}
${gen_factory_sources}
PROPERTIES GENERATED TRUE)

if(WIN32)
set_source_files_properties(${gen_sources}
COMPILE_FLAGS "/wd4100 /wd4512 /wd4127 /wd4068 /wd4244 /wd4267 /wd4251 /wd4146")
endif()

if(NOT MSVC)
# -Wno-switch-default flags is required for suppressing a warning in some of
# the generated protobuf files.
set_source_files_properties(${gen_sources} COMPILE_FLAGS "-Wno-switch-default -Wno-float-equal")
endif()

set(ARGS)
list(APPEND ARGS -I${generate_messages_PROTO_PATH})
list(APPEND ARGS --descriptor_set_out="${target_name}.gz_desc")

foreach(dep ${generate_messages_DEPENDENCIES})
list(APPEND ARGS --descriptor_set_in="${msgs_desc_file}")
endforeach()

list(APPEND ARGS ${generate_messages_INPUT_PROTOS})

add_custom_command(
OUTPUT "${target_name}.gz_desc"
COMMAND protobuf::protoc
ARGS ${ARGS}
DEPENDS ${generate_messages_INPUT_PROTOS}
WORKING_DIRECTORY ${output_directory}
COMMENT "Generating descriptor set"
)

add_library(${target_name} SHARED ${gen_sources} ${gen_factory_sources} ${target_name}.gz_desc)

foreach(dep ${generate_messages_DEPENDENCIES})
add_dependencies(${target_name} ${dep})
endforeach()

target_link_libraries(${target_name} PUBLIC protobuf::libprotobuf ${generate_messages_MSGS_LIB} ${generate_messages_DEPENDENCIES})
target_include_directories(${target_name} PUBLIC
"$<INSTALL_INTERFACE:${GZ_INCLUDE_INSTALL_DIR_FULL}/>"
"$<BUILD_INTERFACE:${output_directory}>")

set_target_properties(
${target_name}
PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR}
VERSION ${PROJECT_VERSION_FULL}
GZ_MSGS_DESC_FILE "\$\{_IMPORT_PREFIX\}/share/gz/protos/${generate_messages_TARGET}.gz_desc"
)
set_property(TARGET ${target_name} PROPERTY EXPORT_PROPERTIES "GZ_MSGS_DESC_FILE")

install(
TARGETS ${target_name}
EXPORT ${target_name}
LIBRARY DESTINATION ${GZ_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${GZ_LIB_INSTALL_DIR}
RUNTIME DESTINATION ${GZ_BIN_INSTALL_DIR}
COMPONENT libraries)

install(FILES ${gen_headers} ${gen_factory_headers} DESTINATION ${GZ_INCLUDE_INSTALL_DIR_FULL}/${proto_package_dir})
install(FILES ${gen_detail_headers} DESTINATION ${GZ_INCLUDE_INSTALL_DIR_FULL}/${proto_package_dir}/details)
install(FILES ${output_directory}/${target_name}.gz_desc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/gz/protos/)

if (NOT GZ_PYTHON_INSTALL_PATH)
find_package(Python3 REQUIRED COMPONENTS Interpreter)
if(USE_SYSTEM_PATHS_FOR_PYTHON_INSTALLATION)
if(USE_DIST_PACKAGES_FOR_PYTHON)
string(REPLACE "site-packages" "dist-packages" GZ_PYTHON_INSTALL_PATH ${Python3_SITELIB})
else()
# Python3_SITELIB might use dist-packages in some platforms
string(REPLACE "dist-packages" "site-packages" GZ_PYTHON_INSTALL_PATH ${Python3_SITELIB})
endif()
else()
# If not a system installation, respect local paths
set(GZ_PYTHON_INSTALL_PATH ${GZ_LIB_INSTALL_DIR}/python)
endif()
endif()
install(FILES ${gen_sources_py} DESTINATION ${GZ_PYTHON_INSTALL_PATH}/gz/msgs${GZ_MSGS_VER})

set(component_name ${generate_messages_TARGET})
set(component_pkg_name ${target_name})
_gz_create_cmake_package(COMPONENT ${component_name})
_gz_create_pkgconfig(COMPONENT ${component_name})
endfunction()
Loading