From 0803a0eb17b0118dcadcf0f999f896268dab14de Mon Sep 17 00:00:00 2001 From: Levi Armstrong Date: Mon, 27 Jun 2022 22:36:38 -0500 Subject: [PATCH 1/3] Fix issue not using library names returned from getAllLibraryNames --- include/boost_plugin_loader/macros.h | 2 +- include/boost_plugin_loader/plugin_loader.hpp | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/boost_plugin_loader/macros.h b/include/boost_plugin_loader/macros.h index 8c4b58a..bc8ad5a 100644 --- a/include/boost_plugin_loader/macros.h +++ b/include/boost_plugin_loader/macros.h @@ -26,4 +26,4 @@ extern "C" BOOST_SYMBOL_EXPORT DERIVED_CLASS ALIAS; \ BOOST_DLL_SECTION(SECTION, read) BOOST_DLL_SELECTANY DERIVED_CLASS ALIAS; -#endif // BOOST_PLUGIN_LOADER_MACROS_H +#endif // BOOST_PLUGIN_LOADER_MACROS_H diff --git a/include/boost_plugin_loader/plugin_loader.hpp b/include/boost_plugin_loader/plugin_loader.hpp index 4c0e8ba..80a576c 100644 --- a/include/boost_plugin_loader/plugin_loader.hpp +++ b/include/boost_plugin_loader/plugin_loader.hpp @@ -60,15 +60,15 @@ template std::shared_ptr PluginLoader::createInstance(const std::string& plugin_name) const { // Check for environment variable for plugin definitions - std::set plugins_local = getAllLibraryNames(search_libraries_env, search_libraries); - if (plugins_local.empty()) + std::set library_names = getAllLibraryNames(search_libraries_env, search_libraries); + if (library_names.empty()) throw PluginLoaderException("No plugin libraries were provided!"); // Check for environment variable for search paths std::set search_paths_local = getAllSearchPaths(search_paths_env, search_paths); for (const auto& path : search_paths_local) { - for (const auto& library : search_libraries) + for (const auto& library : library_names) { try { @@ -84,7 +84,7 @@ std::shared_ptr PluginLoader::createInstance(const std::string& plug // If not found in any of the provided search paths then search system folders if allowed if (search_system_folders) { - for (const auto& library : search_libraries) + for (const auto& library : library_names) { try { @@ -107,7 +107,7 @@ std::shared_ptr PluginLoader::createInstance(const std::string& plug msg << " - " + path << std::endl; msg << "Search Libraries:" << std::endl; - for (const auto& library : search_libraries) + for (const auto& library : library_names) msg << " - " + decorate(library) << std::endl; throw PluginLoaderException(msg.str()); @@ -116,15 +116,15 @@ std::shared_ptr PluginLoader::createInstance(const std::string& plug bool PluginLoader::isPluginAvailable(const std::string& plugin_name) const { // Check for environment variable for plugin definitions - std::set plugins_local = getAllLibraryNames(search_libraries_env, search_libraries); - if (plugins_local.empty()) + std::set library_names = getAllLibraryNames(search_libraries_env, search_libraries); + if (library_names.empty()) throw PluginLoaderException("No plugin libraries were provided!"); // Check for environment variable to override default library std::set search_paths_local = getAllSearchPaths(search_paths_env, search_paths); for (const auto& path : search_paths_local) { - for (const auto& library : search_libraries) + for (const auto& library : library_names) { if (isSymbolAvailable(plugin_name, library, path)) return true; @@ -134,7 +134,7 @@ bool PluginLoader::isPluginAvailable(const std::string& plugin_name) const // If not found in any of the provided search paths then search system folders if allowed if (search_system_folders) { - for (const auto& library : search_libraries) + for (const auto& library : library_names) { if (isSymbolAvailable(plugin_name, library)) return true; @@ -172,7 +172,7 @@ std::vector PluginLoader::getAvailablePlugins(const std::string& se for (const auto& path : search_paths_local) { - for (const auto& library : search_libraries) + for (const auto& library : library_names) { std::vector lib_plugins = getAllAvailableSymbols(section, library, path); plugins.insert(plugins.end(), lib_plugins.begin(), lib_plugins.end()); @@ -187,15 +187,15 @@ std::vector PluginLoader::getAvailableSections(bool include_hidden) std::vector sections; // Check for environment variable for plugin definitions - std::set plugins_local = getAllLibraryNames(search_libraries_env, search_libraries); - if (plugins_local.empty()) + std::set library_names = getAllLibraryNames(search_libraries_env, search_libraries); + if (library_names.empty()) throw PluginLoaderException("No plugin libraries were provided!"); // Check for environment variable to override default library std::set search_paths_local = getAllSearchPaths(search_paths_env, search_paths); for (const auto& path : search_paths_local) { - for (const auto& library : search_libraries) + for (const auto& library : library_names) { std::vector lib_sections = getAllAvailableSections(library, path, include_hidden); sections.insert(sections.end(), lib_sections.begin(), lib_sections.end()); From a9a474d61594671531ba742bfe09658c5723ba18 Mon Sep 17 00:00:00 2001 From: Levi Armstrong Date: Tue, 28 Jun 2022 11:56:27 -0500 Subject: [PATCH 2/3] Add utility function for add library to environment variables using anchor --- include/boost_plugin_loader/utils.h | 17 ++++++++- src/utils.cpp | 48 ++++++++++++++++++++++++- test/CMakeLists.txt | 17 ++++++++- test/plugin_loader_anchor_unit.cpp | 55 +++++++++++++++++++++++++++++ test/plugin_loader_unit.cpp | 3 ++ test/test_plugin_multiply.cpp | 5 +++ test/test_plugin_multiply.h | 3 ++ 7 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 test/plugin_loader_anchor_unit.cpp diff --git a/include/boost_plugin_loader/utils.h b/include/boost_plugin_loader/utils.h index 48ffe49..8f18ea7 100644 --- a/include/boost_plugin_loader/utils.h +++ b/include/boost_plugin_loader/utils.h @@ -63,6 +63,21 @@ bool isSymbolAvailable(const std::string& symbol_name, const std::string& librar std::vector getAllAvailableSymbols(const std::string& section, const std::string& library_name, const std::string& library_directory = ""); +/** + * @brief Utility function to add library containing symbol to the search env variable + * + * In some cases the name and location of a library is unknown at runtime, but a symbol can + * be linked at compile time. This is true for Python auditwheel distributions. This + * utility function will determine the location of the library, and add it to the library search + * environment variable so it can be found. + * + * @param symbol_ptr Pointer to the symbol to find + * @param search_libraries_env The environmental variable to modify with library name + * @param search_paths_env The environment variable to modify with library location + */ +void addSymbolLibraryToSearchLibrariesEnv(const void* symbol_ptr, const std::string& search_libraries_env, + const std::string& search_paths_env); + /** * @brief Get a list of available sections * @param library_name The library name to load which does not include the prefix 'lib' or suffix '.so' @@ -90,7 +105,7 @@ std::string decorate(const std::string& library_name, const std::string& library /** * @brief Extract list form environment variable - * @details The environment variables should be separated by a colon (":") + * @details The environment variables should be separated by a colon (":") on linux and semi-colon (";") on windows * @param env_variable The environment variable name to extract list from * @return A list extracted from variable name */ diff --git a/src/utils.cpp b/src/utils.cpp index 000fc27..d6bf63e 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -82,6 +83,45 @@ std::vector getAllAvailableSymbols(const std::string& section, cons return inf.symbols(section); } +void addSymbolLibraryToSearchLibrariesEnv(const void* symbol_ptr, const std::string& search_libraries_env, + const std::string& search_paths_env) +{ + std::string search_libraries_env_var_str; + char* search_libraries_env_var = std::getenv(search_libraries_env.c_str()); + if (search_libraries_env_var != nullptr) + search_libraries_env_var_str = search_libraries_env_var; + + std::string search_paths_env_var_str; + char* search_paths_env_var = std::getenv(search_paths_env.c_str()); + if (search_paths_env_var != nullptr) + search_paths_env_var_str = search_paths_env_var; + + boost::dll::fs::path lib_path = boost::dll::symbol_location_ptr(symbol_ptr); + + std::string separator{ ":" }; +#ifdef _WIN32 + separator = ";"; +#endif + + if (search_libraries_env_var_str.empty()) + search_libraries_env_var_str = lib_path.filename().string(); + else + search_libraries_env_var_str = search_libraries_env_var_str + separator + lib_path.filename().string(); + + if (search_paths_env_var_str.empty()) + search_paths_env_var_str = lib_path.parent_path().string(); + else + search_paths_env_var_str = search_paths_env_var_str + separator + lib_path.parent_path().string(); + +#ifndef _WIN32 + setenv(search_libraries_env.c_str(), search_libraries_env_var_str.c_str(), 1); + setenv(search_paths_env.c_str(), search_paths_env_var_str.c_str(), 1); +#else + _putenv_s(search_libraries_env.c_str(), search_libraries_env_var_str.c_str()); + _putenv_s(search_paths_env.c_str(), search_paths_env_var_str.c_str()); +#endif +} + std::vector getAllAvailableSections(const std::string& library_name, const std::string& library_directory, bool include_hidden) { @@ -122,7 +162,9 @@ std::string decorate(const std::string& library_name, const std::string& library sl.filename().native()) : sl); - actual_path += boost::dll::shared_library::suffix(); + if (actual_path.extension().empty()) + actual_path += boost::dll::shared_library::suffix(); + return actual_path.string(); } @@ -134,7 +176,11 @@ std::set parseEnvironmentVariableList(const std::string& env_variab return list; std::string evn_str = std::string(env_var); +#ifndef _WIN32 boost::split(list, evn_str, boost::is_any_of(":"), boost::token_compress_on); +#else + boost::split(list, evn_str, boost::is_any_of(";"), boost::token_compress_on); +#endif return list; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8d6e75d..6679a43 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -8,7 +8,7 @@ target_cxx_version(${PROJECT_NAME}_test_plugin_multiply PUBLIC VERSION 17) add_executable(${PROJECT_NAME}_plugin_loader_unit plugin_loader_unit.cpp) target_link_libraries(${PROJECT_NAME}_plugin_loader_unit PRIVATE GTest::GTest GTest::Main ${PROJECT_NAME}) -target_compile_definitions(${PROJECT_NAME}_test_plugin_multiply PRIVATE ${COMPILE_DEFINITIONS}) +target_compile_definitions(${PROJECT_NAME}_plugin_loader_unit PRIVATE ${COMPILE_DEFINITIONS}) target_compile_definitions(${PROJECT_NAME}_plugin_loader_unit PRIVATE PLUGIN_DIR="${CMAKE_CURRENT_BINARY_DIR}" PLUGINS="${PROJECT_NAME}_test_plugin_multiply") target_clang_tidy(${PROJECT_NAME}_plugin_loader_unit ENABLE ${ENABLE_CLANG_TIDY}) @@ -18,6 +18,21 @@ add_gtest_discover_tests(${PROJECT_NAME}_plugin_loader_unit) add_dependencies(${PROJECT_NAME}_plugin_loader_unit ${PROJECT_NAME}) add_dependencies(run_tests ${PROJECT_NAME}_plugin_loader_unit) +add_executable(${PROJECT_NAME}_plugin_loader_anchor_unit plugin_loader_anchor_unit.cpp) +target_link_libraries( + ${PROJECT_NAME}_plugin_loader_anchor_unit + PRIVATE GTest::GTest + GTest::Main + ${PROJECT_NAME} + ${PROJECT_NAME}_test_plugin_multiply) +target_compile_definitions(${PROJECT_NAME}_plugin_loader_anchor_unit PRIVATE ${COMPILE_DEFINITIONS}) +target_clang_tidy(${PROJECT_NAME}_plugin_loader_anchor_unit ENABLE ${ENABLE_CLANG_TIDY}) +target_cxx_version(${PROJECT_NAME}_plugin_loader_anchor_unit PUBLIC VERSION 17) +target_code_coverage(${PROJECT_NAME}_plugin_loader_anchor_unit ALL ENABLE ${ENABLE_CODE_COVERAGE}) +add_gtest_discover_tests(${PROJECT_NAME}_plugin_loader_anchor_unit) +add_dependencies(${PROJECT_NAME}_plugin_loader_anchor_unit ${PROJECT_NAME} ${PROJECT_NAME}_test_plugin_multiply) +add_dependencies(run_tests ${PROJECT_NAME}_plugin_loader_anchor_unit) + install( TARGETS ${PROJECT_NAME}_test_plugin_multiply RUNTIME DESTINATION bin diff --git a/test/plugin_loader_anchor_unit.cpp b/test/plugin_loader_anchor_unit.cpp new file mode 100644 index 0000000..24f13d7 --- /dev/null +++ b/test/plugin_loader_anchor_unit.cpp @@ -0,0 +1,55 @@ +/** + * + * @copyright Copyright (c) 2021, Southwest Research Institute + * + * @par License + * Software License Agreement (Apache License) + * @par + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * @par + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "test_plugin_base.h" +#include "test_plugin_multiply.h" + +TEST(BoostPluginLoaderUnit, LoadTestPluginUsingAnchor) // NOLINT +{ + using boost_plugin_loader::addSymbolLibraryToSearchLibrariesEnv; + using boost_plugin_loader::PluginLoader; + using boost_plugin_loader::TestPluginBase; + + { + PluginLoader plugin_loader; + plugin_loader.search_libraries.clear(); + plugin_loader.search_paths.clear(); + plugin_loader.search_libraries_env = "PLUGIN_LOADER_UNIT_LIBRARY_NAMES_ENV"; + plugin_loader.search_paths_env = "PLUGIN_LOADER_UNIT_LIBRARY_PATHS_ENV"; + plugin_loader.search_system_folders = false; + addSymbolLibraryToSearchLibrariesEnv(boost_plugin_loader::TestPluginMultiplyAnchor(), + plugin_loader.search_libraries_env, plugin_loader.search_paths_env); + EXPECT_EQ(plugin_loader.count(), 1); + EXPECT_FALSE(plugin_loader.empty()); + EXPECT_TRUE(plugin_loader.isPluginAvailable("plugin")); + auto plugin = plugin_loader.createInstance("plugin"); + EXPECT_TRUE(plugin != nullptr); + EXPECT_NEAR(plugin->multiply(5, 5), 25, 1e-8); + } +} + +int main(int argc, char** argv) +{ + testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} diff --git a/test/plugin_loader_unit.cpp b/test/plugin_loader_unit.cpp index 9321410..08cbc73 100644 --- a/test/plugin_loader_unit.cpp +++ b/test/plugin_loader_unit.cpp @@ -31,6 +31,9 @@ TEST(BoostPluginLoaderUnit, Utils) // NOLINT { std::string env_var = "UNITTESTENV=a:b:c"; +#ifdef _WIN32 + env_var = "UNITTESTENV=a;b;c"; +#endif putenv(env_var.data()); std::set s = parseEnvironmentVariableList("UNITTESTENV"); std::vector v(s.begin(), s.end()); diff --git a/test/test_plugin_multiply.cpp b/test/test_plugin_multiply.cpp index 8cfb7d5..551a058 100644 --- a/test/test_plugin_multiply.cpp +++ b/test/test_plugin_multiply.cpp @@ -25,5 +25,10 @@ double boost_plugin_loader::TestPluginMultiply::multiply(double x, double y) return x * y; } +const void* boost_plugin_loader::TestPluginMultiplyAnchor() +{ + return (const void*)(&TestPluginMultiplyAnchor); // NOLINT +} + // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) EXPORT_TEST_PLUGIN(boost_plugin_loader::TestPluginMultiply, plugin) diff --git a/test/test_plugin_multiply.h b/test/test_plugin_multiply.h index 14e27dd..792fd63 100644 --- a/test/test_plugin_multiply.h +++ b/test/test_plugin_multiply.h @@ -34,6 +34,9 @@ class TestPluginMultiply : public TestPluginBase TestPluginMultiply& operator=(TestPluginMultiply&&) = default; double multiply(double x, double y) override; }; + +const void* TestPluginMultiplyAnchor(); + } // namespace boost_plugin_loader #endif // BOOST_PLUGIN_LOADER_TEST_PLUGIN_SUM_H From 07f677057913a88bffcbe3885fb8ba4a6918d6c0 Mon Sep 17 00:00:00 2001 From: Levi Armstrong Date: Tue, 28 Jun 2022 13:56:07 -0500 Subject: [PATCH 3/3] Update to support libraries provided as full path --- include/boost_plugin_loader/plugin_loader.hpp | 65 ++++++++++++++++++- include/boost_plugin_loader/utils.h | 4 +- src/utils.cpp | 58 +++++++++++------ test/plugin_loader_anchor_unit.cpp | 20 +++++- 4 files changed, 121 insertions(+), 26 deletions(-) diff --git a/include/boost_plugin_loader/plugin_loader.hpp b/include/boost_plugin_loader/plugin_loader.hpp index 80a576c..12ac2b7 100644 --- a/include/boost_plugin_loader/plugin_loader.hpp +++ b/include/boost_plugin_loader/plugin_loader.hpp @@ -56,6 +56,30 @@ static std::shared_ptr createSharedInstance(const std::string& symbol return std::shared_ptr(plugin.get(), [plugin](ClassBase*) mutable { plugin.reset(); }); } +/** + * @brief This will remove libraries with full path in the provided library_names and return them. + * @param library_names The set to search and remove libraries with full paths + * @return A set of the libraries provided as full path + */ +inline std::set extractLibrariesWithFullPath(std::set& library_names) +{ + std::set libraries_with_fullpath; + for (auto it = library_names.begin(); it != library_names.end();) + { + if (boost::filesystem::exists(*it)) + { + libraries_with_fullpath.insert(*it); + it = library_names.erase(it); + } + else + { + ++it; + } + } + + return libraries_with_fullpath; +} + template std::shared_ptr PluginLoader::createInstance(const std::string& plugin_name) const { @@ -64,6 +88,20 @@ std::shared_ptr PluginLoader::createInstance(const std::string& plug if (library_names.empty()) throw PluginLoaderException("No plugin libraries were provided!"); + // Check for libraries provided as full paths. These are searched first + std::set libraries_with_fullpath = extractLibrariesWithFullPath(library_names); + for (const auto& library_fullpath : libraries_with_fullpath) + { + try + { + return createSharedInstance(plugin_name, library_fullpath); + } + catch (...) + { + continue; + } + } + // Check for environment variable for search paths std::set search_paths_local = getAllSearchPaths(search_paths_env, search_paths); for (const auto& path : search_paths_local) @@ -120,6 +158,14 @@ bool PluginLoader::isPluginAvailable(const std::string& plugin_name) const if (library_names.empty()) throw PluginLoaderException("No plugin libraries were provided!"); + // Check for libraries provided as full paths. These are searched first + std::set libraries_with_fullpath = extractLibrariesWithFullPath(library_names); + for (const auto& library_fullpath : libraries_with_fullpath) + { + if (isSymbolAvailable(plugin_name, library_fullpath)) + return true; + } + // Check for environment variable to override default library std::set search_paths_local = getAllSearchPaths(search_paths_env, search_paths); for (const auto& path : search_paths_local) @@ -158,8 +204,17 @@ std::vector PluginLoader::getAvailablePlugins(const std::string& se if (library_names.empty()) throw PluginLoaderException("No plugin libraries were provided!"); - // Check for environment variable to override default library std::vector plugins; + + // Check for libraries provided as full paths. These are searched first + std::set libraries_with_fullpath = extractLibrariesWithFullPath(library_names); + for (const auto& library_fullpath : libraries_with_fullpath) + { + std::vector lib_plugins = getAllAvailableSymbols(section, library_fullpath); + plugins.insert(plugins.end(), lib_plugins.begin(), lib_plugins.end()); + } + + // Check for environment variable to override default library std::set search_paths_local = getAllSearchPaths(search_paths_env, search_paths); if (search_paths_local.empty()) { @@ -191,6 +246,14 @@ std::vector PluginLoader::getAvailableSections(bool include_hidden) if (library_names.empty()) throw PluginLoaderException("No plugin libraries were provided!"); + // Check for libraries provided as full paths. These are searched first + std::set libraries_with_fullpath = extractLibrariesWithFullPath(library_names); + for (const auto& library_fullpath : libraries_with_fullpath) + { + std::vector lib_sections = getAllAvailableSections(library_fullpath, "", include_hidden); + sections.insert(sections.end(), lib_sections.begin(), lib_sections.end()); + } + // Check for environment variable to override default library std::set search_paths_local = getAllSearchPaths(search_paths_env, search_paths); for (const auto& path : search_paths_local) diff --git a/include/boost_plugin_loader/utils.h b/include/boost_plugin_loader/utils.h index 8f18ea7..f6f208a 100644 --- a/include/boost_plugin_loader/utils.h +++ b/include/boost_plugin_loader/utils.h @@ -70,13 +70,13 @@ std::vector getAllAvailableSymbols(const std::string& section, cons * be linked at compile time. This is true for Python auditwheel distributions. This * utility function will determine the location of the library, and add it to the library search * environment variable so it can be found. - * + * @note If search_paths_env is empty it will add the library full path to the search_libraries_env. * @param symbol_ptr Pointer to the symbol to find * @param search_libraries_env The environmental variable to modify with library name * @param search_paths_env The environment variable to modify with library location */ void addSymbolLibraryToSearchLibrariesEnv(const void* symbol_ptr, const std::string& search_libraries_env, - const std::string& search_paths_env); + const std::string& search_paths_env = ""); /** * @brief Get a list of available sections diff --git a/src/utils.cpp b/src/utils.cpp index d6bf63e..9c783ff 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -86,16 +86,6 @@ std::vector getAllAvailableSymbols(const std::string& section, cons void addSymbolLibraryToSearchLibrariesEnv(const void* symbol_ptr, const std::string& search_libraries_env, const std::string& search_paths_env) { - std::string search_libraries_env_var_str; - char* search_libraries_env_var = std::getenv(search_libraries_env.c_str()); - if (search_libraries_env_var != nullptr) - search_libraries_env_var_str = search_libraries_env_var; - - std::string search_paths_env_var_str; - char* search_paths_env_var = std::getenv(search_paths_env.c_str()); - if (search_paths_env_var != nullptr) - search_paths_env_var_str = search_paths_env_var; - boost::dll::fs::path lib_path = boost::dll::symbol_location_ptr(symbol_ptr); std::string separator{ ":" }; @@ -103,23 +93,49 @@ void addSymbolLibraryToSearchLibrariesEnv(const void* symbol_ptr, const std::str separator = ";"; #endif - if (search_libraries_env_var_str.empty()) - search_libraries_env_var_str = lib_path.filename().string(); - else - search_libraries_env_var_str = search_libraries_env_var_str + separator + lib_path.filename().string(); + std::string search_libraries_env_var_str; + char* search_libraries_env_var = std::getenv(search_libraries_env.c_str()); + if (search_libraries_env_var != nullptr) + search_libraries_env_var_str = search_libraries_env_var; - if (search_paths_env_var_str.empty()) - search_paths_env_var_str = lib_path.parent_path().string(); + if (search_paths_env.empty()) + { + if (search_libraries_env_var_str.empty()) + search_libraries_env_var_str = lib_path.string(); + else + search_libraries_env_var_str = lib_path.string() + separator + search_libraries_env_var_str; + +#ifndef _WIN32 + setenv(search_libraries_env.c_str(), search_libraries_env_var_str.c_str(), 1); +#else + _putenv_s(search_libraries_env.c_str(), search_libraries_env_var_str.c_str()); +#endif + } else - search_paths_env_var_str = search_paths_env_var_str + separator + lib_path.parent_path().string(); + { + std::string search_paths_env_var_str; + char* search_paths_env_var = std::getenv(search_paths_env.c_str()); + if (search_paths_env_var != nullptr) + search_paths_env_var_str = search_paths_env_var; + + if (search_libraries_env_var_str.empty()) + search_libraries_env_var_str = lib_path.filename().string(); + else + search_libraries_env_var_str = lib_path.filename().string() + separator + search_libraries_env_var_str; + + if (search_paths_env_var_str.empty()) + search_paths_env_var_str = lib_path.parent_path().string(); + else + search_paths_env_var_str = lib_path.parent_path().string() + separator + search_paths_env_var_str; #ifndef _WIN32 - setenv(search_libraries_env.c_str(), search_libraries_env_var_str.c_str(), 1); - setenv(search_paths_env.c_str(), search_paths_env_var_str.c_str(), 1); + setenv(search_libraries_env.c_str(), search_libraries_env_var_str.c_str(), 1); + setenv(search_paths_env.c_str(), search_paths_env_var_str.c_str(), 1); #else - _putenv_s(search_libraries_env.c_str(), search_libraries_env_var_str.c_str()); - _putenv_s(search_paths_env.c_str(), search_paths_env_var_str.c_str()); + _putenv_s(search_libraries_env.c_str(), search_libraries_env_var_str.c_str()); + _putenv_s(search_paths_env.c_str(), search_paths_env_var_str.c_str()); #endif + } } std::vector getAllAvailableSections(const std::string& library_name, const std::string& library_directory, diff --git a/test/plugin_loader_anchor_unit.cpp b/test/plugin_loader_anchor_unit.cpp index 24f13d7..9ad72a2 100644 --- a/test/plugin_loader_anchor_unit.cpp +++ b/test/plugin_loader_anchor_unit.cpp @@ -33,8 +33,8 @@ TEST(BoostPluginLoaderUnit, LoadTestPluginUsingAnchor) // NOLINT PluginLoader plugin_loader; plugin_loader.search_libraries.clear(); plugin_loader.search_paths.clear(); - plugin_loader.search_libraries_env = "PLUGIN_LOADER_UNIT_LIBRARY_NAMES_ENV"; - plugin_loader.search_paths_env = "PLUGIN_LOADER_UNIT_LIBRARY_PATHS_ENV"; + plugin_loader.search_libraries_env = "PLUGIN_LOADER_UNIT_LIBRARY_NAMES_1_ENV"; + plugin_loader.search_paths_env = "PLUGIN_LOADER_UNIT_LIBRARY_PATHS_1_ENV"; plugin_loader.search_system_folders = false; addSymbolLibraryToSearchLibrariesEnv(boost_plugin_loader::TestPluginMultiplyAnchor(), plugin_loader.search_libraries_env, plugin_loader.search_paths_env); @@ -45,6 +45,22 @@ TEST(BoostPluginLoaderUnit, LoadTestPluginUsingAnchor) // NOLINT EXPECT_TRUE(plugin != nullptr); EXPECT_NEAR(plugin->multiply(5, 5), 25, 1e-8); } + + { + PluginLoader plugin_loader; + plugin_loader.search_libraries.clear(); + plugin_loader.search_paths.clear(); + plugin_loader.search_libraries_env = "PLUGIN_LOADER_UNIT_LIBRARY_NAMES_2_ENV"; + plugin_loader.search_system_folders = false; + addSymbolLibraryToSearchLibrariesEnv(boost_plugin_loader::TestPluginMultiplyAnchor(), + plugin_loader.search_libraries_env); + EXPECT_EQ(plugin_loader.count(), 1); + EXPECT_FALSE(plugin_loader.empty()); + EXPECT_TRUE(plugin_loader.isPluginAvailable("plugin")); + auto plugin = plugin_loader.createInstance("plugin"); + EXPECT_TRUE(plugin != nullptr); + EXPECT_NEAR(plugin->multiply(5, 5), 25, 1e-8); + } } int main(int argc, char** argv)