22#include "RConfigure.h"
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"
47 bool inlineInputHeaders,
48 const std::string &shLibFileName,
49 bool writeEmptyRootPCM):
51 fIsPCH(shLibFileName ==
"allDict.cxx"),
63 fModuleDirName =
"./";
65 fModuleDirName +=
"/";
80 auto makeTempFile = [&](
const char *suffix) {
81 llvm::SmallString<64> resultPath;
82 std::string pattern = fModuleDirName + fDictionaryName +
"%%%%%%%%%%" + suffix;
83 llvm::sys::fs::createUniqueFile(pattern, resultPath);
105 if (filename[0] ==
'-')
return kSFKNotC;
111 const size_t len = strlen(filename);
112 const char *ext = filename + len - 1;
113 while (ext >= filename && *ext !=
'.') --ext;
114 if (ext < filename || *ext !=
'.') {
117 clang::Preprocessor &PP =
fCI->getPreprocessor();
118 clang::HeaderSearch &HdrSearch = PP.getHeaderSearchInfo();
119 clang::ConstSearchDirIterator *CurDir =
nullptr;
121 = HdrSearch.LookupFile(filename, clang::SourceLocation(),
122 true ,
nullptr , CurDir,
123 clang::ArrayRef<std::pair<clang::OptionalFileEntryRef,
124 clang::DirectoryEntryRef>>(),
134 const size_t lenExt = filename + len - ext;
139 const char last = toupper(filename[len - 1]);
145 if (filename[len - 2] ==
'h' && filename[len - 1] ==
'h')
147 else if (filename[len - 2] ==
'c' && filename[len - 1] ==
'c')
152 const char last = filename[len - 1];
153 if ((last ==
'x' || last ==
'p')
154 && filename[len - 2] == last) {
168 std::string::size_type posEq = in.find(
'=');
170 if (posEq == std::string::npos)
171 return std::make_pair(in,
"1");
174 return std::pair<std::string, std::string>
175 (in.substr(0, posEq), in.substr(posEq + 1, std::string::npos));
183 std::vector<std::string> systemIncludePaths;
184 for (
size_t iPcmArg = 1 , nPcmArg = args.size();
185 iPcmArg < nPcmArg; ++iPcmArg) {
191 }
else if (sfk ==
kSFKNotC && args[iPcmArg][0] ==
'-') {
192 switch (args[iPcmArg][1]) {
194 if (args[iPcmArg].find(
"-isystem") != std::string::npos) {
195 if (args[iPcmArg].
size() == 8)
196 systemIncludePaths.push_back(args[++iPcmArg]);
199 while (args[iPcmArg][
pos] ==
' ')
201 systemIncludePaths.push_back(args[iPcmArg].substr(
pos));
206 if (args[iPcmArg] !=
"-I." && args[iPcmArg] !=
"-Iinclude") {
207 fCompI.push_back(args[iPcmArg].c_str() + 2);
211 if (args[iPcmArg] !=
"-DTRUE=1" && args[iPcmArg] !=
"-DFALSE=0" && args[iPcmArg] !=
"-DG__NOCINTDLL") {
215 case 'U':
fCompU.push_back(args[iPcmArg].c_str() + 2);
break;
221 std::move(systemIncludePaths.begin(), systemIncludePaths.end(), std::back_inserter(
fCompI));
233 for (
auto const & strPair :
fCompD) {
234 std::string cppname(strPair.first);
235 size_t pos = cppname.find(
'(');
236 if (
pos != std::string::npos) cppname.erase(
pos);
237 out <<
"#ifndef " << cppname <<
"\n"
238 " #define " << strPair.first;
239 out <<
" " << strPair.second;
255 for (
auto const & undef :
fCompU) {
256 out <<
"#ifdef " << undef <<
"\n"
257 " #undef " << undef <<
"\n"
268 const std::string& headerFileContent)
270 std::istringstream headerFile(headerFileContent);
272 while(std::getline(headerFile,
line)){
273 llvm::StringRef lineRef (
line);
274 auto trimmedLineRef = lineRef.trim();
275 if (trimmedLineRef.starts_with(
"#pragma") &&
276 (trimmedLineRef.ends_with(
" once") || trimmedLineRef.ends_with(
"\tonce"))) {
277 std::cerr <<
"Error: #pragma once directive detected in header file "
279 <<
" which was requested to be inlined.\n";
290 std::ifstream buffer(fullHeaderPath);
291 bufferContent = std::string((std::istreambuf_iterator<char>(buffer)),
292 std::istreambuf_iterator<char>());
305 std::string fullHeaderPath;
306 for (
auto const & incl :
fHeaders) {
308 bool headerFound =
FindHeader(incl,fullHeaderPath);
314 std::string bufferContent;
317 out << bufferContent << std::endl;
319 out <<
"#include \"" << incl <<
"\"\n";
329 std::ostream &out)
const
331 for (
auto const & theStr :
vec) {
332 out <<
"\"" << theStr <<
"\",\n";
334 out <<
"nullptr" << std::endl;
341 std::ostream &out)
const
343 for (
auto const & strPair :
vec) {
344 out <<
"\"" << strPair.first;
345 if (!strPair.second.empty()) {
348 for (
const char *
c = strPair.second.c_str(); *
c !=
'\0'; ++
c) {
358 out <<
"nullptr" << std::endl;
364 const std::string &dictName,
365 const std::string &demangledDictName,
366 const std::vector<std::string> &headerArray,
367 const std::vector<std::string> &includePathArray,
368 const std::string &fwdDeclStringRAW,
369 const std::string &fwdDeclnArgsToKeepString,
370 const std::string &payloadCodeWrapped,
371 const std::string &headersClassesMapString,
372 const std::string &extraIncludes,
373 bool hasCxxModule)
const
376 out <<
"namespace {\n"
377 " void TriggerDictionaryInitialization_" << dictName <<
"_Impl() {\n"
378 " static const char* headers[] = {\n";
380 out <<
" static const char* includePaths[] = {\n";
384 out <<
" static const char* fwdDeclCode = " << fwdDeclStringRAW <<
";\n"
385 <<
" static const char* payloadCode = " << payloadCodeWrapped <<
";\n";
387 out <<
" static const char* classesHeaders[] = {\n"
388 << headersClassesMapString
390 out <<
" static bool isInitialized = false;\n"
391 " if (!isInitialized) {\n"
392 " TROOT::RegisterModule(\"" << demangledDictName <<
"\",\n"
393 " headers, includePaths, payloadCode, fwdDeclCode,\n"
394 " TriggerDictionaryInitialization_" << dictName <<
"_Impl, "
395 << fwdDeclnArgsToKeepString <<
", classesHeaders, "
396 << (hasCxxModule ?
"/*hasCxxModule*/true" :
"/*hasCxxModule*/false")
398 " isInitialized = true;\n"
401 " static struct DictInit {\n"
403 " TriggerDictionaryInitialization_" << dictName <<
"_Impl();\n"
405 " } __TheDictionaryInitializer;\n"
407 "void TriggerDictionaryInitialization_" << dictName <<
"() {\n"
408 " TriggerDictionaryInitialization_" << dictName <<
"_Impl();\n"
415 const std::string &headersClassesMapString,
416 const std::string &fwdDeclString,
const std::string &extraIncludes,
bool hasCxxModule)
const
419 std::string emptyStr =
"\"\"";
421 "{}", emptyStr, headersClassesMapString,
"0",
426 std::string fwdDeclStringSanitized = fwdDeclString;
430 constexpr char from[] =
"\n";
431 constexpr char to[] =
"\n)DICTFWDDCLS\"\nR\"DICTFWDDCLS(";
432 size_t start_pos = 0;
433 while ((start_pos = fwdDeclStringSanitized.find(from, start_pos)) != std::string::npos) {
434 if (fwdDeclStringSanitized.find(from, start_pos + 1) == std::string::npos)
436 if ((fwdDeclStringSanitized.at(start_pos + 1) ==
'}') || (fwdDeclStringSanitized.at(start_pos + 1) ==
'\n'))
439 fwdDeclStringSanitized.replace(start_pos, strlen(from), to);
440 start_pos += strlen(to);
444 std::string fwdDeclStringRAW;
445 if (
"nullptr" == fwdDeclStringSanitized ||
"\"\"" == fwdDeclStringSanitized) {
446 fwdDeclStringRAW = fwdDeclStringSanitized;
448 fwdDeclStringRAW =
"R\"DICTFWDDCLS(\n";
449 fwdDeclStringRAW +=
"#line 1 \"";
450 fwdDeclStringRAW +=
fDictionaryName +
" dictionary forward declarations' payload\"\n";
451 fwdDeclStringRAW += fwdDeclStringSanitized;
452 fwdDeclStringRAW +=
")DICTFWDDCLS\"";
456 fwdDeclStringRAW =
"nullptr";
458 std::string payloadCode;
462 payloadCode +=
"#line 1 \"";
466 std::ostringstream definesAndUndefines;
478 payloadCode += definesAndUndefines.str();
481 std::string hdrFullPath;
482 std::string inlinedHeaders;
484 auto findAndAddToInlineHeaders = [&](
const std::string& hdrName) {
485 bool headerFound =
FindHeader(hdrName,hdrFullPath);
489 std::ifstream headerFile(hdrFullPath.c_str());
490 const std::string headerFileAsStr((std::istreambuf_iterator<char>(headerFile)),
491 std::istreambuf_iterator<char>());
492 inlinedHeaders += headerFileAsStr;
497 for (
auto const & hdrName :
fHeaders) {
498 findAndAddToInlineHeaders(hdrName);
505 inlinedHeaders +=
"#include \"" + hdrName +
"\"\n";
520 payloadCode +=
"#define _BACKWARD_BACKWARD_WARNING_H\n"
521 "// Inline headers\n"+
522 inlinedHeaders +
"\n"+
523 (extraIncludes.empty() ?
"" :
"// Extra includes\n" + extraIncludes +
"\n") +
524 "#undef _BACKWARD_BACKWARD_WARNING_H\n";
529 std::vector<std::string> headerArray = {
"0"};
532 const std::vector<std::string>& includePathArray =
fCompI;
534 std::string payloadcodeWrapped =
"nullptr";
536 payloadcodeWrapped =
"R\"DICTPAYLOAD(\n" + payloadCode +
")DICTPAYLOAD\"";
543 fwdDeclnArgsToKeepString,
545 headersClassesMapString,
559 out <<
"namespace ROOT { namespace Dict { namespace _"
562 out <<
"const char* arrIncludes[] = {\n";
565 out <<
"const char* arrIncludePaths[] = {\n";
574 out <<
"} } }" << std::endl;
583 hdrFullPath = hdrName;
584 if (llvm::sys::fs::exists(hdrFullPath))
586 for (
auto const &incDir :
fCompI) {
588 if (llvm::sys::fs::exists(hdrFullPath)) {
592 clang::Preprocessor &PP =
fCI->getPreprocessor();
593 clang::HeaderSearch &HdrSearch = PP.getHeaderSearchInfo();
594 clang::ConstSearchDirIterator *CurDir =
nullptr;
595 if (
auto hdrFileEntry
596 = HdrSearch.LookupFile(hdrName, clang::SourceLocation(),
597 true ,
nullptr , CurDir,
598 clang::ArrayRef<std::pair<clang::OptionalFileEntryRef,
599 clang::DirectoryEntryRef>>(),
602 nullptr ,
nullptr )) {
603 hdrFullPath = hdrFileEntry->getName().str();
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
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
std::string fUmbrellaName
std::string fDictionaryName
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,...
TModuleGenerator(clang::CompilerInstance *CI, bool inlineHeader, const std::string &shLibFileName, bool isInPCH)
std::string fModuleFileName
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 # undef FOO #endif.
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
std::string fDemangledDictionaryName
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::string fModuleDirName
std::ostream & WritePPDefines(std::ostream &out) const
Write #ifndef FOO # define FOO=bar #endif.
if(pos!=-1) leafTypeName.Remove(pos)