Просмотр исходного кода

ENH: add CMakeCache.txt support

Bill Hoffman 25 лет назад
Родитель
Сommit
0b0d1b1d43

+ 8 - 1
CMakeRules.make.in

@@ -20,9 +20,16 @@ depend: ${CMAKE} ${SUBDIR_DEPEND}
 clean: ${SUBDIR_CLEAN}
 	rm -f ${SRC_OBJ} ${EXECUTABLES} 
 
-CMakeTargets.make: ${CMAKE} ${srcdir}/CMakeLists.txt
+CMakeTargets.make: ${CMAKE} ${srcdir}/CMakeLists.txt 
 	${CMAKE} ${currentdir}/CMakeLists.txt -S${currentdir} -O${currentbindir} -H${topdir} -B${CMAKE_CONFIG_DIR}
 
+rebuild_cache: ${CMAKE_CONFIG_DIR}/CMakeCache.txt
+	rm -f ${CMAKE_CONFIG_DIR}/CMakeCache.txt
+	${CMAKE} ${topdir}/CMakeLists.txt -MakeCache -S${topdir} -O${CMAKE_CONFIG_DIR} -H${topdir} -B${CMAKE_CONFIG_DIR}
+
+${CMAKE_CONFIG_DIR}/CMakeCache.txt:
+	${CMAKE} ${topdir}/CMakeLists.txt -MakeCache -S${topdir} -O${CMAKE_CONFIG_DIR} -H${topdir} -B${CMAKE_CONFIG_DIR}
+
 #------------------------------------------------------------------------------
 # rules for the normal library
 #

+ 8 - 0
CMakeTopMakefileTemplate.in

@@ -0,0 +1,8 @@
+srcdir        = @srcdir@
+VPATH         = @srcdir@
+
+topall:
+	cd . ;  ${MAKE} -${MAKEFLAGS} CMakeTargets.make
+	cd . ;  ${MAKE} -${MAKEFLAGS} all
+
+@MAKEINCLUDE@ @MAKEQUOTE@@CMAKE_CONFIG_DIR@/CMake/CMakeMaster.make@MAKEQUOTE@

+ 31 - 2
Source/CMakeBuildTargets.cxx

@@ -43,6 +43,7 @@ int main(int ac, char** av)
   // Create a makefile
   cmMakefile mf;
   mf.AddDefinition("UNIX", "1");
+  bool makeCache = false;
   // Parse the command line
   if(ac > 2)
     {
@@ -50,6 +51,11 @@ int main(int ac, char** av)
       {
       std::string arg = av[i];
       // Set the start source directory with a -S dir options
+      if(arg.find("-MakeCache",0) == 0)
+	{
+        makeCache = true;
+	}
+      // Set the start source directory with a -S dir options
       if(arg.find("-S",0) == 0)
 	{
 	std::string path = arg.substr(2);
@@ -75,7 +81,12 @@ int main(int ac, char** av)
 	}
       }
     }
-  mf.SetMakefileGenerator(new cmUnixMakefileGenerator);
+  // Only generate makefiles if not trying to make the cache
+  if(!makeCache)
+    {
+    mf.SetMakefileGenerator(new cmUnixMakefileGenerator);
+    }
+  
 
   // Read and parse the input makefile
   mf.MakeStartDirectoriesCurrent();
@@ -85,6 +96,24 @@ int main(int ac, char** av)
     Usage(av[0]);
     return -1;
     }
-  mf.GenerateMakefile();
+  if(makeCache)
+    {
+    mf.GenerateCacheOnly();
+    }
+  else
+    {
+    mf.GenerateMakefile();
+    }
   cmCacheManager::GetInstance()->SaveCache(&mf);
+  if(makeCache)
+    {
+    cmCacheManager::GetInstance()->PrintCache(cout);
+    }
+  
+  if(cmSystemTools::GetErrorOccuredFlag())
+    {
+    return -1;
+    }
+  return 0;
 }
+

+ 18 - 1
Source/MFCDialog/CMakeSetupDialog.cpp

@@ -272,9 +272,26 @@ void CMakeSetupDialog::OnOK()
   mf.ReadListFile(makefileIn);
   // Move this to the cache editor
   mf.GenerateMakefile();
-  CDialog::OnOK();
   cmCacheManager::GetInstance()->SaveCache(&mf);
+  std::string command;
+  command = "notepad ";
+  std::string cachefile = m_WhereBuild;
+  cachefile += "/CMakeCache.txt";
+  command += cachefile.c_str();
+  long int originalMT = cmSystemTools::ModifiedTime(cachefile.c_str());
+  system(command.c_str());
+  long int afterEditMT = cmSystemTools::ModifiedTime(cachefile.c_str());
+  // if the cache was changed, re-generate the project
+  if(originalMT != afterEditMT)
+    {
+    cmCacheManager::GetInstance()->LoadCache(&mf);
+    mf.GenerateMakefile();
+    cmCacheManager::GetInstance()->SaveCache(&mf);
+    }
+  
+  // parent class 
   this->SaveToRegistry();
+  CDialog::OnOK();
 }
 
 void CMakeSetupDialog::OnButton3() 

+ 15 - 14
Source/Makefile.in

@@ -7,7 +7,7 @@ VPATH         = @srcdir@
 # command for changing into this directory
 
 # let cmake know that this was done with autoconf
-KIT_FLAGS = -DCMAKE_HAS_AUTOCONF
+KIT_FLAGS = -DCMAKE_HAS_AUTOCONF  -I${CMAKE_CONFIG_DIR}/CMake/Source 
 @MAKEINCLUDE@ @MAKEQUOTE@@CMAKE_CONFIG_DIR@/CMake/CMakeVariables.make@MAKEQUOTE@
 @MAKEINCLUDE@ @MAKEQUOTE@@CMAKE_CONFIG_DIR@/CMake/CMakeSimpleRules.make@MAKEQUOTE@
 
@@ -24,22 +24,23 @@ cmUnixMakefileGenerator.o \
 cmCommands.o \
 cmCacheManager.o
 
