Skip to content
Open
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
4 changes: 2 additions & 2 deletions .github/workflows/ubuntu-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ jobs:
python3-vcstool \
python3-colcon-common-extensions

- name: Install Gazebo Garden
- name: Install Gazebo Harmonic
run: |
sudo wget https://packages.osrfoundation.org/gazebo.gpg -O /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null
sudo apt update && sudo apt install --no-install-recommends -y \
gz-garden
gz-harmonic

- name: Build
run: |
Expand Down
245 changes: 56 additions & 189 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ project(gz-python)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

Expand All @@ -15,50 +16,65 @@ option(BUILD_TESTS "Build tests." OFF)

#============================================================================
# Find Python
#
# macOS: $ brew install python
# macOS: $ brew install pybind11
#
find_package(Python 3.10 EXACT COMPONENTS Interpreter Development)

#============================================================================
# Find Gazebo dependencies

# Default versions to Gazebo Garden
set(GZ_MSGS_VER 9)
set(GZ_TRANSPORT_VER 12)

if("$ENV{GZ_VERSION}" STREQUAL "garden")
# Garden
message(STATUS "Compiling against Gazebo Garden")
else()
# Default to Garden
message(STATUS "Compiling against Gazebo Garden")
endif()

find_package(gz-msgs${GZ_MSGS_VER} REQUIRED)
find_package(gz-transport${GZ_TRANSPORT_VER} REQUIRED)
find_package(Python COMPONENTS Interpreter Development)

#============================================================================
# Build dependencies

set(_protobuf_repository "https://github.com/protocolbuffers/protobuf.git")
set(_protobuf_version 21.5)
set(_protobuf_tag v21.5)
set(_absl_repository "https://github.com/abseil/abseil-cpp.git")
set(_absl_version 20230802)
set(_absl_tag 20230802.1)
find_package(absl ${_absl_version} QUIET)

set(_pybind11_protobuf_repository "https://github.com/pybind/pybind11_protobuf.git")
set(_protobuf_repository "https://github.com/protocolbuffers/protobuf.git")
set(_protobuf_version 3.25.0)
set(_protobuf_tag v25.0)
# do not use system protobuf as it will not include proto_api.h
# see also: https://github.com/pybind/pybind11_protobuf/issues/127
# find_package(Protobuf ${_protobuf_version} QUIET)

set(_pybind11_repository "https://github.com/pybind/pybind11.git")
set(_pybind11_version 2.11.1)
set(_pybind11_tag v2.11.1)
find_package(pybind11 ${_pybind11_version} QUIET)

set(_pybind11_protobuf_repository "https://github.com/srmainwaring/pybind11_protobuf.git")
set(_pybind11_protobuf_version 0.0.0)
set(_pybind11_protobuf_tag main)
set(_pybind11_protobuf_tag prs/pr-proto-api-fix)
find_package(pybind11_protobuf ${_pybind11_version} QUIET)

add_subdirectory(cmake/dependencies dependencies)
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_CURRENT_BINARY_DIR}/dependencies/install)

message("pybind11_protobuf_FOUND: ${pybind11_protobuf_FOUND}")
message("pybind11_protobuf_SOURCE_DIR: ${pybind11_protobuf_SOURCE_DIR}")
message("pybind11_protobuf_INCLUDE_DIRS: ${pybind11_protobuf_INCLUDE_DIRS}")
message("pybind11_protobuf_SOURCE_DIR: ${pybind11_protobuf_SOURCE_DIR}")
message("protobuf_SOURCE_DIR: ${protobuf_SOURCE_DIR}")

# TODO fix upstream...
set(pybind11_protobuf_INCLUDE_DIRS ${pybind11_protobuf_SOURCE_DIR})
set(pybind11_protobuf_INCLUDE_DIRS
${pybind11_protobuf_SOURCE_DIR}
${protobuf_SOURCE_DIR}
)

#============================================================================
# Find Gazebo dependencies

if("$ENV{GZ_VERSION}" STREQUAL "garden")
# Garden
set(GZ_MSGS_VER 9)
set(GZ_TRANSPORT_VER 12)
message(STATUS "Compiling against Gazebo Garden")
elseif("$ENV{GZ_VERSION}" STREQUAL "harmonic" OR NOT DEFINED "ENV{GZ_VERSION}")
# Harmonic (default)
message(STATUS "Compiling against Gazebo Harmonic")
set(GZ_MSGS_VER 10)
set(GZ_TRANSPORT_VER 13)
endif()

