#include "vendor.hpp" #include #include #include #include namespace fs = std::filesystem; /////////////////////////////////////////////////////////////////////////////// std::vector cruft::vk::icd::enumerate (void) { // The predefined, ordered, search locations for manifests static char const *locations[] = { "/usr/local/etc/vulkan/icd.d/", "/usr/local/share/vulkan/icd.d/", "/etc/vulkan/icd.d/", "/usr/share/vulkan/icd.d/", "$HOME/.local/share/vulkan/icd.d/", }; std::vector found; for (auto const &loc: locations) { // We use wordexp rather than std::filesystem because we need to // perform environment expansion to account of $HOME in at least one // of the paths, so we may as well just use the same approach for // everything else too. wordexp_t words; posix::error::try_call (wordexp, loc, &words, WRDE_NOCMD | WRDE_UNDEF); std::unique_ptr cleanup {&words, &wordfree}; // Just try to parse everything we can find in the directory (if it // happens to exist) and fail out if it doesn't work. Marginally safer // than doing various tests. for (size_t i = 0; i < words.we_wordc; ++i) { try { for (auto const &path: fs::directory_iterator (words.we_wordv[i])) { if (path.is_directory ()) continue; found.push_back (from_json (*json::tree::parse (path))); } } catch (std::exception const &e) { LOG_INFO("failed to parse icd manifest; %!", e.what ()); } } } return found; }