Skip to content

Commit

Permalink
Fix cross-compilation support for gz-msg10 (#392)
Browse files Browse the repository at this point in the history
Signed-off-by: Silvio Traversaro <[email protected]>
Co-authored-by: Michael Carroll <[email protected]>
  • Loading branch information
traversaro and mjcarroll authored Oct 11, 2023
1 parent 0f69062 commit 0622409
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 29 deletions.
55 changes: 35 additions & 20 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,49 @@ gz_configure_project(VERSION_SUFFIX
#============================================================================

# Cross-compilation related options
# In a cross-compilation scenario, it is possible that the gz_msgs_gen
# In a cross-compilation scenario, it is possible that the
# ${PROJECT_NAME}_protoc_plugin
# generator compiled for the target machine cannot be used to generate
# the C++ code corresponding to the .proto definition. For this scenario,
# the following two options can be used as follows.
# the C++ code corresponding to the .proto definition.
# Similarly, it is possible that Python3::Interpreter and protobuf::protoc
# found via find_package are not executable that can be run during the build.
# To avoid, that the following options can be used as follows.
# First of all, gz-msgs is compiled targeting the host machine, and in the
# build targeting the host, the INSTALL_GZ_MSGS_GEN_EXECUTABLE option is
# enabled:
# > cmake -DINSTALL_GZ_MSGS_GEN_EXECUTABLE:BOOL=ON ..
# ensuring that the gz_msgs_gen is installed in
# <host_install_prefix>/bin/gz_msgs_gen . Then, the same version of gz-msgs
# build targeting the host, ensuring that the ${PROJECT_NAME}_protoc_plugin
# is installed in <host_install_prefix>/bin/${PROJECT_NAME}_protoc_plugin .
# Then, the same version of gz-msgs
# can be cross-compiled, and in the cross-compilation build the location of the
# host gz_msgs_gen is specified via the GZ_MSGS_GEN_EXECUTABLE
# CMake cache variable:
# > cmake -GZ_MSGS_GEN_EXECUTABLE=<host_install_prefix>/bin/gz_msgs_gen ..
# host gz_msgs_gen is specified via the GZ_MSGS_GEN_EXECUTABLE CMake option.
# Similarly to gz-msgs, also a copy of protoc and of the Python interpreter need
# to be installed in the host at <host_install_prefix>/bin, and they can be passed
# to the build appropriate CMake options:
# > cmake -Dgz-msgs<MajVer>_PROTO_GENERATOR_PLUGIN=gz-msgs<MajVer>_protoc_plugin
# > -Dgz-msgs<MajVer>_PROTOC_EXECUTABLE=<host_install_prefix>/bin/protoc
# > -Dgz-msgs<MajVer>_PYTHON_INTERPRETER=<host_install_prefix>/bin/python
# > ..
# In case the gz-msgs CMake functions are used also in downstream projects,
# the same variables can be passed when configuring the downsream projects.

option(
INSTALL_GZ_MSGS_GEN_EXECUTABLE
"Install the gz_msgs_gen executable."
OFF)
set(
${PROJECT_NAME}_PROTO_GENERATOR_PLUGIN
"${PROJECT_NAME}_protoc_plugin"
CACHE STRING
"gz_msgs_gen executable used in the gz-msgs CMake functions.")
mark_as_advanced(${PROJECT_NAME}_PROTO_GENERATOR_PLUGIN)

mark_as_advanced(INSTALL_GZ_MSGS_GEN_EXECUTABLE)
set(
${PROJECT_NAME}_PROTOC_EXECUTABLE
protobuf::protoc
CACHE STRING
"protoc target or executable used in the gz-msgs CMake functions.")
mark_as_advanced(${PROJECT_NAME}_PROTOC_EXECUTABLE)

set(
GZ_MSGS_GEN_EXECUTABLE
"$<TARGET_FILE:gz_msgs_gen>"
${PROJECT_NAME}_PYTHON_INTERPRETER
Python3::Interpreter
CACHE STRING
"gz_msgs_gen executable used in the gz_msgs_protoc CMake function.")
mark_as_advanced(GZ_MSGS_GEN_EXECUTABLE)
"python target or executable used in the gz-msgs CMake functions.")
mark_as_advanced(${PROJECT_NAME}_PYTHON_INTERPRETER)

# Python interfaces vars
option(USE_SYSTEM_PATHS_FOR_PYTHON_INSTALLATION
Expand Down
10 changes: 8 additions & 2 deletions cmake/gz_msgs_factory.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# 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
# PYTHON_INTERPRETER - Target or path to the Python interpreter to use to execute the generator script
# 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
Expand All @@ -18,13 +18,19 @@ function(gz_msgs_factory)
set(oneValueArgs
FACTORY_GEN_SCRIPT
PROTO_PACKAGE
PYTHON_INTERPRETER
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})

# Default values for optional parameters
if (NOT DEFINED gz_msgs_factory_PYTHON_INTERPRETER)
set(gz_msgs_factory_PYTHON_INTERPRETER Python3::Interpreter)
endif()

_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")
Expand Down Expand Up @@ -57,7 +63,7 @@ function(gz_msgs_factory)

add_custom_command(
OUTPUT ${output_files}
COMMAND Python3::Interpreter
COMMAND ${gz_msgs_factory_PYTHON_INTERPRETER}
ARGS ${gz_msgs_factory_FACTORY_GEN_SCRIPT} ${GENERATE_ARGS}
DEPENDS
${depends_index}
Expand Down
41 changes: 38 additions & 3 deletions cmake/gz_msgs_generate.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# The implementation of gz_msgs_generate_messages
# Options:
# One value arguments:
# PYTHON_INTERPRETER - Target or path to the python interpreter used
# PROTO_PACKAGE - Protobuf package the file belongs to (e.g. "gz.msgs")
# MSGS_GEN_SCRIPT - Location of the messge generator script
# GZ_PROTOC_PLUGIN - Location of the gazebo generator plugin
Expand All @@ -20,6 +21,8 @@ function(gz_msgs_generate_messages_impl)
set(options "")
set(oneValueArgs
# Inputs
PYTHON_INTERPRETER
PROTOC_EXEC
PROTO_PACKAGE MSGS_GEN_SCRIPT GZ_PROTOC_PLUGIN FACTORY_GEN_SCRIPT PROTO_PATH
DEPENDENCY_DESCRIPTIONS
DLLEXPORT_DECL
Expand All @@ -33,6 +36,15 @@ function(gz_msgs_generate_messages_impl)
set(multiValueArgs INPUT_PROTOS)

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

# Default values for optional parameters
if (NOT DEFINED generate_messages_PYTHON_INTERPRETER)
set(generate_messages_PYTHON_INTERPRETER Python3::Interpreter)
endif()
if (NOT DEFINED generate_messages_PROTOC_EXEC)
set(generate_messages_PROTOC_EXEC protobuf::protoc)
endif()

_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)
set(output_directory ${generate_messages_OUTPUT_DIRECTORY})
Expand All @@ -42,14 +54,16 @@ function(gz_msgs_generate_messages_impl)

foreach(proto_file ${generate_messages_INPUT_PROTOS})
gz_msgs_protoc(
PYTHON_INTERPRETER
${generate_messages_PYTHON_INTERPRETER}
MSGS_GEN_SCRIPT
${generate_messages_MSGS_GEN_SCRIPT}
PROTO_PACKAGE
${generate_messages_PROTO_PACKAGE}
INPUT_PROTO
${proto_file}
PROTOC_EXEC
protobuf::protoc
${generate_messages_PROTOC_EXEC}
GZ_PROTOC_PLUGIN
${generate_messages_GZ_PROTOC_PLUGIN}
PROTO_PATH
Expand Down Expand Up @@ -81,6 +95,8 @@ function(gz_msgs_generate_messages_impl)
endforeach()

gz_msgs_factory(
PYTHON_INTERPRETER
${generate_messages_PYTHON_INTERPRETER}
FACTORY_GEN_SCRIPT
${generate_messages_FACTORY_GEN_SCRIPT}
PROTO_PACKAGE
Expand Down Expand Up @@ -130,6 +146,7 @@ endfunction()
##################################################
# Options:
# One value arguments:
# PROTOC_EXEC - protoc target or executable to use
# PROTO_PATH - Base directory of the proto files
# DEPENDENCY_DESCRIPTIONS - Variable containing all depedency description files
# OUTPUT_DIRECTORY - Directory of output gz_desc file
Expand All @@ -140,6 +157,7 @@ function(gz_msgs_generate_desc_impl)
set(options "")
set(oneValueArgs
# Inputs
PROTOC_EXEC
PROTO_PATH
DEPENDENCY_DESCRIPTIONS
OUTPUT_DIRECTORY
Expand All @@ -148,6 +166,10 @@ function(gz_msgs_generate_desc_impl)

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

if (NOT DEFINED generate_messages_PROTOC_EXEC)
set(generate_messages_PROTOC_EXEC protobuf::protoc)
endif()

set(ARGS)
list(APPEND ARGS -I${generate_messages_PROTO_PATH})
list(APPEND ARGS --descriptor_set_out=${generate_messages_OUTPUT_FILENAME})
Expand All @@ -161,7 +183,7 @@ function(gz_msgs_generate_desc_impl)

add_custom_command(
OUTPUT ${generate_messages_OUTPUT_FILENAME}
COMMAND protobuf::protoc
COMMAND ${generate_messages_PROTOC_EXEC}
ARGS ${ARGS}
DEPENDS ${generate_messages_INPUT_PROTOS}
COMMENT "Generating descriptor set"
Expand All @@ -175,6 +197,8 @@ endfunction()
# TARGET - Target (static library) to create
# PROTO_PACKAGE - Protobuf package the file belongs to (e.g. "gz.msgs")
# MSGS_GEN_SCRIPT - Location of the messge generator script
# PYTHON_INTERPRETER - Target or path to the python interpreter used
# PROTOC_EXEC - Protoc target or executable to use
# GZ_PROTOC_PLUGIN - Location of the gazebo generator plugin
# FACTORY_GEN_SCRIPT - Location of the factory generator script
# MSGS_LIB - gz-msgs library to link to
Expand All @@ -186,7 +210,7 @@ endfunction()
# that depend on gz-msgs
function(gz_msgs_generate_messages_lib)
set(options "")
set(oneValueArgs TARGET PROTO_PACKAGE MSGS_GEN_SCRIPT GZ_PROTOC_PLUGIN FACTORY_GEN_SCRIPT MSGS_LIB PROTO_PATH)
set(oneValueArgs TARGET PROTO_PACKAGE MSGS_GEN_SCRIPT PYTHON_INTERPRETER PROTOC_EXEC GZ_PROTOC_PLUGIN FACTORY_GEN_SCRIPT MSGS_LIB PROTO_PATH)
set(multiValueArgs INPUT_PROTOS DEPENDENCIES)

cmake_parse_arguments(generate_messages "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
Expand All @@ -205,9 +229,19 @@ function(gz_msgs_generate_messages_lib)
list(APPEND depends_msgs_desc ${msgs_desc_file})
endforeach()

# Default values for optional parameters
if (NOT DEFINED generate_messages_PYTHON_INTERPRETER)
set(generate_messages_PYTHON_INTERPRETER Python3::Interpreter)
endif()
if (NOT DEFINED generate_messages_PROTOC_EXEC)
set(generate_messages_PROTOC_EXEC protobuf::protoc)
endif()

gz_msgs_generate_messages_impl(
PROTO_PACKAGE ${generate_messages_PROTO_PACKAGE}
MSGS_GEN_SCRIPT ${generate_messages_MSGS_GEN_SCRIPT}
PYTHON_INTERPRETER ${generate_messages_PYTHON_INTERPRETER}
PROTOC_EXEC ${generate_messages_PROTOC_EXEC}
GZ_PROTOC_PLUGIN ${generate_messages_GZ_PROTOC_PLUGIN}
FACTORY_GEN_SCRIPT ${generate_messages_FACTORY_GEN_SCRIPT}
PROTO_PATH ${generate_messages_PROTO_PATH}
Expand All @@ -221,6 +255,7 @@ function(gz_msgs_generate_messages_lib)
)

gz_msgs_generate_desc_impl(
PROTOC_EXEC ${generate_messages_PROTOC_EXEC}
INPUT_PROTOS ${generate_messages_INPUT_PROTOS}
PROTO_PATH ${generate_messages_PROTO_PATH}
DEPENDENCY_DESCRIPTIONS ${depends_msgs_desc}
Expand Down
19 changes: 17 additions & 2 deletions cmake/gz_msgs_protoc.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# GENERATE_CPP - generates c++ code for the message if specified
# GENERATE_PYTHON - generates python code for the message if specified
# One value arguments:
# PYTHON_INTERPRETER - Target or path to the Python interpreter to use to run generation scripts
# MSGS_GEN_SCRIPT - Path to the message generation python script
# PROTO_PACKAGE - Protobuf package the file belongs to (e.g. "gz.msgs")
# PROTOC_EXEC - Path to protoc
Expand All @@ -22,6 +23,7 @@
function(gz_msgs_protoc)
set(options GENERATE_CPP GENERATE_PYTHON)
set(oneValueArgs
PYTHON_INTERPRETER
MSGS_GEN_SCRIPT
PROTO_PACKAGE
PROTOC_EXEC
Expand All @@ -38,6 +40,13 @@ function(gz_msgs_protoc)

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

if (NOT DEFINED gz_msgs_protoc_PYTHON_INTERPRETER)
set(gz_msgs_protoc_PYTHON_INTERPRETER Python3::Interpreter)
endif()
if (NOT DEFINED gz_msgs_protoc_PROTOC_EXEC)
set(gz_msgs_protoc_PROTOC_EXEC protobuf::protoc)
endif()

get_filename_component(ABS_FIL ${gz_msgs_protoc_INPUT_PROTO} ABSOLUTE)
get_filename_component(FIL_WE ${gz_msgs_protoc_INPUT_PROTO} NAME_WE)

Expand Down Expand Up @@ -85,8 +94,14 @@ function(gz_msgs_protoc)
set(${gz_msgs_protoc_OUTPUT_PYTHON_VAR} ${${gz_msgs_protoc_OUTPUT_PYTHON_VAR}} PARENT_SCOPE)
endif()

if(TARGET ${gz_msgs_protoc_PROTOC_EXEC})
set(gz_msgs_protoc_PROTOC_EXEC_FILE_ABS_PATH "$<TARGET_FILE:${gz_msgs_protoc_PROTOC_EXEC}>")
else()
set(gz_msgs_protoc_PROTOC_EXEC_FILE_ABS_PATH ${gz_msgs_protoc_PROTOC_EXEC})
endif()

set(GENERATE_ARGS
--protoc-exec "$<TARGET_FILE:${gz_msgs_protoc_PROTOC_EXEC}>"
--protoc-exec "${gz_msgs_protoc_PROTOC_EXEC_FILE_ABS_PATH}"
--gz-generator-bin "${gz_msgs_protoc_GZ_PROTOC_PLUGIN}"
--proto-path "${gz_msgs_protoc_PROTO_PATH}"
--input-path "${ABS_FIL}"
Expand Down Expand Up @@ -118,7 +133,7 @@ function(gz_msgs_protoc)

add_custom_command(
OUTPUT ${output_files}
COMMAND Python3::Interpreter
COMMAND ${gz_msgs_protoc_PYTHON_INTERPRETER}
ARGS ${gz_msgs_protoc_MSGS_GEN_SCRIPT} ${GENERATE_ARGS}
DEPENDS
${ABS_FIL}
Expand Down
13 changes: 12 additions & 1 deletion core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,23 @@ include(${PROJECT_SOURCE_DIR}/cmake/gz_msgs_generate.cmake)
include(${PROJECT_SOURCE_DIR}/cmake/gz_msgs_protoc.cmake)
include(${PROJECT_SOURCE_DIR}/cmake/gz_msgs_string_utils.cmake)

if(TARGET ${${PROJECT_NAME}_PROTO_GENERATOR_PLUGIN})
set(${PROJECT_NAME}_PROTO_GENERATOR_PLUGIN_FILE $<TARGET_FILE:${${PROJECT_NAME}_PROTO_GENERATOR_PLUGIN}>)
else()
set(${PROJECT_NAME}_PROTO_GENERATOR_PLUGIN_FILE ${${PROJECT_NAME}_PROTO_GENERATOR_PLUGIN})
endif()

gz_msgs_generate_messages_impl(
MSGS_GEN_SCRIPT
${PROJECT_SOURCE_DIR}/tools/gz_msgs_generate.py
FACTORY_GEN_SCRIPT
${PROJECT_SOURCE_DIR}/tools/gz_msgs_generate_factory.py
PYTHON_INTERPRETER
${${PROJECT_NAME}_PYTHON_INTERPRETER}
PROTOC_EXEC
${${PROJECT_NAME}_PROTOC_EXECUTABLE}
GZ_PROTOC_PLUGIN
$<TARGET_FILE:${PROJECT_NAME}_protoc_plugin>
${${PROJECT_NAME}_PROTO_GENERATOR_PLUGIN_FILE}
INPUT_PROTOS
${proto_files}
DLLEXPORT_DECL
Expand All @@ -54,6 +64,7 @@ gz_msgs_generate_messages_impl(
)

gz_msgs_generate_desc_impl(
PROTOC_EXEC ${${PROJECT_NAME}_PROTOC_EXECUTABLE}
INPUT_PROTOS ${proto_files}
PROTO_PATH ${PROJECT_SOURCE_DIR}/proto
DEPENDENCY_DESCRIPTIONS ${depends_msgs_desc}
Expand Down
15 changes: 14 additions & 1 deletion gz-msgs-extras.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,16 @@ set(PROTO_SCRIPT_NAME "@PROJECT_NAME@_generate.py")
set(FACTORY_SCRIPT_NAME "@PROJECT_NAME@_generate_factory.py")

set(@PROJECT_NAME@_PROTO_PATH ${@PROJECT_NAME@_INSTALL_PATH}/share/protos)
set(@PROJECT_NAME@_PROTO_GENERATOR_PLUGIN ${@PROJECT_NAME@_INSTALL_PATH}/bin/${PROTOC_NAME})
# Provide support to override generator executable used during cross-compilation
if(NOT DEFINED @PROJECT_NAME@_PROTO_GENERATOR_PLUGIN)
set(@PROJECT_NAME@_PROTO_GENERATOR_PLUGIN ${@PROJECT_NAME@_INSTALL_PATH}/bin/${PROTOC_NAME})
endif()
if(NOT DEFINED @PROJECT_NAME@_PROTOC_EXECUTABLE)
set(@PROJECT_NAME@_PROTOC_EXECUTABLE protobuf::protoc)
endif()
if(NOT DEFINED @PROJECT_NAME@_PYTHON_INTERPRETER)
set(@PROJECT_NAME@_PYTHON_INTERPRETER Python3::Interpreter)
endif()
set(@PROJECT_NAME@_PROTO_GENERATOR_SCRIPT ${@PROJECT_NAME@_INSTALL_PATH}/bin/${PROTO_SCRIPT_NAME})
set(@PROJECT_NAME@_FACTORY_GENERATOR_SCRIPT ${@PROJECT_NAME@_INSTALL_PATH}/bin/${FACTORY_SCRIPT_NAME})

Expand Down Expand Up @@ -64,6 +73,10 @@ function(gz_msgs_generate_messages)

cmake_parse_arguments(generate_messages "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
gz_msgs_generate_messages_lib(
PYTHON_INTERPRETER
${@PROJECT_NAME@_PYTHON_INTERPRETER}
PROTOC_EXEC
${@PROJECT_NAME@_PROTOC_EXECUTABLE}
MSGS_GEN_SCRIPT
${@PROJECT_NAME@_PROTO_GENERATOR_SCRIPT}
FACTORY_GEN_SCRIPT
Expand Down

0 comments on commit 0622409

Please sign in to comment.