Selaa lähdekoodia

HPCC-8159 Add option to generate precompiled header for eclcc-generated code

The (undocumented, for now) option -pch passed to eclcc will cause it to
generate a precompiled header eclinclude.hpp.gch, whcih may speed up the c++
compile phase of (small) compilations.

For now, this option will need to be run manually. A later commit may run it
automatically when eclccsrever starts up.

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 12 vuotta sitten
vanhempi
commit
b790466f16
5 muutettua tiedostoa jossa 100 lisäystä ja 13 poistoa
  1. 69 9
      ecl/eclcc/eclcc.cpp
  2. 2 0
      system/include/platform.h
  3. 26 4
      system/jlib/jcomp.cpp
  4. 1 0
      system/jlib/jcomp.hpp
  5. 2 0
      system/jlib/jcomp.ipp

+ 69 - 9
ecl/eclcc/eclcc.cpp

@@ -226,7 +226,8 @@ protected:
     void applyDebugOptions(IWorkUnit * wu);
     bool checkWithinRepository(StringBuffer & attributePath, const char * sourcePathname);
     IFileIO * createArchiveOutputFile(EclCompileInstance & instance);
-    ICppCompiler * createCompiler(const char * coreName);
+    ICppCompiler *createCompiler(const char * coreName, const char * sourceDir = NULL, const char * targetDir = NULL);
+    bool generatePrecompiledHeader();
     void generateOutput(EclCompileInstance & instance);
     void instantECL(EclCompileInstance & instance, IWorkUnit *wu, const char * queryFullName, IErrorReceiver *errs, const char * outputFile);
     bool isWithinPath(const char * sourcePathname, const char * searchPath);
@@ -252,6 +253,7 @@ protected:
     Owned<IEclRepository> includeRepository;
     const char * programName;
 
+    StringBuffer cppIncludePath;
     StringBuffer pluginsPath;
     StringBuffer hooksPath;
     StringBuffer templatePath;
@@ -292,6 +294,7 @@ protected:
     bool optOnlyCompile;
     bool optSaveQueryText;
     bool optLegacy;
+    bool optGenerateHeader;
     int argc;
     const char **argv;
 };
@@ -419,7 +422,7 @@ void EclCC::loadOptions()
 
     globals.setown(createProperties(optIniFilename, true));
 
-    StringBuffer compilerPath, includePath, libraryPath;
+    StringBuffer compilerPath, libraryPath;
 
     if (globals->hasProp("targetGcc"))
         optTargetCompiler = globals->getPropBool("targetGcc") ? GccCppCompiler : Vs6CppCompiler;
@@ -433,7 +436,7 @@ void EclCC::loadOptions()
         extractOption(compilerPath, globals, "CL_PATH", "compilerPath", "/usr", NULL);
 #endif
         extractOption(libraryPath, globals, "ECLCC_LIBRARY_PATH", "libraryPath", syspath, "lib");
-        extractOption(includePath, globals, "ECLCC_INCLUDE_PATH", "includePath", syspath, "componentfiles/cl/include");
+        extractOption(cppIncludePath, globals, "ECLCC_INCLUDE_PATH", "includePath", syspath, "componentfiles/cl/include");
         extractOption(pluginsPath, globals, "ECLCC_PLUGIN_PATH", "plugins", syspath, "plugins");
         extractOption(hooksPath, globals, "HPCC_FILEHOOKS_PATH", "filehooks", syspath, "filehooks");
         extractOption(templatePath, globals, "ECLCC_TPL_PATH", "templatePath", syspath, "componentfiles");
@@ -458,7 +461,7 @@ void EclCC::loadOptions()
         installFileHooks(hooksPath.str());
 
     if (!optNoCompile)
-        setCompilerPath(compilerPath.str(), includePath.str(), libraryPath.str(), NULL, optTargetCompiler, logVerbose);
+        setCompilerPath(compilerPath.str(), cppIncludePath.str(), libraryPath.str(), NULL, optTargetCompiler, logVerbose);
 }
 
 //=========================================================================================
@@ -496,10 +499,8 @@ void EclCC::applyDebugOptions(IWorkUnit * wu)
 
 //=========================================================================================
 
