CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
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
19namespace CppAD {
20namespace cg {
21
28template<class Base>
29class AbstractCCompiler : public CCompiler<Base> {
30protected:
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;
41public:
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
270protected:
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
virtual void compileSource(const std::string &source, const std::string &output, bool posIndepCode)=0
void compileSources(const std::map< std::string, std::string > &sources, bool posIndepCode, JobTimer *timer=nullptr) override
const std::string & getTemporaryFolder() const override
virtual void buildDynamic(const std::string &library, JobTimer *timer=nullptr) override=0
const std::string & getSourcesFolder() const override
void setTemporaryFolder(const std::string &tmpFolder) override
virtual void compileFile(const std::string &path, const std::string &output, bool posIndepCode)=0
void setSourcesFolder(const std::string &srcFolder) override
size_t getJobCount() const
std::string createPath(const std::string &baseFolder, const std::string &file)
void createFolder(const std::string &folder)