CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
abstract_c_compiler.hpp
1 #ifndef CPPAD_CG_ABSTRACT_C_COMPILER_INCLUDED
2 #define CPPAD_CG_ABSTRACT_C_COMPILER_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2012 Ciengis
6  * Copyright (C) 2018 Joao Leal
7  *
8  * CppADCodeGen is distributed under multiple licenses:
9  *
10  * - Eclipse Public License Version 1.0 (EPL1), and
11  * - GNU General Public License Version 3 (GPL3).
12  *
13  * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
14  * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
15  * ----------------------------------------------------------------------------
16  * Author: Joao Leal
17  */
18 
19 namespace CppAD {
20 namespace cg {
21 
28 template<class Base>
29 class AbstractCCompiler : public CCompiler<Base> {
30 protected:
31  std::string _path; // the path to the gcc executable
32  std::string _tmpFolder;
33  std::string _sourcesFolder; // path where source files are saved
34  std::set<std::string> _ofiles; // compiled object files
35  std::set<std::string> _sfiles; // compiled source files
36  std::vector<std::string> _compileFlags;
37  std::vector<std::string> _compileLibFlags;
38  std::vector<std::string> _linkFlags;
39  bool _verbose;
40  bool _saveToDiskFirst;
41 public:
42 
43  AbstractCCompiler(const std::string& compilerPath) :
44  _path(compilerPath),
45  _tmpFolder("cppadcg_tmp"),
46  _sourcesFolder("cppadcg_sources"),
47  _verbose(false),
48  _saveToDiskFirst(false) {
49  }
50 
51  AbstractCCompiler(const AbstractCCompiler& orig) = delete;
52  AbstractCCompiler& operator=(const AbstractCCompiler& rhs) = delete;
53 
54  std::string getCompilerPath() const {
55  return _path;
56  }
57 
58  void setCompilerPath(const std::string& path) {
59  _path = path;
60  }
61 
62  const std::string& getTemporaryFolder() const override {
63  return _tmpFolder;
64  }
65 
66  void setTemporaryFolder(const std::string& tmpFolder) override {
67  _tmpFolder = tmpFolder;
68  }
69 
70  bool isSaveToDiskFirst() const override {
71  return _saveToDiskFirst;
72  }
73 
74  void setSaveToDiskFirst(bool saveToDiskFirst) override {
75  _saveToDiskFirst = saveToDiskFirst;
76  }
77 
78  const std::string& getSourcesFolder() const override {
79  return _sourcesFolder;
80  }
81 
82  void setSourcesFolder(const std::string& srcFolder) override {
83  _sourcesFolder = srcFolder;
84  }
85 
86  const std::set<std::string>& getObjectFiles() const override {
87  return _ofiles;
88  }
89 
90  const std::set<std::string>& getSourceFiles() const override {
91  return _sfiles;
92  }
93 
94  const std::vector<std::string>& getCompileFlags() const {
95  return _compileFlags;
96  }
97 
98  void setCompileFlags(const std::vector<std::string>& compileFlags) {
99  _compileFlags = compileFlags;
100  }
101 
102  void addCompileFlag(const std::string& compileFlag) {
103  _compileFlags.push_back(compileFlag);
104  }
105 
106  const std::vector<std::string>& getLinkFlags() const {
107  return _linkFlags;
108  }
109 
110  void setLinkFlags(const std::vector<std::string>& linkFlags) {
111  _linkFlags = linkFlags;
112  }
113 
114  void addLinkFlag(const std::string& linkFlag) {
115  _linkFlags.push_back(linkFlag);
116  }
117 
118  const std::vector<std::string>& getCompileLibFlags() const {
119  return _compileLibFlags;
120  }
121 
122  void setCompileLibFlags(const std::vector<std::string>& compileLibFlags) {
123  _compileLibFlags = compileLibFlags;
124  }
125 
126  void addCompileLibFlag(const std::string& compileLibFlag) {
127  _compileLibFlags.push_back(compileLibFlag);
128  }
129 
130  bool isVerbose() const override {
131  return _verbose;
132  }
133 
134  void setVerbose(bool verbose) override {
135  _verbose = verbose;
136  }
137 
146  void compileSources(const std::map<std::string, std::string>& sources,
147  bool posIndepCode,
148  JobTimer* timer = nullptr) override {
149  compileSources(sources, posIndepCode, timer, ".o", _ofiles);
150  }
151 
152  virtual void compileSources(const std::map<std::string, std::string>& sources,
153  bool posIndepCode,
154  JobTimer* timer,
155  const std::string& outputExtension,
156  std::set<std::string>& outputFiles) {
157  using namespace std::chrono;
158 
159  if (sources.empty())
160  return; // nothing to do
161 
162  system::createFolder(this->_tmpFolder);
163 
164  // determine the maximum file name length
165  size_t maxsize = 0;
166  std::map<std::string, std::string>::const_iterator it;
167  for (it = sources.begin(); it != sources.end(); ++it) {
168  _sfiles.insert(it->first);
169  std::string file = system::createPath(this->_tmpFolder, it->first + outputExtension);
170  maxsize = std::max<size_t>(maxsize, file.size());
171  }
172 
173  size_t countWidth = std::ceil(std::log10(sources.size()));
174 
175  size_t count = 0;
176  if (timer != nullptr) {
177  size_t ms = 3 + 2 * countWidth + 1 + JobTypeHolder<>::COMPILING.getActionName().size() + 2 + maxsize + 5;
178  ms += timer->getJobCount() * 2;
179  if (timer->getMaxLineWidth() < ms)
180  timer->setMaxLineWidth(ms);
181  } else if (_verbose) {
182  std::cout << std::endl;
183  }
184 
185  std::ostringstream os;
186 
187  if (_saveToDiskFirst) {
188  system::createFolder(_sourcesFolder);
189  }
190 
191  // compile each source code file into a different object file
192  for (it = sources.begin(); it != sources.end(); ++it) {
193  count++;
194  std::string file = system::createPath(this->_tmpFolder, it->first + outputExtension);
195  outputFiles.insert(file);
196 
197  steady_clock::time_point beginTime;
198 
199  if (timer != nullptr || _verbose) {
200  os << "[" << std::setw(countWidth) << std::setfill(' ') << std::right << count
201  << "/" << sources.size() << "]";
202  }
203 
204  if (timer != nullptr) {
205  timer->startingJob("'" + file + "'", JobTypeHolder<>::COMPILING, os.str());
206  os.str("");
207  } else if (_verbose) {
208  beginTime = steady_clock::now();
209  char f = std::cout.fill();
210  std::cout << os.str() << " compiling "
211  << std::setw(maxsize + 9) << std::setfill('.') << std::left
212  << ("'" + file + "' ") << " ";
213  os.str("");
214  std::cout.flush();
215  std::cout.fill(f); // restore fill character
216  }
217 
218  if (_saveToDiskFirst) {
219  // save a new source file to disk
220  std::ofstream sourceFile;
221  std::string srcfile = system::createPath(_sourcesFolder, it->first);
222  sourceFile.open(srcfile.c_str());
223  sourceFile << it->second;
224  sourceFile.close();
225 
226  // compile the file
227  compileFile(srcfile, file, posIndepCode);
228  } else {
229  // compile without saving the source code to disk
230  compileSource(it->second, file, posIndepCode);
231  }
232 
233  if (timer != nullptr) {
234  timer->finishedJob();
235  } else if (_verbose) {
236  steady_clock::time_point endTime = steady_clock::now();
237  duration<float> dt = endTime - beginTime;
238  std::cout << "done [" << std::fixed << std::setprecision(3)
239  << dt.count() << "]" << std::endl;
240  }
241 
242  }
243 
244  }
245 
251  virtual void buildDynamic(const std::string& library,
252  JobTimer* timer = nullptr) override = 0;
253 
254  void cleanup() override {
255  // clean up;
256  for (const std::string& it : _ofiles) {
257  if (remove(it.c_str()) != 0)
258  std::cerr << "Failed to delete temporary file '" << it << "'" << std::endl;
259  }
260  _ofiles.clear();
261  _sfiles.clear();
262 
263  remove(this->_tmpFolder.c_str());
264  }
265 
266  virtual ~AbstractCCompiler() {
267  cleanup();
268  }
269 
270 protected:
271 
278  virtual void compileSource(const std::string& source,
279  const std::string& output,
280  bool posIndepCode) = 0;
281 
288  virtual void compileFile(const std::string& path,
289  const std::string& output,
290  bool posIndepCode) = 0;
291 };
292 
293 } // END cg namespace
294 } // END CppAD namespace
295 
296 #endif
void setSourcesFolder(const std::string &srcFolder) override
void compileSources(const std::map< std::string, std::string > &sources, bool posIndepCode, JobTimer *timer=nullptr) override
std::string createPath(const std::string &baseFolder, const std::string &file)
virtual void compileFile(const std::string &path, const std::string &output, bool posIndepCode)=0
virtual void compileSource(const std::string &source, const std::string &output, bool posIndepCode)=0
virtual void buildDynamic(const std::string &library, JobTimer *timer=nullptr) override=0
size_t getJobCount() const
Definition: job_timer.hpp:248
const std::string & getSourcesFolder() const override
const std::string & getTemporaryFolder() const override
void createFolder(const std::string &folder)
void setTemporaryFolder(const std::string &tmpFolder) override