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 = 0;
 
  119      const clang::FileEntry *hdrFileEntry
 
  120         =  HdrSearch.LookupFile(filename, clang::SourceLocation(),
 
  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 << 
"0" << 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 << 
"0" << 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 = 0;
 
  581   if (
const clang::FileEntry *hdrFileEntry
 
  582         =  HdrSearch.LookupFile(hdrName, clang::SourceLocation(),
 
  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...