+DEPENDS = $(srcdir)/*.h ${CMAKE_CONFIG_DIR}/CMake/Source/cmConfigure.h
 
-cmCollectFlags.o : $(srcdir)/*.h 
-CMakeBuildTargets.o  : $(srcdir)/*.h
-cmMakeDepend.o : $(srcdir)/*.h
-cmMakefile.o : $(srcdir)/*.h
-cmMakefileGenerator.o : $(srcdir)/*.h
-cmAuxSourceDirectoryCommand.o : $(srcdir)/*.h
-cmRegularExpression.o : $(srcdir)/*.h
-cmClassFile.o : $(srcdir)/*.h
-cmDirectory.o : $(srcdir)/*.h
-cmUnixMakefileGenerator.o : $(srcdir)/*.h
-cmCommands.o : $(srcdir)/*.h
-cmCacheManager.o : $(srcdir)/*.h
+cmCollectFlags.o : $(DEPENDS)
+CMakeBuildTargets.o  : $(DEPENDS)
+cmMakeDepend.o : $(DEPENDS)
+cmMakefile.o : $(DEPENDS)
+cmMakefileGenerator.o : $(DEPENDS)
+cmAuxSourceDirectoryCommand.o : $(DEPENDS)
+cmRegularExpression.o : $(DEPENDS)
+cmClassFile.o : $(DEPENDS)
+cmDirectory.o : $(DEPENDS)
+cmUnixMakefileGenerator.o : $(DEPENDS)
+cmCommands.o : $(DEPENDS)
+cmCacheManager.o : $(DEPENDS)
 
 
 
 CMakeBuildTargets: ${OBJS}
-	${CXX}  ${OBJS} ${CXX_FLAGS}  -o CMakeBuildTargets
+	${CXX} ${OBJS} ${CXX_FLAGS}  -o CMakeBuildTargets
 

+ 51 - 11
Source/cmCacheManager.cxx

@@ -18,6 +18,7 @@
 #include "cmSystemTools.h"
 #include "cmCacheManager.h"
 #include "cmMakefile.h"
+#include "cmRegularExpression.h"
 
 const char* cmCacheManagerTypes[] = 
 { "BOOL",
@@ -68,21 +69,27 @@ bool cmCacheManager::LoadCache(cmMakefile* mf)
     }
   const int bsize = 4096;
   char buffer[bsize];
-  std::string inputLine;
+  // input line is:         key:type=value
+  cmRegularExpression reg("(.*):(.*)=(.*)");
   while(fin)
     {
     // Format is key:type=value
     CacheEntry e;
-    std::string key;
-    fin.getline(buffer, bsize, ':');
-    key = buffer;
-    fin.getline(buffer, bsize, '=');
-    e.m_Type = cmCacheManager::StringToType(buffer);
-    fin.getline(buffer, bsize); // last token is separated by a newline
-    e.m_Value = buffer;
-    if(fin)
+    fin.getline(buffer, bsize);
+    // skip blank lines and comment lines
+    if(buffer[0] == '#' || buffer[0] == 0)
       {
-      m_Cache[key] = e;
+      continue;
+      }
+    if(reg.find(buffer))
+      {
+      e.m_Type = cmCacheManager::StringToType(reg.match(2).c_str());
+      e.m_Value = reg.match(3);
+      m_Cache[reg.match(1)] = e;
+      }
+    else
+      {
+      cmSystemTools::Error("Parse error in cache file ", cacheFile.c_str());
       }
     }
   return true;
@@ -92,13 +99,25 @@ bool cmCacheManager::SaveCache(cmMakefile* mf)
 {
   std::string cacheFile = mf->GetHomeOutputDirectory();
   cacheFile += "/CMakeCache.txt";
-  std::ofstream fout(cacheFile.c_str());
+  std::string tempFile = cacheFile;
+  tempFile += ".tmp";
+  std::ofstream fout(tempFile.c_str());
   if(!fout)
     {
     cmSystemTools::Error("Unable to open cache file for save. ", 
                          cacheFile.c_str());
     return false;
     }
+  fout << "# This is the CMakeCache file.\n"
+       << "# You can edit this file to change values found and used by cmake.\n"
+       << "# If you do not want to change any of the values, simply exit the editor.\n"
+       << "# If you do want to change a value, simply edit, save, and exit the editor.\n"
+       << "# The syntax for the file is as follows:\n"
+       << "# KEY:TYPE=VALUE\n"
+       << "# KEY is the name of a varible in the cache.\n"
+       << "# TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT TYPE!.\n"
+       << "# VALUE is the current value for the KEY.\n\n";
+
   for( std::map<std::string, CacheEntry>::iterator i = m_Cache.begin();
        i != m_Cache.end(); ++i)
     {
@@ -109,6 +128,10 @@ bool cmCacheManager::SaveCache(cmMakefile* mf)
          << (*i).second.m_Value << "\n";
     }
   fout << "\n";
+  fout.close();
+  cmSystemTools::CopyFileIfDifferent(tempFile.c_str(),
+                                     cacheFile.c_str());
+  cmSystemTools::RemoveFile(tempFile.c_str());
   return true;
 }
 
@@ -130,3 +153,20 @@ const char* cmCacheManager::GetCacheValue(const char* key)
     }
   return 0;
 }
+
+
+void cmCacheManager::PrintCache(std::ostream& out)
+{
+  out << "=================================================" << std::endl;
+  out << "CMakeCache Contents:" << std::endl;
+  for(std::map<std::string, CacheEntry>::iterator i = m_Cache.begin();
+      i != m_Cache.end(); ++i)
+    {
+    out << (*i).first.c_str() << " = " << (*i).second.m_Value.c_str() << std::endl;
+    }
+  out << "\n\n";
+  out << "To change values in the CMakeCache, \nedit CMakeCache.txt in your output directory.\n";
+  out << "=================================================" << std::endl;
+}
+
+

+ 2 - 0
Source/cmCacheManager.h

@@ -52,6 +52,8 @@ public:
   //! Get a value from the cache given a key
   const char* GetCacheValue(const char* key);
   
+  //! Print the cache to a stream
+  void PrintCache(std::ostream&);
 private:
   static cmCacheManager* s_Instance;
   class CacheEntry

+ 2 - 0
Source/cmConfigure.h.in

@@ -0,0 +1,2 @@
+#undef CMAKE_NO_STD_NAMESPACE
+#undef CMAKE_NO_ANSI_STREAM_HEADERS

+ 16 - 5
Source/cmConfigureFileNoAutoconf.cxx

@@ -49,11 +49,13 @@ void cmConfigureFileNoAutoconf::FinalPass()
     std::string path = m_OuputFile.substr(0, pos);
     cmSystemTools::MakeDirectory(path.c_str());
     }
-  std::ofstream fout(m_OuputFile.c_str());
+  std::string tempOutputFile = m_OuputFile;
+  tempOutputFile += ".tmp";
+  std::ofstream fout(tempOutputFile.c_str());
   if(!fout)
     {
     cmSystemTools::Error("Could not open file for write in copy operatation", 
-                         m_OuputFile.c_str());
+                         tempOutputFile.c_str());
     return;
     }
   // now copy input to output and expand varibles in the
@@ -64,10 +66,19 @@ void cmConfigureFileNoAutoconf::FinalPass()
   while(fin)
     {
     fin.getline(buffer, bufSize);
-    inLine = buffer;
-    m_Makefile->ExpandVariablesInString(inLine);
-    fout << inLine << "\n";
+    if(fin)
+      {
+      inLine = buffer;
+      m_Makefile->ExpandVariablesInString(inLine);
+      fout << inLine << "\n";
+      }
     }
+  // close the files before attempting to copy
+  fin.close();
+  fout.close();
+  cmSystemTools::CopyFileIfDifferent(tempOutputFile.c_str(),
+                                     m_OuputFile.c_str());
+  cmSystemTools::RemoveFile(tempOutputFile.c_str());
 #endif
 }
 

+ 23 - 34
Source/cmDSPMakefile.cxx

@@ -16,15 +16,8 @@
 #include "cmDSPMakefile.h"
 #include "cmStandardIncludes.h"
 #include "cmSystemTools.h"
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef GetCurrentDirectory
 
-static void Die(const char* message)
-{
-  MessageBox(0, message, 0, MB_OK);
-  exit(-1);
-}
+
 cmDSPMakefile::~cmDSPMakefile()
 {
 }
@@ -37,7 +30,18 @@ cmDSPMakefile::cmDSPMakefile(cmMakefile*mf)
 
 void cmDSPMakefile::OutputDSPFile()
 { 
-  // Setup /I and /LIBPATH options
+  // If not an in source build, then create the output directory
+  if(strcmp(m_Makefile->GetStartOutputDirectory(),
+            m_Makefile->GetHomeDirectory()) != 0)
+    {
+    if(!cmSystemTools::MakeDirectory(m_Makefile->GetStartOutputDirectory()))
+      {
+      cmSystemTools::Error("Error creating directory ",
+                           m_Makefile->GetStartOutputDirectory());
+      }
+    }
+
+  // Setup /I and /LIBPATH options for the resulting DSP file
   std::vector<std::string>& includes = m_Makefile->GetIncludeDirectories();
   std::vector<std::string>::iterator i;
   for(i = includes.begin(); i != includes.end(); ++i)
@@ -77,20 +81,10 @@ void cmDSPMakefile::OutputDSPFile()
   // add any extra define flags 
   m_ReleaseLibraryOptions = m_DebugLibraryOptions;
   cmSystemTools::ReplaceString(m_ReleaseLibraryOptions, "Debug", "Release");
-  // If the output directory is not the m_cmHomeDirectory
-  // then create it.
-  if(strcmp(m_Makefile->GetStartOutputDirectory(),
-            m_Makefile->GetHomeDirectory()) != 0)
-    {
-    if(!cmSystemTools::MakeDirectory(m_Makefile->GetStartOutputDirectory()))
-      {
-      std::string message = "Error creating directory ";
-      message += m_Makefile->GetStartOutputDirectory();
-      Die(message.c_str());
-      }
-    }
   
-  // if there is a library, build it
+
+  
+  // Create the DSP or set of DSP's for libraries and executables
   if(strlen(m_Makefile->GetLibraryName()) != 0)
     {
     this->SetBuildType(STATIC_LIBRARY);
@@ -117,9 +111,8 @@ void cmDSPMakefile::CreateExecutableDSPFiles()
       std::ofstream fout(fname.c_str());
       if(!fout)
         {
-        std::string message = "Error Writing ";
-        message += fname;
-        Die(message.c_str());
+        cmSystemTools::Error("Error Writing ",
+                             fname.c_str());
         }
       else
         {
@@ -153,9 +146,8 @@ void cmDSPMakefile::CreateSingleDSP()
   std::ofstream fout(fname.c_str());
   if(!fout)
     {
-    std::string message = "Error Writing ";
-    message += fname;
-    Die(message.c_str());
+    cmSystemTools::Error("Error Writing ",
+                         fname.c_str());
     }
   this->WriteDSPFile(fout);
 }
@@ -257,9 +249,7 @@ void cmDSPMakefile::WriteDSPHeader(std::ostream& fout)
   std::ifstream fin(m_DSPHeaderTemplate.c_str());
   if(!fin)
     {
-    std::string message = "Error Reading ";
-    message += m_DSPHeaderTemplate;
-    Die(message.c_str());
+    cmSystemTools::Error("Error Reading ", m_DSPHeaderTemplate.c_str());
     }
   char buffer[2048];
 
@@ -288,9 +278,8 @@ void cmDSPMakefile::WriteDSPFooter(std::ostream& fout)
   std::ifstream fin(m_DSPFooterTemplate.c_str());
   if(!fin)
     {
-    std::string message = "Error Reading ";
-    message += m_DSPFooterTemplate;
-    Die(message.c_str());
+    cmSystemTools::Error("Error Reading ",
+                         m_DSPFooterTemplate.c_str());
     }
   char buffer[2048];
   while(fin)

+ 23 - 34
Source/cmDSPWriter.cxx

@@ -16,15 +16,8 @@
 #include "cmDSPMakefile.h"
 #include "cmStandardIncludes.h"
 #include "cmSystemTools.h"
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef GetCurrentDirectory
 
-static void Die(const char* message)
-{
-  MessageBox(0, message, 0, MB_OK);
-  exit(-1);
-}
+
 cmDSPMakefile::~cmDSPMakefile()
 {
 }
@@ -37,7 +30,18 @@ cmDSPMakefile::cmDSPMakefile(cmMakefile*mf)
 
 void cmDSPMakefile::OutputDSPFile()
 { 
-  // Setup /I and /LIBPATH options
+  // If not an in source build, then create the output directory
+  if(strcmp(m_Makefile->GetStartOutputDirectory(),
+            m_Makefile->GetHomeDirectory()) != 0)
+    {
+    if(!cmSystemTools::MakeDirectory(m_Makefile->GetStartOutputDirectory()))
+      {
+      cmSystemTools::Error("Error creating directory ",
+                           m_Makefile->GetStartOutputDirectory());
+      }
+    }
+
+  // Setup /I and /LIBPATH options for the resulting DSP file
   std::vector<std::string>& includes = m_Makefile->GetIncludeDirectories();
   std::vector<std::string>::iterator i;
   for(i = includes.begin(); i != includes.end(); ++i)
@@ -77,20 +81,10 @@ void cmDSPMakefile::OutputDSPFile()
   // add any extra define flags 
   m_ReleaseLibraryOptions = m_DebugLibraryOptions;
   cmSystemTools::ReplaceString(m_ReleaseLibraryOptions, "Debug", "Release");
-  // If the output directory is not the m_cmHomeDirectory
-  // then create it.
-  if(strcmp(m_Makefile->GetStartOutputDirectory(),
-            m_Makefile->GetHomeDirectory()) != 0)
-    {
-    if(!cmSystemTools::MakeDirectory(m_Makefile->GetStartOutputDirectory()))
-      {
-      std::string message = "Error creating directory ";
-      message += m_Makefile->GetStartOutputDirectory();
-      Die(message.c_str());
-      }
-    }
   
-  // if there is a library, build it
+
+  
+  // Create the DSP or set of DSP's for libraries and executables
   if(strlen(m_Makefile->GetLibraryName()) != 0)
     {
     this->SetBuildType(STATIC_LIBRARY);
@@ -117,9 +111,8 @@ void cmDSPMakefile::CreateExecutableDSPFiles()
       std::ofstream fout(fname.c_str());
       if(!fout)
         {
-        std::string message = "Error Writing ";
-        message += fname;
-        Die(message.c_str());
+        cmSystemTools::Error("Error Writing ",
+                             fname.c_str());
         }
       else
         {
@@ -153,9 +146,8 @@ void cmDSPMakefile::CreateSingleDSP()
   std::ofstream fout(fname.c_str());
   if(!fout)
     {
-    std::string message = "Error Writing ";
-    message += fname;
-    Die(message.c_str());
+    cmSystemTools::Error("Error Writing ",
+                         fname.c_str());
     }
   this->WriteDSPFile(fout);
 }
@@ -257,9 +249,7 @@ void cmDSPMakefile::WriteDSPHeader(std::ostream& fout)
   std::ifstream fin(m_DSPHeaderTemplate.c_str());
   if(!fin)
     {
-    std::string message = "Error Reading ";
-    message += m_DSPHeaderTemplate;
-    Die(message.c_str());
+    cmSystemTools::Error("Error Reading ", m_DSPHeaderTemplate.c_str());
     }
   char buffer[2048];
 
@@ -288,9 +278,8 @@ void cmDSPMakefile::WriteDSPFooter(std::ostream& fout)
   std::ifstream fin(m_DSPFooterTemplate.c_str());
   if(!fin)
     {
-    std::string message = "Error Reading ";
-    message += m_DSPFooterTemplate;
-    Die(message.c_str());
+    cmSystemTools::Error("Error Reading ",
+                         m_DSPFooterTemplate.c_str());
     }
   char buffer[2048];
   while(fin)

+ 43 - 116
Source/cmDSWMakefile.cxx

@@ -20,9 +20,6 @@
 #include "cmMSProjectGenerator.h"
 #include <windows.h>
 
-// microsoft nonsense
-#undef GetCurrentDirectory
-#undef SetCurrentDirectory
 
 cmDSWMakefile::cmDSWMakefile(cmMakefile* m)
 {
@@ -32,22 +29,17 @@ cmDSWMakefile::cmDSWMakefile(cmMakefile* m)
 // output the DSW file
 void cmDSWMakefile::OutputDSWFile()
 { 
-  if(m_Makefile->GetStartOutputDirectory() == "")
-    {
-    // default to build in place
-    m_Makefile->SetStartOutputDirectory(m_Makefile->GetHomeDirectory());
-    }
-  // If the output directory is not the m_cmHomeDirectory
-  // then create it.
+  // if this is an out of source build, create the output directory
   if(strcmp(m_Makefile->GetStartOutputDirectory(),
             m_Makefile->GetHomeDirectory()) != 0)
     {
     if(!cmSystemTools::MakeDirectory(m_Makefile->GetStartOutputDirectory()))
       {
-      MessageBox(0, "Error creating directory ", 0, MB_OK);
-      MessageBox(0, m_Makefile->GetStartOutputDirectory(), 0, MB_OK);
+      cmSystemTools::Error("Error creating output directory for DSW file",
+                           m_Makefile->GetStartOutputDirectory());
       }
     }
+  // create the dsw file name
   std::string fname;
   fname = m_Makefile->GetStartOutputDirectory();
   fname += "/";
@@ -56,139 +48,72 @@ void cmDSWMakefile::OutputDSWFile()
   std::ofstream fout(fname.c_str());
   if(!fout)
     {
-    cmSystemTools::Error("Error can not open for write: " , fname.c_str());
+    cmSystemTools::Error("Error can not open DSW file for write: "
+                         ,fname.c_str());
     return;
     }
   this->WriteDSWFile(fout);
 }
 
-// ------------------------------------------------
-// Recursive function to find all the CMakeLists.txt files
-// in a project.  As each file is read in, any directories in
-// the SUBDIR variable are also passed back to this function.
-// The result is a vector of cmDSPMakefile objects, one for
-// each directory with a CMakeLists.txt file
-//
-void 
-cmDSWMakefile
-::FindAllCMakeListsFiles(const char* subdir,
-                         std::vector<cmMSProjectGenerator*>& makefiles)
-{
-  std::string currentDir = m_Makefile->GetCurrentDirectory();
-  currentDir += "/";
-  currentDir += subdir;
-  currentDir += "/";
-  currentDir += "CMakeLists.txt";
-  // CMakeLists.txt exits in the subdirectory
-  // then create a cmDSPMakefile for it
-  if(cmSystemTools::FileExists(currentDir.c_str()))
-    {
-    // Create a new cmDSPMakefile to read the currentDir CMakeLists.txt file
-    cmMSProjectGenerator* pg = new cmMSProjectGenerator;
-    pg->BuildDSWOff();
-    cmMakefile* mf = new cmMakefile;
-    mf->SetMakefileGenerator(pg);
-    // add it to the vector
-    makefiles.push_back(pg);
-    // Set up the file with the current context
-    mf->SetHomeOutputDirectory(m_Makefile->GetStartOutputDirectory());
-    mf->SetHomeDirectory(m_Makefile->GetHomeDirectory());
-    // Set the output directory which may be different than the source
-    std::string outdir = m_Makefile->GetStartOutputDirectory();
-    outdir += "/";
-    outdir += subdir;
-    mf->SetStartOutputDirectory(outdir.c_str());
-    // set the current directory in the Source as a full
-    // path
-    std::string currentDir = m_Makefile->GetStartDirectory();
-    currentDir += "/";
-    currentDir += subdir;
-    mf->SetStartDirectory(currentDir.c_str());
-    // Parse the CMakeLists.txt file
-    currentDir += "/CMakeLists.txt";
-    mf->MakeStartDirectoriesCurrent();
-    mf->ReadListFile(currentDir.c_str());
-    // Create the DSP file
-    mf->GenerateMakefile();
-    // Look at any sub directories parsed (SUBDIRS) and 
-    // recurse into them    
-    const std::vector<std::string>& subdirs = mf->GetSubDirectories();
-    for(std::vector<std::string>::const_iterator i = subdirs.begin();
-	i != subdirs.end(); ++i)
-      {
-      // append the subdirectory to the current directoy subdir
-      std::string nextDir = subdir;
-      nextDir += "/";
-      nextDir += i->c_str();
-      // recurse into nextDir
-      this->FindAllCMakeListsFiles(nextDir.c_str(),
-				   makefiles);
-      }
-    }
-  else
-    {
-    cmSystemTools::Error("Can not find CMakeLists.txt in ",
-                         currentDir.c_str());
-    }
-}
-
 
 // Write a DSW file to the stream
 void cmDSWMakefile::WriteDSWFile(std::ostream& fout)
 {
   // Write out the header for a DSW file
   this->WriteDSWHeader(fout);
-  // Create an array of dsp files for the project
-  std::vector<cmMSProjectGenerator*> dspfiles;
-  // loop over all the subdirectories for the DSW file,
-  // and find all sub directory projects
-  const std::vector<std::string>& dirs = m_Makefile->GetSubDirectories();
-  for(std::vector<std::string>::const_iterator j = dirs.begin();
-      j != dirs.end(); ++j)
-    {
-    this->FindAllCMakeListsFiles(j->c_str(), dspfiles);
-    }
-  // For each DSP file created insert them into the DSW file
-  for(std::vector<cmMSProjectGenerator*>::iterator k = dspfiles.begin();
-      k != dspfiles.end(); ++k)
+  
+  // Create a list of cmMakefile created from all the
+  // CMakeLists.txt files that are in sub directories of
+  // this one.
+  std::vector<cmMakefile*> allListFiles;
+  m_Makefile->FindSubDirectoryCMakeListsFiles(allListFiles);
+  
+  // For each cmMakefile, create a DSP for it, and
+  // add it to this DSW file
+  for(std::vector<cmMakefile*>::iterator k = allListFiles.begin();
+      k != allListFiles.end(); ++k)
     {
-    // Get the directory for the dsp file, it comes
-    // from the source, so it has the source path which needs
-    // to be removed as this may be built in a different directory
-    // than the source
-    std::string dir = (*k)->GetDSPMakefile()->
-      GetMakefile()->GetStartDirectory();
+    cmMakefile* mf = *k;
+    // Create an MS generator with DSW off, so it only creates dsp files
+    cmMSProjectGenerator* pg = new cmMSProjectGenerator;
+    pg->BuildDSWOff();
+    mf->SetMakefileGenerator(pg);
+    mf->GenerateMakefile();
+    // Get the source directory from the makefile
+    std::string dir = mf->GetStartDirectory();
     // Get the home directory with the trailing slash
     std::string homedir = m_Makefile->GetHomeDirectory();
     homedir += "/";
-    // make the directory relative by removing the home directory part
+    // remove the home directory and / from the source directory
+    // this gives a relative path 
     cmSystemTools::ReplaceString(dir, homedir.c_str(), "");
-    // Get the list of create dsp files from the cmDSPMakefile, more
+    // Get the list of create dsp files names from the cmDSPMakefile, more
     // than one dsp could have been created per input CMakeLists.txt file
     std::vector<std::string> dspnames =
-      (*k)->GetDSPMakefile()->GetCreatedProjectNames();
+      pg->GetDSPMakefile()->GetCreatedProjectNames();
     for(std::vector<std::string>::iterator si = dspnames.begin();
 	si != dspnames.end(); ++si)
       {
       // Write the project into the DSW file
       this->WriteProject(fout, si->c_str(), dir.c_str(), 
-                         (*k)->GetDSPMakefile());
+                         pg->GetDSPMakefile());
       }
-    // delete the cmDSPMakefile object once done with it to avoid
-    // leaks
-    delete (*k)->GetDSPMakefile()->GetMakefile();
+    // delete the cmMakefile which also deletes the cmMSProjectGenerator
+    delete mf;
     }
   // Write the footer for the DSW file
   this->WriteDSWFooter(fout);
 }
 
 
+// Write a dsp file into the DSW file,
+// Note, that dependencies from executables to 
+// the libraries it uses are also done here
 void cmDSWMakefile::WriteProject(std::ostream& fout, 
 				 const char* dspname,
 				 const char* dir,
                                  cmDSPMakefile* project)
 {
-  project->GetMakefile()->ExpandVariables();
   fout << "#########################################################"
     "######################\n\n";
   fout << "Project: \"" << dspname << "\"=" 
@@ -204,17 +129,18 @@ void cmDSWMakefile::WriteProject(std::ostream& fout,
     end = project->GetMakefile()->GetLinkLibraries().end();
     for(;i!= end; ++i)
       {
-		if (strcmp(i->c_str(),dspname))
-			{
-			fout << "Begin Project Dependency\n";
-			fout << "Project_Dep_Name " << *i << "\n";
-			fout << "End Project Dependency\n";
-			}
+      if (strcmp(i->c_str(),dspname))
+        {
+        fout << "Begin Project Dependency\n";
+        fout << "Project_Dep_Name " << *i << "\n";
+        fout << "End Project Dependency\n";
+        }
       }
     }
   fout << "}}}\n\n";
 }
 
+// Standard end of dsw file
 void cmDSWMakefile::WriteDSWFooter(std::ostream& fout)
 {
   fout << "######################################################"
@@ -227,6 +153,7 @@ void cmDSWMakefile::WriteDSWFooter(std::ostream& fout)
 }
 
   
+// ouput standard header for dsw file
 void cmDSWMakefile::WriteDSWHeader(std::ostream& fout)
 {
   fout << "Microsoft Developer Studio Workspace File, Format Version 6.00\n";

+ 43 - 116
Source/cmDSWWriter.cxx

@@ -20,9 +20,6 @@
 #include "cmMSProjectGenerator.h"
 #include <windows.h>
 
-// microsoft nonsense
-#undef GetCurrentDirectory
-#undef SetCurrentDirectory
 
 cmDSWMakefile::cmDSWMakefile(cmMakefile* m)
 {
@@ -32,22 +29,17 @@ cmDSWMakefile::cmDSWMakefile(cmMakefile* m)
 // output the DSW file
 void cmDSWMakefile::OutputDSWFile()
 { 
-  if(m_Makefile->GetStartOutputDirectory() == "")
-    {
-    // default to build in place
-    m_Makefile->SetStartOutputDirectory(m_Makefile->GetHomeDirectory());
-    }
-  // If the output directory is not the m_cmHomeDirectory
-  // then create it.
+  // if this is an out of source build, create the output directory
   if(strcmp(m_Makefile->GetStartOutputDirectory(),
             m_Makefile->GetHomeDirectory()) != 0)
     {
     if(!cmSystemTools::MakeDirectory(m_Makefile->GetStartOutputDirectory()))
       {
-      MessageBox(0, "Error creating directory ", 0, MB_OK);
-      MessageBox(0, m_Makefile->GetStartOutputDirectory(), 0, MB_OK);
+      cmSystemTools::Error("Error creating output directory for DSW file",
+                           m_Makefile->GetStartOutputDirectory());
       }
     }
+  // create the dsw file name
   std::string fname;
   fname = m_Makefile->GetStartOutputDirectory();
   fname += "/";
@@ -56,139 +48,72 @@ void cmDSWMakefile::OutputDSWFile()
   std::ofstream fout(fname.c_str());
   if(!fout)
     {
-    cmSystemTools::Error("Error can not open for write: " , fname.c_str());
+    cmSystemTools::Error("Error can not open DSW file for write: "
+                         ,fname.c_str());
     return;
     }
   this->WriteDSWFile(fout);
 }
 
-// ------------------------------------------------
-// Recursive function to find all the CMakeLists.txt files
-// in a project.  As each file is read in, any directories in
-// the SUBDIR variable are also passed back to this function.
-// The result is a vector of cmDSPMakefile objects, one for
-// each directory with a CMakeLists.txt file
-//
-void 
-cmDSWMakefile
-::FindAllCMakeListsFiles(const char* subdir,
-                         std::vector<cmMSProjectGenerator*>& makefiles)
-{
-  std::string currentDir = m_Makefile->GetCurrentDirectory();
-  currentDir += "/";
-  currentDir += subdir;
-  currentDir += "/";
-  currentDir += "CMakeLists.txt";
-  // CMakeLists.txt exits in the subdirectory
-  // then create a cmDSPMakefile for it
-  if(cmSystemTools::FileExists(currentDir.c_str()))
-    {
-    // Create a new cmDSPMakefile to read the currentDir CMakeLists.txt file
-    cmMSProjectGenerator* pg = new cmMSProjectGenerator;
-    pg->BuildDSWOff();
-    cmMakefile* mf = new cmMakefile;
-    mf->SetMakefileGenerator(pg);
-    // add it to the vector
-    makefiles.push_back(pg);
-    // Set up the file with the current context
-    mf->SetHomeOutputDirectory(m_Makefile->GetStartOutputDirectory());
-    mf->SetHomeDirectory(m_Makefile->GetHomeDirectory());
-    // Set the output directory which may be different than the source
-    std::string outdir = m_Makefile->GetStartOutputDirectory();
-    outdir += "/";
-    outdir += subdir;
-    mf->SetStartOutputDirectory(outdir.c_str());
-    // set the current directory in the Source as a full
-    // path
-    std::string currentDir = m_Makefile->GetStartDirectory();
-    currentDir += "/";
-    currentDir += subdir;
-    mf->SetStartDirectory(currentDir.c_str());
-    // Parse the CMakeLists.txt file
-    currentDir += "/CMakeLists.txt";
-    mf->MakeStartDirectoriesCurrent();
-    mf->ReadListFile(currentDir.c_str());
-    // Create the DSP file
-    mf->GenerateMakefile();
-    // Look at any sub directories parsed (SUBDIRS) and 
-    // recurse into them    
-    const std::vector<std::string>& subdirs = mf->GetSubDirectories();
-    for(std::vector<std::string>::const_iterator i = subdirs.begin();
-	i != subdirs.end(); ++i)
-      {
-      // append the subdirectory to the current directoy subdir
-      std::string nextDir = subdir;
-      nextDir += "/";
-      nextDir += i->c_str();
-      // recurse into nextDir
-      this->FindAllCMakeListsFiles(nextDir.c_str(),
-				   makefiles);
-      }
-    }
-  else
-    {
-    cmSystemTools::Error("Can not find CMakeLists.txt in ",
-                         currentDir.c_str());
-    }
-}
-
 
 // Write a DSW file to the stream
 void cmDSWMakefile::WriteDSWFile(std::ostream& fout)
 {
   // Write out the header for a DSW file
   this->WriteDSWHeader(fout);
-  // Create an array of dsp files for the project
-  std::vector<cmMSProjectGenerator*> dspfiles;
-  // loop over all the subdirectories for the DSW file,
-  // and find all sub directory projects
-  const std::vector<std::string>& dirs = m_Makefile->GetSubDirectories();
-  for(std::vector<std::string>::const_iterator j = dirs.begin();
-      j != dirs.end(); ++j)
-    {
-    this->FindAllCMakeListsFiles(j->c_str(), dspfiles);
-    }
-  // For each DSP file created insert them into the DSW file
-  for(std::vector<cmMSProjectGenerator*>::iterator k = dspfiles.begin();
-      k != dspfiles.end(); ++k)
+  
+  // Create a list of cmMakefile created from all the
+  // CMakeLists.txt files that are in sub directories of
+  // this one.
+  std::vector<cmMakefile*> allListFiles;
+  m_Makefile->FindSubDirectoryCMakeListsFiles(allListFiles);
+  
+  // For each cmMakefile, create a DSP for it, and
+  // add it to this DSW file
+  for(std::vector<cmMakefile*>::iterator k = allListFiles.begin();
+      k != allListFiles.end(); ++k)
     {
-    // Get the directory for the dsp file, it comes
-    // from the source, so it has the source path which needs
-    // to be removed as this may be built in a different directory
-    // than the source
-    std::string dir = (*k)->GetDSPMakefile()->
-      GetMakefile()->GetStartDirectory();
+    cmMakefile* mf = *k;
+    // Create an MS generator with DSW off, so it only creates dsp files
+    cmMSProjectGenerator* pg = new cmMSProjectGenerator;
+    pg->BuildDSWOff();
+    mf->SetMakefileGenerator(pg);
+    mf->GenerateMakefile();
+    // Get the source directory from the makefile
+    std::string dir = mf->GetStartDirectory();
     // Get the home directory with the trailing slash
     std::string homedir = m_Makefile->GetHomeDirectory();
     homedir += "/";
-    // make the directory relative by removing the home directory part
+    // remove the home directory and / from the source directory
+    // this gives a relative path 
     cmSystemTools::ReplaceString(dir, homedir.c_str(), "");
-    // Get the list of create dsp files from the cmDSPMakefile, more
+    // Get the list of create dsp files names from the cmDSPMakefile, more
     // than one dsp could have been created per input CMakeLists.txt file
     std::vector<std::string> dspnames =
-      (*k)->GetDSPMakefile()->GetCreatedProjectNames();
+      pg->GetDSPMakefile()->GetCreatedProjectNames();
     for(std::vector<std::string>::iterator si = dspnames.begin();
 	si != dspnames.end(); ++si)
       {
       // Write the project into the DSW file
       this->WriteProject(fout, si->c_str(), dir.c_str(), 
-                         (*k)->GetDSPMakefile());
+                         pg->GetDSPMakefile());
       }
-    // delete the cmDSPMakefile object once done with it to avoid
-    // leaks
-    delete (*k)->GetDSPMakefile()->GetMakefile();
+    // delete the cmMakefile which also deletes the cmMSProjectGenerator
+    delete mf;
     }
   // Write the footer for the DSW file
   this->WriteDSWFooter(fout);
 }
 
 
+// Write a dsp file into the DSW file,
+// Note, that dependencies from executables to 
+// the libraries it uses are also done here
 void cmDSWMakefile::WriteProject(std::ostream& fout, 
 				 const char* dspname,
 				 const char* dir,
                                  cmDSPMakefile* project)
 {
-  project->GetMakefile()->ExpandVariables();
   fout << "#########################################################"
     "######################\n\n";
   fout << "Project: \"" << dspname << "\"=" 
@@ -204,17 +129,18 @@ void cmDSWMakefile::WriteProject(std::ostream& fout,
     end = project->GetMakefile()->GetLinkLibraries().end();
     for(;i!= end; ++i)
       {
-		if (strcmp(i->c_str(),dspname))
-			{
-			fout << "Begin Project Dependency\n";
-			fout << "Project_Dep_Name " << *i << "\n";
-			fout << "End Project Dependency\n";
-			}
+      if (strcmp(i->c_str(),dspname))
+        {
+        fout << "Begin Project Dependency\n";
+        fout << "Project_Dep_Name " << *i << "\n";
+        fout << "End Project Dependency\n";
+        }
       }
     }
   fout << "}}}\n\n";
 }
 
+// Standard end of dsw file
 void cmDSWMakefile::WriteDSWFooter(std::ostream& fout)
 {
   fout << "######################################################"
@@ -227,6 +153,7 @@ void cmDSWMakefile::WriteDSWFooter(std::ostream& fout)
 }
 
   
+// ouput standard header for dsw file
 void cmDSWMakefile::WriteDSWHeader(std::ostream& fout)
 {
   fout << "Microsoft Developer Studio Workspace File, Format Version 6.00\n";

+ 65 - 0
Source/cmMakefile.cxx

@@ -460,3 +460,68 @@ void cmMakefile::ExpandVariablesInString(std::string& source)
     }
 }
 
+
+// recursive function to create a vector of cmMakefile objects
+// This is done by reading the sub directory CMakeLists.txt files,
+// then calling this function with the new cmMakefile object
+void 
+cmMakefile::FindSubDirectoryCMakeListsFiles(std::vector<cmMakefile*>&
+                                            makefiles)
+{ 
+  // loop over all the sub directories of this makefile
+  const std::vector<std::string>& subdirs = this->GetSubDirectories();
+  for(std::vector<std::string>::const_iterator i = subdirs.begin();
+      i != subdirs.end(); ++i)
+    {
+    std::string subdir = *i;
+    // Create a path to the list file in the sub directory
+    std::string listFile = this->GetCurrentDirectory();
+    listFile += "/";
+    listFile += subdir;
+    listFile += "/CMakeLists.txt";
+    // if there is a CMakeLists.txt file read it
+    if(!cmSystemTools::FileExists(listFile.c_str()))
+      {
+      cmSystemTools::Error("CMakeLists.txt file missing from sub directory:",
+                           listFile.c_str());
+      }
+    else
+      {
+      cmMakefile* mf = new cmMakefile;
+      makefiles.push_back(mf);
+      // initialize new makefile
+      mf->SetHomeOutputDirectory(this->GetHomeOutputDirectory());
+      mf->SetHomeDirectory(this->GetHomeDirectory());
+      // add the subdir to the start output directory
+      std::string outdir = this->GetStartOutputDirectory();
+      outdir += "/";
+      outdir += subdir;
+      mf->SetStartOutputDirectory(outdir.c_str());
+      // add the subdir to the start source directory
+      std::string currentDir = this->GetStartDirectory();
+      currentDir += "/";
+      currentDir += subdir;
+      mf->SetStartDirectory(currentDir.c_str());
+      // Parse the CMakeLists.txt file
+      currentDir += "/CMakeLists.txt";
+      mf->MakeStartDirectoriesCurrent();
+      mf->ReadListFile(currentDir.c_str());
+      // recurse into nextDir
+      mf->FindSubDirectoryCMakeListsFiles(makefiles);
+      }
+    }
+}
+
+      
+void cmMakefile::GenerateCacheOnly()
+{
+  std::vector<cmMakefile*> makefiles;
+  this->FindSubDirectoryCMakeListsFiles(makefiles);
+  for(int i =0; i < makefiles.size(); ++i)
+    {
+    delete makefiles[i];
+    }
+}
+
+  
+

+ 13 - 0
Source/cmMakefile.h

@@ -346,6 +346,19 @@ public:
    */
   void ExpandVariables();
 
