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