From 250e95f0757af410adfaab213b3077c0a501252e Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Fri, 8 Nov 2024 14:47:06 -0800 Subject: [PATCH] Permit building python bindings separately from main library (#554) 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 Signed-off-by: Steve Peters Co-authored-by: Silvio Traversaro --- CMakeLists.txt | 16 ++---- python/CMakeLists.txt | 30 ++++++++++-- tutorials/02_installation.md | 94 +++++++++++++++++++++--------------- 3 files changed, 86 insertions(+), 54 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c69aa0e..6c814bd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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() @@ -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() diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index eb348471..aafad62e 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,3 +1,27 @@ +# 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 14) + 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) +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) if(NOT Python3_SITEARCH) # Get install variable from Python3 module @@ -12,7 +36,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") @@ -68,10 +92,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") diff --git a/tutorials/02_installation.md b/tutorials/02_installation.md index 89207356..9cf90e16 100644 --- a/tutorials/02_installation.md +++ b/tutorials/02_installation.md @@ -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<#> @@ -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 24.04 (Noble) or newer. @@ -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-msgs11-dev libgz-utils3-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 ``` @@ -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 @@ -159,6 +184,28 @@ modify your `LD_LIBRARY_PATH`: echo "export LD_LIBRARY_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. +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= +``` + +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 @@ -170,37 +217,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