Logo ROOT  
Reference Guide
TModuleGenerator.cxx
Go to the documentation of this file.
1// @(#)root/utils:$Id$
2// Author: Axel Naumann, 2-13-07-02
3// Author: Danilo Piparo, 2013, 2014
4
5/*************************************************************************
6 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13////////////////////////////////////////////////////////////////////////////////
14//
15// PCM writer.
16//
17////////////////////////////////////////////////////////////////////////////////
18
19#include "TModuleGenerator.h"
20
21#include "TClingUtils.h"
22#include "RConfigure.h"
23#include <ROOT/RConfig.hxx>
24
25#include "cling/Interpreter/CIFactory.h"
26#include "clang/Basic/SourceManager.h"
27#include "clang/Frontend/CompilerInstance.h"
28#include "clang/Lex/HeaderSearch.h"
29#include "clang/Lex/Preprocessor.h"
30#include "llvm/Support/Path.h"
31
32#include <map>
33
34#ifndef R__WIN32
35#include <unistd.h>
36#endif
37
38#include <iostream>
39
40using namespace ROOT;
41using namespace clang;
42
43////////////////////////////////////////////////////////////////////////////////
44
45TModuleGenerator::TModuleGenerator(CompilerInstance *CI,
46 bool inlineInputHeaders,
47 const std::string &shLibFileName,
48 bool writeEmptyRootPCM):
49 fCI(CI),
50 fIsPCH(shLibFileName == "allDict.cxx"),
51 fIsInPCH(writeEmptyRootPCM),
52 fInlineInputHeaders(inlineInputHeaders),
53 fDictionaryName(llvm::sys::path::stem(shLibFileName)),
54 fDemangledDictionaryName(llvm::sys::path::stem(shLibFileName)),
55 fModuleDirName(llvm::sys::path::parent_path(shLibFileName)),
56 fErrorCount(0)
57{
58 // Need to resolve _where_ to create the pcm
59 // We default in the lib subdirectory
60 // otherwise we put it in the same directory as the dictionary file (for ACLiC)
61 if (fModuleDirName.empty()) {
62 fModuleDirName = "./";
63 } else {
64 fModuleDirName += "/";
65 }
66
68 + ROOT::TMetaUtils::GetModuleFileName(fDictionaryName.c_str());
69
70 // Clean the dictionary name from characters which are not accepted in C++
71 std::string tmpName = fDictionaryName;
72 fDictionaryName.clear();
73 ROOT::TMetaUtils::GetCppName(fDictionaryName, tmpName.c_str());
74
75 // .pcm -> .pch
76 if (IsPCH()) fModuleFileName[fModuleFileName.length() - 1] = 'h';
77
78 // Add a random string to the filename to avoid races
79 llvm::SmallString<10> resultPath("%%%%%%%%%%");
80 llvm::sys::fs::createUniqueFile(resultPath.str(), resultPath);
81 fUmbrellaName = fModuleDirName + fDictionaryName + resultPath.c_str() + "_dictUmbrella.h";
82 fContentName = fModuleDirName + fDictionaryName + resultPath.c_str() + "_dictContent.h";
83}
84
86{
87 unlink(fUmbrellaName.c_str());
88 unlink(fContentName.c_str());
89}
90
91////////////////////////////////////////////////////////////////////////////////
92/// Check whether the file's extension is compatible with C or C++.
93/// Return whether source, header, Linkdef or nothing.
94
96TModuleGenerator::GetSourceFileKind(const char *filename) const
97{
98 if (filename[0] == '-') return kSFKNotC;
99
100 if (ROOT::TMetaUtils::IsLinkdefFile(filename)) {
101 return kSFKLinkdef;
102 }
103
104 const size_t len = strlen(filename);
105 const char *ext = filename + len - 1;
106 while (ext >= filename && *ext != '.') --ext;
107 if (ext < filename || *ext != '.') {
108 // This might still be a system header, let's double check
109 // via the FileManager.
110 clang::Preprocessor &PP = fCI->getPreprocessor();
111 clang::HeaderSearch &HdrSearch = PP.getHeaderSearchInfo();
112 const clang::DirectoryLookup *CurDir = 0;
113 const clang::FileEntry *hdrFileEntry
114 = HdrSearch.LookupFile(filename, clang::SourceLocation(),
115 true /*isAngled*/, 0 /*FromDir*/, CurDir,
116 clang::ArrayRef<std::pair<const clang::FileEntry*,
117 const clang::DirectoryEntry*>>(),
118 0 /*IsMapped*/, 0 /*SearchPath*/, 0 /*RelativePath*/,
119 0 /*RequestingModule*/, 0/*SuggestedModule*/);
120 if (hdrFileEntry) {
121 return kSFKHeader;
122 }
123 return kSFKNotC;
124 }
125 ++ext;
126 const size_t lenExt = filename + len - ext;
127
129 switch (lenExt) {
130 case 1: {
131 const char last = toupper(filename[len - 1]);
132 if (last == 'H') ret = kSFKHeader;
133 else if (last == 'C') ret = kSFKSource;
134 break;
135 }
136 case 2: {
137 if (filename[len - 2] == 'h' && filename[len - 1] == 'h')
138 ret = kSFKHeader;
139 else if (filename[len - 2] == 'c' && filename[len - 1] == 'c')
140 ret = kSFKSource;
141 break;
142 }
143 case 3: {
144 const char last = filename[len - 1];
145 if ((last == 'x' || last == 'p')
146 && filename[len - 2] == last) {
147 if (filename[len - 3] == 'h') ret = kSFKHeader;
148 else if (filename[len - 3] == 'c') ret = kSFKSource;
149 }
150 }
151 } // switch extension length
152
153 return ret;
154}
155
156
157static
158std::pair<std::string, std::string> SplitPPDefine(const std::string &in)
159{
160 std::string::size_type posEq = in.find('=');
161 // No equal found: define to 1
162 if (posEq == std::string::npos)
163 return std::make_pair(in, "1");
164
165 // Equal found
166 return std::pair<std::string, std::string>
167 (in.substr(0, posEq), in.substr(posEq + 1, std::string::npos));
168}
169
170////////////////////////////////////////////////////////////////////////////////
171/// Parse -I -D -U headers.h SomethingLinkdef.h.
172
173void TModuleGenerator::ParseArgs(const std::vector<std::string> &args)
174{
175 for (size_t iPcmArg = 1 /*skip argv0*/, nPcmArg = args.size();
176 iPcmArg < nPcmArg; ++iPcmArg) {
177 ESourceFileKind sfk = GetSourceFileKind(args[iPcmArg].c_str());
178 if (sfk == kSFKHeader || sfk == kSFKSource) {
179 fHeaders.push_back(args[iPcmArg]);
180 } else if (sfk == kSFKLinkdef) {
181 fLinkDefFile = args[iPcmArg];
182 } else if (sfk == kSFKNotC && args[iPcmArg][0] == '-') {
183 switch (args[iPcmArg][1]) {
184 case 'I':
185 if (args[iPcmArg] != "-I." && args[iPcmArg] != "-Iinclude") {
186 fCompI.push_back(args[iPcmArg].c_str() + 2);
187 }
188 break;
189 case 'D':
190 if (args[iPcmArg] != "-DTRUE=1" && args[iPcmArg] != "-DFALSE=0"
191 && args[iPcmArg] != "-DG__NOCINTDLL") {
192 fCompD.push_back(SplitPPDefine(args[iPcmArg].c_str() + 2));
193 }
194 break;
195 case 'U':
196 fCompU.push_back(args[iPcmArg].c_str() + 2);
197 break;
198 }
199 }
200 }
201}
202
203////////////////////////////////////////////////////////////////////////////////
204/// Write
205/// #ifndef FOO
206/// # define FOO=bar
207/// #endif
208
209std::ostream &TModuleGenerator::WritePPDefines(std::ostream &out) const
210{
211 for (auto const & strPair : fCompD) {
212 std::string cppname(strPair.first);
213 size_t pos = cppname.find('(');
214 if (pos != std::string::npos) cppname.erase(pos);
215 out << "#ifndef " << cppname << "\n"
216 " #define " << strPair.first;
217 out << " " << strPair.second;
218 out << "\n"
219 "#endif\n";
220 }
221 out << std::endl;
222 return out;
223}
224
225////////////////////////////////////////////////////////////////////////////////
226/// Write
227/// #ifdef FOO
228/// # undef FOO
229/// #endif
230
231std::ostream &TModuleGenerator::WritePPUndefines(std::ostream &out) const
232{
233 for (auto const & undef : fCompU) {
234 out << "#ifdef " << undef << "\n"
235 " #undef " << undef << "\n"
236 "#endif\n";
237 }
238 out << std::endl;
239 return out;
240}
241
242////////////////////////////////////////////////////////////////////////////////
243/// To be replaced with proper pragma handlers.
244
245int WarnIfPragmaOnceDetected(const std::string& fullHeaderPath,
246 const std::string& headerFileContent)
247{
248 std::istringstream headerFile(headerFileContent);
249 std::string line;
250 while(std::getline(headerFile,line)){
251 llvm::StringRef lineRef (line);
252 auto trimmedLineRef = lineRef.trim();
253 if (trimmedLineRef.startswith("#pragma") &&
254 (trimmedLineRef.endswith(" once") || trimmedLineRef.endswith("\tonce"))) {
255 std::cerr << "Error: #pragma once directive detected in header file "
256 << fullHeaderPath
257 << " which was requested to be inlined.\n";
258 return 1;
259 }
260 }
261 return 0;
262}
263
264////////////////////////////////////////////////////////////////////////////////
265
266int ExtractBufferContent(const std::string& fullHeaderPath, std::string& bufferContent)
267{
268 std::ifstream buffer(fullHeaderPath);
269 bufferContent = std::string((std::istreambuf_iterator<char>(buffer)),
270 std::istreambuf_iterator<char>());
271
272 return WarnIfPragmaOnceDetected(fullHeaderPath,bufferContent);
273}
274
275////////////////////////////////////////////////////////////////////////////////
276/// Write
277/// #include "header1.h"
278/// #include "header2.h"
279/// or, if inlining of headers is requested, dump the content of the files.
280
281std::ostream &TModuleGenerator::WritePPIncludes(std::ostream &out) const
282{
283 std::string fullHeaderPath;
284 for (auto const & incl : fHeaders) {
286 bool headerFound = FindHeader(incl,fullHeaderPath);
287 if (!headerFound){
288 ROOT::TMetaUtils::Error(0, "Cannot find header %s: cannot inline it.\n", fullHeaderPath.c_str());
289 continue;
290 }
291
292 std::string bufferContent;
293 fErrorCount += ExtractBufferContent(fullHeaderPath, bufferContent);
294
295 out << bufferContent << std::endl;
296 } else {
297 out << "#include \"" << incl << "\"\n";
298 }
299 }
300 out << std::endl;
301 return out;
302}
303
304////////////////////////////////////////////////////////////////////////////////
305
306std::ostream &TModuleGenerator::WriteStringVec(const std::vector<std::string> &vec,
307 std::ostream &out) const
308{
309 for (auto const & theStr : vec) {
310 out << "\"" << theStr << "\",\n";
311 }
312 out << "0" << std::endl;
313 return out;
314}
315
316////////////////////////////////////////////////////////////////////////////////
317
319 std::ostream &out) const
320{
321 for (auto const & strPair : vec) {
322 out << "\"" << strPair.first;
323 if (!strPair.second.empty()) {
324 out << "=";
325 // Need to escape the embedded quotes.
326 for (const char *c = strPair.second.c_str(); *c != '\0'; ++c) {
327 if (*c == '"') {
328 out << "\\\"";
329 } else {
330 out << *c;
331 }
332 }
333 }
334 out << "\",\n";
335 }
336 out << "0" << std::endl;
337 return out;
338}
339
340
342 const std::string &dictName,
343 const std::string &demangledDictName,
344 const std::vector<std::string> &headerArray,
345 const std::vector<std::string> &includePathArray,
346 const std::string &fwdDeclStringRAW,
347 const std::string &fwdDeclnArgsToKeepString,
348 const std::string &payloadCodeWrapped,
349 const std::string &headersClassesMapString,
350 const std::string &extraIncludes,
351 bool hasCxxModule) const
352{
353 // Dictionary initialization code for loading the module
354 out << "namespace {\n"
355 " void TriggerDictionaryInitialization_" << dictName << "_Impl() {\n"
356 " static const char* headers[] = {\n";
357 WriteStringVec(headerArray, out) << " };\n";
358 out << " static const char* includePaths[] = {\n";
359 WriteStringVec(includePathArray, out)
360 << " };\n";
361
362 out << " static const char* fwdDeclCode = " << fwdDeclStringRAW << ";\n"
363 << " static const char* payloadCode = " << payloadCodeWrapped << ";\n";
364 // classesHeaders may depen on payloadCode
365 out << " static const char* classesHeaders[] = {\n"
366 << headersClassesMapString
367 << "\n};\n";
368 out << " static bool isInitialized = false;\n"
369 " if (!isInitialized) {\n"
370 " TROOT::RegisterModule(\"" << demangledDictName << "\",\n"
371 " headers, includePaths, payloadCode, fwdDeclCode,\n"
372 " TriggerDictionaryInitialization_" << dictName << "_Impl, "
373 << fwdDeclnArgsToKeepString << ", classesHeaders, "
374 << (hasCxxModule ? "/*hasCxxModule*/true" : "/*hasCxxModule*/false")
375 << ");\n"
376 " isInitialized = true;\n"
377 " }\n"
378 " }\n"
379 " static struct DictInit {\n"
380 " DictInit() {\n"
381 " TriggerDictionaryInitialization_" << dictName << "_Impl();\n"
382 " }\n"
383 " } __TheDictionaryInitializer;\n"
384 "}\n"
385 "void TriggerDictionaryInitialization_" << dictName << "() {\n"
386 " TriggerDictionaryInitialization_" << dictName << "_Impl();\n"
387 "}\n";
388}
389
390////////////////////////////////////////////////////////////////////////////////
391
392void TModuleGenerator::WriteRegistrationSource(std::ostream &out, const std::string &fwdDeclnArgsToKeepString,
393 const std::string &headersClassesMapString,
394 const std::string &fwdDeclString, const std::string &extraIncludes, bool hasCxxModule) const
395{
396 if (hasCxxModule) {
397 std::string emptyStr = "\"\"";
399 fwdDeclString, "{}",
400 emptyStr, headersClassesMapString, "0",
401 /*HasCxxModule*/ true);
402 return;
403 }
404
405 std::string fwdDeclStringSanitized = fwdDeclString;
406#ifdef R__WIN32
407 // Visual sudio has a limitation of 2048 characters max in raw strings, so split
408 // the potentially huge DICTFWDDCLS raw string into multiple smaller ones
409 constexpr char from[] = "\n";
410 constexpr char to[] = "\n)DICTFWDDCLS\"\nR\"DICTFWDDCLS(";
411 size_t start_pos = 0;
412 while ((start_pos = fwdDeclStringSanitized.find(from, start_pos)) != std::string::npos) {
413 if (fwdDeclStringSanitized.find(from, start_pos + 1) == std::string::npos) // skip the last
414 break;
415 if ((fwdDeclStringSanitized.at(start_pos + 1) == '}') || (fwdDeclStringSanitized.at(start_pos + 1) == '\n'))
416 start_pos += 2;
417 else {
418 fwdDeclStringSanitized.replace(start_pos, strlen(from), to);
419 start_pos += strlen(to); // In case 'to' contains 'from', like replacing 'x' with 'yx'
420 }
421 }
422#endif
423 std::string fwdDeclStringRAW;
424 if ("nullptr" == fwdDeclStringSanitized || "\"\"" == fwdDeclStringSanitized) {
425 fwdDeclStringRAW = fwdDeclStringSanitized;
426 } else {
427 fwdDeclStringRAW = "R\"DICTFWDDCLS(\n";
428 fwdDeclStringRAW += "#line 1 \"";
429 fwdDeclStringRAW += fDictionaryName +" dictionary forward declarations' payload\"\n";
430 fwdDeclStringRAW += fwdDeclStringSanitized;
431 fwdDeclStringRAW += ")DICTFWDDCLS\"";
432 }
433
434 if (fIsInPCH)
435 fwdDeclStringRAW = "nullptr";
436
437 std::string payloadCode;
438
439 // Increase the value of the diagnostics pointing out from which
440 // dictionary this payload comes from in case of errors
441 payloadCode += "#line 1 \"";
442 payloadCode += fDictionaryName +" dictionary payload\"\n";
443
444 // Add defines and undefines to the payloadCode
445 std::ostringstream definesAndUndefines;
446 // Anticipate the undefines.
447 // Suppose to have a namespace called "declarations" used in R5 for template
448 // instantiations in the header given to genreflex.
449 // Now, in this namespace, objects with some names, typically dummy, will be
450 // present.
451 // If you give such headers to cling to parse, problems will occour, as the
452 // names appear multiple times. One possible solution is to get out of this
453 // with preprocessor defines given to genreflex, redefining "declarations"
454 // to a hash or <project>_<package> via the build system.
455 WritePPUndefines(definesAndUndefines);
456 WritePPDefines(definesAndUndefines);
457 payloadCode += definesAndUndefines.str();
458
459 // If necessary, inline the headers
460 std::string hdrFullPath;
461 std::string inlinedHeaders;
462
463 auto findAndAddToInlineHeaders = [&](const std::string& hdrName) {
464 bool headerFound = FindHeader(hdrName,hdrFullPath);
465 if (!headerFound) {
466 ROOT::TMetaUtils::Error(0, "Cannot find header %s: cannot inline it.\n", hdrName.c_str());
467 } else {
468 std::ifstream headerFile(hdrFullPath.c_str());
469 const std::string headerFileAsStr((std::istreambuf_iterator<char>(headerFile)),
470 std::istreambuf_iterator<char>());
471 inlinedHeaders += headerFileAsStr;
472 }
473 };
474
476 for (auto const & hdrName : fHeaders) {
477 findAndAddToInlineHeaders(hdrName);
478 }
479
480 } else {
481 // Now, if not, just #include them in the payload except for the linkdef
482 // file, if any.
483 for (auto & hdrName : fHeaders) {
484 inlinedHeaders += "#include \"" + hdrName + "\"\n";
485 }
486 }
487
488 if (0 != fLinkDefFile.size() && !fIsPCH) {
489 findAndAddToInlineHeaders(fLinkDefFile);
490 }
491
492 // Recover old genreflex behaviour, i.e. do not print warnings due to glitches
493 // in the headers at runtime. This is not synonym of ignoring warnings as they
494 // will be printed at dictionary generation time.
495 // In order to do this we leverage the diagnostic pragmas and, since there is no
496 // way to express as a pragma the option "-Wno-deprecated" the
497 // _BACKWARD_BACKWARD_WARNING_H macro, used to avoid to go through
498 // backward/backward_warning.h.
499 payloadCode += "#define _BACKWARD_BACKWARD_WARNING_H\n"
500 "// Inline headers\n"+
501 inlinedHeaders + "\n"+
502 (extraIncludes.empty() ? "" : "// Extra includes\n" + extraIncludes + "\n") +
503 "#undef _BACKWARD_BACKWARD_WARNING_H\n";
504
505 // We cannot stream the contents in strings and pass it to
506 // WriteRegistrationSourceImpl because we exceed the std::string::max_size on
507 // Windows.
508 std::vector<std::string> headerArray = {"0"};
510 headerArray = fHeaders;
511 const std::vector<std::string>& includePathArray = fCompI;
512
513 std::string payloadcodeWrapped = "nullptr";
514 if (!fIsInPCH)
515 payloadcodeWrapped = "R\"DICTPAYLOAD(\n" + payloadCode + ")DICTPAYLOAD\"";
516
519 headerArray,
520 includePathArray,
521 fwdDeclStringRAW,
522 fwdDeclnArgsToKeepString,
523 payloadcodeWrapped,
524 headersClassesMapString,
525 extraIncludes,
526 /*HasCxxModule*/false);
527}
528
529////////////////////////////////////////////////////////////////////////////////
530/// Write a header file describing the content of this module
531/// through a series of variables inside the namespace
532/// ROOT::Dict::[DictionaryName]. Each variable is an array of string
533/// literals, with a const char* of 0 being the last element, e.g.
534/// ROOT::Dict::_DictName::arrIncludes[] = { "A.h", "B.h", 0 };
535
536void TModuleGenerator::WriteContentHeader(std::ostream &out) const
537{
538 out << "namespace ROOT { namespace Dict { namespace _"
539 << GetDictionaryName() << "{\n";
540
541 out << "const char* arrIncludes[] = {\n";
542 WriteHeaderArray(out) << "};\n";
543
544 out << "const char* arrIncludePaths[] = {\n";
545 WriteIncludePathArray(out) << "};\n";
546 /*
547 out << "const char* arrDefines[] = {\n";
548 WriteDefinesArray(out) << "};\n";
549
550 out << "const char* arrUndefines[] = {\n";
551 WriteUndefinesArray(out) << "};\n";*/
552
553 out << "} } }" << std::endl;
554}
555
556////////////////////////////////////////////////////////////////////////////////
557/// Return true if the header is found in the include paths
558/// in this case also fill the full path variable with the full path.
559
560bool TModuleGenerator::FindHeader(const std::string &hdrName, std::string &hdrFullPath) const
561{
562 hdrFullPath = hdrName;
563 if (llvm::sys::fs::exists(hdrFullPath))
564 return true;
565 for (auto const &incDir : fCompI) {
566 hdrFullPath = incDir + ROOT::TMetaUtils::GetPathSeparator() + hdrName;
567 if (llvm::sys::fs::exists(hdrFullPath)) {
568 return true;
569 }
570 }
571 clang::Preprocessor &PP = fCI->getPreprocessor();
572 clang::HeaderSearch &HdrSearch = PP.getHeaderSearchInfo();
573 const clang::DirectoryLookup *CurDir = 0;
574 if (const clang::FileEntry *hdrFileEntry
575 = HdrSearch.LookupFile(hdrName, clang::SourceLocation(),
576 true /*isAngled*/, 0 /*FromDir*/, CurDir,
577 clang::ArrayRef<std::pair<const clang::FileEntry*,
578 const clang::DirectoryEntry*>>(),
579 0 /*IsMapped*/, 0 /*SearchPath*/, 0 /*RelativePath*/,
580 0 /*RequestingModule*/, 0/*SuggestedModule*/)) {
581 hdrFullPath = hdrFileEntry->getName();
582 return true;
583 }
584
585 return false;
586}
587
588////////////////////////////////////////////////////////////////////////////////
589/// Write a header file pulling in the content of this module
590/// through a series of #defined, #undefs and #includes.
591/// The sequence corrsponds to a rootcling invocation with
592/// -c -DFOO -UBAR header.h
593/// I.e. defines, undefines and finally includes.
594
595void TModuleGenerator::WriteUmbrellaHeader(std::ostream &out) const
596{
597 WritePPDefines(out);
598 WritePPUndefines(out);
599 WritePPIncludes(out);
600}
#define c(i)
Definition: RSha256.hxx:101
void Error(const char *location, const char *msgfmt,...)
int ExtractBufferContent(const std::string &fullHeaderPath, std::string &bufferContent)
int WarnIfPragmaOnceDetected(const std::string &fullHeaderPath, const std::string &headerFileContent)
To be replaced with proper pragma handlers.
static std::pair< std::string, std::string > SplitPPDefine(const std::string &in)
std::vector< std::string > fCompU
void WriteUmbrellaHeader(std::ostream &out) const
Write a header file pulling in the content of this module through a series of #defined,...
std::ostream & WriteHeaderArray(std::ostream &out) const
std::vector< std::pair< std::string, std::string > > StringPairVec_t
std::ostream & WriteStringVec(const std::vector< std::string > &vec, std::ostream &out) const
std::ostream & WriteStringPairVec(const StringPairVec_t &vecP, std::ostream &out) const
void WriteRegistrationSource(std::ostream &out, const std::string &fwdDeclnArgsToKeepString, const std::string &headersClassesMapString, const std::string &fwdDeclsString, const std::string &extraIncludes, bool hasCxxModule) const
ESourceFileKind GetSourceFileKind(const char *filename) const
Check whether the file's extension is compatible with C or C++.
std::ostream & WritePPIncludes(std::ostream &out) const
Write #include "header1.h" #include "header2.h" or, if inlining of headers is requested,...
std::ostream & WriteIncludePathArray(std::ostream &out) const
void WriteContentHeader(std::ostream &out) const
Write a header file describing the content of this module through a series of variables inside the na...
std::vector< std::string > fCompI
std::vector< std::string > fHeaders
std::ostream & WritePPUndefines(std::ostream &out) const
Write #ifdef FOO.
void WriteRegistrationSourceImpl(std::ostream &out, const std::string &dictName, const std::string &demangledDictName, const std::vector< std::string > &headerArray, const std::vector< std::string > &includePathArray, const std::string &fwdDeclStringRAW, const std::string &fwdDeclnArgsToKeepString, const std::string &payloadCodeWrapped, const std::string &headersClassesMapString, const std::string &extraIncludes, bool hasCxxModule) const
const std::string & GetDictionaryName() const
clang::CompilerInstance * fCI
bool FindHeader(const std::string &hdrName, std::string &hdrFullPath) const
Return true if the header is found in the include paths in this case also fill the full path variable...
const std::string & GetDemangledDictionaryName() const
void ParseArgs(const std::vector< std::string > &args)
Parse -I -D -U headers.h SomethingLinkdef.h.
std::ostream & WritePPDefines(std::ostream &out) const
Write #ifndef FOO.
TLine * line
const std::string & GetPathSeparator()
VSD Structures.
Definition: StringConv.hxx:21
Definition: TString.h:845
bool IsLinkdefFile(const clang::PresumedLoc &PLoc)