+  /** Recursivly read and create a cmMakefile object for
+   *  all CMakeLists.txt files in the GetSubDirectories list.
+   *  Once the file is found, it ReadListFile is called on
+   *  the cmMakefile created for it.
+   */
+  void FindSubDirectoryCMakeListsFiles(std::vector<cmMakefile*>& makefiles);
+  
+  /** Generate the cache file only.  This is done
+   *  by calling FindSubDirectoryCMakeListsFiles which
+   *  will cause all the rules to fire, and the cache to
+   *  be filled.
+   */
+  void GenerateCacheOnly();
 protected:
   std::string m_Prefix;
   std::vector<std::string> m_AuxSourceDirectories; // 

+ 5 - 0
Source/cmStandardIncludes.h

@@ -20,6 +20,11 @@
 #ifndef cmStandardIncludes_h
 #define cmStandardIncludes_h
 
+// include configure generated  header to define
+// CMAKE_NO_ANSI_STREAM_HEADERS and CMAKE_NO_STD_NAMESPACE
+#ifdef CMAKE_HAS_AUTOCONF
+#include "cmConfigure.h"
+#endif
 
 #ifdef _MSC_VER
 #pragma warning ( disable : 4786 )

+ 102 - 0
Source/cmSystemTools.cxx

@@ -15,12 +15,14 @@
 =========================================================================*/
 #include "cmSystemTools.h"
 #include "errno.h"
