From 16e76d712a5794e8420e68634c0e0f6c2610f13b Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Fri, 12 Jan 2024 11:01:39 +0100 Subject: [PATCH] Ensure that files generated by yarp_configure_plugins_installation are relocatable --- cmake/YarpInstallationHelpers.cmake | 11 ++++--- doc/release/master.md | 2 ++ src/libYARP_os/src/yarp/os/YarpPlugin.cpp | 37 ++++++++++++++++++----- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/cmake/YarpInstallationHelpers.cmake b/cmake/YarpInstallationHelpers.cmake index b23eabdf533..147bd2c37c8 100644 --- a/cmake/YarpInstallationHelpers.cmake +++ b/cmake/YarpInstallationHelpers.cmake @@ -65,17 +65,18 @@ function(YARP_CONFIGURE_PLUGINS_INSTALLATION _package) mark_as_advanced(YARP_FORCE_DYNAMIC_PLUGINS) set(_in_file "${CMAKE_BINARY_DIR}/CMakeFiles/${_package}.ini.in") - set(_build_file "${CMAKE_BINARY_DIR}/${${YCPI_INSTALL_VARS_PREFIX}_PLUGIN_MANIFESTS_INSTALL_DIR}/${_package}.ini") + set(_build_destination "${CMAKE_BINARY_DIR}/${${YCPI_INSTALL_VARS_PREFIX}_PLUGIN_MANIFESTS_INSTALL_DIR}") + set(_build_file "${_build_destination}/${_package}.ini") set(_install_file "${CMAKE_BINARY_DIR}/CMakeFiles/${_package}_for_install.ini") set(_destination "${${YCPI_INSTALL_VARS_PREFIX}_PLUGIN_MANIFESTS_INSTALL_DIR}") - unset(_path) + unset(_relative_path) unset(_extension) unset(_type) file(WRITE "${_in_file}" "###### This file is automatically generated by CMake. [search ${_package}] -path \"@_path@\" +relative_path \"@_relative_path@\" extension \"@_extension@\" type \"@_type@\" ") @@ -88,10 +89,10 @@ type \"@_type@\" set(_type "static") endif() - set(_path "${CMAKE_BINARY_DIR}/${${YCPI_INSTALL_VARS_PREFIX}_DYNAMIC_PLUGINS_INSTALL_DIR}") # (build tree) + file(RELATIVE_PATH _relative_path "${_build_destination}" "${CMAKE_BINARY_DIR}/${${YCPI_INSTALL_VARS_PREFIX}_DYNAMIC_PLUGINS_INSTALL_DIR}") # (build tree) configure_file("${_in_file}" "${_build_file}" @ONLY) - set(_path "${CMAKE_INSTALL_PREFIX}/${${YCPI_INSTALL_VARS_PREFIX}_DYNAMIC_PLUGINS_INSTALL_DIR}") # (install tree) + file(RELATIVE_PATH _relative_path "${CMAKE_INSTALL_PREFIX}/${_destination}" "${CMAKE_INSTALL_PREFIX}/${${YCPI_INSTALL_VARS_PREFIX}_DYNAMIC_PLUGINS_INSTALL_DIR}") # (install tree) configure_file("${_in_file}" "${_install_file}" @ONLY) install(FILES "${_install_file}" RENAME ${_package}.ini diff --git a/doc/release/master.md b/doc/release/master.md index 712078c88c1..8839e98fc22 100644 --- a/doc/release/master.md +++ b/doc/release/master.md @@ -25,5 +25,7 @@ Deprecations and removals Fixes ----- +* Configuration files installed by the `yarp_configure_plugins_installation` CMake macro are now relocatable (https://github.com/robotology/yarp/issues/2445, ). + New Features ------------ diff --git a/src/libYARP_os/src/yarp/os/YarpPlugin.cpp b/src/libYARP_os/src/yarp/os/YarpPlugin.cpp index 9cdaf33aa3f..7cc74085488 100644 --- a/src/libYARP_os/src/yarp/os/YarpPlugin.cpp +++ b/src/libYARP_os/src/yarp/os/YarpPlugin.cpp @@ -14,6 +14,7 @@ #include #include +#include using namespace yarp::os; using namespace yarp::os::impl; @@ -90,7 +91,19 @@ bool YarpPluginSettings::open(SharedLibraryFactory& factory) Bottle paths = selector->getSearchPath(); for (size_t i = 0; i < paths.size(); i++) { Searchable& options = paths.get(i); - std::string path = options.find("path").asString(); + std::string absolute_search_path; + if (options.check("path")) { + // If path is present in the .ini file generated by yarp_configure_plugins_installation, + // we use it directly + absolute_search_path = options.find("path").asString(); + } else if (options.check("relative_path")) { + // If instead relative_path is present, we use it to build absolute_search_path + // using relative_path and the absolute path to hte .ini file, contained in inifile + std::filesystem::path relative_search_path = std::filesystem::path(options.find("relative_path").asString()); + std::filesystem::path absolute_ini_file_path = std::filesystem::path(options.find("inifile").asString()); + absolute_search_path = std::filesystem::weakly_canonical(absolute_ini_file_path.parent_path() / relative_search_path).string(); + } + std::string ext = options.find("extension").asString(); std::string basename = (dll_name.find('.') != std::string::npos) ? name : dll_name; std::string fn = (fn_name.empty()) ? name : fn_name; @@ -99,20 +112,20 @@ bool YarpPluginSettings::open(SharedLibraryFactory& factory) #if defined(_MSC_VER) && !defined(NDEBUG) // MSVC DEBUG build: try debug name before basic name - fullpath = std::string(path).append("/").append(basename).append("d").append(ext); + fullpath = std::string(absolute_search_path).append("/").append(basename).append("d").append(ext); if (subopen(factory, fullpath, fn)) return true; #endif // defined(_MSC_VER) && !defined(NDEBUG) // Basic name - fullpath = std::string(path).append("/").append(basename).append(ext); + fullpath = std::string(absolute_search_path).append("/").append(basename).append(ext); if (subopen(factory, fullpath, fn)) { return true; } #if defined(_MSC_VER) && defined(NDEBUG) // MSVC RELEASE build: try debug name after basic name - fullpath = std::string(path).append("/").append(basename).append("d").append(ext); + fullpath = std::string(absolute_search_path).append("/").append(basename).append("d").append(ext); if (subopen(factory, fullpath, fn)) return true; #endif // defined(_MSC_VER) && defined(NDEBUG) @@ -124,19 +137,19 @@ bool YarpPluginSettings::open(SharedLibraryFactory& factory) # if defined(_MSC_VER) && !defined(NDEBUG) // MSVC DEBUG build: try debug name before basic name - fullpath = std::string(path).append("/" CMAKE_INTDIR "/").append(dll_name).append("d").append(ext); + fullpath = std::string(absolute_search_path).append("/" CMAKE_INTDIR "/").append(dll_name).append("d").append(ext); if (subopen(factory, fullpath, fn)) return true; # endif // defined(_MSC_VER) && !defined(NDEBUG) // Basic name - fullpath = std::string(path).append("/" CMAKE_INTDIR "/").append(dll_name).append(ext); + fullpath = std::string(absolute_search_path).append("/" CMAKE_INTDIR "/").append(dll_name).append(ext); if (subopen(factory, fullpath, fn)) return true; # if defined(_MSC_VER) && defined(NDEBUG) // MSVC RELEASE build: try debug name after basic name - fullpath = std::string(path).append("/" CMAKE_INTDIR "/").append(dll_name).append("d").append(ext); + fullpath = std::string(absolute_search_path).append("/" CMAKE_INTDIR "/").append(dll_name).append("d").append(ext); if (subopen(factory, fullpath, fn)) return true; # endif // defined(_MSC_VER) && defined(NDEBUG) @@ -258,6 +271,8 @@ void YarpPluginSelector::scan() for (size_t i = 0; i < inilst.size(); i++) { std::string inifile = inilst.get(i).asString(); Bottle inigroup = config.findGroup(inifile); + + // If a .ini file containes a "plugin" key, it identifies a plugin Bottle lst = inigroup.findGroup("plugin").tail(); for (size_t i = 0; i < lst.size(); i++) { std::string plugin_name = lst.get(i).asString(); @@ -267,10 +282,18 @@ void YarpPluginSelector::scan() plugins.addList() = group; } } + + // If a .ini file containes a "search" key, it is a .ini file used to identify + // a search path, created by the yarp_configure_plugins_installation CMake macro + // from YarpInstallationHelpers.cmake lst = inigroup.findGroup("search").tail(); for (size_t i = 0; i < lst.size(); i++) { std::string search_name = lst.get(i).asString(); Bottle group = inigroup.findGroup(search_name); + // Propagate the inifile absolute path, so it can be used in YarpPluginSettings::open + // to obtain the absolute search path given the relative_path contained in the .ini file + // generated by yarp_configure_plugins_installation + group.add(Value::makeValue(std::string("(inifile \"") + inifile + "\")")); search_path.addList() = group; } }