CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
clang_compiler.hpp
1#ifndef CPPAD_CG_CLANG_COMPILER_INCLUDED
2#define CPPAD_CG_CLANG_COMPILER_INCLUDED
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2014 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
27template<class Base>
28class ClangCompiler : public AbstractCCompiler<Base> {
29protected:
30 std::set<std::string> _bcfiles; // bitcode files
31 std::string _version;
32public:
33
34 ClangCompiler(const std::string& clangPath = "/usr/bin/clang") :
35 AbstractCCompiler<Base>(clangPath) {
36
37 this->_compileFlags.push_back("-O2"); // Optimization level
38 this->_compileLibFlags.push_back("-O2"); // Optimization level
39 this->_compileLibFlags.push_back("-shared"); // Make shared object
40 this->_compileLibFlags.push_back("-rdynamic"); // add all symbols to the dynamic symbol table
41 }
42
43 ClangCompiler(const ClangCompiler& orig) = delete;
44 ClangCompiler& operator=(const ClangCompiler& rhs) = delete;
45
46 const std::string& getVersion() {
47 if(_version.empty()) {
48 std::vector<std::string> args {"--version"};
49 std::string output;
50 system::callExecutable(this->_path, args, &output);
51
52 std::string vv = "version ";
53 size_t is = output.find(vv);
54 if(is == std::string::npos) {
55 throw CGException("Failed to determine Clang version");
56 }
57 is += vv.size();
58 size_t i = is;
59 while (i < output.size() && output[i] != ' ' && output[i] != '\n') {
60 i++;
61 }
62
63 _version = output.substr(is, i - is);
64 }
65 return _version;
66 }
67
68 virtual const std::set<std::string>& getBitCodeFiles() const {
69 return _bcfiles;
70 }
71
72 virtual void generateLLVMBitCode(const std::map<std::string, std::string>& sources,
73 JobTimer* timer = nullptr) {
74 bool posIndepCode = false;
75 this->_compileFlags.push_back("-emit-llvm");
76 try {
77 this->compileSources(sources, posIndepCode, timer, ".bc", this->_bcfiles);
78 } catch (...) {
79 this->_compileFlags.pop_back();
80 throw;
81 }
82 }
83
89 void buildDynamic(const std::string& library,
90 JobTimer* timer = nullptr) override {
91
92#if CPPAD_CG_SYSTEM_APPLE
93 std::string linkerName = "-install_name";
94#elif CPPAD_CG_SYSTEM_LINUX
95 std::string linkerName = "-soname";
96#endif
97 std::string linkerFlags = "-Wl," + linkerName + "," + system::filenameFromPath(library);
98 for (size_t i = 0; i < this->_linkFlags.size(); i++)
99 linkerFlags += "," + this->_linkFlags[i];
100
101 std::vector<std::string> args;
102 args.insert(args.end(), this->_compileLibFlags.begin(), this->_compileLibFlags.end());
103 args.push_back(linkerFlags); // Pass suitable options to linker
104 args.push_back("-o"); // Output file name
105 args.push_back(library); // Output file name
106
107 for (const std::string& it : this->_ofiles) {
108 args.push_back(it);
109 }
110
111 if (timer != nullptr) {
112 timer->startingJob("'" + library + "'", JobTimer::COMPILING_DYNAMIC_LIBRARY);
113 } else if (this->_verbose) {
114 std::cout << "building library '" << library << "'" << std::endl;
115 }
116
117 system::callExecutable(this->_path, args);
118
119 if (timer != nullptr) {
120 timer->finishedJob();
121 }
122 }
123
124 void cleanup() override {
125 // clean up
126 for (const std::string& it : _bcfiles) {
127 if (remove(it.c_str()) != 0)
128 std::cerr << "Failed to delete temporary file '" << it << "'" << std::endl;
129 }
130 _bcfiles.clear();
131
132 // other files and temporary folder
134 }
135
136 virtual ~ClangCompiler() {
137 cleanup();
138 }
139
140 static std::vector<std::string> parseVersion(const std::string& version) {
141 auto vv = explode(version, ".");
142 if (vv.size() > 2) {
143 auto vv2 = explode(vv[2], "-");
144 if (vv2.size() > 1) {
145 vv.erase(vv.begin() + 2);
146 vv.insert(vv.begin() + 2, vv2.begin(), vv2.end());
147 }
148 }
149 return vv;
150 }
151
152protected:
153
161 void compileSource(const std::string& source,
162 const std::string& output,
163 bool posIndepCode) override {
164 std::vector<std::string> args;
165 args.push_back("-x");
166 args.push_back("c"); // C source files
167 args.insert(args.end(), this->_compileFlags.begin(), this->_compileFlags.end());
168 args.push_back("-c");
169 args.push_back("-");
170 if (posIndepCode) {
171 args.push_back("-fPIC"); // position-independent code for dynamic linking
172 }
173 args.push_back("-o");
174 args.push_back(output);
175
176 system::callExecutable(this->_path, args, nullptr, &source);
177 }
178
179 void compileFile(const std::string& path,
180 const std::string& output,
181 bool posIndepCode) override {
182 std::vector<std::string> args;
183 args.push_back("-x");
184 args.push_back("c"); // C source files
185 args.insert(args.end(), this->_compileFlags.begin(), this->_compileFlags.end());
186 if (posIndepCode) {
187 args.push_back("-fPIC"); // position-independent code for dynamic linking
188 }
189 args.push_back("-c");
190 args.push_back(path);
191 args.push_back("-o");
192 args.push_back(output);
193
194 system::callExecutable(this->_path, args);
195 }
196
197};
198
199} // END cg namespace
200} // END CppAD namespace
201
202#endif
void compileSources(const std::map< std::string, std::string > &sources, bool posIndepCode, JobTimer *timer=nullptr) override
void compileSource(const std::string &source, const std::string &output, bool posIndepCode) override
void compileFile(const std::string &path, const std::string &output, bool posIndepCode) override
void buildDynamic(const std::string &library, JobTimer *timer=nullptr) override
void callExecutable(const std::string &executable, const std::vector< std::string > &args, std::string *stdOutErrMessage=nullptr, const std::string *stdInMessage=nullptr)