diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ccd722..85f13d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,20 @@ endif() add_library(${PROJECT_NAME} INTERFACE) install(TARGETS ${PROJECT_NAME} EXPORT ${TARGETS_EXPORT_NAME} DESTINATION lib) +option(GENERATE_PYTHON_STUBS "Generate Python stubs (.pyi files)" ON) +if(GENERATE_PYTHON_STUBS) + find_program(PYBIND11_STUBGEN_EXECUTABLE pybind11-stubgen) + if(NOT PYBIND11_STUBGEN_EXECUTABLE) + message( + WARNING + "pybind11-stubgen not found. Stubs will not be generated." + ) + set(GENERATE_PYTHON_STUBS OFF CACHE BOOL "Generate Python stubs" FORCE) + else() + message(STATUS "pybind11-stubgen found: ${PYBIND11_STUBGEN_EXECUTABLE}") + endif() +endif() + add_subdirectory(src) if(BUILD_TESTING) add_subdirectory(tests) diff --git a/flake.nix b/flake.nix index 91de00e..861e72b 100644 --- a/flake.nix +++ b/flake.nix @@ -27,19 +27,22 @@ inputs.hpp-core.overlays.flakoboros inputs.hpp-manipulation.overlays.flakoboros ]; - pyOverrideAttrs.hpp-python = { - src = lib.fileset.toSource { - root = ./.; - fileset = lib.fileset.unions [ - ./CMakeLists.txt - ./doc - ./include - ./package.xml - ./src - ./tests - ]; + pyOverrideAttrs.hpp-python = + { drv-prev, python-final, ... }: + { + nativeBuildInputs = drv-prev.nativeBuildInputs ++ [ python-final.pybind11-stubgen ]; + src = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions [ + ./CMakeLists.txt + ./doc + ./include + ./package.xml + ./src + ./tests + ]; + }; }; - }; } ); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7664b04..a8a59d0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -80,6 +80,40 @@ macro(ADD_PYTHON_LIBRARY MODULE) FILES ${CMAKE_CURRENT_BINARY_DIR}/${MODULE}/__init__.py DESTINATION ${PYTHON_SITELIB}/${MODULE} ) + + set_property( + GLOBAL + APPEND + PROPERTY PYHPP_ALL_BINDING_TARGETS ${TARGET_NAME} + ) + + if(GENERATE_PYTHON_STUBS AND PYBIND11_STUBGEN_EXECUTABLE) + string(REPLACE "/" "." MODULE_DOT_PATH "${MODULE}") + set(STUB_OUTPUT_DIR ${CMAKE_BINARY_DIR}/stubs) + + add_custom_command( + OUTPUT ${STUB_OUTPUT_DIR}/${MODULE}/${LIBNAME}.pyi + COMMAND + ${CMAKE_COMMAND} -E env + "PYTHONPATH=${CMAKE_BINARY_DIR}/src:$ENV{PYTHONPATH}" + ${PYBIND11_STUBGEN_EXECUTABLE} ${MODULE_DOT_PATH}.${LIBNAME} + --output-dir ${STUB_OUTPUT_DIR} + DEPENDS all_pyhpp_bindings + COMMENT "Generating Python stubs for ${MODULE_DOT_PATH}.${LIBNAME}" + VERBATIM + ) + + add_custom_target( + stubs_${TARGET_NAME} + ALL + DEPENDS ${STUB_OUTPUT_DIR}/${MODULE}/${LIBNAME}.pyi + ) + + install( + FILES ${STUB_OUTPUT_DIR}/${MODULE}/${LIBNAME}.pyi + DESTINATION ${PYTHON_SITELIB}/${MODULE} + ) + endif() endmacro() python_install_on_site(pyhpp __init__.py) @@ -199,6 +233,9 @@ add_python_library( hpp-manipulation-urdf::hpp-manipulation-urdf ) +get_property(PYHPP_ALL_BINDINGS GLOBAL PROPERTY PYHPP_ALL_BINDING_TARGETS) +add_custom_target(all_pyhpp_bindings DEPENDS ${PYHPP_ALL_BINDINGS}) + # Install tool submodule python_install_on_site(pyhpp/tools __init__.py) python_install_on_site(pyhpp/tools xacro.py)