find_package(gz-msgs${GZ_MSGS_VER} REQUIRED)
find_package(gz-transport${GZ_TRANSPORT_VER} REQUIRED)

#============================================================================
# gz_msgs_extras_lib C++ library
Expand All @@ -79,33 +95,33 @@ target_include_directories(gz_msgs_extras_lib
#============================================================================
# msgs extras Python extension module

pybind11_add_module(extras MODULE
pybind11_add_module(msgs_extras MODULE
src/pybind11/gz/msgs/_gz_msgs_extras_pybind11.cc
)

target_link_libraries(extras
target_link_libraries(msgs_extras
PRIVATE
gz_msgs_extras_lib
gz-msgs${GZ_MSGS_VER}::gz-msgs${GZ_MSGS_VER}
protobuf::libprotobuf
pybind11_native_proto_caster
)

target_include_directories(extras
target_include_directories(msgs_extras
PRIVATE
${PROJECT_SOURCE_DIR}/include
${pybind11_protobuf_INCLUDE_DIRS}
)

add_dependencies(extras
add_dependencies(msgs_extras
gz_msgs_extras_lib
)

set_target_properties(extras
set_target_properties(msgs_extras
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/gz/msgs"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/gz/msgs"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/gz/msgs"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/gz/python"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/gz/python"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/gz/python"
)

#============================================================================
Expand All @@ -131,9 +147,9 @@ target_include_directories(transport

set_target_properties(transport
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/gz"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/gz"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/gz"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/gz/python"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/gz/python"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/gz/python"
)

#============================================================================
Expand Down Expand Up @@ -214,152 +230,3 @@ target_link_libraries(gz_topic_echo
gz-transport${GZ_TRANSPORT_VER}::gz-transport${GZ_TRANSPORT_VER}
)

#============================================================================
# generate protobuf Python bindings

# Get the proto files from the installed location of gz-msgs
set(PROTO_PATH ${gz-msgs${GZ_MSGS_VER}_INCLUDE_DIRS})
file(GLOB PROTO_FILES ${PROTO_PATH}/gz/msgs/*.proto)

#============================================================================
# Modified from gz-msgs/src/CMakeLists.txt for Python
#============================================================================
# A function that calls protoc on a protobuf file
# Options:
# GENERATE_RUBY - generates ruby code for the message if specified
# GENERATE_CPP - generates c++ code for the message if specified
# GENERATE_PY - generates Python code for the message if specified
# One value arguments:
# PROTO_PACKAGE - Protobuf package the file belongs to (e.g. ".gz.msgs")
# PROTOC_EXEC - Path to protoc
# INPUT_PROTO - Path to the input .proto file
# OUTPUT_CPP_DIR - Path where C++ files are saved
# OUTPUT_RUBY_DIR - Path where Ruby files are saved
# OUTPUT_PY_DIR - Path where Python files are saved
# OUTPUT_CPP_HH_VAR - A CMake variable name containing a list that the C++ header path should be appended to
# OUTPUT_CPP_CC_VAR - A CMake variable name containing a list that the C++ source path should be appended to
# OUTPUT_RUBY_VAR - A CMake variable name containing a list that the ruby file should be appended to
# OUTPUT_PY_VAR - A CMake variable name containing a list that the Python file should be appended to
# Multi value arguments
# PROTO_PATH - Passed to protoc --proto_path
function(gz_msgs_protoc)
set(options GENERATE_RUBY GENERATE_CPP GENERATE_PY)
set(oneValueArgs PROTO_PACKAGE PROTOC_EXEC INPUT_PROTO OUTPUT_CPP_DIR OUTPUT_RUBY_DIR OUTPUT_PY_DIR OUTPUT_CPP_HH_VAR OUTPUT_CPP_CC_VAR OUTPUT_RUBY_VAR OUTPUT_PY_VAR)
set(multiValueArgs PROTO_PATH)

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

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

set(protoc_args)
set(output_files)

foreach(proto_path ${gz_msgs_protoc_PROTO_PATH})
list(APPEND protoc_args "--proto_path=${proto_path}")
endforeach()

set(proto_package_dir ".")
if(gz_msgs_protoc_PROTO_PACKAGE)
string(REPLACE "." "/" proto_package_dir ${gz_msgs_protoc_PROTO_PACKAGE})
endif()

if(gz_msgs_protoc_GENERATE_CPP)
set(output_header "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/${FIL_WE}.pb.h")
set(output_source "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/${FIL_WE}.pb.cc")
list(APPEND ${gz_msgs_protoc_OUTPUT_CPP_HH_VAR} ${output_header})
list(APPEND ${gz_msgs_protoc_OUTPUT_CPP_CC_VAR} ${output_source})
list(APPEND output_files ${output_header})
list(APPEND output_files ${output_source})
list(APPEND protoc_args "--plugin=protoc-gen-gzmsgs=${GZ_MSGS_GEN_EXECUTABLE}")
list(APPEND protoc_args "--cpp_out=dllexport_decl=GZ__MSGS_VISIBLE:${gz_msgs_protoc_OUTPUT_CPP_DIR}")
list(APPEND protoc_args "--gzmsgs_out" "${gz_msgs_protoc_OUTPUT_CPP_DIR}")
set(${gz_msgs_protoc_OUTPUT_CPP_HH_VAR} ${${gz_msgs_protoc_OUTPUT_CPP_HH_VAR}} PARENT_SCOPE)
set(${gz_msgs_protoc_OUTPUT_CPP_CC_VAR} ${${gz_msgs_protoc_OUTPUT_CPP_CC_VAR}} PARENT_SCOPE)
endif()

if(gz_msgs_protoc_GENERATE_RUBY)
file(MAKE_DIRECTORY ${gz_msgs_protoc_OUTPUT_RUBY_DIR})
set(output_ruby "${gz_msgs_protoc_OUTPUT_RUBY_DIR}${proto_package_dir}/${FIL_WE}_pb.rb")
list(APPEND ${gz_msgs_protoc_OUTPUT_RUBY_VAR} ${output_ruby})
list(APPEND output_files ${output_ruby})
list(APPEND protoc_args "--ruby_out=${gz_msgs_protoc_OUTPUT_RUBY_DIR}")
set(${gz_msgs_protoc_OUTPUT_RUBY_VAR} ${${gz_msgs_protoc_OUTPUT_RUBY_VAR}} PARENT_SCOPE)
endif()

if(gz_msgs_protoc_GENERATE_PY)
file(MAKE_DIRECTORY ${gz_msgs_protoc_OUTPUT_PY_DIR})
set(output_py "${gz_msgs_protoc_OUTPUT_PY_DIR}${proto_package_dir}/${FIL_WE}_pb2.py")
list(APPEND ${gz_msgs_protoc_OUTPUT_PY_VAR} ${output_py})
list(APPEND output_files ${output_py})
list(APPEND protoc_args "--python_out=${gz_msgs_protoc_OUTPUT_PY_DIR}")
set(${gz_msgs_protoc_OUTPUT_PY_VAR} ${${gz_msgs_protoc_OUTPUT_PY_VAR}} PARENT_SCOPE)
endif()

#get_cmake_property(_variableNames VARIABLES)
#foreach (_variableName ${_variableNames})
# message(STATUS "${_variableName}=${${_variableName}}")
#endforeach()

add_custom_command(
OUTPUT
${output_files}
COMMAND
${gz_msgs_protoc_PROTOC_EXEC}
ARGS
${protoc_args}
${ABS_FIL}
DEPENDS
${ABS_FIL}
# gz_msgs_gen
COMMENT "Running protoc on ${gz_msgs_protoc_INPUT_PROTO}"
VERBATIM)
endfunction()

#============================================================================
# run the code generation
foreach(proto_file ${PROTO_FILES})
gz_msgs_protoc(
PROTO_PACKAGE
.gz.msgs
# GENERATE_CPP
# GENERATE_RUBY
GENERATE_PY
INPUT_PROTO
${proto_file}
PROTOC_EXEC
protobuf::protoc
OUTPUT_CPP_DIR
"${PROJECT_BINARY_DIR}/include"
OUTPUT_RUBY_DIR
"${PROJECT_BINARY_DIR}/ruby"
OUTPUT_PY_DIR
"${PROJECT_BINARY_DIR}/python"
OUTPUT_CPP_HH_VAR
gen_headers
OUTPUT_CPP_CC_VAR
gen_sources
OUTPUT_RUBY_VAR
gen_ruby_scripts
OUTPUT_PY_VAR
gen_py_scripts
PROTO_PATH
"${PROTO_PATH}")

endforeach()

#============================================================================
# add custom target to force .proto compilation

set_source_files_properties(
${gen_headers}
${gen_sources}
${gen_ruby_scripts}
${gen_py_scripts}
PROPERTIES GENERATED TRUE
)

foreach(gen_py_script ${gen_py_scripts})
get_filename_component(FIL_WE ${gen_py_script} NAME_WE)
add_custom_target(${FIL_WE} ALL DEPENDS ${gen_py_script})
endforeach()
Loading