From 5ed3e382cefef0148ff9d26d8b6a38f6fbd22574 Mon Sep 17 00:00:00 2001 From: Silvio Date: Wed, 25 Sep 2024 19:49:56 +0200 Subject: [PATCH] Ensure that wearables and hde Python bindings work on Windows when installed in arbitrary directories --- bindings/CMakeLists.txt | 25 ++++++++++++++++++++++++ bindings/python-hde/CMakeLists.txt | 4 +--- bindings/python-wearables/CMakeLists.txt | 4 +--- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt index da48f355..a34237d8 100644 --- a/bindings/CMakeLists.txt +++ b/bindings/CMakeLists.txt @@ -35,6 +35,31 @@ if(HDE_COMPILE_PYTHON_BINDINGS) "Do you want HDE to detect and use the active site-package directory? (it could be a system dir)" FALSE) + # Function to generate __init__.py file for both hde and wearables + # It contains logic to ensure that it works fine on Windows when installing in arbitrary folders, + # See https://docs.python.org/3.8/library/os.html#os.add_dll_directory + function(hde_generate_init_py_file GENERATION_LOCATION_OF_INIT_PY_FILE INSTALLATION_LOCATION_OF_INIT_PY_FILE) + file(WRITE ${GENERATION_LOCATION_OF_INIT_PY_FILE}/__init__.py "") + if(WIN32 AND BUILD_SHARED_LIBS) + if(IS_ABSOLUTE ${INSTALLATION_LOCATION_OF_INIT_PY_FILE}) + set(PYTHON_FULL_INSTDIR "${INSTALLATION_LOCATION_OF_INIT_PY_FILE}") + else() + set(PYTHON_FULL_INSTDIR "${CMAKE_INSTALL_PREFIX}/${INSTALLATION_LOCATION_OF_INIT_PY_FILE}") + endif() + file(RELATIVE_PATH RELATIVE_PATH_BETWEEN_INIT_PY_AND_DLL_DIRECTORY ${PYTHON_FULL_INSTDIR} ${CMAKE_INSTALL_FULL_BINDIR}) + file(APPEND ${GENERATION_LOCATION_OF_INIT_PY_FILE}/__init__.py "import os\n") + file(APPEND ${GENERATION_LOCATION_OF_INIT_PY_FILE}/__init__.py "library_dll_path = os.path.join(os.path.dirname(__file__),'${RELATIVE_PATH_BETWEEN_INIT_PY_AND_DLL_DIRECTORY}')\n") + file(APPEND ${GENERATION_LOCATION_OF_INIT_PY_FILE}/__init__.py "# Avoid to call add_dll_directory if not necessary,\n") + file(APPEND ${GENERATION_LOCATION_OF_INIT_PY_FILE}/__init__.py "# for example if the library to find are already found in the proper location in a conda\n") + file(APPEND ${GENERATION_LOCATION_OF_INIT_PY_FILE}/__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')):\n") + file(APPEND ${GENERATION_LOCATION_OF_INIT_PY_FILE}/__init__.py " if(os.path.exists(library_dll_path)):\n") + file(APPEND ${GENERATION_LOCATION_OF_INIT_PY_FILE}/__init__.py " os.add_dll_directory(library_dll_path)$\n") + file(APPEND ${GENERATION_LOCATION_OF_INIT_PY_FILE}/__init__.py "\n") + endif() + + file(APPEND ${GENERATION_LOCATION_OF_INIT_PY_FILE}/__init__.py "from .bindings import *\n") + endfunction() + # Install the resulting Python package for the active interpreter if(NOT DEFINED HDE_PYTHON_INSTALL_DIR) if(HDE_DETECT_ACTIVE_PYTHON_SITEPACKAGES) diff --git a/bindings/python-hde/CMakeLists.txt b/bindings/python-hde/CMakeLists.txt index 7b400d54..006ab8d6 100644 --- a/bindings/python-hde/CMakeLists.txt +++ b/bindings/python-hde/CMakeLists.txt @@ -43,9 +43,7 @@ set_target_properties(pybind11_hde PROPERTIES install(TARGETS pybind11_hde DESTINATION ${PYTHON_INSTDIR}) # Create the __init__.py file -file(GENERATE - OUTPUT "${HDE_PYTHON_PACKAGE}/__init__.py" - CONTENT "from .bindings import *\n") +hde_generate_init_py_file("${HDE_PYTHON_PACKAGE}" "${PYTHON_INSTDIR}") # Install the __init__.py file install(FILES "${HDE_PYTHON_PACKAGE}/__init__.py" DESTINATION ${PYTHON_INSTDIR}) diff --git a/bindings/python-wearables/CMakeLists.txt b/bindings/python-wearables/CMakeLists.txt index cd94f5e8..b5626247 100644 --- a/bindings/python-wearables/CMakeLists.txt +++ b/bindings/python-wearables/CMakeLists.txt @@ -42,9 +42,7 @@ set_target_properties(pybind11_wearables PROPERTIES install(TARGETS pybind11_wearables DESTINATION ${PYTHON_INSTDIR}) -file(GENERATE - OUTPUT "${WEARABLES_PYTHON_PACKAGE}/__init__.py" - CONTENT "from .bindings import *\n") +hde_generate_init_py_file("${WEARABLES_PYTHON_PACKAGE}" "${PYTHON_INSTDIR}") # Install the __init__.py file install(FILES "${WEARABLES_PYTHON_PACKAGE}/__init__.py" DESTINATION ${PYTHON_INSTDIR})