The Gaudi Framework  master (37c0b60a)
listcomponents.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 2013-2024 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 
13 
14 #include <cstdlib>
15 #include <fstream>
16 #include <iostream>
17 #include <list>
18 #include <memory>
19 #include <string>
20 
21 #include <dlfcn.h>
22 #include <getopt.h>
23 
24 #define GAUDI_PLUGIN_SERVICE_V2
26 #include <Gaudi/PluginServiceV1.h>
27 
28 void help( const std::string& argv0 ) {
29  std::cout << "Usage: " << argv0
30  << " [option] library1 [library2 ...]\n"
31  "\n list the component factories present in the given libraries\n\n"
32  "Options:\n\n"
33  " -h, --help show this help message and exit\n"
34  " -o OUTPUT, --output OUTPUT\n"
35  " write the list of factories on the file OUTPUT, use - for\n"
36  " standard output (default)\n"
37  << std::endl;
38 }
39 
40 void usage( const std::string& argv0 ) {
41  std::cout << "Usage: " << argv0
42  << " [option] library1 [library2 ...]\n"
43  "Try `"
44  << argv0 << " -h' for more information.\n"
45  << std::endl;
46 }
47 
48 int main( int argc, char* argv[] ) {
49  auto& reg2 = Gaudi::PluginService::v2::Details::Registry::instance();
51 
52  using key_type = Gaudi::PluginService::v2::Details::Registry::KeyType;
53 
54  // cache to keep track of the loaded factories
56  // initialize the local cache
57  for ( const auto& name : reg2.loadedFactoryNames() ) loaded.emplace( name, "<preloaded>" );
58  for ( const auto& name : reg1.loadedFactoryNames() ) loaded.emplace( name, "<preloaded>" );
59 
60  // Parse command line
61  std::list<char*> libs;
62  std::string output_opt( "-" );
63  {
64  std::string argv0( argv[0] );
65  {
66  auto i = argv0.rfind( '/' );
67  if ( i != std::string::npos ) argv0 = argv0.substr( i + 1 );
68  }
69 
70  int i = 1;
71  while ( i < argc ) {
72  const std::string arg( argv[i] );
73  if ( arg == "-o" || arg == "--output" ) {
74  if ( ++i < argc ) {
75  output_opt = argv[i];
76  } else {
77  std::cerr << "ERROR: missing argument for option " << arg << std::endl;
78  std::cerr << "See `" << argv0 << " -h' for more details." << std::endl;
79  return EXIT_FAILURE;
80  }
81  } else if ( arg == "-h" || arg == "--help" ) {
82  help( argv0 );
83  return EXIT_SUCCESS;
84  } else {
85  libs.push_back( argv[i] );
86  }
87  ++i;
88  }
89  if ( libs.empty() ) {
90  usage( argv0 );
91  return EXIT_FAILURE;
92  }
93  }
94 
95  // handle output option
97  if ( output_opt != "-" ) { output_file.reset( new std::ofstream{ output_opt } ); }
98  std::ostream& output = ( output_file ? *output_file : std::cout );
99 
100  auto dump_from = [&output, &loaded]( const auto& reg, const char* lib, const char* prefix ) {
101  for ( const auto& factoryName : reg.loadedFactoryNames() ) {
102  // Skip if the component does not come from the same library we are processing
103  // (i.e. we found a symbol that is coming from a library loaded by the linker).
104  const auto& info = reg.factories().find( factoryName )->second;
105  if ( lib != info.library && !info.library.empty() && info.library != "unknown" ) {
106  std::cerr << "WARNING: library [" << lib << "] exposes factory [" << factoryName << "] which is declared in ["
107  << info.library << "] !!" << std::endl;
108  continue;
109  }
110  auto f = loaded.find( factoryName );
111  if ( f == loaded.end() ) {
112  output << prefix << "::" << lib << ":" << factoryName << std::endl;
113  loaded.emplace( factoryName, lib );
114  } else
115  std::cerr << "WARNING: factory '" << factoryName << "' already found in " << f->second << std::endl;
116  }
117  };
118 
119  // loop over the list of libraries passed on the command line
120  for ( const char* lib : libs ) {
121  if ( dlopen( lib, RTLD_LAZY | RTLD_LOCAL ) ) {
122  dump_from( reg2, lib, "v2" );
123  dump_from( reg1, lib, "v1" );
124  } else {
125  std::cerr << "ERROR: failed to load " << lib << ": " << dlerror() << std::endl;
126  return EXIT_FAILURE;
127  }
128  }
129  return EXIT_SUCCESS;
130 }
std::string
STL class.
std::list
STL class.
plotBacklogPyRoot.argc
argc
Definition: plotBacklogPyRoot.py:173
std::map::find
T find(T... args)
std::map::emplace
T emplace(T... args)
gaudirun.prefix
string prefix
Definition: gaudirun.py:361
gaudirun.output
output
Definition: gaudirun.py:521
help
void help(const std::string &argv0)
Definition: listcomponents.cpp:28
std::unique_ptr::reset
T reset(T... args)
Gaudi::PluginService::v1::Details::Registry::instance
static Registry & instance()
Retrieve the singleton instance of Registry.
Definition: PluginServiceV1.cpp:133
std::list::push_back
T push_back(T... args)
PluginService.h
main
int main(int argc, char *argv[])
Definition: listcomponents.cpp:48
std::cout
std::ofstream
STL class.
std::map
STL class.
std::string::substr
T substr(T... args)
ConditionsStallTest.name
name
Definition: ConditionsStallTest.py:77
std::endl
T endl(T... args)
PluginServiceV1.h
usage
void usage(const std::string &argv0)
Definition: listcomponents.cpp:40
std::list::empty
T empty(T... args)
std::map::end
T end(T... args)
std::unique_ptr
STL class.
std::string::rfind
T rfind(T... args)
gaudirun.argv
list argv
Definition: gaudirun.py:327