-ICppCompiler * EclCC::createCompiler(const char * coreName)
+ICppCompiler * EclCC::createCompiler(const char * coreName, const char * sourceDir, const char * targetDir)
 {
-    const char * sourceDir = NULL;
-    const char * targetDir = NULL;
     Owned<ICppCompiler> compiler = ::createCompiler(coreName, sourceDir, targetDir, optTargetCompiler, logVerbose);
     compiler->setOnlyCompile(optOnlyCompile);
     compiler->setCCLogPath(cclogFilename);
@@ -1257,6 +1258,55 @@ void EclCC::processReference(EclCompileInstance & instance, const char * queryAt
     generateOutput(instance);
 }
 
+bool EclCC::generatePrecompiledHeader()
+{
+    if (inputFiles.ordinality() != 0)
+    {
+        ERRLOG("No input files should be specified when generating precompiled header");
+        return false;
+    }
+    StringArray paths;
+    paths.appendList(cppIncludePath, ENVSEPSTR);
+    const char *foundPath = NULL;
+    ForEachItemIn(idx, paths)
+    {
+        StringBuffer fullpath;
+        fullpath.append(paths.item(idx));
+        addPathSepChar(fullpath).append("eclinclude.hpp");
+        if (checkFileExists(fullpath))
+        {
+            foundPath = paths.item(idx);
+            break;
+        }
+    }
+    if (!foundPath)
+    {
+        ERRLOG("Cannot find eclinclude.hpp");
+        return false;
+    }
+    Owned<ICppCompiler> compiler = createCompiler("eclinclude.hpp", foundPath, NULL);
+    compiler->setDebug(true);  // a precompiled header with debug can be used for no-debug, but not vice versa
+    compiler->setPrecompileHeader(true);
+    if (compiler->compile())
+    {
+        try
+        {
+            Owned<IFile> log = createIFile(cclogFilename);
+            log->remove();
+        }
+        catch (IException * e)
+        {
+            e->Release();
+        }
+        return true;
+    }
+    else
+    {
+        ERRLOG("Compilation failed - see %s for details", cclogFilename.str());
+        return false;
+    }
+}
+
 
 bool EclCC::processFiles()
 {
@@ -1265,7 +1315,11 @@ bool EclCC::processFiles()
     {
         processArgvFilename(inputFiles, inputFileNames.item(idx));
     }
-    if (inputFiles.ordinality() == 0)
+    if (optGenerateHeader)
+    {
+        return generatePrecompiledHeader();
+    }
+    else if (inputFiles.ordinality() == 0)
     {
         if (optBatchMode || !optQueryRepositoryReference)
         {
@@ -1431,6 +1485,9 @@ bool EclCC::parseCommandLineOptions(int argc, const char* argv[])
         else if (iter.matchFlag(optOutputDirectory, "-P"))
         {
         }
+        else if (iter.matchFlag(optGenerateHeader, "-pch"))
+        {
+        }
         else if (iter.matchFlag(optSaveQueryText, "-q"))
         {
         }
@@ -1531,7 +1588,7 @@ bool EclCC::parseCommandLineOptions(int argc, const char* argv[])
 
     if (inputFileNames.ordinality() == 0)
     {
-        if (!optBatchMode && optQueryRepositoryReference)
+        if (optGenerateHeader || (!optBatchMode && optQueryRepositoryReference))
             return true;
         ERRLOG("No input filenames supplied");
         return false;
@@ -1602,6 +1659,9 @@ const char * const helpText[] = {
 #ifdef _WIN32
     "!   -m            Enable leak checking",
 #endif
+#ifndef _WIN32
+    "!   -pch          Generate precompiled header for eclinclude.hpp",
+#endif
     "!   -P <path>     Specify the path of the output files (only with -b option)",
     "    -specs file   Read eclcc configuration from specified file",
     "!   -split m:n    Process a subset m of n input files (only with -b option)",

+ 2 - 0
system/include/platform.h

@@ -126,6 +126,7 @@ typedef memsize_t rowsize_t;
 #define TEXT_TRANS "t"
 #define LLC(NUM) NUM
 #define ENVSEPCHAR ';'
+#define ENVSEPSTR ";"
 
 #define SEPARATE_LIB_DLL_FILES
 #define SharedObjectPrefix         ""
@@ -282,6 +283,7 @@ typedef int socklen_t;
 #define __TIMESTAMP__ "<__TIMESTAMP__ unsupported>"
 #endif
 #define ENVSEPCHAR ':'
+#define ENVSEPSTR ":"
 #define PATHSEPCHAR '/'
 #define PATHSEPSTR "/"
 #define TEXT_TRANS

+ 26 - 4
system/jlib/jcomp.cpp

@@ -72,6 +72,7 @@ static const char * USE_INCLUDE_TAIL[] = { "\"", "\"" };
 static const char * INCLUDEPATH[] = { "\"#\\include\"", "\"#/include\"" };
 static const char * LINK_SEPARATOR[] = { " /link ", " " };
 static const char * OBJECT_FILE_EXT[] = { "obj", "o" };
+static const char * PCH_FILE_EXT[] = { "", "gch" };
 
 static const char * LIBFLAG_DEBUG[] = { "/MDd", "" };
 static const char * LIBFLAG_RELEASE[] = { "/MD", "" };
@@ -86,6 +87,8 @@ static const char * EXE_LINK_OPTION_DEBUG[] = { "/BASE:" BASE_ADDRESS " /NOLOGO
 
 static const char * CC_OPTION_RELEASE[] = { "/Zm500 /EHsc /GR /Oi /Ob1 /GF /nologo /bigobj", "-fPIC -pipe -O0" };
 
+static const char * CC_OPTION_PRECOMPILEHEADER[] = { "", " -x c++-header" };
+
 static const char * DLL_LINK_OPTION_RELEASE[] = { "/BASE:" BASE_ADDRESS " /NOLOGO /LARGEADDRESSAWARE /INCREMENTAL:NO", "-shared -L. -fPIC -pipe -O0" };
 static const char * EXE_LINK_OPTION_RELEASE[] = { "/BASE:" BASE_ADDRESS " /NOLOGO /LARGEADDRESSAWARE /INCREMENTAL:NO", "-L. -Wl,-E -fPIC -pipe -O0" };
 
@@ -254,6 +257,7 @@ CppCompiler::CppCompiler(const char * _coreName, const char * _sourceDir, const
     verbose = _verbose;
     saveTemps = false;
     abortChecker = NULL;
+    precompileHeader = false;
 }
 
 void CppCompiler::addCompileOption(const char * option)
@@ -261,6 +265,13 @@ void CppCompiler::addCompileOption(const char * option)
     compilerOptions.append(' ').append(option);
 }
 
+void CppCompiler::setPrecompileHeader(bool _pch)
+{
+    if (targetCompiler!=GccCppCompiler)
+        throw MakeStringException(0, "precompiled header generation only supported for g++ and compatible compilers");
+    precompileHeader = _pch;
+}
+
 void CppCompiler::addDefine(const char * symbolName, const char * value)
 {
     compilerOptions.append(" ").append(USE_DEFINE_FLAG[targetCompiler]).append(symbolName);
@@ -398,7 +409,7 @@ bool CppCompiler::compile()
 
     if (atomic_read(&numFailed) > 0)
         ret = false;
-    else if (!onlyCompile)
+    else if (!onlyCompile && !precompileHeader)
         ret = doLink();
 
     if (!saveTemps && !onlyCompile)
@@ -436,13 +447,19 @@ bool CppCompiler::compileFile(IThreadPool * pool, const char * filename, Semapho
         return false;
 
     StringBuffer cmdline;
-    cmdline.append(CC_NAME[targetCompiler]).append(" \"");
+    cmdline.append(CC_NAME[targetCompiler]);
+    if (precompileHeader)
+        cmdline.append(CC_OPTION_PRECOMPILEHEADER[targetCompiler]);
+    cmdline.append(" \"");
     if (sourceDir.length())
     {
         cmdline.append(sourceDir);
         addPathSepChar(cmdline);
     }
-    cmdline.append(filename).append(".cpp\" ");
+    cmdline.append(filename);
+    if (!precompileHeader)
+        cmdline.append(".cpp");
+    cmdline.append("\" ");
     expandCompileOptions(cmdline);
 
     if (useDebugLibrary)
@@ -460,7 +477,12 @@ bool CppCompiler::compileFile(IThreadPool * pool, const char * filename, Semapho
     }
     else
     {
-        cmdline.append(" -o ").append("\"").append(targetDir).append(filename).append('.').append(OBJECT_FILE_EXT[targetCompiler]).append("\"");
+        cmdline.append(" -o ").append("\"").append(targetDir).append(filename).append('.');
+        if (precompileHeader)
+            cmdline.append(PCH_FILE_EXT[targetCompiler]);
+        else
+            cmdline.append(OBJECT_FILE_EXT[targetCompiler]);
+        cmdline.append("\"");
     }
     
     StringBuffer expanded;

+ 1 - 0
system/jlib/jcomp.hpp

@@ -61,6 +61,7 @@ public:
     virtual void setMaxCompileThreads(const unsigned max) = 0;
     virtual void setCCLogPath(const char* path) = 0;
     virtual void setSaveTemps(bool _save) = 0;
+    virtual void setPrecompileHeader(bool _pch) = 0;
     virtual void setAbortChecker(IAbortRequestCallback * abortChecker) = 0;
 };
 

+ 2 - 0
system/jlib/jcomp.ipp

@@ -46,6 +46,7 @@ public:
     virtual IPooledThread *createNew();
     virtual void setCCLogPath(const char* path);
     virtual void setSaveTemps(bool _save) { saveTemps = _save; }
+    virtual void setPrecompileHeader(bool _pch);
     virtual void setAbortChecker(IAbortRequestCallback * _abortChecker) {abortChecker = _abortChecker;}
 
 protected:
@@ -78,6 +79,7 @@ protected:
     bool            verbose;
     void _addInclude(StringBuffer &s, const char *paths);
     bool            saveTemps;
+    bool            precompileHeader;
     IAbortRequestCallback * abortChecker;
 };