+#include "stdio.h"
 #include <sys/stat.h>
 #include "cmRegularExpression.h"
 
 #if defined(_MSC_VER) || defined(__BORLANDC__)
 #include <windows.h>
 #include <direct.h>
+#define _unlink unlink
 inline int Mkdir(const char* dir)
 {
   return _mkdir(dir);
@@ -35,6 +37,8 @@ inline int Mkdir(const char* dir)
 }
 #endif
 
+bool cmSystemTools::s_ErrorOccured = false;
+
 // adds the elements of the env variable path to the arg passed in
 void cmSystemTools::GetPath(std::vector<std::string>& path)
 {
@@ -327,6 +331,7 @@ void cmSystemTools::Error(const char* m1, const char* m2)
     {
     message += m2;
     }
+  cmSystemTools::s_ErrorOccured = true;
 #if defined(_WIN32) && !defined(__CYGWIN__)
   ::MessageBox(0, message.c_str(), 0, MB_OK);
   std::cerr << message.c_str() << std::endl;
@@ -335,3 +340,100 @@ void cmSystemTools::Error(const char* m1, const char* m2)
 #endif
 }
 
+
+
+void cmSystemTools::CopyFileIfDifferent(const char* source,
+                                        const char* destination)
+{
+  if(cmSystemTools::FilesDiffer(source, destination))
+    {
+    cmSystemTools::Error("doing copy ", destination);
+    cmSystemTools::cmCopyFile(source, destination);
+    }
+}
+
+  
+bool cmSystemTools::FilesDiffer(const char* source,
+                                const char* destination)
+{
+  struct stat statSource;
+  if (stat(source, &statSource) != 0) 
+    {
+    return true;
+    }
+  struct stat statDestination;
+  if (stat(destination, &statDestination) != 0) 
+    {
+    return true;
+    }
+  if(statSource.st_size != statDestination.st_size)
+    {
+    return true;
+    }
+  std::ifstream finSource(source);
+  std::ifstream finDestination(destination);
+  if(!finSource || !finDestination)
+    {
+    return true;
+    }
+  
+  while(finSource && finDestination)
+    {
+    char s, d;
+    finSource >> s;
+    finDestination >> d;
+    if(s != d)
+      {
+      return true;
+      }
+    }
+  return false;
+}
+
+
+
+void cmSystemTools::cmCopyFile(const char* source,
+                             const char* destination)
+{
+  std::ifstream fin(source);
+  char buff[4096];
+  std::ofstream fout(destination);
+  if(!fout )
+    {
+    cmSystemTools::Error("CopyFile failed to open input file", source);
+    }
+  if(!fin)
+    {
+    cmSystemTools::Error("CopyFile failed to open output file", destination);
+    }
+  while(fin)
+    {
+    fin.getline(buff, 4096);
+    if(fin)
+      {
+      fout << buff << "\n";
+      }
+    }
+}
+
+// return true if the file exists
+long int cmSystemTools::ModifiedTime(const char* filename)
+{
+  struct stat fs;
+  if (stat(filename, &fs) != 0) 
+    {
+    return 0;
+    }
+  else
+    {
+    return (long int)fs.st_mtime;
+    }
+}
+
+
+  
+void cmSystemTools::RemoveFile(const char* source)
+{
+  unlink(source);
+}
+

