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

Fix cross-compilation support for gz-msg10 #392

Merged
merged 2 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
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