File indexing completed on 2024-04-06 12:01:19
0001 #include "CommonTools/Utils/interface/ExpressionEvaluator.h"
0002 #include "FWCore/Utilities/interface/GetEnvironmentVariable.h"
0003 #include "FWCore/Utilities/interface/Exception.h"
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005
0006 #include "popenCPP.h"
0007
0008 #include <fstream>
0009 #include <regex>
0010 #include <dlfcn.h>
0011
0012
0013
0014 #ifdef VI_DEBUG
0015 #include <iostream>
0016 #define COUT std::cout
0017 #else
0018 #define COUT LogDebug("ExpressionEvaluator")
0019 #endif
0020
0021 using namespace reco::exprEvalDetails;
0022
0023 namespace {
0024 std::string generateName() {
0025 auto n1 = execSysCommand("uuidgen | sed 's/-//g'");
0026 n1.pop_back();
0027 return n1;
0028 }
0029
0030 void remove(std::string const& name, std::string const& tmpDir = "/tmp") {
0031 std::string sfile = tmpDir + "/" + name + ".cc";
0032 std::string ofile = tmpDir + "/" + name + ".so";
0033
0034 std::string rm = "rm -f ";
0035 rm += sfile + ' ' + ofile;
0036
0037 system(rm.c_str());
0038 }
0039
0040 }
0041
0042 namespace reco {
0043
0044 ExpressionEvaluator::ExpressionEvaluator(const char* pkg, const char* iname, std::string const& iexpr)
0045 : m_name("VI_" + generateName()) {
0046 std::string pch = pkg;
0047 pch += "/src/precompile.h";
0048 std::string quote("\"");
0049
0050 auto arch = edm::getEnvironmentVariable("SCRAM_ARCH");
0051 auto baseDir = edm::getEnvironmentVariable("CMSSW_BASE");
0052 auto relDir = edm::getEnvironmentVariable("CMSSW_RELEASE_BASE");
0053
0054 std::string sfile = baseDir + "/tmp/" + m_name + ".cc";
0055 std::string ofile = baseDir + "/tmp/" + m_name + ".so";
0056
0057 std::string incDir = "/include/" + arch + "/";
0058 std::string cxxf;
0059 {
0060
0061 std::string file = baseDir + incDir + pch + ".cxxflags";
0062 std::ifstream ss(file.c_str());
0063 COUT << "local file: " << file << std::endl;
0064 if (ss) {
0065 std::getline(ss, cxxf);
0066 incDir = baseDir + incDir;
0067 } else {
0068
0069 std::string file = relDir + incDir + pch + ".cxxflags";
0070 COUT << "file in release area: " << file << std::endl;
0071 std::ifstream ss(file.c_str());
0072 if (ss) {
0073 std::getline(ss, cxxf);
0074 incDir = relDir + incDir;
0075 } else {
0076
0077 auto paDir = edm::getEnvironmentVariable("CMSSW_FULL_RELEASE_BASE");
0078 if (paDir.empty())
0079 throw cms::Exception("ExpressionEvaluator", "error in opening patch area for " + baseDir);
0080 std::string file = paDir + incDir + pch + ".cxxflags";
0081 COUT << "file in base release area: " << file << std::endl;
0082 std::ifstream ss(file.c_str());
0083 if (!ss)
0084 throw cms::Exception(
0085 "ExpressionEvaluator",
0086 pch + " file not found neither in " + baseDir + " nor in " + relDir + " nor in " + paDir);
0087 std::getline(ss, cxxf);
0088 incDir = paDir + incDir;
0089 }
0090 }
0091
0092 {
0093 std::regex rq("-I[^ ]+");
0094 cxxf = std::regex_replace(cxxf, rq, std::string(""));
0095 }
0096 {
0097 std::regex rq("=\"");
0098 cxxf = std::regex_replace(cxxf, rq, std::string("='\""));
0099 }
0100 {
0101 std::regex rq("\" ");
0102 cxxf = std::regex_replace(cxxf, rq, std::string("\"' "));
0103 }
0104 COUT << '|' << cxxf << "|\n" << std::endl;
0105 }
0106
0107 std::string cpp = "c++ -H -Wall -shared -Winvalid-pch ";
0108 cpp += cxxf;
0109 cpp += " -I" + incDir;
0110 cpp += " -o " + ofile + ' ' + sfile + " 2>&1\n";
0111
0112 COUT << cpp << std::endl;
0113
0114
0115 std::string factory = "factory" + m_name;
0116
0117 std::string source = std::string("#include ") + quote + pch + quote + "\n";
0118 source += "struct " + m_name + " final : public " + iname + "{\n";
0119 source += iexpr;
0120 source += "\n};\n";
0121
0122 source += "extern " + quote + 'C' + quote + ' ' + std::string(iname) + "* " + factory + "() {\n";
0123 source += "static " + m_name + " local;\n";
0124 source += "return &local;\n}\n";
0125
0126 COUT << source << std::endl;
0127
0128 {
0129 std::ofstream tmp(sfile.c_str());
0130 tmp << source << std::endl;
0131 }
0132
0133
0134 auto ss = execSysCommand(cpp);
0135 COUT << ss << std::endl;
0136
0137 void* dl = dlopen(ofile.c_str(), RTLD_LAZY);
0138 if (!dl) {
0139 remove(m_name, baseDir + "/tmp");
0140 throw cms::Exception("ExpressionEvaluator",
0141 std::string("compilation/linking failed\n") + cpp + ss + "dlerror " + dlerror());
0142 return;
0143 }
0144
0145 m_expr = dlsym(dl, factory.c_str());
0146 remove(m_name, baseDir + "/tmp");
0147 }
0148
0149 ExpressionEvaluator::~ExpressionEvaluator() { remove(m_name, edm::getEnvironmentVariable("CMSSW_BASE") + "/tmp"); }
0150
0151 }