File indexing completed on 2023-03-17 11:03:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include "FWCore/Utilities/interface/ConvertException.h"
0028 #include "FWCore/Utilities/interface/Exception.h"
0029 #include "FWCore/Utilities/interface/TimeOfDay.h"
0030 #include "FWCore/PluginManager/interface/PluginManager.h"
0031 #include "FWCore/PluginManager/interface/standard.h"
0032 #include "FWCore/Utilities/interface/FileInPath.h"
0033 #include "FWCore/ParameterSet/interface/ParameterSetDescriptionFillerPluginFactory.h"
0034 #include "FWCore/Utilities/interface/Algorithms.h"
0035 #include "FWCore/PluginManager/interface/PluginInfo.h"
0036 #include "FWCore/ParameterSet/interface/ParameterSetDescriptionFillerBase.h"
0037 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0038 #include "FWCore/PluginManager/interface/SharedLibrary.h"
0039 #include "FWCore/PluginManager/interface/PluginFactoryBase.h"
0040 #include "FWCore/PluginManager/interface/PluginFactoryManager.h"
0041
0042 #include <boost/program_options.hpp>
0043
0044 #include <set>
0045 #include <string>
0046 #include <iostream>
0047 #include <vector>
0048 #include <exception>
0049 #include <filesystem>
0050 #include <functional>
0051 #include <memory>
0052 #include <utility>
0053 #include "FWCore/Utilities/interface/Signal.h"
0054 #include <sstream>
0055
0056 static char const* const kHelpOpt = "help";
0057 static char const* const kHelpCommandOpt = "help,h";
0058 static char const* const kLibraryOpt = "library";
0059 static char const* const kLibraryCommandOpt = "library,l";
0060 static char const* const kPathOpt = "path";
0061 static char const* const kPathCommandOpt = "path,p";
0062 static char const* const kPluginOpt = "plugin";
0063 static char const* const kPluginCommandOpt = "plugin,x";
0064
0065 namespace {
0066 void getMatchingPluginNames(edmplugin::PluginInfo const& pluginInfo,
0067 std::vector<std::string>& pluginNames,
0068 std::string& previousName,
0069 std::string const& library) {
0070
0071
0072
0073
0074 if (pluginInfo.name_ == previousName)
0075 return;
0076 previousName = pluginInfo.name_;
0077
0078
0079 if (pluginInfo.loadable_.filename() == library) {
0080 pluginNames.push_back(pluginInfo.name_);
0081 }
0082 }
0083
0084 void writeCfisForPlugin(std::string const& pluginName,
0085 edm::ParameterSetDescriptionFillerPluginFactory* factory,
0086 std::set<std::string>& usedCfiFileNames) {
0087 std::unique_ptr<edm::ParameterSetDescriptionFillerBase> filler(factory->create(pluginName));
0088
0089 std::string baseType = filler->baseType();
0090
0091 edm::ConfigurationDescriptions descriptions(filler->baseType(), pluginName);
0092
0093 try {
0094 edm::convertException::wrap([&]() { filler->fill(descriptions); });
0095 } catch (cms::Exception& e) {
0096 std::ostringstream ost;
0097 ost << "Filling ParameterSetDescriptions for module of base type " << baseType << " with plugin name \'"
0098 << pluginName << "\'";
0099 e.addContext(ost.str());
0100 throw;
0101 }
0102
0103 try {
0104 edm::convertException::wrap([&]() { descriptions.writeCfis(usedCfiFileNames); });
0105 } catch (cms::Exception& e) {
0106 std::ostringstream ost;
0107 ost << "Writing cfi files using ParameterSetDescriptions for module of base type " << baseType
0108 << " with plugin name \'" << pluginName << "\'";
0109 e.addContext(ost.str());
0110 throw;
0111 }
0112 }
0113
0114 struct Listener {
0115 typedef std::pair<std::string, std::string> NameAndType;
0116 typedef std::vector<NameAndType> NameAndTypes;
0117
0118 void newFactory(edmplugin::PluginFactoryBase const* iBase) {
0119 using std::placeholders::_1;
0120 using std::placeholders::_2;
0121 iBase->newPluginAdded_.connect(std::bind(std::mem_fn(&Listener::newPlugin), this, _1, _2));
0122 }
0123 void newPlugin(std::string const& iCategory, edmplugin::PluginInfo const& iInfo) {
0124 nameAndTypes_.push_back(NameAndType(iInfo.name_, iCategory));
0125 }
0126 NameAndTypes nameAndTypes_;
0127 };
0128
0129 void getPluginsMatchingCategory(Listener::NameAndType const& nameAndType,
0130 std::vector<std::string>& pluginNames,
0131 std::string const& category) {
0132 if (category == nameAndType.second) {
0133 pluginNames.push_back(nameAndType.first);
0134 }
0135 }
0136 }
0137
0138 int main(int argc, char** argv) try {
0139 edm::FileInPath::disableFileLookup();
0140
0141 using std::placeholders::_1;
0142 std::filesystem::path initialWorkingDirectory = std::filesystem::current_path();
0143
0144
0145 std::string descString(argv[0]);
0146 descString += " [options] [[--";
0147 descString += kLibraryOpt;
0148 descString += "] library_filename]\n\n";
0149 descString += "Generates and writes configuration files that have the suffix _cfi.py.\n";
0150 descString += "One configuration file is written for each configuration defined with a\n";
0151 descString += "module label in the fillDescriptions functions of the plugins in the library.\n";
0152 descString += "Silently does nothing if the library is not in the edmplugincache, does not\n";
0153 descString += "exist at all, or the plugins in the library have not defined any configurations.\n";
0154 descString += "Instead of specifying a library, there is also an option to specify a plugin.\n\n";
0155 descString += "Allowed options";
0156 boost::program_options::options_description desc(descString);
0157
0158
0159 desc.add_options()(kHelpCommandOpt, "produce help message")(
0160 kLibraryCommandOpt, boost::program_options::value<std::string>(), "library filename")(
0161 kPathCommandOpt,
0162 "When this option is set, the library filename "
0163 "is interpreted as a relative or absolute path. If there are no directories in "
0164 "the library filename, then it looks for the library file in the current directory. "
0165 "Fails with an error message if the path does not lead to a library file that exists "
0166 "or can be loaded. "
0167 "If this option is not set, then the library filename should only be "
0168 "a filename without any directories. In that case, it is assumed "
0169 "the build system has already put the library file in the "
0170 "appropriate place, built the edmplugincache, and the PluginManager "
0171 "is used to find and load the library.")(
0172 kPluginCommandOpt,
0173 boost::program_options::value<std::string>(),
0174 "plugin name. You must specify either a library or plugin, but not both.");
0175
0176
0177 boost::program_options::positional_options_description p;
0178 p.add(kLibraryOpt, -1);
0179
0180 boost::program_options::variables_map vm;
0181 try {
0182 store(boost::program_options::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
0183 notify(vm);
0184 } catch (boost::program_options::error const& iException) {
0185 std::cerr << "Exception from command line processing: " << iException.what() << "\n";
0186 std::cerr << desc << std::endl;
0187 return 1;
0188 }
0189
0190 if (vm.count(kHelpOpt)) {
0191 std::cout << desc << std::endl;
0192 return 0;
0193 }
0194
0195 std::string library;
0196 std::string requestedPlugin;
0197
0198 try {
0199 edm::convertException::wrap([&]() {
0200 if (vm.count(kLibraryOpt) && vm.count(kPluginOpt)) {
0201 throw cms::Exception("Command Line Arguments")
0202 << "Both library and plugin specified. You must specify one or the other, but not both.";
0203 }
0204 if (vm.count(kLibraryOpt)) {
0205 library = vm[kLibraryOpt].as<std::string>();
0206 } else if (vm.count(kPluginOpt)) {
0207 requestedPlugin = vm[kPluginOpt].as<std::string>();
0208 } else {
0209 throw cms::Exception("Command Line Arguments")
0210 << "No library or plugin specified. You must specify one or the other (but not both).";
0211 }
0212
0213 edm::ParameterSetDescriptionFillerPluginFactory* factory;
0214 std::vector<std::string> pluginNames;
0215
0216 if (vm.count(kPluginOpt)) {
0217 edmplugin::PluginManager::configure(edmplugin::standard::config());
0218 factory = edm::ParameterSetDescriptionFillerPluginFactory::get();
0219 pluginNames.push_back(requestedPlugin);
0220 }
0221
0222 else if (!vm.count(kPathOpt)) {
0223
0224
0225
0226 edmplugin::PluginManager::configure(edmplugin::standard::config());
0227 typedef edmplugin::PluginManager::CategoryToInfos CatToInfos;
0228 CatToInfos const& catToInfos = edmplugin::PluginManager::get()->categoryToInfos();
0229 factory = edm::ParameterSetDescriptionFillerPluginFactory::get();
0230 CatToInfos::const_iterator itPlugins = catToInfos.find(factory->category());
0231
0232
0233 if (itPlugins == catToInfos.end())
0234 return;
0235
0236 std::vector<edmplugin::PluginInfo> const& infos = itPlugins->second;
0237 std::string previousName;
0238
0239 edm::for_all(
0240 infos,
0241 std::bind(&getMatchingPluginNames, _1, std::ref(pluginNames), std::ref(previousName), std::cref(library)));
0242
0243 } else {
0244
0245
0246 Listener listener;
0247 edmplugin::PluginFactoryManager* pfm = edmplugin::PluginFactoryManager::get();
0248 pfm->newFactory_.connect(std::bind(std::mem_fn(&Listener::newFactory), &listener, _1));
0249 edm::for_all(*pfm, std::bind(std::mem_fn(&Listener::newFactory), &listener, _1));
0250
0251 std::filesystem::path loadableFile(library);
0252
0253
0254
0255
0256
0257
0258
0259
0260 if (loadableFile.filename() == loadableFile.string()) {
0261 loadableFile = initialWorkingDirectory / loadableFile;
0262 }
0263
0264
0265
0266 try {
0267 edmplugin::SharedLibrary lib(loadableFile);
0268 } catch (cms::Exception const& iException) {
0269 if (iException.category() == "PluginLibraryLoadError") {
0270 std::cerr << "error: edmWriteConfigs caught an exception while loading a plugin library.\n"
0271 << "The executable will return success (0) so scram will continue,\n"
0272 << "but no cfi files will be written.\n"
0273 << iException.what() << std::endl;
0274 return;
0275 } else {
0276 throw;
0277 }
0278 }
0279
0280
0281
0282 factory = edm::ParameterSetDescriptionFillerPluginFactory::get();
0283
0284 edm::for_all(listener.nameAndTypes_,
0285 std::bind(&getPluginsMatchingCategory, _1, std::ref(pluginNames), std::cref(factory->category())));
0286 }
0287
0288 std::set<std::string> usedCfiFileNames;
0289 edm::for_all(pluginNames, std::bind(&writeCfisForPlugin, _1, factory, std::ref(usedCfiFileNames)));
0290 });
0291 } catch (cms::Exception& iException) {
0292 if (!library.empty()) {
0293 std::ostringstream ost;
0294 ost << "Processing library " << library;
0295 iException.addContext(ost.str());
0296 }
0297 iException.addContext("Running executable \"edmWriteConfigs\"");
0298 std::cerr << "----- Begin Fatal Exception " << std::setprecision(0) << edm::TimeOfDay()
0299 << "-----------------------\n"
0300 << iException.explainSelf()
0301 << "----- End Fatal Exception -------------------------------------------------" << std::endl;
0302 return 1;
0303 }
0304 return 0;
0305 } catch (cms::Exception const& e) {
0306 std::cerr << e.explainSelf() << std::endl;
0307 return 1;
0308 } catch (std::exception const& e) {
0309 std::cerr << e.what() << std::endl;
0310 return 1;
0311 }