CMS 3D CMS Logo

ExpressionEvaluator.cc
Go to the documentation of this file.
5 
6 #include "popenCPP.h"
7 
8 #include <fstream>
9 #include <regex>
10 #include <dlfcn.h>
11 
12 // #define VI_DEBUG
13 
14 #ifdef VI_DEBUG
15 #include <iostream>
16 #define COUT std::cout
17 #else
18 #define COUT LogDebug("ExpressionEvaluator")
19 #endif
20 
21 using namespace reco::exprEvalDetails;
22 
23 namespace {
24  std::string generateName() {
25  auto n1 = execSysCommand("uuidgen | sed 's/-//g'");
26  n1.pop_back();
27  return n1;
28  }
29 
30  void remove(std::string const& name, std::string const& tmpDir = "/tmp") {
31  std::string sfile = tmpDir + "/" + name + ".cc";
32  std::string ofile = tmpDir + "/" + name + ".so";
33 
34  std::string rm = "rm -f ";
35  rm += sfile + ' ' + ofile;
36 
37  system(rm.c_str());
38  }
39 
40 } // namespace
41 
42 namespace reco {
43 
44  ExpressionEvaluator::ExpressionEvaluator(const char* pkg, const char* iname, std::string const& iexpr)
45  : m_name("VI_" + generateName()) {
46  std::string pch = pkg;
47  pch += "/src/precompile.h";
48  std::string quote("\"");
49 
50  auto arch = edm::getEnvironmentVariable("SCRAM_ARCH");
51  auto baseDir = edm::getEnvironmentVariable("CMSSW_BASE");
52  auto relDir = edm::getEnvironmentVariable("CMSSW_RELEASE_BASE");
53 
54  std::string sfile = baseDir + "/tmp/" + m_name + ".cc";
55  std::string ofile = baseDir + "/tmp/" + m_name + ".so";
56 
57  std::string incDir = "/include/" + arch + "/";
58  std::string cxxf;
59  {
60  // look in local dir
61  std::string file = baseDir + incDir + pch + ".cxxflags";
62  std::ifstream ss(file.c_str());
63  COUT << "local file: " << file << std::endl;
64  if (ss) {
65  std::getline(ss, cxxf);
66  incDir = baseDir + incDir;
67  } else {
68  // look in release area
69  std::string file = relDir + incDir + pch + ".cxxflags";
70  COUT << "file in release area: " << file << std::endl;
71  std::ifstream ss(file.c_str());
72  if (ss) {
73  std::getline(ss, cxxf);
74  incDir = relDir + incDir;
75  } else {
76  // look in release is a patch area
77  auto paDir = edm::getEnvironmentVariable("CMSSW_FULL_RELEASE_BASE");
78  if (paDir.empty())
79  throw cms::Exception("ExpressionEvaluator", "error in opening patch area for " + baseDir);
80  std::string file = paDir + incDir + pch + ".cxxflags";
81  COUT << "file in base release area: " << file << std::endl;
82  std::ifstream ss(file.c_str());
83  if (!ss)
84  throw cms::Exception(
85  "ExpressionEvaluator",
86  pch + " file not found neither in " + baseDir + " nor in " + relDir + " nor in " + paDir);
87  std::getline(ss, cxxf);
88  incDir = paDir + incDir;
89  }
90  }
91 
92  {
93  std::regex rq("-I[^ ]+");
94  cxxf = std::regex_replace(cxxf, rq, std::string(""));
95  }
96  {
97  std::regex rq("=\"");
98  cxxf = std::regex_replace(cxxf, rq, std::string("='\""));
99  }
100  {
101  std::regex rq("\" ");
102  cxxf = std::regex_replace(cxxf, rq, std::string("\"' "));
103  }
104  COUT << '|' << cxxf << "|\n" << std::endl;
105  }
106 
107  std::string cpp = "c++ -H -Wall -shared -Winvalid-pch ";
108  cpp += cxxf;
109  cpp += " -I" + incDir;
110  cpp += " -o " + ofile + ' ' + sfile + " 2>&1\n";
111 
112  COUT << cpp << std::endl;
113 
114  // prepare the file to compile
115  std::string factory = "factory" + m_name;
116 
117  std::string source = std::string("#include ") + quote + pch + quote + "\n";
118  source += "struct " + m_name + " final : public " + iname + "{\n";
119  source += iexpr;
120  source += "\n};\n";
121 
122  source += "extern " + quote + 'C' + quote + ' ' + std::string(iname) + "* " + factory + "() {\n";
123  source += "static " + m_name + " local;\n";
124  source += "return &local;\n}\n";
125 
126  COUT << source << std::endl;
127 
128  {
129  std::ofstream tmp(sfile.c_str());
130  tmp << source << std::endl;
131  }
132 
133  // compile
134  auto ss = execSysCommand(cpp);
135  COUT << ss << std::endl;
136 
137  void* dl = dlopen(ofile.c_str(), RTLD_LAZY);
138  if (!dl) {
139  remove(m_name, baseDir + "/tmp");
140  throw cms::Exception("ExpressionEvaluator",
141  std::string("compilation/linking failed\n") + cpp + ss + "dlerror " + dlerror());
142  return;
143  }
144 
145  m_expr = dlsym(dl, factory.c_str());
146  remove(m_name, baseDir + "/tmp");
147  }
148 
150 
151 } // namespace reco
def rm(path, rec=False)
Definition: eostools.py:363
std::string execSysCommand(const std::string &cmdline)
Definition: popenCPP.h:12
Definition: pkg.py:1
ExpressionEvaluator(const char *pkg, const char *iname, const std::string &iexpr)
#define COUT
fixed size matrix
tmp
align.sh
Definition: createJobs.py:716
static std::string const source
Definition: EdmProvDump.cc:49
std::string getEnvironmentVariable(std::string const &name, std::string const &defaultValue=std::string())