1313 */
1414
1515// C++
16+ #include < filesystem>
1617#include < memory>
18+ #include < sstream>
1719#include < string>
1820#include < string_view>
1921#include < unordered_map>
@@ -128,7 +130,7 @@ class GManager : public GBase<GManager>
128130 *
129131 * \note The manager uses the `PLUGIN_LOGGER` channel for plugin-related output.
130132 */
131- explicit GManager (const std::shared_ptr<GOptions>& gopt) : GBase(gopt, PLUGIN_LOGGER ) {
133+ explicit GManager (const std::shared_ptr<GOptions>& gopt) : GBase(gopt, PLUGIN_LOGGER ), gopts_(gopt) {
132134 }
133135
134136 // / No copy – the manager owns unique resources (factory objects and loaded libraries).
@@ -218,6 +220,9 @@ class GManager : public GBase<GManager>
218220 // / Map from plugin key to the loaded library handle.
219221 std::unordered_map<std::string, std::shared_ptr<DynamicLib>> dlMap_;
220222
223+ // / Options retained so registerDL can read plugin_path at load time.
224+ std::shared_ptr<GOptions> gopts_;
225+
221226 // / Optional human-readable manager name (currently unused here).
222227 std::string gname;
223228};
@@ -230,14 +235,32 @@ inline void GManager::clearDLMap() noexcept {
230235}
231236
232237inline void GManager::registerDL (std::string_view name) {
233- // Convention: plugins are packaged as "<name>.gplugin".
234- const std::string filename = std::string{name} + " .gplugin" ;
238+ const std::string basename = std::string{name} + " .gplugin" ;
239+
240+ // Build the colon-separated search path: -plugin_path option takes
241+ // precedence, then GEMC_PLUGIN_PATH env var, then CWD / system library path.
242+ std::string filename = basename;
243+ if (gopts_) {
244+ std::string searchPath = gopts_->getScalarString (" plugin_path" );
245+ if (searchPath.empty ()) {
246+ if (const char * env = std::getenv (" GEMC_PLUGIN_PATH" )) { searchPath = env; }
247+ }
248+ if (!searchPath.empty ()) {
249+ std::istringstream ss (searchPath);
250+ std::string dir;
251+ while (std::getline (ss, dir, ' :' )) {
252+ const std::string candidate = dir + " /" + basename;
253+ if (std::filesystem::exists (candidate)) {
254+ filename = candidate;
255+ break ;
256+ }
257+ }
258+ }
259+ }
235260
236- // Store the DynamicLib in a shared_ptr so it can be safely captured by
237- // a shared_ptr deleter in LoadAndRegisterObjectFromLibrary().
238261 dlMap_.emplace (std::string{name},
239262 std::make_shared<DynamicLib>(log, filename));
240- log->debug (NORMAL , " Loading DL " , name);
263+ log->debug (NORMAL , " Loading DL " , name, " (resolved: " , filename, " ) " );
241264}
242265
243266template <class Derived >
@@ -291,5 +314,10 @@ std::shared_ptr<T> GManager::LoadAndRegisterObjectFromLibrary(std::string_view
291314 });
292315 }
293316
294- log->error (ERR_DLHANDLENOTFOUND , " Plugin " , name, " could not be loaded." );
317+ const char * envPath = std::getenv (" GEMC_PLUGIN_PATH" );
318+ log->error (ERR_DLHANDLENOTFOUND ,
319+ " Plugin " , name, " .gplugin could not be loaded.\n " ,
320+ " GEMC_PLUGIN_PATH = " , (envPath ? envPath : " (not set)" ), " \n " ,
321+ " Hint: set GEMC_PLUGIN_PATH or use -plugin_path=<dir> to point to the directory " ,
322+ " containing *.gplugin files." );
295323}
0 commit comments