summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorAndy Cedilnik <andy.cedilnik@kitware.com>2004-04-18 18:41:46 (GMT)
committerAndy Cedilnik <andy.cedilnik@kitware.com>2004-04-18 18:41:46 (GMT)
commit55a71ba572c54dbb3485a76e9615c1c8bf688fd4 (patch)
treeac692b4ef198284cf7c0e9b65ab854f93e7f865a /Source
parentaf61b685839fae6af72ba4c4d42ebf39a7d1a324 (diff)
downloadCMake-55a71ba572c54dbb3485a76e9615c1c8bf688fd4.zip
CMake-55a71ba572c54dbb3485a76e9615c1c8bf688fd4.tar.gz
CMake-55a71ba572c54dbb3485a76e9615c1c8bf688fd4.tar.bz2
ENH: Add check for infinite loops. Make sure that files written using WRITE_FILE and FILE WRITE are not used as input files. Fixes Bug #678 - WRITE_FILE and FILE(WRITE...) lead to infinite loops
Diffstat (limited to 'Source')
-rw-r--r--Source/cmFileCommand.cxx1
-rw-r--r--Source/cmFileCommand.h4
-rw-r--r--Source/cmGlobalGenerator.cxx1
-rw-r--r--Source/cmMakefile.cxx21
-rw-r--r--Source/cmMakefile.h12
-rw-r--r--Source/cmWriteFileCommand.cxx1
-rw-r--r--Source/cmWriteFileCommand.h8
-rw-r--r--Source/cmake.cxx10
-rw-r--r--Source/cmake.h8
9 files changed, 64 insertions, 2 deletions
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 04608b5..ecac040 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -100,6 +100,7 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args,
}
file << message;
file.close();
+ m_Makefile->AddWrittenFile(fileName.c_str());
return true;
}
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 60e25e8..5d00acf 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -81,6 +81,10 @@ public:
"if it does not exists.\n"
"APPEND will write a message into a file same as WRITE, except "
"it will append it to the end of the file\n"
+ "NOTE: When using FILE WRITE and FILE APPEND, the produced file "
+ "cannot be used as an input to CMake (CONFIGURE_FILE, source file ...) "
+ "because it will lead to infinite loop. Use CONFIGURE_FILE if you "
+ "want to generate input files to CMake.\n"
"READ will read the content of a file and store it into the "
"variable.\n"
"GLOB will generate a list of all files that match the globbing "
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index b09ab9d..1315bb6 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -326,6 +326,7 @@ void cmGlobalGenerator::Configure()
}
m_CMakeInstance->UpdateProgress("Configuring",
0.9f+0.1f*(i+1.0f)/m_LocalGenerators.size());
+ m_LocalGenerators[i]->GetMakefile()->CheckInfiniteLoops();
}
}
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 4f287f6..59b270a 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -2357,5 +2357,26 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
return 1;
}
+void cmMakefile::AddWrittenFile(const char* file)
+{ this->GetCMakeInstance()->AddWrittenFile(file); }
+bool cmMakefile::HasWrittenFile(const char* file)
+{ return this->GetCMakeInstance()->HasWrittenFile(file); }
+bool cmMakefile::CheckInfiniteLoops()
+{
+ std::vector<std::string>::iterator it;
+ for ( it = m_ListFiles.begin();
+ it != m_ListFiles.end();
+ ++ it )
+ {
+ if ( this->HasWrittenFile(it->c_str()) )
+ {
+ cmOStringStream str;
+ str << "File " << it->c_str() << " is written by WRITE_FILE (or FILE WRITE) command and should not be used as input to CMake. Please use CONFIGURE_FILE to be safe. Refer to the note next to FILE WRITE command.";
+ cmSystemTools::Error(str.str().c_str());
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 092d742..194729e 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -82,6 +82,18 @@ public:
void RemoveFunctionBlocker(cmFunctionBlocker *fb)
{ m_FunctionBlockers.remove(fb);}
void RemoveFunctionBlocker(const cmListFileFunction& lff);
+
+ /**
+ * Add file to the written file list. These file should not be in the list
+ * of dependencies because they cause infinite loops.
+ */
+ void AddWrittenFile(const char* file);
+ bool HasWrittenFile(const char* file);
+
+ /**
+ * Check if there are any infinite loops
+ */
+ bool CheckInfiniteLoops();
/**
* Try running cmake and building a file. This is used for dynalically
diff --git a/Source/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx
index 79a8b46..dbf14ec 100644
--- a/Source/cmWriteFileCommand.cxx
+++ b/Source/cmWriteFileCommand.cxx
@@ -55,6 +55,7 @@ bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args)
}
file << message << std::endl;
file.close();
+ m_Makefile->AddWrittenFile(fileName.c_str());
return true;
}
diff --git a/Source/cmWriteFileCommand.h b/Source/cmWriteFileCommand.h
index ef2561d..31e1687 100644
--- a/Source/cmWriteFileCommand.h
+++ b/Source/cmWriteFileCommand.h
@@ -67,7 +67,13 @@ public:
" WRITE_FILE(filename \"message to write\"... [APPEND])\n"
"The first argument is the file name, the rest of the arguments are "
"messages to write. If the argument APPEND is specified, then "
- "the message will be appended.";
+ "the message will be appended.\n"
+ "NOTE 1: FILE WRITE and FILE APPEND do exactly the same as this one "
+ "but add some more functionality.\n"
+ "NOTE 2: When using WRITE_FILE the produced file cannot be used as an "
+ "input to CMake (CONFIGURE_FILE, source file ...) because it will "
+ "lead to infinite loop. Use CONFIGURE_FILE if you want to generate "
+ "input files to CMake.";
}
cmTypeMacro(cmWriteFileCommand, cmCommand);
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 5ce680e..a49559b 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -1416,3 +1416,13 @@ void cmake::GetGeneratorDocumentation(std::vector<cmDocumentationEntry>& v)
cmDocumentationEntry empty = {0,0,0};
v.push_back(empty);
}
+
+void cmake::AddWrittenFile(const char* file)
+{
+ m_WrittenFiles.insert(file);
+}
+
+bool cmake::HasWrittenFile(const char* file)
+{
+ return m_WrittenFiles.find(file) != m_WrittenFiles.end();
+}
diff --git a/Source/cmake.h b/Source/cmake.h
index 833b454..dc79604 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -257,7 +257,11 @@ class cmake
///! Debug the try compile stuff by not delelting the files
bool GetDebugTryCompile(){return m_DebugTryCompile;}
void DebugTryCompileOn(){m_DebugTryCompile = true;}
-
+
+ ///! Get the list of files written by CMake using FILE(WRITE / WRITE_FILE
+ void AddWrittenFile(const char* file);
+ bool HasWrittenFile(const char* file);
+
protected:
typedef cmGlobalGenerator* (*CreateGeneratorFunctionType)();
typedef std::map<cmStdString, CreateGeneratorFunctionType> RegisteredGeneratorsMap;
@@ -273,6 +277,8 @@ protected:
std::string m_cmStartDirectory;
std::string m_StartOutputDirectory;
+ std::set<cmStdString> m_WrittenFiles;
+
///! return true if the same cmake was used to make the cache.
bool CacheVersionMatches();
///! read in a cmake list file to initialize the cache