Newer
Older
Markus Frank
committed
/*****************************************************************************\
* (c) Copyright 2013 CERN *
* *
* This software is distributed under the terms of the GNU General Public *
* Licence version 3 (GPL Version 3), copied verbatim in the file "LICENCE". *
* *
* In applying this licence, CERN does not waive the privileges and immunities *
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\*****************************************************************************/
/// @author Marco Clemencic <marco.clemencic@cern.ch>
#include <cstdlib>
Markus Frank
committed
#include <fstream>
#include <iostream>
Markus Frank
committed
#include <list>
#include <memory>
#include <set>
#include <string>
Markus Frank
committed
#include <dlfcn.h>
#include <getopt.h>
Markus Frank
committed
#define GAUDI_PLUGIN_SERVICE_V2
Markus Frank
committed
#include <Gaudi/PluginService.h>
#include <Gaudi/PluginServiceV1.h>
void help( std::string argv0 ) {
std::cout << "Usage: " << argv0
<< " [option] library1 [library2 ...]\n"
"\n list the component factories present in the given libraries\n\n"
"Options:\n\n"
" -h, --help show this help message and exit\n"
" -o OUTPUT, --output OUTPUT\n"
" write the list of factories on the file OUTPUT, use - for\n"
" standard output (default)\n"
<< std::endl;
Markus Frank
committed
}
void usage( std::string argv0 ) {
std::cout << "Usage: " << argv0
<< " [option] library1 [library2 ...]\n"
"Try `"
<< argv0 << " -h' for more information.\n"
<< std::endl;
Markus Frank
committed
}
int main( int argc, char* argv[] ) {
auto& reg2 = Gaudi::PluginService::v2::Details::Registry::instance();
auto& reg1 = Gaudi::PluginService::v1::Details::Registry::instance();
using key_type = Gaudi::PluginService::v2::Details::Registry::KeyType;
Markus Frank
committed
// cache to keep track of the loaded factories
std::map<key_type, std::string> loaded;
// initialize the local cache
for ( const auto& name : reg2.loadedFactoryNames() ) loaded.emplace( name, "<preloaded>" );
for ( const auto& name : reg1.loadedFactoryNames() ) loaded.emplace( name, "<preloaded>" );
Markus Frank
committed
// Parse command line
std::list<char*> libs;
std::string output_opt( "-" );
Markus Frank
committed
{
std::string argv0( argv[0] );
Markus Frank
committed
{
auto i = argv0.rfind( '/' );
if ( i != std::string::npos ) argv0 = argv0.substr( i + 1 );
Markus Frank
committed
}
int i = 1;
while ( i < argc ) {
const std::string arg( argv[i] );
if ( arg == "-o" || arg == "--output" ) {
if ( ++i < argc ) {
Markus Frank
committed
output_opt = argv[i];
} else {
std::cerr << "ERROR: missing argument for option " << arg << std::endl;
std::cerr << "See `" << argv0 << " -h' for more details." << std::endl;
return EXIT_FAILURE;
}
} else if ( arg == "-h" || arg == "--help" ) {
help( argv0 );
Markus Frank
committed
return EXIT_SUCCESS;
} else {
libs.push_back( argv[i] );
Markus Frank
committed
}
++i;
}
if ( libs.empty() ) {
usage( argv0 );
Markus Frank
committed
return EXIT_FAILURE;
}
}
// handle output option
std::unique_ptr<std::ostream> output_file;
if ( output_opt != "-" ) { output_file.reset( new std::ofstream{output_opt} ); }
std::ostream& output = ( output_file ? *output_file : std::cout );
auto dump_from = [&output, &loaded]( auto& reg, const char* lib, const char* prefix ) {
for ( const auto& factoryName : reg.loadedFactoryNames() ) {
auto f = loaded.find( factoryName );
if ( f == loaded.end() ) {
output << prefix << "::" << lib << ":" << factoryName << std::endl;
loaded.emplace( factoryName, lib );
} else
std::cerr << "WARNING: factory '" << factoryName << "' already found in " << f->second << std::endl;
}
};
Markus Frank
committed
// loop over the list of libraries passed on the command line
Andre Sailer
committed
for ( const char* aLib : libs ) {
if ( dlopen( aLib, RTLD_LAZY | RTLD_LOCAL ) ) {
dump_from( reg2, aLib, "v2" );
dump_from( reg1, aLib, "v1" );
Markus Frank
committed
} else {
Andre Sailer
committed
std::cerr << "ERROR: failed to load " << aLib << ": " << dlerror() << std::endl;
Markus Frank
committed
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}