The Gaudi Framework  master (82fdf313)
Loading...
Searching...
No Matches
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
25#include <Gaudi/PluginService.h>
27
28void 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
40void 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
48int 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
55 std::map<key_type, std::string> loaded;
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
96 std::unique_ptr<std::ostream> output_file;
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}
int main()
static Registry & instance()
Retrieve the singleton instance of Registry.
void usage(const std::string &argv0)
void help(const std::string &argv0)