diff --git a/onnxruntime/core/session/environment.cc b/onnxruntime/core/session/environment.cc index 523ff8eaf13b8..827cb13127745 100644 --- a/onnxruntime/core/session/environment.cc +++ b/onnxruntime/core/session/environment.cc @@ -17,6 +17,7 @@ #include "core/session/allocator_adapters.h" #include "core/session/inference_session.h" #include "core/session/onnxruntime_env_config_keys.h" +#include "core/session/onnxruntime_ep_device_ep_metadata_keys.h" #include "core/session/plugin_ep/ep_factory_internal.h" #include "core/session/plugin_ep/ep_library_internal.h" #include "core/session/plugin_ep/ep_library_plugin.h" @@ -896,8 +897,15 @@ Status Environment::EpInfo::Create(std::unique_ptr library_in, std::u factory.GetSupportedDevices(&factory, sorted_devices.data(), sorted_devices.size(), ep_devices.data(), ep_devices.size(), &num_ep_devices))); + const auto* library_path = instance.library->LibraryPath(); for (size_t i = 0; i < num_ep_devices; ++i) { - if (ep_devices[i] != nullptr) { // should never happen but just in case... + if (ep_devices[i] != nullptr) { // should never happen but just in case... + if (library_path != nullptr) { + // Add library path to EP metadata if available. + // This is used by GenAI for custom library loading so we want to consistently set it. + ep_devices[i]->ep_metadata.Add(kOrtEpDevice_EpMetadataKey_LibraryPath, library_path->string()); + } + instance.execution_devices.emplace_back(ep_devices[i]); // take ownership } } diff --git a/onnxruntime/core/session/plugin_ep/ep_factory_provider_bridge.cc b/onnxruntime/core/session/plugin_ep/ep_factory_provider_bridge.cc index 42b65239de92c..0e2c4b4217702 100644 --- a/onnxruntime/core/session/plugin_ep/ep_factory_provider_bridge.cc +++ b/onnxruntime/core/session/plugin_ep/ep_factory_provider_bridge.cc @@ -22,11 +22,6 @@ OrtStatus* ProviderBridgeEpFactory::GetSupportedDevices(EpFactoryInternal& ep_fa auto* ep_device = ep_devices[i]; if (ep_device) { ep_device->ep_factory = &ep_factory; - - // Add library path to EP metadata if available - if (library_path_.has_value()) { - ep_device->ep_metadata.Add(kOrtEpDevice_EpMetadataKey_LibraryPath, library_path_->string()); - } } } diff --git a/onnxruntime/core/session/plugin_ep/ep_library.h b/onnxruntime/core/session/plugin_ep/ep_library.h index af5bc23143e33..fed9eb072c704 100644 --- a/onnxruntime/core/session/plugin_ep/ep_library.h +++ b/onnxruntime/core/session/plugin_ep/ep_library.h @@ -20,6 +20,7 @@ class EpLibrary { EpLibrary() = default; virtual const char* RegistrationName() const = 0; + virtual const std::filesystem::path* LibraryPath() const { return nullptr; } virtual Status Load() { return Status::OK(); } virtual const std::vector& GetFactories() = 0; // valid after Load() virtual Status Unload() { return Status::OK(); } diff --git a/onnxruntime/core/session/plugin_ep/ep_library_plugin.h b/onnxruntime/core/session/plugin_ep/ep_library_plugin.h index e044e91b61e37..cce52b3d5d282 100644 --- a/onnxruntime/core/session/plugin_ep/ep_library_plugin.h +++ b/onnxruntime/core/session/plugin_ep/ep_library_plugin.h @@ -25,6 +25,10 @@ class EpLibraryPlugin : public EpLibrary { return registration_name_.c_str(); } + const std::filesystem::path* LibraryPath() const override { + return &library_path_; + } + Status Load() override; const std::vector& GetFactories() override { diff --git a/onnxruntime/core/session/plugin_ep/ep_library_provider_bridge.h b/onnxruntime/core/session/plugin_ep/ep_library_provider_bridge.h index 45277b2828f56..f3147794bc823 100644 --- a/onnxruntime/core/session/plugin_ep/ep_library_provider_bridge.h +++ b/onnxruntime/core/session/plugin_ep/ep_library_provider_bridge.h @@ -22,7 +22,7 @@ class EpLibraryProviderBridge : public EpLibrary { public: EpLibraryProviderBridge(std::unique_ptr provider_library, std::unique_ptr ep_library_plugin, - std::optional library_path = std::nullopt) + std::filesystem::path library_path) : provider_library_{std::move(provider_library)}, ep_library_plugin_{std::move(ep_library_plugin)}, library_path_{std::move(library_path)} { @@ -32,6 +32,10 @@ class EpLibraryProviderBridge : public EpLibrary { return ep_library_plugin_->RegistrationName(); } + const std::filesystem::path* LibraryPath() const override { + return &library_path_; + } + const std::vector& GetFactories() override { return factory_ptrs_; } @@ -56,7 +60,7 @@ class EpLibraryProviderBridge : public EpLibrary { std::unique_ptr ep_library_plugin_; // Library path for EP metadata - std::optional library_path_; + std::filesystem::path library_path_; std::vector> factories_; std::vector factory_ptrs_; // for convenience diff --git a/onnxruntime/test/autoep/test_registration.cc b/onnxruntime/test/autoep/test_registration.cc index 7b6679ffaf462..79bc34572a6f7 100644 --- a/onnxruntime/test/autoep/test_registration.cc +++ b/onnxruntime/test/autoep/test_registration.cc @@ -74,6 +74,15 @@ TEST(OrtEpLibrary, LoadUnloadPluginLibraryCxxApi) { auto options = test_ep_device->EpOptions(); ASSERT_STREQ(options.GetValue("run_really_fast"), "true"); + // Verify the library path is present in the EP metadata + const char* metadata_library_path = metadata.GetValue(kOrtEpDevice_EpMetadataKey_LibraryPath); + ASSERT_NE(metadata_library_path, nullptr) << "Expected library_path to be present in EP metadata."; + + // Verify the library path matches the registered path + std::filesystem::path metadata_path{metadata_library_path}; + ASSERT_EQ(std::filesystem::canonical(metadata_path), std::filesystem::canonical(library_path)) + << "Expected library_path in EP metadata to match the registered library path."; + // the CPU device info will vary by machine so check for the lowest common denominator values Ort::ConstHardwareDevice device = test_ep_device->Device(); ASSERT_EQ(device.Type(), OrtHardwareDeviceType_CPU);