18 #if defined(__unix__) || defined(__APPLE__) 19 if (sharedObjectPath.empty())
21 throw RuntimeException(
"OpenHandle error: shared object path must not be empty");
24 void* sharedObjectHandle = dlopen(sharedObjectPath.c_str(), RTLD_LAZY);
25 if (!sharedObjectHandle)
30 return sharedObjectHandle;
38 #if defined(__unix__) || defined(__APPLE__) 39 if (!sharedObjectHandle)
44 dlclose(const_cast<void*>(sharedObjectHandle));
64 std::string DynamicBackendUtils::GetDlError()
66 #if defined(__unix__) || defined(__APPLE__) 67 const char* errorMessage = dlerror();
73 return std::string(errorMessage);
82 if (!overrideBackendPath.empty())
86 ARMNN_LOG(
warning) <<
"WARNING: The given override path for dynamic backends \"" 87 << overrideBackendPath <<
"\" is not valid";
92 return std::vector<std::string>{ overrideBackendPath };
104 if (backendPaths.empty())
111 std::unordered_set<std::string> uniqueBackendPaths;
112 std::vector<std::string> validBackendPaths;
117 for (
const std::string& path : tempBackendPaths)
126 auto it = uniqueBackendPaths.find(path);
127 if (it != uniqueBackendPaths.end())
134 uniqueBackendPaths.insert(path);
137 validBackendPaths.push_back(path);
140 return validBackendPaths;
151 fs::path fsPath(path);
153 if (!fs::exists(fsPath))
155 ARMNN_LOG(
warning) <<
"WARNING: The given backend path \"" << path <<
"\" does not exist";
159 if (!fs::is_directory(fsPath))
161 ARMNN_LOG(
warning) <<
"WARNING: The given backend path \"" << path <<
"\" is not a directory";
165 if (!fsPath.is_absolute())
167 ARMNN_LOG(
warning) <<
"WARNING: The given backend path \"" << path <<
"\" is not absolute";
176 std::unordered_set<std::string> uniqueSharedObjects;
177 std::vector<std::string> sharedObjects;
179 for (
const std::string& backendPath : backendPaths)
190 std::vector<path> backendPathFiles;
191 std::copy(directory_iterator(backendPath), directory_iterator(), std::back_inserter(backendPathFiles));
192 std::sort(backendPathFiles.begin(), backendPathFiles.end());
195 for (
const path& backendPathFile : backendPathFiles)
198 std::string filename = backendPathFile.filename().string();
200 if (filename.empty())
211 canonicalPath = canonical(backendPathFile);
213 catch (
const filesystem_error& e)
217 if (canonicalPath.empty())
226 const std::regex dynamicBackendRegex(
"^[a-zA-Z0-9]+_[a-zA-Z0-9]+_backend.so(\\.[0-9]+)*$");
228 bool filenameMatch =
false;
232 filenameMatch = std::regex_match(filename, dynamicBackendRegex);
234 catch (
const std::exception& e)
245 std::string validCanonicalPath = canonicalPath.string();
246 auto it = uniqueSharedObjects.find(validCanonicalPath);
247 if (it == uniqueSharedObjects.end())
250 sharedObjects.push_back(validCanonicalPath);
253 uniqueSharedObjects.insert(validCanonicalPath);
258 return sharedObjects;
264 std::vector<DynamicBackendPtr> dynamicBackends;
265 for (
const std::string& sharedObject : sharedObjects)
268 void* sharedObjectHandle =
nullptr;
276 << sharedObject <<
"\": " << e.
what();
279 if (!sharedObjectHandle)
281 ARMNN_LOG(
warning) <<
"Invalid handle to the shared object file \"" << sharedObject <<
"\"";
294 ARMNN_LOG(
warning) <<
"Cannot create a valid dynamic backend from the shared object file \"" 295 << sharedObject <<
"\": " << e.
what();
300 ARMNN_LOG(
warning) <<
"Invalid dynamic backend object for the shared object file \"" 301 << sharedObject <<
"\"";
306 dynamicBackends.push_back(std::move(dynamicBackend));
309 return dynamicBackends;
317 for (
const auto&
id : dynamicBackends)
334 const std::vector<DynamicBackendPtr>& dynamicBackends)
346 dynamicBackendId = dynamicBackend->GetBackendId();
351 <<
"an error has occurred when getting the backend id: " << e.
what();
354 if (dynamicBackendId.
IsEmpty() ||
357 ARMNN_LOG(
warning) <<
"Cannot register dynamic backend, invalid backend id: " << dynamicBackendId;
363 if (backendAlreadyRegistered)
365 ARMNN_LOG(
warning) <<
"Cannot register dynamic backend \"" << dynamicBackendId
366 <<
"\": backend already registered";
374 dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction();
378 ARMNN_LOG(
warning) <<
"Cannot register dynamic backend \"" << dynamicBackendId
379 <<
"\": an error has occurred when getting the backend factory function: " 383 if (dynamicBackendFactoryFunction ==
nullptr)
385 ARMNN_LOG(
warning) <<
"Cannot register dynamic backend \"" << dynamicBackendId
386 <<
"\": invalid backend factory function";
393 backendRegistry.
Register(dynamicBackendId, dynamicBackendFactoryFunction);
397 ARMNN_LOG(
warning) <<
"An error has occurred when registering the dynamic backend \"" 398 << dynamicBackendId <<
"\": " << e.
what();
403 registeredBackendIds.insert(dynamicBackendId);
406 return registeredBackendIds;
std::vector< std::string > StringTokenizer(const std::string &str, const char *delimiters, bool tokenCompression=true)
Function to take a string and a list of delimiters and split the string into tokens based on those de...
static void DeregisterDynamicBackends(const BackendIdSet &dynamicBackends)
bool IsBackendRegistered(const BackendId &id) const
std::function< PointerType()> FactoryFunction
void Register(const BackendId &id, FactoryFunction factory)
std::unordered_set< BackendId > BackendIdSet
static bool IsBackendCompatible(const BackendVersion &backendVersion)
virtual const char * what() const noexcept override
#define ARMNN_LOG(severity)
BackendRegistry & BackendRegistryInstance()
static void * OpenHandle(const std::string &sharedObjectPath)
static std::vector< DynamicBackendPtr > CreateDynamicBackends(const std::vector< std::string > &sharedObjects)
Copyright (c) 2020 ARM Limited.
static std::vector< std::string > GetBackendPaths(const std::string &overrideBackendPath="")
std::unique_ptr< DynamicBackend > DynamicBackendPtr
static constexpr BackendVersion GetApiVersion()
Returns the version of the Backend API.
static std::vector< std::string > GetSharedObjects(const std::vector< std::string > &backendPaths)
static bool IsPathValid(const std::string &path)
static BackendIdSet RegisterDynamicBackendsImpl(BackendRegistry &backendRegistry, const std::vector< DynamicBackendPtr > &dynamicBackends)
#define DYNAMIC_BACKEND_PATHS
Base class for all ArmNN exceptions so that users can filter to just those.
void Deregister(const BackendId &id)
static bool IsBackendCompatibleImpl(const BackendVersion &backendApiVersion, const BackendVersion &backendVersion)
Protected methods for testing purposes.
static std::vector< std::string > GetBackendPathsImpl(const std::string &backendPaths)
static BackendIdSet RegisterDynamicBackends(const std::vector< DynamicBackendPtr > &dynamicBackends)
static void CloseHandle(const void *sharedObjectHandle)