Skip to content

Commit

Permalink
Permit building python bindings separately from main library (#554)
Browse files Browse the repository at this point in the history
This allows the python/CMakeLists.txt file to be built
as a top-level cmake project against an external gz-transport
library, with documentation added to the installation tutorial.

The logic for finding pybind11 is also moved from the root
CMakeLists.txt to python/CMakeLists.txt to reduce code
duplication. When invoked through the root CMakeLists.txt,
pybind11 is treated as an optional dependency, but when
invoked from the python folder, pybind11 is treated as
required by setting the variable
CMAKE_REQUIRE_FIND_PACKAGE_pybind11 to TRUE.

Signed-off-by: Silvio Traversaro <[email protected]>
Signed-off-by: Steve Peters <[email protected]>
Co-authored-by: Silvio Traversaro <[email protected]>
(cherry picked from commit 250e95f)
  • Loading branch information
scpeters committed Dec 9, 2024
1 parent 254921a commit 0b52db6
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 59 deletions.
16 changes: 4 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,11 @@ if (SKIP_PYBIND11)
message(STATUS "SKIP_PYBIND11 set - disabling python bindings")
find_package(Python3 COMPONENTS Interpreter)
else()
find_package(Python3 COMPONENTS Interpreter Development)
find_package(Python3
COMPONENTS Interpreter
OPTIONAL_COMPONENTS Development)
if (NOT Python3_Development_FOUND)
GZ_BUILD_WARNING("Python development libraries are missing: Python interfaces are disabled.")
else()
set(PYBIND11_PYTHON_VERSION 3)
find_package(pybind11 2.4 CONFIG QUIET)

if (pybind11_FOUND)
message (STATUS "Searching for pybind11 - found version ${pybind11_VERSION}.")
else()
GZ_BUILD_WARNING("pybind11 is missing: Python interfaces are disabled.")
message (STATUS "Searching for pybind11 - not found.")
endif()
endif()
endif()

Expand Down Expand Up @@ -164,7 +156,7 @@ add_subdirectory(conf)
#============================================================================
# gz transport python bindings
#============================================================================
if (pybind11_FOUND AND NOT SKIP_PYBIND11)
if (Python3_Development_FOUND AND NOT SKIP_PYBIND11)
add_subdirectory(python)
endif()

Expand Down
41 changes: 33 additions & 8 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
if(WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Debug")
# pybind11 logic for setting up a debug build when both a debug and release
# python interpreter are present in the system seems to be pretty much broken.
# This works around the issue.
set(PYTHON_LIBRARIES "${PYTHON_DEBUG_LIBRARIES}")
# Detect if we are doing a standalone build of the bindings, using an external gz-transport
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
cmake_minimum_required(VERSION 3.22.1)
set(GZ_TRANSPORT_VER 13)
project(gz-transport${GZ_TRANSPORT_VER}-python VERSION ${GZ_TRANSPORT_VER})
find_package(gz-transport${PROJECT_VERSION_MAJOR} REQUIRED)
set(PROJECT_LIBRARY_TARGET_NAME "gz-transport${PROJECT_VERSION_MAJOR}::gz-transport${PROJECT_VERSION_MAJOR}")
# require python dependencies to be found
find_package(Python3 COMPONENTS Interpreter Development REQUIRED)
set(CMAKE_REQUIRE_FIND_PACKAGE_pybind11 TRUE)
include(GNUInstallDirs)
include(CTest)
elseif(${CMAKE_VERSION} VERSION_LESS "3.12.0")
# TODO: remove once the minimum CMake version is increased
if(WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Debug")
# pybind11 logic for setting up a debug build when both a debug and release
# python interpreter are present in the system seems to be pretty much broken.
# This works around the issue.
set(PYTHON_LIBRARIES "${PYTHON_DEBUG_LIBRARIES}")
endif()
endif()

set(PYBIND11_PYTHON_VERSION 3)
find_package(pybind11 2.4 CONFIG QUIET)

if (pybind11_FOUND)
message (STATUS "Searching for pybind11 - found version ${pybind11_VERSION}.")
else()
message(WARNING "pybind11 is missing: Python interfaces are disabled.")
return()
endif()

if(USE_SYSTEM_PATHS_FOR_PYTHON_INSTALLATION)
Expand All @@ -27,7 +52,7 @@ if(USE_SYSTEM_PATHS_FOR_PYTHON_INSTALLATION)
endif()
else()
# If not a system installation, respect local paths
set(GZ_PYTHON_INSTALL_PATH ${GZ_LIB_INSTALL_DIR}/python)
set(GZ_PYTHON_INSTALL_PATH ${CMAKE_INSTALL_LIBDIR}/python)
endif()

set(GZ_PYTHON_INSTALL_PATH "${GZ_PYTHON_INSTALL_PATH}/gz")
Expand Down Expand Up @@ -83,10 +108,10 @@ if (BUILD_TESTING AND NOT WIN32)
foreach (test ${python_tests})
if (pytest_FOUND)
add_test(NAME ${test}.py COMMAND
"${Python3_EXECUTABLE}" -m pytest "${CMAKE_SOURCE_DIR}/python/test/${test}.py" --junitxml "${CMAKE_BINARY_DIR}/test_results/${test}.xml")
"${Python3_EXECUTABLE}" -m pytest "${CMAKE_CURRENT_SOURCE_DIR}/test/${test}.py" --junitxml "${CMAKE_BINARY_DIR}/test_results/${test}.xml")
else()
add_test(NAME ${test}.py COMMAND
"${Python3_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/python/test/${test}.py")
"${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/test/${test}.py")
endif()
set(_env_vars)
list(APPEND _env_vars "CMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}/bin")
Expand Down
96 changes: 57 additions & 39 deletions tutorials/02_installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,10 @@ library and rebuilding dependencies due to the use of c++11. For
purposes of this documentation, Assuming OS X 10.9 or greater is in
use. Here are the instructions:

Install homebrew, which should also prompt you to install the XCode
command-line tools:
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
After installing the [Homebrew package manager](https://brew.sh),
which should also prompt you to install the XCode command-line tools
add OSRF packages and run the install command:

Run the following commands:
```
brew tap osrf/simulation
brew install gz-transport<#>
Expand Down Expand Up @@ -81,7 +78,9 @@ which version you need.

# Source Install

## Ubuntu Linux
## Install Prerequisites

### Ubuntu Linux

For compiling the latest version of Gazebo Transport you will need an
Ubuntu distribution equal to 20.04 (Focal) or newer.
Expand All @@ -97,10 +96,29 @@ Install prerequisites. A clean Ubuntu system will need:
sudo apt-get install git cmake pkg-config python ruby-ronn libprotoc-dev libprotobuf-dev protobuf-compiler uuid-dev libzmq3-dev libgz-msgs10-dev libgz-utils2-cli-dev
```

### macOS

After installing the [Homebrew package manager](https://brew.sh),
which should also prompt you to install the XCode command-line tools
add OSRF packages and run the command to install dependencies:

```
brew tap osrf/simulation
brew install --only-dependencies gz-transport<#>
```

Be sure to replace `<#>` with a number value, such as 10 or 11, depending on
which version you need.

## Clone, Configure, and Build

Clone the repository
```
git clone https://github.com/gazebosim/gz-transport
git clone https://github.com/gazebosim/gz-transport -b gz-transport<#>
```
Be sure to replace `<#>` with a number value, such as 10 or 11, depending on
which version you need. From version 12 use `gz-transport<#>` for lower versions
use `ign-transport<#>`

Configure and build
```
Expand All @@ -111,6 +129,13 @@ cmake ..
make
```

Optionally, install
```
sudo make install
```

### Configuration options

Configure Gazebo Transport (choose either method a or b below):

A. Release mode (recommended): This will generate optimized code, but will not have
Expand Down Expand Up @@ -159,6 +184,30 @@ modify your `LD_LIBRARY_PATH`:
echo "export LD_LIBRARY_PATH=<install_path>/local/lib:$LD_LIBRARY_PATH" >> ~/.bashrc
```

### Build python bindings separately from main library

If you want to build Python bindings separately from the main gz-transport library
(for example if you want to build Python bindings for multiple versions of Python),
you can invoke cmake on the `python` folder instead of the root folder.
This requires cmake version 3.22.1 due to the use of a `CMAKE_REQUIRE_FIND_PACKAGE_*`
variable, which is newer than the minimum required version of cmake for gz-transport13.
Specify the path to the python executable with which you wish to build bindings
in the `Python3_EXECUTABLE` cmake variable.
Specify the install path for the bindings in the `CMAKE_INSTALL_PREFIX`
variable, and be sure to set your `PYTHONPATH` accordingly after install.

```bash
cd sdformat
mkdir build_python3
cd build_python3
cmake ../python \
-DPython3_EXECUTABLE=/usr/local/bin/python3.12 \
-DCMAKE_INSTALL_PREFIX=<prefix>
```

See the homebrew [sdformat15 formula](https://github.com/osrf/homebrew-simulation/blob/027d06f5be49da1e40d01180aedae7f76dc7ff47/Formula/sdformat15.rb#L12-L56)
for an example of building bindings for multiple versions of Python.

### Uninstalling Source-based Install

If you need to uninstall Gazebo Transport or switch back to a
Expand All @@ -170,37 +219,6 @@ cd /tmp/gz-transport/build
sudo make uninstall
```

### macOS

1. Clone the repository
```
git clone https://github.com/gazebosim/gz-transport -b gz-transport<#>
```
Be sure to replace `<#>` with a number value, such as 10 or 11, depending on
which version you need. From version 12 use `gz-transport<#>` for lower versions
use `ign-transport<#>`

2. Install dependencies
```
brew install --only-dependencies gz-transport<#>
```
Be sure to replace `<#>` with a number value, such as 10 or 11, depending on
which version you need.

3. Configure and build
```
cd gz-transport
mkdir build
cd build
cmake ..
make
```

4. Optionally, install
```
sudo make install
```

## Windows

### Prerequisites
Expand Down

0 comments on commit 0b52db6

Please sign in to comment.