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"
46 bool inlineInputHeaders,
47 const std::string &shLibFileName,
48 bool writeEmptyRootPCM):
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)),
79 auto makeTempFile = [&](
const char *suffix) {
80 llvm::SmallString<64> resultPath;
82 llvm::sys::fs::createUniqueFile(pattern, resultPath);
104 if (filename[0] ==
'-')
return kSFKNotC;
110 const size_t len = strlen(filename);
111 const char *ext = filename + len - 1;
112 while (ext >= filename && *ext !=
'.') --ext;
113 if (ext < filename || *ext !=
'.') {
116 clang::Preprocessor &PP =
fCI->getPreprocessor();
117 clang::HeaderSearch &HdrSearch = PP.getHeaderSearchInfo();
118 const clang::DirectoryLookup *CurDir =
nullptr;
119 const clang::FileEntry *hdrFileEntry
120 = HdrSearch.LookupFile(filename, clang::SourceLocation(),
121 true ,
nullptr , CurDir,
122 clang::ArrayRef<std::pair<
const clang::FileEntry*,
123 const clang::DirectoryEntry*>>(),
133 const size_t lenExt = filename + len - ext;
138 const char last = toupper(filename[len - 1]);
144 if (filename[len - 2] ==
'h' && filename[len - 1] ==
'h')
146 else if (filename[len - 2] ==
'c' && filename[len - 1] ==
'c')
151 const char last = filename[len - 1];
152 if ((last ==
'x' || last ==
'p')
153 && filename[len - 2] == last) {
154 if (filename[len - 3] ==
'h') ret =
kSFKHeader;
155 else if (filename[len - 3] ==
'c') ret =
kSFKSource;
167 std::string::size_type posEq = in.find(
'=');
169 if (posEq == std::string::npos)
170 return std::make_pair(in,
"1");
173 return std::pair<std::string, std::string>
174 (in.substr(0, posEq), in.substr(posEq + 1, std::string::npos));
182 for (
size_t iPcmArg = 1 , nPcmArg = args.size();
183 iPcmArg < nPcmArg; ++iPcmArg) {
189 }
else if (sfk ==
kSFKNotC && args[iPcmArg][0] ==
'-') {
190 switch (args[iPcmArg][1]) {
192 if (args[iPcmArg] !=
"-I." && args[iPcmArg] !=
"-Iinclude") {
193 fCompI.push_back(args[iPcmArg].c_str() + 2);
197 if (args[iPcmArg] !=
"-DTRUE=1" && args[iPcmArg] !=
"-DFALSE=0"
198 && args[iPcmArg] !=
"-DG__NOCINTDLL") {
203 fCompU.push_back(args[iPcmArg].c_str() + 2);
218 for (
auto const & strPair :
fCompD) {
219 std::string cppname(strPair.first);
220 size_t pos = cppname.find(
'(');
221 if (pos != std::string::npos) cppname.erase(pos);
222 out <<
"#ifndef " << cppname <<
"\n"
223 " #define " << strPair.first;
224 out <<
" " << strPair.second;
240 for (
auto const & undef :
fCompU) {
241 out <<
"#ifdef " << undef <<
"\n"
242 " #undef " << undef <<
"\n"
253 const std::string& headerFileContent)
255 std::istringstream headerFile(headerFileContent);
257 while(std::getline(headerFile,
line)){
258 llvm::StringRef lineRef (
line);
259 auto trimmedLineRef = lineRef.trim();
260 if (trimmedLineRef.startswith(
"#pragma") &&
261 (trimmedLineRef.endswith(
" once") || trimmedLineRef.endswith(
"\tonce"))) {
262 std::cerr <<
"Error: #pragma once directive detected in header file "
264 <<
" which was requested to be inlined.\n";
275 std::ifstream buffer(fullHeaderPath);
276 bufferContent = std::string((std::istreambuf_iterator<char>(buffer)),
277 std::istreambuf_iterator<char>());
290 std::string fullHeaderPath;
291 for (
auto const & incl :
fHeaders) {
293 bool headerFound =
FindHeader(incl,fullHeaderPath);
299 std::string bufferContent;
302 out << bufferContent << std::endl;
304 out <<
"#include \"" << incl <<
"\"\n";
314 std::ostream &out)
const
316 for (
auto const & theStr :
vec) {
317 out <<
"\"" << theStr <<
"\",\n";
319 out <<
"nullptr" << std::endl;
326 std::ostream &out)
const
328 for (
auto const & strPair :
vec) {
329 out <<
"\"" << strPair.first;
330 if (!strPair.second.empty()) {
333 for (
const char *
c = strPair.second.c_str(); *
c !=
'\0'; ++
c) {
343 out <<
"nullptr" << std::endl;
349 const std::string &dictName,
350 const std::string &demangledDictName,
351 const std::vector<std::string> &headerArray,
352 const std::vector<std::string> &includePathArray,
353 const std::string &fwdDeclStringRAW,
354 const std::string &fwdDeclnArgsToKeepString,
355 const std::string &payloadCodeWrapped,
356 const std::string &headersClassesMapString,
357 const std::string &extraIncludes,
358 bool hasCxxModule)
const
361 out <<
"namespace {\n"
362 " void TriggerDictionaryInitialization_" << dictName <<
"_Impl() {\n"
363 " static const char* headers[] = {\n";
365 out <<
" static const char* includePaths[] = {\n";
369 out <<
" static const char* fwdDeclCode = " << fwdDeclStringRAW <<
";\n"
370 <<
" static const char* payloadCode = " << payloadCodeWrapped <<
";\n";
372 out <<
" static const char* classesHeaders[] = {\n"
373 << headersClassesMapString
375 out <<
" static bool isInitialized = false;\n"
376 " if (!isInitialized) {\n"
377 " TROOT::RegisterModule(\"" << demangledDictName <<
"\",\n"
378 " headers, includePaths, payloadCode, fwdDeclCode,\n"
379 " TriggerDictionaryInitialization_" << dictName <<
"_Impl, "
380 << fwdDeclnArgsToKeepString <<
", classesHeaders, "
381 << (hasCxxModule ?
"/*hasCxxModule*/true" :
"/*hasCxxModule*/false")
383 " isInitialized = true;\n"
386 " static struct DictInit {\n"
388 " TriggerDictionaryInitialization_" << dictName <<
"_Impl();\n"
390 " } __TheDictionaryInitializer;\n"
392 "void TriggerDictionaryInitialization_" << dictName <<
"() {\n"
393 " TriggerDictionaryInitialization_" << dictName <<
"_Impl();\n"
400 const std::string &headersClassesMapString,
401 const std::string &fwdDeclString,
const std::string &extraIncludes,
bool hasCxxModule)
const
404 std::string emptyStr =
"\"\"";
407 emptyStr, headersClassesMapString,
"0",
412 std::string fwdDeclStringSanitized = fwdDeclString;
416 constexpr char from[] =
"\n";
417 constexpr char to[] =
"\n)DICTFWDDCLS\"\nR\"DICTFWDDCLS(";
418 size_t start_pos = 0;
419 while ((start_pos = fwdDeclStringSanitized.find(from, start_pos)) != std::string::npos) {
420 if (fwdDeclStringSanitized.find(from, start_pos + 1) == std::string::npos)
422 if ((fwdDeclStringSanitized.at(start_pos + 1) ==
'}') || (fwdDeclStringSanitized.at(start_pos + 1) ==
'\n'))
425 fwdDeclStringSanitized.replace(start_pos, strlen(from), to);
426 start_pos += strlen(to);
430 std::string fwdDeclStringRAW;
431 if (
"nullptr" == fwdDeclStringSanitized ||
"\"\"" == fwdDeclStringSanitized) {
432 fwdDeclStringRAW = fwdDeclStringSanitized;
434 fwdDeclStringRAW =
"R\"DICTFWDDCLS(\n";
435 fwdDeclStringRAW +=
"#line 1 \"";
436 fwdDeclStringRAW +=
fDictionaryName +
" dictionary forward declarations' payload\"\n";
437 fwdDeclStringRAW += fwdDeclStringSanitized;
438 fwdDeclStringRAW +=
")DICTFWDDCLS\"";
442 fwdDeclStringRAW =
"nullptr";
444 std::string payloadCode;
448 payloadCode +=
"#line 1 \"";
452 std::ostringstream definesAndUndefines;
464 payloadCode += definesAndUndefines.str();
467 std::string hdrFullPath;
468 std::string inlinedHeaders;
470 auto findAndAddToInlineHeaders = [&](
const std::string& hdrName) {
471 bool headerFound =
FindHeader(hdrName,hdrFullPath);
475 std::ifstream headerFile(hdrFullPath.c_str());
476 const std::string headerFileAsStr((std::istreambuf_iterator<char>(headerFile)),
477 std::istreambuf_iterator<char>());
478 inlinedHeaders += headerFileAsStr;
483 for (
auto const & hdrName :
fHeaders) {
484 findAndAddToInlineHeaders(hdrName);
491 inlinedHeaders +=
"#include \"" + hdrName +
"\"\n";
506 payloadCode +=
"#define _BACKWARD_BACKWARD_WARNING_H\n"
507 "// Inline headers\n"+
508 inlinedHeaders +
"\n"+
509 (extraIncludes.empty() ?
"" :
"// Extra includes\n" + extraIncludes +
"\n") +
510 "#undef _BACKWARD_BACKWARD_WARNING_H\n";
515 std::vector<std::string> headerArray = {
"0"};
518 const std::vector<std::string>& includePathArray =
fCompI;
520 std::string payloadcodeWrapped =
"nullptr";
522 payloadcodeWrapped =
"R\"DICTPAYLOAD(\n" + payloadCode +
")DICTPAYLOAD\"";
529 fwdDeclnArgsToKeepString,
531 headersClassesMapString,
545 out <<
"namespace ROOT { namespace Dict { namespace _"
548 out <<
"const char* arrIncludes[] = {\n";
551 out <<
"const char* arrIncludePaths[] = {\n";
560 out <<
"} } }" << std::endl;
569 hdrFullPath = hdrName;
570 if (llvm::sys::fs::exists(hdrFullPath))
572 for (
auto const &incDir :
fCompI) {
574 if (llvm::sys::fs::exists(hdrFullPath)) {
578 clang::Preprocessor &PP =
fCI->getPreprocessor();
579 clang::HeaderSearch &HdrSearch = PP.getHeaderSearchInfo();
580 const clang::DirectoryLookup *CurDir =
nullptr;
581 if (
const clang::FileEntry *hdrFileEntry
582 = HdrSearch.LookupFile(hdrName, clang::SourceLocation(),
583 true ,
nullptr , CurDir,
584 clang::ArrayRef<std::pair<
const clang::FileEntry*,
585 const clang::DirectoryEntry*>>(),
588 nullptr ,
nullptr )) {
589 hdrFullPath = hdrFileEntry->getName();
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.
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::string fModuleDirName
std::ostream & WritePPDefines(std::ostream &out) const
Write #ifndef FOO.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...