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
This commit is contained in:
parent
af61b68583
commit
55a71ba572
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -83,6 +83,18 @@ public:
|
|||
{ 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
|
||||
* loaded commands, not as part of the usual build process.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -258,6 +258,10 @@ class cmake
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue