Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:03:19

0001 // -*- C++ -*-
0002 //
0003 // Package:     ParameterSet
0004 // Class  :     edmPluginHelp
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Original Author:  Chris Jones, W. David Dagenhart
0010 //         Created:  Thu Aug  2 13:33:53 EDT 2007
0011 //
0012 
0013 #include "FWCore/PluginManager/interface/PluginInfo.h"
0014 #include "FWCore/ParameterSet/interface/ParameterSetDescriptionFillerPluginFactory.h"
0015 #include "FWCore/ParameterSet/interface/ParameterSetDescriptionFillerBase.h"
0016 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0017 #include "FWCore/ParameterSet/interface/validateTopLevelParameterSets.h"
0018 #include "FWCore/ParameterSet/interface/DocFormatHelper.h"
0019 
0020 #include "FWCore/Utilities/interface/Exception.h"
0021 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0022 #include "FWCore/PluginManager/interface/PluginManager.h"
0023 #include "FWCore/PluginManager/interface/standard.h"
0024 #include "FWCore/Utilities/interface/Algorithms.h"
0025 
0026 #include <boost/program_options.hpp>
0027 
0028 #include <vector>
0029 #include <string>
0030 #include <iostream>
0031 #include <iomanip>
0032 #include <memory>
0033 #include <sys/ioctl.h>
0034 #include <unistd.h>
0035 #include <map>
0036 #include <exception>
0037 #include <utility>
0038 
0039 static char const* const kHelpOpt = "help";
0040 static char const* const kHelpCommandOpt = "help,h";
0041 static char const* const kPluginOpt = "plugin";
0042 static char const* const kPluginCommandOpt = "plugin,p";
0043 static char const* const kLibraryOpt = "library";
0044 static char const* const kLibraryCommandOpt = "library,l";
0045 static char const* const kAllLibrariesOpt = "allLibraries";
0046 static char const* const kAllLibrariesCommandOpt = "allLibraries,a";
0047 static char const* const kModuleLabelOpt = "moduleLabel";
0048 static char const* const kModuleLabelCommandOpt = "moduleLabel,m";
0049 static char const* const kBriefOpt = "brief";
0050 static char const* const kBriefCommandOpt = "brief,b";
0051 static char const* const kPrintOnlyLabelsOpt = "printOnlyLabels";
0052 static char const* const kPrintOnlyLabelsCommandOpt = "printOnlyLabels,o";
0053 static char const* const kPrintOnlyPluginsOpt = "printOnlyPlugins";
0054 static char const* const kPrintOnlyPluginsCommandOpt = "printOnlyPlugins,q";
0055 static char const* const kLineWidthOpt = "lineWidth";
0056 static char const* const kLineWidthCommandOpt = "lineWidth,w";
0057 static char const* const kTopLevelOpt = "topLevel";
0058 static char const* const kTopLevelCommandOpt = "topLevel,t";
0059 
0060 namespace {
0061 
0062   void getMatchingPlugins(edmplugin::PluginInfo const& pluginInfo,
0063                           std::vector<edmplugin::PluginInfo>& matchingInfos,
0064                           std::string& previousName,
0065                           std::string const& library,
0066                           std::string const& plugin) {
0067     // We do not want duplicate plugin names and
0068     // can safely assume the calls to this function
0069     // occur with the pluginInfo argument sorted by
0070     // pluginName
0071     if (pluginInfo.name_ == previousName)
0072       return;
0073     previousName = pluginInfo.name_;
0074 
0075     if (!library.empty() && pluginInfo.loadable_.filename() != library) {
0076       return;
0077     }
0078 
0079     if (!plugin.empty() && pluginInfo.name_ != plugin) {
0080       return;
0081     }
0082 
0083     matchingInfos.push_back(pluginInfo);
0084   }
0085 
0086   // -------------------------------------------------------------------
0087 
0088   void writeDocForPlugin(edmplugin::PluginInfo const& pluginInfo,
0089                          edm::ParameterSetDescriptionFillerPluginFactory* factory,
0090                          std::string const& moduleLabel,
0091                          bool brief,
0092                          bool printOnlyLabels,
0093                          bool printOnlyPlugins,
0094                          unsigned lineWidth,
0095                          int& iPlugin) {
0096     // Define the output stream for all output
0097     std::ostream& os = std::cout;
0098     std::ios::fmtflags oldFlags = os.flags();
0099 
0100     ++iPlugin;
0101 
0102     std::unique_ptr<edm::ParameterSetDescriptionFillerBase> filler;
0103 
0104     try {
0105       filler = std::unique_ptr<edm::ParameterSetDescriptionFillerBase>{factory->create(pluginInfo.name_)};
0106     } catch (cms::Exception& e) {
0107       os << "\nSTART ERROR FROM edmPluginHelp\n";
0108       os << "The executable \"edmPluginHelp\" encountered a problem while creating a\n"
0109             "ParameterSetDescriptionFiller, probably related to loading a plugin.\n"
0110             "This plugin is being skipped.  Here is the info from the exception:\n"
0111          << e.what() << std::endl;
0112       os << "END ERROR FROM edmPluginHelp\n\n";
0113       return;
0114     }
0115 
0116     std::string const& baseType =
0117         (filler->extendedBaseType().empty() ? filler->baseType() : filler->extendedBaseType());
0118 
0119     if (printOnlyPlugins) {
0120       os << std::setfill(' ');
0121       os << std::left;
0122       if (iPlugin == 1) {
0123         os << std::setw(6) << ""
0124            << " ";
0125         os << std::setw(50) << "Plugin Name";
0126         os << std::setw(24) << "Plugin Type";
0127         os << "Library Name"
0128            << "\n";
0129         os << std::setw(6) << ""
0130            << " ";
0131         os << std::setw(50) << "-----------";
0132         os << std::setw(24) << "-----------";
0133         os << "------------"
0134            << "\n";
0135       }
0136       os << std::setw(6) << iPlugin << " ";
0137       os << std::setw(50) << pluginInfo.name_;
0138       os << std::setw(24) << baseType;
0139       os << pluginInfo.loadable_.filename() << "\n";
0140       os.flags(oldFlags);
0141       return;
0142     }
0143 
0144     os << std::left << iPlugin << "  " << pluginInfo.name_ << "  (" << baseType << ")  "
0145        << pluginInfo.loadable_.filename() << "\n";
0146     os.flags(oldFlags);
0147 
0148     edm::ConfigurationDescriptions descriptions(filler->baseType(), pluginInfo.name_);
0149 
0150     try {
0151       filler->fill(descriptions);
0152     } catch (cms::Exception& e) {
0153       os << "\nSTART ERROR FROM edmPluginHelp\n";
0154       os << "The executable \"edmPluginHelp\" encountered a problem while filling a\n"
0155             "ParameterSetDescription.  We give up for this plugin and skip printing out\n"
0156             "this description and any following descriptions for this plugin.  Here\n"
0157             "is the info from the exception:\n"
0158          << e.what() << std::endl;
0159       os << "END ERROR FROM edmPluginHelp\n\n";
0160       return;
0161     }
0162 
0163     try {
0164       int indentation = 0;
0165       descriptions.print(os, moduleLabel, brief, printOnlyLabels, lineWidth, indentation, iPlugin);
0166     } catch (cms::Exception& e) {
0167       os << "\nSTART ERROR FROM edmPluginHelp\n";
0168       os << "The executable \"edmPluginHelp\" encountered a problem while printing out a\n"
0169             "ParameterSetDescription.  We give up for this plugin and skip printing out\n"
0170             "this description and any following descriptions for this plugin.  Here\n"
0171             "is the info from the exception:\n"
0172          << e.what() << std::endl;
0173       os << "END ERROR FROM edmPluginHelp\n\n";
0174       return;
0175     }
0176   }
0177 
0178   void printTopLevelParameterSets(bool brief, size_t lineWidth, std::string const& psetName) {
0179     std::ostream& os = std::cout;
0180 
0181     edm::ParameterSetDescription description;
0182 
0183     if (psetName == "options") {
0184       os << "\nDescription of \'options\' top level ParameterSet\n\n";
0185       edm::fillOptionsDescription(description);
0186 
0187     } else if (psetName == "maxEvents") {
0188       os << "\nDescription of \'maxEvents\' top level ParameterSet\n\n";
0189       edm::fillMaxEventsDescription(description);
0190 
0191     } else if (psetName == "maxLuminosityBlocks") {
0192       os << "\nDescription of \'maxLuminosityBlocks\' top level ParameterSet\n\n";
0193       edm::fillMaxLuminosityBlocksDescription(description);
0194 
0195     } else if (psetName == "maxSecondsUntilRampdown") {
0196       os << "\nDescription of \'maxSecondsUntilRampdown\' top level ParameterSet\n\n";
0197       edm::fillMaxSecondsUntilRampdownDescription(description);
0198     } else {
0199       throw cms::Exception("CommandLineArgument")
0200           << "Unrecognized name for top level parameter set. "
0201           << "Allowed values are 'options', 'maxEvents', 'maxLuminosityBlocks', and 'maxSecondsUntilRampdown'";
0202     }
0203 
0204     edm::DocFormatHelper dfh;
0205     dfh.setBrief(brief);
0206     dfh.setLineWidth(lineWidth);
0207     dfh.setSection("1");
0208 
0209     description.print(os, dfh);
0210     os << "\n";
0211   }
0212 }  // namespace
0213 // ---------------------------------------------------------------------------------
0214 
0215 int main(int argc, char** argv) try {
0216   // Process the command line arguments
0217   std::string descString(argv[0]);
0218   descString += " option [options]\n\n";
0219   descString += "Prints descriptions of the allowed/required parameters used to\n";
0220   descString += "configure plugins. Output is ordered by plugin name. Within a\n";
0221   descString += "plugin, the labels and parameters are ordered based on the order\n";
0222   descString += "declared by the plugin. Formatted as follows:\n\n";
0223   descString += "PluginName (PluginType) Library\n";
0224   descString += "  ModuleLabel\n";
0225   descString += "    Details of parameters corresponding to this module label\n\n";
0226   descString += "For more information about the output format see:\n";
0227   descString += "https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideConfigurationValidationAndHelp\n\n";
0228 
0229   descString += "At least one of the following options must be used: -p, -l, -a, -q, or -t\n\n";
0230   descString += "Allowed options:";
0231   boost::program_options::options_description desc(descString);
0232 
0233   // clang-format off
0234   desc.add_options()(kHelpCommandOpt, "produce help message")(
0235       kPluginCommandOpt, boost::program_options::value<std::string>(), "only print descriptions for this plugin")(
0236       kLibraryCommandOpt,
0237       boost::program_options::value<std::string>(),
0238       "only print descriptions for plugins in this library")(
0239       kAllLibrariesCommandOpt,
0240       "allows the program to run without selecting a plugin or library. "
0241       "This will take a significant amount of time.")(kModuleLabelCommandOpt,
0242                                                       boost::program_options::value<std::string>(),
0243                                                       "only print descriptions for this module label")(
0244       kBriefCommandOpt,
0245       "do not print comments, more compact format, suppress text"
0246       " added to help the user understand what the output means")(
0247       kPrintOnlyLabelsCommandOpt,
0248       "do not print parameter descriptions, just list module labels matching selection criteria")(
0249       kPrintOnlyPluginsCommandOpt,
0250       "do not print parameter descriptions or module labels, just list plugins matching selection criteria")(
0251       kLineWidthCommandOpt,
0252       boost::program_options::value<unsigned>(),
0253       "try to limit lines to this length by inserting newlines between words in comments. Long words or names can "
0254       "cause the line length to exceed this limit. Defaults to terminal screen width or 80")(
0255       kTopLevelCommandOpt,
0256       boost::program_options::value<std::string>(),
0257       "print only the description for the top level parameter set with this name. Allowed names are 'options', "
0258       "'maxEvents', 'maxLuminosityBlocks', and 'maxSecondsUntilRampdown'.");
0259   // clang-format on
0260 
0261   boost::program_options::variables_map vm;
0262   try {
0263     store(boost::program_options::command_line_parser(argc, argv).options(desc).run(), vm);
0264     notify(vm);
0265   } catch (boost::program_options::error const& iException) {
0266     std::cerr << "Exception from command line processing: " << iException.what() << "\n";
0267     std::cerr << desc << std::endl;
0268     return 1;
0269   }
0270 
0271   if (vm.count(kHelpOpt)) {
0272     std::cout << desc << std::endl;
0273     return 0;
0274   }
0275 
0276   std::string plugin;
0277   std::string library;
0278   std::string moduleLabel;
0279   bool brief = false;
0280   bool printOnlyLabels = false;
0281   bool printOnlyPlugins = false;
0282   std::string printOnlyTopLevel;
0283 
0284   if (vm.count(kPluginOpt)) {
0285     plugin = vm[kPluginOpt].as<std::string>();
0286   }
0287   if (vm.count(kLibraryOpt)) {
0288     library = vm[kLibraryOpt].as<std::string>();
0289   }
0290   if (!vm.count(kAllLibrariesOpt)) {
0291     if (!vm.count(kPluginOpt) && !vm.count(kLibraryOpt) && !vm.count(kPrintOnlyPluginsOpt) && !vm.count(kTopLevelOpt)) {
0292       std::cerr << "\nERROR: At least one of the following options must be used: -p, -l, -a, -q, or -t\n\n";
0293       std::cerr << desc << std::endl;
0294       return 1;
0295     }
0296   }
0297   if (vm.count(kModuleLabelOpt)) {
0298     moduleLabel = vm[kModuleLabelOpt].as<std::string>();
0299   }
0300   if (vm.count(kBriefOpt)) {
0301     brief = true;
0302   }
0303   if (vm.count(kPrintOnlyLabelsOpt)) {
0304     printOnlyLabels = true;
0305   }
0306   if (vm.count(kPrintOnlyPluginsOpt)) {
0307     printOnlyPlugins = true;
0308   }
0309 
0310   unsigned lineWidth = 80U;
0311 
0312   // This next little bit of code was sent to me.  It gets the number
0313   // of characters per line that show up on the display terminal in
0314   // use.  It is not standard C++ code and I do not understand sys/ioctl.h
0315   // very well.  From what I got via google, it should work on any UNIX platform,
0316   // which as far as I know is all we need to support.  If this code causes
0317   // problems, then deleting it and just having the default be 80 should
0318   // work fine.  Or someone could add the appropriate #ifdef for the
0319   // OS/platform/compiler where this fails.
0320 
0321   if (isatty(2)) {
0322 #ifdef TIOCGWINSZ
0323     {
0324       struct winsize w;
0325       if (ioctl(2, TIOCGWINSZ, &w) == 0) {
0326         if (w.ws_col > 0)
0327           lineWidth = w.ws_col;
0328       }
0329     }
0330 #else
0331 #ifdef WIOCGETD
0332     {
0333       struct uwdata w;
0334       if (ioctl(2, WIOCGETD, &w) == 0) {
0335         if (w.uw_width > 0)
0336           lineWidth = w.uw_width / w.uw_hs;
0337       }
0338     }
0339 #endif
0340 #endif
0341   }
0342 
0343   if (vm.count(kLineWidthOpt)) {
0344     lineWidth = vm[kLineWidthOpt].as<unsigned>();
0345   }
0346 
0347   if (vm.count(kTopLevelOpt)) {
0348     printOnlyTopLevel = vm[kTopLevelOpt].as<std::string>();
0349     printTopLevelParameterSets(brief, lineWidth, printOnlyTopLevel);
0350     return 0;
0351   }
0352 
0353   // Get the list of plugins from the plugin cache
0354 
0355   edm::ParameterSetDescriptionFillerPluginFactory* factory;
0356   std::vector<edmplugin::PluginInfo> infos;
0357 
0358   try {
0359     edmplugin::PluginManager::configure(edmplugin::standard::config());
0360     typedef edmplugin::PluginManager::CategoryToInfos CatToInfos;
0361     CatToInfos const& catToInfos = edmplugin::PluginManager::get()->categoryToInfos();
0362     factory = edm::ParameterSetDescriptionFillerPluginFactory::get();
0363 
0364     CatToInfos::const_iterator itPlugins = catToInfos.find(factory->category());
0365     if (itPlugins == catToInfos.end()) {
0366       return 0;
0367     }
0368     infos = itPlugins->second;
0369 
0370   } catch (cms::Exception& e) {
0371     std::cerr << "The executable \"edmPluginHelp\" failed while retrieving the list of parameter description plugins "
0372                  "from the cache.\n"
0373               << "The following problem occurred:\n"
0374               << e.what() << std::endl;
0375     return 1;
0376   } catch (const std::exception& e) {
0377     std::cerr << "The executable \"edmPluginHelp\" failed while retrieving the list of parameter description plugins "
0378                  "from the cache.\n"
0379               << "The following problem occurred:\n"
0380               << e.what() << std::endl;
0381     return 1;
0382   }
0383 
0384   // Select the plugins that match the library and plugin names if
0385   // any are specified in the command line arguments
0386 
0387   std::vector<edmplugin::PluginInfo> matchingInfos;
0388 
0389   try {
0390     std::string previousName;
0391 
0392     edm::for_all(infos,
0393                  std::bind(&getMatchingPlugins,
0394                            std::placeholders::_1,
0395                            std::ref(matchingInfos),
0396                            std::ref(previousName),
0397                            std::cref(library),
0398                            std::cref(plugin)));
0399   } catch (cms::Exception& e) {
0400     std::cerr << "The executable \"edmPluginHelp\" failed while selecting plugins.\n"
0401               << "The following problem occurred:\n"
0402               << e.what() << std::endl;
0403     return 1;
0404   } catch (const std::exception& e) {
0405     std::cerr << "The executable \"edmPluginHelp\" failed while selecting plugins.\n"
0406               << "The following problem occurred:\n"
0407               << e.what() << std::endl;
0408     return 1;
0409   }
0410 
0411   // For each selected plugin, fill the ParameterSetDescription for all defined
0412   // module labels and then print out the details of the description.
0413   try {
0414     int iPlugin = 0;
0415 
0416     edm::for_all(matchingInfos,
0417                  std::bind(&writeDocForPlugin,
0418                            std::placeholders::_1,
0419                            factory,
0420                            std::cref(moduleLabel),
0421                            brief,
0422                            printOnlyLabels,
0423                            printOnlyPlugins,
0424                            lineWidth,
0425                            std::ref(iPlugin)));
0426   } catch (cms::Exception& e) {
0427     std::cerr << "\nThe executable \"edmPluginHelp\" failed. The following problem occurred:\n"
0428               << e.what() << std::endl;
0429     return 1;
0430   } catch (const std::exception& e) {
0431     std::cerr << "\nThe executable \"edmPluginHelp\" failed. The following problem occurred:\n"
0432               << e.what() << std::endl;
0433     return 1;
0434   }
0435 
0436   return 0;
0437 } catch (cms::Exception const& e) {
0438   std::cerr << e.explainSelf() << std::endl;
0439   return 1;
0440 } catch (std::exception const& e) {
0441   std::cerr << e.what() << std::endl;
0442   return 1;
0443 }