Skip to content

Commit f158141

Browse files
psakhamooriJaswanth51
authored andcommitted
Add custom ops library_path to EP metadata (microsoft#25830)
## Summary Adds EP metadata library path support to enable custom ops DLL registration with proper path resolution. ## Changes - Added `library_path` metadata key to EP metadata infrastructure - Pass resolved library path directly to `EpLibraryProviderBridge` constructor - Simplified implementation per reviewer feedback (removed virtual method complexity) - Added `#include <utility>` for std::move compliance ## Purpose Enables downstream applications (like onnxruntime-genai) to resolve relative custom ops library paths using EP metadata, improving DLL registration reliability. ## Files Modified - `plugin_ep/ep_factory_provider_bridge.h` - `plugin_ep/ep_library.h` - `plugin_ep/ep_library_plugin.h` - `plugin_ep/ep_library_provider_bridge.cc` - `plugin_ep/ep_library_provider_bridge.h` - `utils.cc`
1 parent 67ff56b commit f158141

File tree

7 files changed

+36
-10
lines changed

7 files changed

+36
-10
lines changed

include/onnxruntime/core/session/onnxruntime_ep_device_ep_metadata_keys.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,7 @@ static const char* const kOrtEpDevice_EpMetadataKey_Version = "version";
1212
// Prefix for execution provider compatibility information stored in model metadata.
1313
// Used when generating EP context models to store compatibility strings for each EP.
1414
// Full key format: "ep_compatibility_info.<EP_TYPE>"
15-
static const char* const kOrtModelMetadata_EpCompatibilityInfoPrefix = "ep_compatibility_info.";
15+
static const char* const kOrtModelMetadata_EpCompatibilityInfoPrefix = "ep_compatibility_info.";
16+
17+
// Key for the execution provider library path (for dynamically loaded EPs)
18+
static const char* const kOrtEpDevice_EpMetadataKey_LibraryPath = "library_path";

onnxruntime/core/session/plugin_ep/ep_factory_provider_bridge.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include "core/session/plugin_ep/ep_factory_provider_bridge.h"
55

66
#include "core/providers/shared_library/provider_host_api.h"
7+
#include "core/session/plugin_ep/ep_library_plugin.h"
8+
#include "core/session/onnxruntime_ep_device_ep_metadata_keys.h"
79

810
namespace onnxruntime {
911
OrtStatus* ProviderBridgeEpFactory::GetSupportedDevices(EpFactoryInternal& ep_factory,
@@ -20,6 +22,11 @@ OrtStatus* ProviderBridgeEpFactory::GetSupportedDevices(EpFactoryInternal& ep_fa
2022
auto* ep_device = ep_devices[i];
2123
if (ep_device) {
2224
ep_device->ep_factory = &ep_factory;
25+
26+
// Add library path to EP metadata if available
27+
if (library_path_.has_value()) {
28+
ep_device->ep_metadata.Add(kOrtEpDevice_EpMetadataKey_LibraryPath, library_path_->string());
29+
}
2330
}
2431
}
2532

onnxruntime/core/session/plugin_ep/ep_factory_provider_bridge.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
#pragma once
55

6+
#include <filesystem>
7+
#include <optional>
8+
#include <utility>
9+
610
#include "core/framework/error_code_helper.h"
711
#include "core/session/abi_devices.h"
812
#include "core/session/abi_session_options_impl.h"
@@ -12,12 +16,14 @@
1216
namespace onnxruntime {
1317
class ProviderBridgeEpFactory : public EpFactoryInternalImpl {
1418
public:
15-
ProviderBridgeEpFactory(OrtEpFactory& ep_factory, ProviderLibrary& provider_library)
19+
ProviderBridgeEpFactory(OrtEpFactory& ep_factory, ProviderLibrary& provider_library,
20+
std::optional<std::filesystem::path> library_path = std::nullopt)
1621
: EpFactoryInternalImpl(ep_factory.GetName(&ep_factory),
1722
ep_factory.GetVendor(&ep_factory),
1823
ep_factory.GetVendorId(&ep_factory)),
1924
ep_factory_{ep_factory},
20-
provider_library_{provider_library} {
25+
provider_library_{provider_library},
26+
library_path_{std::move(library_path)} {
2127
}
2228

2329
private:
@@ -59,8 +65,9 @@ class ProviderBridgeEpFactory : public EpFactoryInternalImpl {
5965
return ep_factory_.CreateSyncStreamForDevice(&ep_factory_, device, stream_options, stream);
6066
}
6167

62-
OrtEpFactory& ep_factory_; // OrtEpFactory from the provider bridge EP
63-
ProviderLibrary& provider_library_; // ProviderLibrary from the provider bridge EP
68+
OrtEpFactory& ep_factory_;
69+
ProviderLibrary& provider_library_;
70+
std::optional<std::filesystem::path> library_path_;
6471
};
6572

6673
} // namespace onnxruntime

onnxruntime/core/session/plugin_ep/ep_library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class EpLibrary {
2323
virtual Status Load() { return Status::OK(); }
2424
virtual const std::vector<OrtEpFactory*>& GetFactories() = 0; // valid after Load()
2525
virtual Status Unload() { return Status::OK(); }
26+
2627
virtual ~EpLibrary() = default;
2728

2829
ORT_DISALLOW_COPY_AND_ASSIGNMENT(EpLibrary);

onnxruntime/core/session/plugin_ep/ep_library_provider_bridge.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "core/session/plugin_ep/ep_library_provider_bridge.h"
55

66
#include "core/session/plugin_ep/ep_factory_provider_bridge.h"
7+
#include "core/session/plugin_ep/ep_library_plugin.h"
78

89
namespace onnxruntime {
910
Status EpLibraryProviderBridge::Load() {
@@ -26,8 +27,9 @@ Status EpLibraryProviderBridge::Load() {
2627
// to do this we need to capture `factory` and plug it in to is_supported_fn and create_fn.
2728
// we also need to update any returned OrtEpDevice instances to swap the wrapper EpFactoryInternal in so that we can
2829
// call Provider::CreateIExecutionProvider in EpFactoryInternal::CreateIExecutionProvider.
30+
2931
for (const auto& factory : ep_library_plugin_->GetFactories()) {
30-
auto factory_impl = std::make_unique<ProviderBridgeEpFactory>(*factory, *provider_library_);
32+
auto factory_impl = std::make_unique<ProviderBridgeEpFactory>(*factory, *provider_library_, library_path_);
3133
auto internal_factory = std::make_unique<EpFactoryInternal>(std::move(factory_impl));
3234

3335
factory_ptrs_.push_back(internal_factory.get());

onnxruntime/core/session/plugin_ep/ep_library_provider_bridge.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ namespace onnxruntime {
2121
class EpLibraryProviderBridge : public EpLibrary {
2222
public:
2323
EpLibraryProviderBridge(std::unique_ptr<ProviderLibrary> provider_library,
24-
std::unique_ptr<EpLibrary> ep_library_plugin)
24+
std::unique_ptr<EpLibrary> ep_library_plugin,
25+
std::optional<std::filesystem::path> library_path = std::nullopt)
2526
: provider_library_{std::move(provider_library)},
26-
ep_library_plugin_{std::move(ep_library_plugin)} {
27+
ep_library_plugin_{std::move(ep_library_plugin)},
28+
library_path_{std::move(library_path)} {
2729
}
2830

2931
const char* RegistrationName() const override {
@@ -53,6 +55,9 @@ class EpLibraryProviderBridge : public EpLibrary {
5355
// implement EpFactoryInternal::CreateIExecutionProvider by calling Provider::CreateIExecutionProvider.
5456
std::unique_ptr<EpLibrary> ep_library_plugin_;
5557

58+
// Library path for EP metadata
59+
std::optional<std::filesystem::path> library_path_;
60+
5661
std::vector<std::unique_ptr<EpFactoryInternal>> factories_;
5762
std::vector<OrtEpFactory*> factory_ptrs_; // for convenience
5863
std::vector<EpFactoryInternal*> internal_factory_ptrs_; // for convenience

onnxruntime/core/session/utils.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,13 +421,14 @@ Status LoadPluginOrProviderBridge(const std::string& registration_name,
421421
<< (is_provider_bridge ? " as a provider bridge" : " as a plugin");
422422

423423
// create EpLibraryPlugin to ensure CreateEpFactories and ReleaseEpFactory are available
424-
auto ep_library_plugin = std::make_unique<EpLibraryPlugin>(registration_name, std::move(resolved_library_path));
424+
auto ep_library_plugin = std::make_unique<EpLibraryPlugin>(registration_name, resolved_library_path);
425425
ORT_RETURN_IF_ERROR(ep_library_plugin->Load());
426426

427427
if (is_provider_bridge) {
428428
// wrap the EpLibraryPlugin with EpLibraryProviderBridge to add to directly create an IExecutionProvider
429429
auto ep_library_provider_bridge = std::make_unique<EpLibraryProviderBridge>(std::move(provider_library),
430-
std::move(ep_library_plugin));
430+
std::move(ep_library_plugin),
431+
resolved_library_path);
431432
ORT_RETURN_IF_ERROR(ep_library_provider_bridge->Load());
432433
internal_factories = ep_library_provider_bridge->GetInternalFactories();
433434
ep_library = std::move(ep_library_provider_bridge);

0 commit comments

Comments
 (0)