26#include "boost/tokenizer.hpp"
28#include "boost/algorithm/string.hpp"
29#include <boost/regex.hpp>
32#include "TClassEdit.h"
35#include "GaudiKernel/System.h"
37namespace fs = std::filesystem;
40 typedef std::vector<std::string> Strings_t;
41 const std::string RootMap =
".rootmap";
42 const std::string Components =
".components";
43 const std::string PluginNs=
"__pf__";
46 const std::string SHLIB_PREFIX =
"lib";
47 const std::string SHLIB_SUFFIX =
".dll";
49 const std::string SHLIB_PREFIX =
"lib";
50 const std::string SHLIB_SUFFIX =
".so";
54 bool is_rootcint_dict(
const std::string& libname)
56 if (libname ==
"liblistDict.so")
return true;
57 if (libname ==
"libmapDict.so")
return true;
58 if (libname ==
"libmap2Dict.so")
return true;
59 if (libname ==
"libmultimapDict.so")
return true;
60 if (libname ==
"libsetDict.so")
return true;
61 if (libname ==
"libvectorDict.so")
return true;
62 if (libname ==
"libCore.so")
return true;
63 if (libname ==
"libMathCore.so")
return true;
65 static const std::string dll =
".dll";
69 static const boost::regex
e(
"\\w*?.dll");
70 return !libname.starts_with(SHLIB_PREFIX) &&
71 boost::regex_match(libname, e);
80 std::string getlibname(
const std::string& libname)
82 std::string lib = libname;
83 if (!lib.starts_with(
"lib")) {
84 lib = std::string(
"lib") + lib;
86 if (!lib.ends_with(SHLIB_SUFFIX)) {
92 const std::set<std::string>&
95 static const std::set<std::string>
s = {
125 "unsigned long long",
138 const std::map<std::string, std::string>&
141 static const std::map<std::string, std::string>
s =
142 {{
"ElementLinkInt_p1",
"ElementLink_p1<unsigned int>"},
143 {
"basic_string<char>",
"string"},
144 {
"vector<basic_string<char> >",
"vector<string>"},
145 {
"INavigable4MomentumCollection",
"DataVector<INavigable4Momentum>"},
146 {
"IParticleContainer",
"DataVector<IParticle>"},
151 const std::map<std::string, std::string>&
154 static const std::map<std::string, std::string>
s =
155 {{
"INavigable4MomentumCollection",
"DataVector<INavigable4Momentum>"},
156 {
"IParticleContainer",
"DataVector<IParticle>"},
165 to_rootmap_name(
const std::string& type_name_)
167 std::string type_name = type_name_;
168 boost::algorithm::replace_all(type_name,
", ",
",");
170 if (s_cxx_builtins().
find(type_name) != s_cxx_builtins().
end()) {
175 if (s_cxx_aliases().
find(type_name) != s_cxx_aliases().
end()) {
176 return ::to_rootmap_name(s_cxx_aliases().
find(type_name)->second);
183 R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
184 type_name = TClassEdit::ShortType(type_name.c_str(),
185 TClassEdit::kDropDefaultAlloc|
186 TClassEdit::kDropStd);
188 boost::algorithm::replace_all(type_name,
"basic_string<char> >",
"string>");
189 boost::algorithm::replace_all(type_name,
"basic_string<char>",
"string");
197 to_rflx_name(
const std::string& type_name_)
199 std::string type_name = type_name_;
200 boost::algorithm::replace_all(type_name,
", ",
",");
202 if (s_cxx_builtins().
find(type_name) != s_cxx_builtins().
end()) {
207 if (s_cxx_typedefs().
find(type_name) != s_cxx_typedefs().
end()) {
208 return ::to_rflx_name(s_cxx_typedefs().
find(type_name)->second);
214 R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
215 type_name = TClassEdit::ShortType(type_name.c_str(),
216 TClassEdit::kDropDefaultAlloc);
219 boost::algorithm::replace_all(type_name,
221 "std::basic_string<char> >");
222 boost::algorithm::replace_all(type_name,
224 "std::basic_string<char>");
265 if (s_cxx_builtins().
find(type_name) != s_cxx_builtins().end()) {
268 const std::string n = ::to_rootmap_name(type_name);
279 RootType t = this->rflx_type(type_name);
283 return std::string();
296 typedef boost::tokenizer<boost::char_separator<char> > Tokenizer_t;
297 typedef std::vector<fs::path> Paths_t;
299 std::set<std::string> dsofiles;
301 std::string dsopath = System::getEnv(
"LD_LIBRARY_PATH");
302 std::string rootsys = System::getEnv(
"ROOTSYS");
304 Tokenizer_t tok(dsopath, boost::char_separator<char>(
":"));
306 for (Tokenizer_t::iterator itr = tok.begin(), iend = tok.end();
310 if (itr->starts_with(rootsys)) {
314 if (!std::filesystem::exists(*itr)) {
317 Paths_t dir_content {fs::directory_iterator(p),
318 fs::directory_iterator()};
321 for (Paths_t::iterator ipath = dir_content.begin(),
322 ipath_end = dir_content.end();
325 const fs::path& dsomap = *ipath;
327 bool is_components =
false;
328 if (dsomap.extension() == Components)
329 is_components =
true;
330 else if (dsomap.extension() != RootMap)
333 if (!fs::exists(dsomap))
continue;
336 dsofiles.insert(dsomap.c_str());
337 std::ifstream f(dsomap.c_str());
343 std::getline(f, line);
344 boost::algorithm::trim(line);
351 else if (line.compare (0, 8,
"Library.")==0) {
353 boost::algorithm::split(ll, line,
354 boost::is_any_of(
" "),
355 boost::token_compress_on);
357 std::cerr <<
"DsoDb:: **error** could not parse "
358 << dsomap <<
":" << line_nbr
360 <<
"DsoDb:: (some) reflex-dicts may fail to be autoloaded"
365 if (::is_rootcint_dict(libname)) {
369 libname = ::getlibname(libname);
370 boost::algorithm::replace_all(dso_key,
"Library.",
"");
371 boost::algorithm::replace_all(dso_key,
":",
"");
372 std::replace(dso_key.begin(), dso_key.end(),
'@',
':');
373 std::replace(dso_key.begin(), dso_key.end(),
'-',
' ');
376 else if (line[0] ==
'[') {
377 libname = line.substr (1, line.size()-2);
378 boost::algorithm::trim (libname);
379 if (::is_rootcint_dict(libname)) {
383 if (!libname.empty())
384 lastlib = ::getlibname (libname);
388 else if (line.compare(0, 8,
"# --End ")==0) {
393 else if (line.compare(0, 6,
"class ")==0) {
396 dso_key = std::move(line);
399 else if (is_components && line.compare(0, 3,
"lib") ==0) {
400 std::string::size_type pos = line.find (
':');
401 if (pos == std::string::npos)
continue;
402 libname = line.substr(0, pos);
403 line.erase (0, pos+1);
404 dso_key = std::move(line);
406 if (dso_key.compare(0, 6,
"_PERS_")==0 ||
407 dso_key.compare(0, 7,
"_TRANS_")==0)
410 if (libname.find (
"AthenaPoolPoolCnv") != std::string::npos)
414 if (libname.empty() || dso_key.empty())
continue;
416 const std::string fullpath_libname =
to_string(dsomap.parent_path() / fs::path(libname));
421 if (dso_key.starts_with(PluginNs) || is_components) {
426 if (
db->find(dso_key) ==
db->end()) {
427 db->insert(std::make_pair(dso_key, Strings_t()));
429 (*db)[dso_key].push_back(std::move(fullpath_libname));
437 std::copy(dsofiles.begin(), dsofiles.end(), std::back_inserter(
m_dsofiles));
443std::vector<std::string>
446 fs::path p(libname_);
448 const std::string libname = ::getlibname(
to_string(p.filename()));
449 std::set<std::string> caps;
452 for (std::size_t i = 0,
imax = 2; i <
imax; ++i) {
454 for (DsoMap_t::const_iterator idb =
db->begin(), iend=
db->end();
457 for (Libs_t::const_iterator ilib = idb->second.begin(),
458 ilibend = idb->second.end();
462 if (
to_string(lib.filename()) == libname) {
463 caps.insert(idb->first);
469 return std::vector<std::string>(caps.begin(), caps.end());
477 const std::string basename_lib =
to_string(fs::path(libname).filename());
478 std::vector<std::string> caps = this->
capabilities(libname);
481 for (std::size_t i = 0,
imax = 2; i <
imax; ++i) {
483 this->
get_dups(dup_db, *dbs[i], pedantic);
484 for (DsoMap_t::const_iterator
485 idb = dup_db.begin(),
486 idbend = dup_db.end();
489 if (std::find(caps.begin(), caps.end(), idb->first) != caps.end()) {
490 for (Libs_t::const_iterator
491 ilib = idb->second.begin(),
492 ilibend=idb->second.end();
498 dups[idb->first].push_back(*ilib);
530 std::set<std::string>
libs;
533 for (std::size_t i = 0,
imax = 2; i <
imax; ++i) {
535 for (DsoMap_t::const_iterator idb =
db.begin(), iend=
db.end();
538 for (Libs_t::const_iterator
539 ilib = idb->second.begin(),
540 ilibend=idb->second.end();
563 for (std::size_t i = 0,
imax = 2; i <
imax; ++i) {
565 for (DsoMap_t::const_iterator idb = d.begin(), idbend=d.end();
569 db[idb->first] = idb->second;
572 std::set<std::string> baselibs;
573 for (Libs_t::const_iterator
574 ilib = idb->second.begin(),
575 ilibend= idb->second.end();
578 const std::string baselib =
to_string(fs::path(*ilib).filename());
579 if (baselibs.find(baselib) == baselibs.end()) {
580 libs.push_back(*ilib);
581 baselibs.insert(std::move(baselib));
584 db[idb->first] = std::move(
libs);
596 for (DsoMap_t::const_iterator idb =
db.begin(), iend =
db.end();
599 if (idb->second.size() == 1) {
606 std::unordered_set<std::string> baselibs;
607 for (Libs_t::const_iterator
608 ilib = idb->second.begin(),
609 ilend= idb->second.end();
614 if (! baselibs.emplace (
to_string(p.filename())) . second) {
616 libs.push_back(*ilib);
620 if (
libs.size() > 1) {
621 dups[idb->first] = std::move(
libs);
630 const std::string rootmap_name = ::to_rootmap_name(type_name);
631 const std::string rflx_name = ::to_rflx_name(type_name);
639 if (s_cxx_builtins().
find(type_name) != s_cxx_builtins().end()) {
643 if (!this->has_type(rootmap_name)) {
644#ifdef ATH_DSODB_VERBOSE
645 std::cerr <<
"DsoDb **error**: no such type [" << rootmap_name <<
"]"
646 <<
" in rootmap files\n";
650 DsoMap_t::const_iterator
idb = m_db.find(rootmap_name);
651 if (idb == m_db.end()) {
653 idb = m_pf.find(rootmap_name);
654 if (idb == m_pf.end()) {
658 const Libs_t&
libs =
idb->second;
660#ifdef ATH_DSODB_VERBOSE
661 std::cerr <<
"DsoDb **error**: no library hosting [" << type_name <<
"]\n";
666 System::ImageHandle handle;
668 boost::algorithm::trim(libname);
669 if (libname.starts_with(SHLIB_PREFIX)) {
670 libname = libname.substr(SHLIB_PREFIX.size(), std::string::npos);
672 if (libname.ends_with(SHLIB_SUFFIX)) {
673 libname.resize(libname.size() - SHLIB_SUFFIX.size());
676 unsigned long err = System::loadDynamicLib( libname, &handle );
678 std::cerr <<
"DsoDb **error**: could not load library ["
679 <<
libs[0] <<
"] (" << System::getLastErrorString()
#define ATLAS_NOT_THREAD_SAFE
getNoisyStrip() Find noisy strips from hitmaps and write out into xml/db formats
DsoMap_t pf_duplicates(bool pedantic=false) const
table of plugin-factories-duplicates: {type: [lib1, lib2, ...]}
DsoMap_t m_db
repository of components
std::vector< std::string > Libs_t
Libs_t libs(bool detailed=false) const
list of all libraries we know about
std::vector< std::string > m_dsofiles
list of dsofiles
std::unordered_map< std::string, Libs_t > DsoMap_t
void build_repository()
initialize the repository of dso file names
DsoDb()
Default constructor:
std::vector< std::string > capabilities(const std::string &libname) const
list of reflex-types associated with a library name
bool has_type(const std::string &type_name) const
void get_dups(DsoMap_t &dups, const DsoMap_t &db, bool pedantic) const
get the duplicates for a given repository of components
const DsoMap_t & db() const
repository of components
static const DsoDb * instance()
factory for the DsoDb
DsoMap_t dict_duplicates(bool pedantic=false) const
table of dict-duplicates: {type: [lib1, lib2, ...]}
DsoMap_t m_pf
repository of plugin factories
DsoMap_t content(bool pedantic) const
return the table {type: [lib1, ...]} - concatenation of all dict-entries and plugin-factories entries...
DsoMap_t duplicates(const std::string &libname, bool pedantic=false) const
list of libraries hosting duplicate reflex-types
std::string find(const std::string &s)
return a remapped string
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
std::string basename(std::string name)