From a60b73d52925e3690083d3bbf5d4c501c84e493b Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Fri, 25 Oct 2024 08:53:08 +0200 Subject: [PATCH] Fix loading of Python bindings on Windows when installed in arbitrary directory (#905) --- CHANGELOG.md | 1 + bindings/CMakeLists.txt | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f26bbe71ff..38eb5dfb43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to this project are documented in this file. - Bug fix of `JointTorqueControlDevice` device (https://github.com/ami-iit/bipedal-locomotion-framework/pull/890) - Bug fix of `prepare_data` method calling in `joints-grid-position-tracking` (https://github.com/ami-iit/bipedal-locomotion-framework/pull/895) - Fix the normal force limit constraint in the `CentroidalMPC` (https://github.com/ami-iit/bipedal-locomotion-framework/pull/898) +- Fix loading of Python bindings on Windows when installed in arbitrary directory (https://github.com/ami-iit/bipedal-locomotion-framework/pull/905) ## [0.19.0] - 2024-09-06 ### Added diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt index 554769769b..10fb7b3d49 100644 --- a/bindings/CMakeLists.txt +++ b/bindings/CMakeLists.txt @@ -50,9 +50,27 @@ if(FRAMEWORK_COMPILE_PYTHON_BINDINGS) add_subdirectory(python) # Create the __init__.py file - file(GENERATE - OUTPUT "${BLF_PYTHON_PACKAGE}/__init__.py" - CONTENT "from .bindings import *${NEW_LINE}from . import utils${NEW_LINE}") + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/__init__.py "") + + # If we are on Windows and BUILD_SHARED_LIBS is ON, handle the fact that + # the Python interpreter does not look into PATH to find dll (see https://docs.python.org/3.8/library/os.html#os.add_dll_directory) + if(WIN32 AND BUILD_SHARED_LIBS) + if(IS_ABSOLUTE PYTHON_INSTDIR) + set(PYTHON_FULL_INSTDIR "${PYTHON_INSTDIR}") + else() + set(PYTHON_FULL_INSTDIR "${CMAKE_INSTALL_PREFIX}/${PYTHON_INSTDIR}") + endif() + file(RELATIVE_PATH RELATIVE_PATH_BETWEEN_INIT_PY_AND_DLL_DIRECTORY ${PYTHON_FULL_INSTDIR} ${CMAKE_INSTALL_FULL_BINDIR}) + file(APPEND "${BLF_PYTHON_PACKAGE}/__init__.py" "import os${NEW_LINE}") + file(APPEND "${BLF_PYTHON_PACKAGE}/__init__.py" "library_dll_path = os.path.join(os.path.dirname(__file__),'${RELATIVE_PATH_BETWEEN_INIT_PY_AND_DLL_DIRECTORY}')${NEW_LINE}") + file(APPEND "${BLF_PYTHON_PACKAGE}/__init__.py" "# Avoid to call add_dll_directory if not necessary,${NEW_LINE}") + file(APPEND "${BLF_PYTHON_PACKAGE}/__init__.py" "# for example if the library to find are already found in the proper location in a conda environment${NEW_LINE}") + file(APPEND "${BLF_PYTHON_PACKAGE}/__init__.py" "if(library_dll_path != os.path.join(os.environ.get('CONDA_PREFIX', ''),'Library','bin') and library_dll_path != os.path.join(os.environ.get('CONDA_PREFIX', ''),'bin')):${NEW_LINE}") + file(APPEND "${BLF_PYTHON_PACKAGE}/__init__.py" " if(os.path.exists(library_dll_path)):${NEW_LINE}") + file(APPEND "${BLF_PYTHON_PACKAGE}/__init__.py" " os.add_dll_directory(library_dll_path)${NEW_LINE}") + endif() + + file(APPEND "${BLF_PYTHON_PACKAGE}/__init__.py" "from .bindings import *${NEW_LINE}from . import utils${NEW_LINE}") # Install the __init__.py file install(FILES "${BLF_PYTHON_PACKAGE}/__init__.py"