From f0c286b5759f5328a5d7db536ab5d056411163f6 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Thu, 24 Oct 2024 17:10:19 +0200 Subject: [PATCH] Fix loading of Python bindings on Windows when installed in arbitrary directory --- bindings/CMakeLists.txt | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt index 554769769b..bb45ae5250 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"