CMS 3D CMS Logo

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