9 #include <boost/filesystem.hpp> 10 #include <boost/algorithm/string.hpp> 20 if (sharedObjectPath.empty())
22 throw RuntimeException(
"OpenHandle error: shared object path must not be empty");
25 void* sharedObjectHandle = dlopen(sharedObjectPath.c_str(), RTLD_LAZY);
26 if (!sharedObjectHandle)
28 throw RuntimeException(boost::str(boost::format(
"OpenHandle error: %1%") % GetDlError()));
31 return sharedObjectHandle;
40 if (!sharedObjectHandle)
45 dlclose(const_cast<void*>(sharedObjectHandle));
65 std::string DynamicBackendUtils::GetDlError()
68 const char* errorMessage = dlerror();
74 return std::string(errorMessage);
83 if (!overrideBackendPath.empty())
87 ARMNN_LOG(
warning) <<
"WARNING: The given override path for dynamic backends \"" 88 << overrideBackendPath <<
"\" is not valid";
93 return std::vector<std::string>{ overrideBackendPath };
105 if (backendPaths.empty())
112 std::unordered_set<std::string> uniqueBackendPaths;
113 std::vector<std::string> tempBackendPaths;
114 std::vector<std::string> validBackendPaths;
117 boost::split(tempBackendPaths, backendPaths, boost::is_any_of(
":"));
119 for (
const std::string& path : tempBackendPaths)
128 auto it = uniqueBackendPaths.find(path);
129 if (it != uniqueBackendPaths.end())
136 uniqueBackendPaths.insert(path);
139 validBackendPaths.push_back(path);
142 return validBackendPaths;
153 boost::filesystem::path boostPath(path);
155 if (!boost::filesystem::exists(boostPath))
157 ARMNN_LOG(
warning) <<
"WARNING: The given backend path \"" << path <<
"\" does not exist";
161 if (!boost::filesystem::is_directory(boostPath))
163 ARMNN_LOG(
warning) <<
"WARNING: The given backend path \"" << path <<
"\" is not a directory";
167 if (!boostPath.is_absolute())
169 ARMNN_LOG(
warning) <<
"WARNING: The given backend path \"" << path <<
"\" is not absolute";
178 std::unordered_set<std::string> uniqueSharedObjects;
179 std::vector<std::string> sharedObjects;
181 for (
const std::string& backendPath : backendPaths)
183 using namespace boost::filesystem;
192 std::vector<path> backendPathFiles;
193 std::copy(directory_iterator(backendPath), directory_iterator(), std::back_inserter(backendPathFiles));
194 std::sort(backendPathFiles.begin(), backendPathFiles.end());
197 for (
const path& backendPathFile : backendPathFiles)
200 std::string filename = backendPathFile.filename().string();
202 if (filename.empty())
213 canonicalPath = canonical(backendPathFile);
215 catch (
const filesystem_error& e)
219 if (canonicalPath.empty())
228 const std::regex dynamicBackendRegex(
"^[a-zA-Z0-9]+_[a-zA-Z0-9]+_backend.so(\\.[0-9]+)*$");
230 bool filenameMatch =
false;
234 filenameMatch = std::regex_match(filename, dynamicBackendRegex);
236 catch (
const std::exception& e)
247 std::string validCanonicalPath = canonicalPath.string();
248 auto it = uniqueSharedObjects.find(validCanonicalPath);
249 if (it == uniqueSharedObjects.end())
252 sharedObjects.push_back(validCanonicalPath);
255 uniqueSharedObjects.insert(validCanonicalPath);
260 return sharedObjects;
266 std::vector<DynamicBackendPtr> dynamicBackends;
267 for (
const std::string& sharedObject : sharedObjects)
270 void* sharedObjectHandle =
nullptr;
278 << sharedObject <<
"\": " << e.
what();
281 if (!sharedObjectHandle)
283 ARMNN_LOG(
warning) <<
"Invalid handle to the shared object file \"" << sharedObject <<
"\"";
296 ARMNN_LOG(
warning) <<
"Cannot create a valid dynamic backend from the shared object file \"" 297 << sharedObject <<
"\": " << e.
what();
302 ARMNN_LOG(
warning) <<
"Invalid dynamic backend object for the shared object file \"" 303 << sharedObject <<
"\"";
308 dynamicBackends.push_back(std::move(dynamicBackend));
311 return dynamicBackends;
319 for (
const auto&
id : dynamicBackends)
336 const std::vector<DynamicBackendPtr>& dynamicBackends)
348 dynamicBackendId = dynamicBackend->GetBackendId();
353 <<
"an error has occurred when getting the backend id: " << e.
what();
356 if (dynamicBackendId.
IsEmpty() ||
359 ARMNN_LOG(
warning) <<
"Cannot register dynamic backend, invalid backend id: " << dynamicBackendId;
365 if (backendAlreadyRegistered)
367 ARMNN_LOG(
warning) <<
"Cannot register dynamic backend \"" << dynamicBackendId
368 <<
"\": backend already registered";
376 dynamicBackendFactoryFunction = dynamicBackend->GetFactoryFunction();
380 ARMNN_LOG(
warning) <<
"Cannot register dynamic backend \"" << dynamicBackendId
381 <<
"\": an error has occurred when getting the backend factory function: " 385 if (dynamicBackendFactoryFunction ==
nullptr)
387 ARMNN_LOG(
warning) <<
"Cannot register dynamic backend \"" << dynamicBackendId
388 <<
"\": invalid backend factory function";
395 backendRegistry.
Register(dynamicBackendId, dynamicBackendFactoryFunction);
399 ARMNN_LOG(
warning) <<
"An error has occurred when registering the dynamic backend \"" 400 << dynamicBackendId <<
"\": " << e.
what();
405 registeredBackendIds.insert(dynamicBackendId);
408 return registeredBackendIds;
std::function< PointerType()> FactoryFunction
static std::vector< std::string > GetBackendPaths(const std::string &overrideBackendPath="")
static void CloseHandle(const void *sharedObjectHandle)
static BackendIdSet RegisterDynamicBackendsImpl(BackendRegistry &backendRegistry, const std::vector< DynamicBackendPtr > &dynamicBackends)
#define ARMNN_LOG(severity)
static std::vector< std::string > GetSharedObjects(const std::vector< std::string > &backendPaths)
virtual const char * what() const noexcept override
static std::vector< DynamicBackendPtr > CreateDynamicBackends(const std::vector< std::string > &sharedObjects)
BackendRegistry & BackendRegistryInstance()
std::unique_ptr< DynamicBackend > DynamicBackendPtr
#define DYNAMIC_BACKEND_PATHS
static std::vector< std::string > GetBackendPathsImpl(const std::string &backendPaths)
Base class for all ArmNN exceptions so that users can filter to just those.
static bool IsBackendCompatibleImpl(const BackendVersion &backendApiVersion, const BackendVersion &backendVersion)
Protected methods for testing purposes.
static bool IsPathValid(const std::string &path)
bool IsBackendRegistered(const BackendId &id) const
static BackendIdSet RegisterDynamicBackends(const std::vector< DynamicBackendPtr > &dynamicBackends)
static constexpr BackendVersion GetApiVersion()
Returns the version of the Backend API.
std::unordered_set< BackendId > BackendIdSet
void Deregister(const BackendId &id)
static bool IsBackendCompatible(const BackendVersion &backendVersion)
static void * OpenHandle(const std::string &sharedObjectPath)
void Register(const BackendId &id, FactoryFunction factory)
static void DeregisterDynamicBackends(const BackendIdSet &dynamicBackends)