+ 30 - 3
Source/cmSystemTools.h

@@ -47,9 +47,7 @@ public:
    */
   static void ConvertToUnixSlashes(std::string& path);
  
-  /**
-   * Return true if a file exists in the current directory.
-   */
+  ///! Return true if a file exists in the current directory.
   static bool FileExists(const char* filename);
 
   /**
@@ -91,7 +89,36 @@ public:
    * Display an error message.
    */
   static void Error(const char* m, const char* m2=0 );
+
+  ///! Return true if there was an error at any point.
+  static bool GetErrorOccuredFlag() 
+    {
+      return cmSystemTools::s_ErrorOccured;
+    }
+  
+  /**
+   * Copy the source file to the destination file only
+   * if the two files differ.  
+   */
+  static void CopyFileIfDifferent(const char* source,
+                                  const char* destination);
   
+  ///! Compare the contents of two files.  Return true if different.
+  static bool FilesDiffer(const char* source,
+                          const char* destination);
+  ///! Copy a file.
+  static void cmCopyFile(const char* source,
+                       const char* destination);
+  
+  ///! Remove a file.
+  static void RemoveFile(const char* source);
+  
+  
+  static long int ModifiedTime(const char* filename);
+  
+
+private:
+  static bool s_ErrorOccured;
 };