21#include "TClingUtils.h"
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"
45TModuleGenerator::TModuleGenerator(CompilerInstance *CI,
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 llvm::SmallString<10> resultPath(
"%%%%%%%%%%");
80 llvm::sys::fs::createUniqueFile(resultPath.str(), resultPath);
98 if (filename[0] ==
'-')
return kSFKNotC;
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 !=
'.') {
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(),
116 clang::ArrayRef<std::pair<
const clang::FileEntry*,
117 const clang::DirectoryEntry*>>(),
126 const size_t lenExt = filename + len - ext;
131 const char last = toupper(filename[len - 1]);
137 if (filename[len - 2] ==
'h' && filename[len - 1] ==
'h')
139 else if (filename[len - 2] ==
'c' && filename[len - 1] ==
'c')
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;
160 std::string::size_type posEq = in.find(
'=');
162 if (posEq == std::string::npos)
163 return std::make_pair(in,
"1");
166 return std::pair<std::string, std::string>
167 (in.substr(0, posEq), in.substr(posEq + 1, std::string::npos));
175 for (
size_t iPcmArg = 1 , nPcmArg = args.size();
176 iPcmArg < nPcmArg; ++iPcmArg) {
182 }
else if (sfk ==
kSFKNotC && args[iPcmArg][0] ==
'-') {
183 switch (args[iPcmArg][1]) {
185 if (args[iPcmArg] !=
"-I." && args[iPcmArg] !=
"-Iinclude") {
186 fCompI.push_back(args[iPcmArg].c_str() + 2);
190 if (args[iPcmArg] !=
"-DTRUE=1" && args[iPcmArg] !=
"-DFALSE=0"
191 && args[iPcmArg] !=
"-DG__NOCINTDLL") {
196 fCompU.push_back(args[iPcmArg].c_str() + 2);
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;
233 for (
auto const & undef :
fCompU) {
234 out <<
"#ifdef " << undef <<
"\n"
235 " #undef " << undef <<
"\n"
246 const std::string& headerFileContent)
248 std::istringstream headerFile(headerFileContent);
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 "
257 <<
" which was requested to be inlined.\n";
268 std::ifstream buffer(fullHeaderPath);
269 bufferContent = std::string((std::istreambuf_iterator<char>(buffer)),
270 std::istreambuf_iterator<char>());
283 std::string fullHeaderPath;
284 for (
auto const & incl :
fHeaders) {
286 bool headerFound =
FindHeader(incl,fullHeaderPath);
292 std::string bufferContent;
295 out << bufferContent << std::endl;
297 out <<
"#include \"" << incl <<
"\"\n";
307 std::ostream &out)
const
309 for (
auto const & theStr : vec) {
310 out <<
"\"" << theStr <<
"\",\n";
312 out <<
"0" << std::endl;
319 std::ostream &out)
const
321 for (
auto const & strPair : vec) {
322 out <<
"\"" << strPair.first;
323 if (!strPair.second.empty()) {
326 for (
const char *
c = strPair.second.c_str(); *
c !=
'\0'; ++
c) {
336 out <<
"0" << std::endl;
345 const std::string &fwdDeclnArgsToKeepString,
346 const std::string &headersClassesMapString,
347 const std::string &fwdDeclString,
348 const std::string &extraIncludes)
const
351 std::string fwdDeclStringSanitized = fwdDeclString;
355 constexpr char from[] =
"\n";
356 constexpr char to[] =
"\n)DICTFWDDCLS\"\nR\"DICTFWDDCLS(";
357 size_t start_pos = 0;
358 while ((start_pos = fwdDeclStringSanitized.find(from, start_pos)) != std::string::npos) {
359 if (fwdDeclStringSanitized.find(from, start_pos + 1) == std::string::npos)
361 if ((fwdDeclStringSanitized.at(start_pos + 1) ==
'}') || (fwdDeclStringSanitized.at(start_pos + 1) ==
'\n'))
364 fwdDeclStringSanitized.replace(start_pos, strlen(from), to);
365 start_pos += strlen(to);
369 std::string fwdDeclStringRAW;
370 if (
"nullptr" == fwdDeclStringSanitized ||
"\"\"" == fwdDeclStringSanitized) {
371 fwdDeclStringRAW = fwdDeclStringSanitized;
373 fwdDeclStringRAW =
"R\"DICTFWDDCLS(\n";
374 fwdDeclStringRAW +=
"#line 1 \"";
375 fwdDeclStringRAW +=
fDictionaryName +
" dictionary forward declarations' payload\"\n";
376 fwdDeclStringRAW += fwdDeclStringSanitized;
377 fwdDeclStringRAW +=
")DICTFWDDCLS\"";
381 fwdDeclStringRAW =
"nullptr";
383 std::string payloadCode;
387 payloadCode +=
"#line 1 \"";
391 std::ostringstream definesAndUndefines;
403 payloadCode += definesAndUndefines.str();
406 std::string hdrFullPath;
407 std::string inlinedHeaders;
409 auto findAndAddToInlineHeaders = [&](
const std::string& hdrName) {
410 bool headerFound =
FindHeader(hdrName,hdrFullPath);
414 std::ifstream headerFile(hdrFullPath.c_str());
415 const std::string headerFileAsStr((std::istreambuf_iterator<char>(headerFile)),
416 std::istreambuf_iterator<char>());
417 inlinedHeaders += headerFileAsStr;
422 for (
auto const & hdrName :
fHeaders) {
423 findAndAddToInlineHeaders(hdrName);
430 inlinedHeaders +=
"#include \"" + hdrName +
"\"\n";
445 payloadCode +=
"#define _BACKWARD_BACKWARD_WARNING_H\n"
446 "// Inline headers\n"+
447 inlinedHeaders +
"\n"+
448 (extraIncludes.empty() ?
"" :
"// Extra includes\n" + extraIncludes +
"\n") +
449 "#undef _BACKWARD_BACKWARD_WARNING_H\n";
452 out <<
"namespace {\n"
453 " void TriggerDictionaryInitialization_"
455 " static const char* headers[] = {\n";
462 std::string payloadcodeWrapped =
"nullptr";
464 payloadcodeWrapped =
"R\"DICTPAYLOAD(\n" + payloadCode +
")DICTPAYLOAD\"";
467 <<
" static const char* includePaths[] = {\n";
470 " static const char* fwdDeclCode = " << fwdDeclStringRAW <<
";\n"
471 " static const char* payloadCode = " << payloadcodeWrapped <<
";\n"
472 " " << headersClassesMapString <<
"\n"
473 " static bool isInitialized = false;\n"
474 " if (!isInitialized) {\n"
476 " headers, includePaths, payloadCode, fwdDeclCode,\n"
477 " TriggerDictionaryInitialization_" <<
GetDictionaryName() <<
"_Impl, " << fwdDeclnArgsToKeepString <<
", classesHeaders, " << (
fCI->getLangOpts().Modules ?
"/*has C++ module*/true" :
"/*has no C++ module*/false") <<
");\n"
478 " isInitialized = true;\n"
481 " static struct DictInit {\n"
485 " } __TheDictionaryInitializer;\n"
501 out <<
"namespace ROOT { namespace Dict { namespace _"
504 out <<
"const char* arrIncludes[] = {\n";
507 out <<
"const char* arrIncludePaths[] = {\n";
516 out <<
"} } }" << std::endl;
525 hdrFullPath = hdrName;
526 if (llvm::sys::fs::exists(hdrFullPath))
528 for (
auto const &incDir :
fCompI) {
529 hdrFullPath = incDir + ROOT::TMetaUtils::GetPathSeparator() + hdrName;
530 if (llvm::sys::fs::exists(hdrFullPath)) {
534 clang::Preprocessor &PP =
fCI->getPreprocessor();
535 clang::HeaderSearch &HdrSearch = PP.getHeaderSearchInfo();
536 const clang::DirectoryLookup *CurDir = 0;
537 if (
const clang::FileEntry *hdrFileEntry
538 = HdrSearch.LookupFile(hdrName, clang::SourceLocation(),
540 clang::ArrayRef<std::pair<
const clang::FileEntry*,
541 const clang::DirectoryEntry*>>(),
544 hdrFullPath = hdrFileEntry->getName();
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
std::string fUmbrellaName
void WriteRegistrationSource(std::ostream &out, const std::string &fwdDeclnArgsToKeepString, const std::string &headersClassesMapString, const std::string &fwdDeclsString, const std::string &extraIncludes) const
std::string fDictionaryName
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::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.
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.
Namespace for new ROOT classes and functions.
bool IsLinkdefFile(const clang::PresumedLoc &PLoc)