From 0b0d1b1d436c6e59ed9ea5c25e1f454fc0ae7827 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Thu, 22 Feb 2001 19:24:43 -0500 Subject: ENH: add CMakeCache.txt support --- CMakeRules.make.in | 9 +- CMakeTopMakefileTemplate.in | 8 ++ Source/CMakeBuildTargets.cxx | 33 ++++++- Source/MFCDialog/CMakeSetupDialog.cpp | 19 +++- Source/Makefile.in | 29 ++++--- Source/cmCacheManager.cxx | 62 ++++++++++--- Source/cmCacheManager.h | 2 + Source/cmConfigure.h.in | 2 + Source/cmConfigureFileNoAutoconf.cxx | 21 +++-- Source/cmDSPMakefile.cxx | 57 +++++------- Source/cmDSPWriter.cxx | 57 +++++------- Source/cmDSWMakefile.cxx | 159 +++++++++------------------------- Source/cmDSWWriter.cxx | 159 +++++++++------------------------- Source/cmMakefile.cxx | 65 ++++++++++++++ Source/cmMakefile.h | 13 +++ Source/cmStandardIncludes.h | 5 ++ Source/cmSystemTools.cxx | 102 ++++++++++++++++++++++ Source/cmSystemTools.h | 33 ++++++- 18 files changed, 498 insertions(+), 337 deletions(-) create mode 100644 CMakeTopMakefileTemplate.in create mode 100644 Source/cmConfigure.h.in diff --git a/CMakeRules.make.in b/CMakeRules.make.in index 11b813b..7b73ca5 100644 --- a/CMakeRules.make.in +++ b/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 # diff --git a/CMakeTopMakefileTemplate.in b/CMakeTopMakefileTemplate.in new file mode 100644 index 0000000..3780cb3 --- /dev/null +++ b/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@ diff --git a/Source/CMakeBuildTargets.cxx b/Source/CMakeBuildTargets.cxx index 243cac0..8b6adba 100644 --- a/Source/CMakeBuildTargets.cxx +++ b/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; } + diff --git a/Source/MFCDialog/CMakeSetupDialog.cpp b/Source/MFCDialog/CMakeSetupDialog.cpp index c9c8e86..97b80ee 100644 --- a/Source/MFCDialog/CMakeSetupDialog.cpp +++ b/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() diff --git a/Source/Makefile.in b/Source/Makefile.in index 620d255..fcaeb9a 100644 --- a/Source/Makefile.in +++ b/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 diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index f1682a9..0dbdd9d 100644 --- a/Source/cmCacheManager.cxx +++ b/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::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::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; +} + + diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index f983ea5..7ed5f92 100644 --- a/Source/cmCacheManager.h +++ b/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 diff --git a/Source/cmConfigure.h.in b/Source/cmConfigure.h.in new file mode 100644 index 0000000..bcdd682 --- /dev/null +++ b/Source/cmConfigure.h.in @@ -0,0 +1,2 @@ +#undef CMAKE_NO_STD_NAMESPACE +#undef CMAKE_NO_ANSI_STREAM_HEADERS diff --git a/Source/cmConfigureFileNoAutoconf.cxx b/Source/cmConfigureFileNoAutoconf.cxx index 4d60e81..270c4fb 100644 --- a/Source/cmConfigureFileNoAutoconf.cxx +++ b/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 } diff --git a/Source/cmDSPMakefile.cxx b/Source/cmDSPMakefile.cxx index f43afce..6d61c25 100644 --- a/Source/cmDSPMakefile.cxx +++ b/Source/cmDSPMakefile.cxx @@ -16,15 +16,8 @@ #include "cmDSPMakefile.h" #include "cmStandardIncludes.h" #include "cmSystemTools.h" -#define WIN32_LEAN_AND_MEAN -#include -#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& includes = m_Makefile->GetIncludeDirectories(); std::vector::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) diff --git a/Source/cmDSPWriter.cxx b/Source/cmDSPWriter.cxx index f43afce..6d61c25 100644 --- a/Source/cmDSPWriter.cxx +++ b/Source/cmDSPWriter.cxx @@ -16,15 +16,8 @@ #include "cmDSPMakefile.h" #include "cmStandardIncludes.h" #include "cmSystemTools.h" -#define WIN32_LEAN_AND_MEAN -#include -#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& includes = m_Makefile->GetIncludeDirectories(); std::vector::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) diff --git a/Source/cmDSWMakefile.cxx b/Source/cmDSWMakefile.cxx index 082f64e..991bac1 100644 --- a/Source/cmDSWMakefile.cxx +++ b/Source/cmDSWMakefile.cxx @@ -20,9 +20,6 @@ #include "cmMSProjectGenerator.h" #include -// 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& 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& subdirs = mf->GetSubDirectories(); - for(std::vector::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 dspfiles; - // loop over all the subdirectories for the DSW file, - // and find all sub directory projects - const std::vector& dirs = m_Makefile->GetSubDirectories(); - for(std::vector::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::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 allListFiles; + m_Makefile->FindSubDirectoryCMakeListsFiles(allListFiles); + + // For each cmMakefile, create a DSP for it, and + // add it to this DSW file + for(std::vector::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 dspnames = - (*k)->GetDSPMakefile()->GetCreatedProjectNames(); + pg->GetDSPMakefile()->GetCreatedProjectNames(); for(std::vector::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"; diff --git a/Source/cmDSWWriter.cxx b/Source/cmDSWWriter.cxx index 082f64e..991bac1 100644 --- a/Source/cmDSWWriter.cxx +++ b/Source/cmDSWWriter.cxx @@ -20,9 +20,6 @@ #include "cmMSProjectGenerator.h" #include -// 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& 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& subdirs = mf->GetSubDirectories(); - for(std::vector::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 dspfiles; - // loop over all the subdirectories for the DSW file, - // and find all sub directory projects - const std::vector& dirs = m_Makefile->GetSubDirectories(); - for(std::vector::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::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 allListFiles; + m_Makefile->FindSubDirectoryCMakeListsFiles(allListFiles); + + // For each cmMakefile, create a DSP for it, and + // add it to this DSW file + for(std::vector::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 dspnames = - (*k)->GetDSPMakefile()->GetCreatedProjectNames(); + pg->GetDSPMakefile()->GetCreatedProjectNames(); for(std::vector::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"; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 1acaf7c..7c8f7e0 100644 --- a/Source/cmMakefile.cxx +++ b/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& + makefiles) +{ + // loop over all the sub directories of this makefile + const std::vector& subdirs = this->GetSubDirectories(); + for(std::vector::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 makefiles; + this->FindSubDirectoryCMakeListsFiles(makefiles); + for(int i =0; i < makefiles.size(); ++i) + { + delete makefiles[i]; + } +} + + + diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 2556601..6e8a0fe 100644 --- a/Source/cmMakefile.h +++ b/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& 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 m_AuxSourceDirectories; // diff --git a/Source/cmStandardIncludes.h b/Source/cmStandardIncludes.h index 88bc306..0aed2a7 100644 --- a/Source/cmStandardIncludes.h +++ b/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 ) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index ce2ebc8..141b4ea 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -15,12 +15,14 @@ =========================================================================*/ #include "cmSystemTools.h" #include "errno.h" +#include "stdio.h" #include #include "cmRegularExpression.h" #if defined(_MSC_VER) || defined(__BORLANDC__) #include #include +#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& 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); +} + diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index bdcac7a..6175623 100644 --- a/Source/cmSystemTools.h +++ b/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; }; -- cgit v0.12