ENH: Split dependency scanning and checking into separate cmDepends superclass with language-specific subclasses such as cmDependsC.
This commit is contained in:
parent
ed9e0626fd
commit
195cdf172e
|
@ -46,6 +46,11 @@ SET(SRCS
|
||||||
cmake.h
|
cmake.h
|
||||||
cmakewizard.cxx
|
cmakewizard.cxx
|
||||||
cmakewizard.h
|
cmakewizard.h
|
||||||
|
|
||||||
|
cmDepends.h
|
||||||
|
cmDepends.cxx
|
||||||
|
cmDependsC.h
|
||||||
|
cmDependsC.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*=========================================================================
|
||||||
|
|
||||||
|
Program: CMake - Cross-Platform Makefile Generator
|
||||||
|
Module: $RCSfile$
|
||||||
|
Language: C++
|
||||||
|
Date: $Date$
|
||||||
|
Version: $Revision$
|
||||||
|
|
||||||
|
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||||
|
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||||
|
|
||||||
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||||
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. See the above copyright notices for more information.
|
||||||
|
|
||||||
|
=========================================================================*/
|
||||||
|
#include "cmDepends.h"
|
||||||
|
|
||||||
|
#include "cmGeneratedFileStream.h"
|
||||||
|
#include "cmSystemTools.h"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
cmDepends::cmDepends(const char* dir, const char* targetFile):
|
||||||
|
m_Directory(dir),
|
||||||
|
m_TargetFile(targetFile),
|
||||||
|
m_DependsMakeFile(dir),
|
||||||
|
m_DependsMarkFile(dir)
|
||||||
|
{
|
||||||
|
// Construct the path to the make and mark files. Append
|
||||||
|
// appropriate extensions to their names.
|
||||||
|
m_DependsMakeFile += "/";
|
||||||
|
m_DependsMarkFile += "/";
|
||||||
|
m_DependsMakeFile += m_TargetFile;
|
||||||
|
m_DependsMarkFile += m_TargetFile;
|
||||||
|
m_DependsMakeFile += ".depends.make";
|
||||||
|
m_DependsMarkFile += ".depends";
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
cmDepends::~cmDepends()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmDepends::Write()
|
||||||
|
{
|
||||||
|
// Try to generate dependencies for the target file.
|
||||||
|
cmGeneratedFileStream fout(m_DependsMakeFile.c_str());
|
||||||
|
fout << "# Dependencies for " << m_TargetFile.c_str() << std::endl;
|
||||||
|
if(this->WriteDependencies(fout) && fout)
|
||||||
|
{
|
||||||
|
// Dependencies were generated. Touch the mark file.
|
||||||
|
std::ofstream fmark(m_DependsMarkFile.c_str());
|
||||||
|
fmark << "Dependencies updated for " << m_TargetFile.c_str() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmDepends::Check()
|
||||||
|
{
|
||||||
|
// Check whether dependencies must be regenerated.
|
||||||
|
std::ifstream fin(m_DependsMakeFile.c_str());
|
||||||
|
if(!(fin && this->CheckDependencies(fin)))
|
||||||
|
{
|
||||||
|
// Clear all dependencies so they will be regenerated.
|
||||||
|
this->Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmDepends::Clear()
|
||||||
|
{
|
||||||
|
// Remove the dependency mark file to be sure dependencies will be
|
||||||
|
// regenerated.
|
||||||
|
cmSystemTools::RemoveFile(m_DependsMarkFile.c_str());
|
||||||
|
|
||||||
|
// Write an empty dependency file.
|
||||||
|
cmGeneratedFileStream depFileStream(m_DependsMakeFile.c_str());
|
||||||
|
depFileStream
|
||||||
|
<< "# Empty dependencies file for " << m_TargetFile.c_str() << ".\n"
|
||||||
|
<< "# This may be replaced when dependencies are built." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
const char* cmDepends::GetMakeFileName()
|
||||||
|
{
|
||||||
|
// Skip over the directory part of the name.
|
||||||
|
return m_DependsMakeFile.c_str() + m_Directory.length() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
const char* cmDepends::GetMarkFileName()
|
||||||
|
{
|
||||||
|
// Skip over the directory part of the name.
|
||||||
|
return m_DependsMarkFile.c_str() + m_Directory.length() + 1;
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*=========================================================================
|
||||||
|
|
||||||
|
Program: CMake - Cross-Platform Makefile Generator
|
||||||
|
Module: $RCSfile$
|
||||||
|
Language: C++
|
||||||
|
Date: $Date$
|
||||||
|
Version: $Revision$
|
||||||
|
|
||||||
|
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||||
|
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||||
|
|
||||||
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||||
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. See the above copyright notices for more information.
|
||||||
|
|
||||||
|
=========================================================================*/
|
||||||
|
#ifndef cmDepends_h
|
||||||
|
#define cmDepends_h
|
||||||
|
|
||||||
|
#include "cmStandardIncludes.h"
|
||||||
|
|
||||||
|
/** \class cmDepends
|
||||||
|
* \brief Dependency scanner superclass.
|
||||||
|
*
|
||||||
|
* This class is responsible for maintaining a .depends.make file in
|
||||||
|
* the build tree corresponding to an object file. Subclasses help it
|
||||||
|
* maintain dependencies for particular languages.
|
||||||
|
*/
|
||||||
|
class cmDepends
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Instances need to know the build directory name and the relative
|
||||||
|
path from the build directory to the target file. */
|
||||||
|
cmDepends(const char* dir, const char* targetFile);
|
||||||
|
|
||||||
|
/** Virtual destructor to cleanup subclasses properly. */
|
||||||
|
virtual ~cmDepends();
|
||||||
|
|
||||||
|
/** Write dependencies for the target file. */
|
||||||
|
void Write();
|
||||||
|
|
||||||
|
/** Check dependencies for the target file. */
|
||||||
|
void Check();
|
||||||
|
|
||||||
|
/** Clear dependencies for the target file so they will be regenerated. */
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
/** Get the name of the dependency make file. */
|
||||||
|
const char* GetMakeFileName();
|
||||||
|
|
||||||
|
/** Get the name of the dependency mark file. */
|
||||||
|
const char* GetMarkFileName();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Write dependencies for the target file to the given stream.
|
||||||
|
// Return true for success and false for failure.
|
||||||
|
virtual bool WriteDependencies(std::ostream& os)=0;
|
||||||
|
|
||||||
|
// Check dependencies for the target file in the given stream.
|
||||||
|
// Return false if dependencies must be regenerated and true
|
||||||
|
// otherwise.
|
||||||
|
virtual bool CheckDependencies(std::istream& is)=0;
|
||||||
|
|
||||||
|
// The directory in which the build rule for the target file is executed.
|
||||||
|
std::string m_Directory;
|
||||||
|
|
||||||
|
// The name of the target file for which dependencies are maintained.
|
||||||
|
std::string m_TargetFile;
|
||||||
|
|
||||||
|
// The name of the .depends.make file corresponding to the target.
|
||||||
|
std::string m_DependsMakeFile;
|
||||||
|
|
||||||
|
// The name of the .depends file marking when dependencies were generated.
|
||||||
|
std::string m_DependsMarkFile;
|
||||||
|
|
||||||
|
private:
|
||||||
|
cmDepends(cmDepends const&); // Purposely not implemented.
|
||||||
|
void operator=(cmDepends const&); // Purposely not implemented.
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,247 @@
|
||||||
|
/*=========================================================================
|
||||||
|
|
||||||
|
Program: CMake - Cross-Platform Makefile Generator
|
||||||
|
Module: $RCSfile$
|
||||||
|
Language: C++
|
||||||
|
Date: $Date$
|
||||||
|
Version: $Revision$
|
||||||
|
|
||||||
|
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||||
|
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||||
|
|
||||||
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||||
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. See the above copyright notices for more information.
|
||||||
|
|
||||||
|
=========================================================================*/
|
||||||
|
#include "cmDependsC.h"
|
||||||
|
|
||||||
|
#include "cmSystemTools.h"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
cmDependsC::cmDependsC(const char* dir, const char* targetFile):
|
||||||
|
cmDepends(dir, targetFile),
|
||||||
|
m_SourceFile(),
|
||||||
|
m_IncludePath(0),
|
||||||
|
m_IncludeLineRegex()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
cmDependsC::cmDependsC(const char* dir, const char* targetFile,
|
||||||
|
const char* sourceFile,
|
||||||
|
std::vector<std::string> const& includes):
|
||||||
|
cmDepends(dir, targetFile),
|
||||||
|
m_SourceFile(sourceFile),
|
||||||
|
m_IncludePath(&includes),
|
||||||
|
m_IncludeLineRegex("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)[\">]")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
cmDependsC::~cmDependsC()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool cmDependsC::WriteDependencies(std::ostream& os)
|
||||||
|
{
|
||||||
|
// Make sure this is a scanning instance.
|
||||||
|
if(m_SourceFile == "")
|
||||||
|
{
|
||||||
|
cmSystemTools::Error("Cannot scan dependencies without an source file.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!m_IncludePath)
|
||||||
|
{
|
||||||
|
cmSystemTools::Error("Cannot scan dependencies without an include path.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk the dependency graph starting with the source file.
|
||||||
|
bool first = true;
|
||||||
|
m_Unscanned.push(m_SourceFile);
|
||||||
|
m_Encountered.insert(m_SourceFile);
|
||||||
|
std::set<cmStdString> dependencies;
|
||||||
|
std::set<cmStdString> scanned;
|
||||||
|
while(!m_Unscanned.empty())
|
||||||
|
{
|
||||||
|
// Get the next file to scan.
|
||||||
|
std::string fname = m_Unscanned.front();
|
||||||
|
m_Unscanned.pop();
|
||||||
|
|
||||||
|
// If not a full path, find the file in the include path.
|
||||||
|
std::string fullName;
|
||||||
|
if(first || cmSystemTools::FileIsFullPath(fname.c_str()))
|
||||||
|
{
|
||||||
|
fullName = fname;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(std::vector<std::string>::const_iterator i = m_IncludePath->begin();
|
||||||
|
i != m_IncludePath->end(); ++i)
|
||||||
|
{
|
||||||
|
std::string temp = *i;
|
||||||
|
temp += "/";
|
||||||
|
temp += fname;
|
||||||
|
if(cmSystemTools::FileExists(temp.c_str()))
|
||||||
|
{
|
||||||
|
fullName = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan the file if it was found and has not been scanned already.
|
||||||
|
if(fullName.size() && (scanned.find(fullName) == scanned.end()))
|
||||||
|
{
|
||||||
|
// Record scanned files.
|
||||||
|
scanned.insert(fullName);
|
||||||
|
|
||||||
|
// Try to scan the file. Just leave it out if we cannot find
|
||||||
|
// it.
|
||||||
|
std::ifstream fin(fullName.c_str());
|
||||||
|
if(fin)
|
||||||
|
{
|
||||||
|
// Add this file as a dependency.
|
||||||
|
dependencies.insert(fullName);
|
||||||
|
|
||||||
|
// Scan this file for new dependencies.
|
||||||
|
this->Scan(fin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
m_Encountered.clear();
|
||||||
|
|
||||||
|
// Write the dependencies to the output stream.
|
||||||
|
for(std::set<cmStdString>::iterator i=dependencies.begin();
|
||||||
|
i != dependencies.end(); ++i)
|
||||||
|
{
|
||||||
|
os << m_TargetFile.c_str() << ": "
|
||||||
|
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
os << std::endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool cmDependsC::CheckDependencies(std::istream& is)
|
||||||
|
{
|
||||||
|
// Parse dependencies from the stream. If any dependee is missing
|
||||||
|
// or newer than the depender then dependencies should be
|
||||||
|
// regenerated.
|
||||||
|
bool okay = true;
|
||||||
|
std::string line;
|
||||||
|
std::string depender;
|
||||||
|
std::string dependee;
|
||||||
|
while(cmSystemTools::GetLineFromStream(is, line))
|
||||||
|
{
|
||||||
|
// Skip empty lines and comments.
|
||||||
|
std::string::size_type pos = line.find_first_not_of(" \t\r\n");
|
||||||
|
if(pos == std::string::npos || line[pos] == '#')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip leading whitespace.
|
||||||
|
if(pos > 0)
|
||||||
|
{
|
||||||
|
line = line.substr(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip lines too short to have a dependency.
|
||||||
|
if(line.size() < 3)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the colon on the line. Skip the first two characters to
|
||||||
|
// avoid finding the colon in a drive letter on Windows. Ignore
|
||||||
|
// the line if a colon cannot be found.
|
||||||
|
if((pos = line.find(':', 2)) == std::string::npos)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split the line into depender and dependee.
|
||||||
|
depender = line.substr(0, pos);
|
||||||
|
dependee = line.substr(pos+1);
|
||||||
|
|
||||||
|
// Strip whitespace from the dependee.
|
||||||
|
if((pos = dependee.find_first_not_of(" \t\r\n")) != std::string::npos &&
|
||||||
|
pos > 0)
|
||||||
|
{
|
||||||
|
dependee = dependee.substr(pos);
|
||||||
|
}
|
||||||
|
if((pos = dependee.find_last_not_of(" \t\r\n")) != std::string::npos)
|
||||||
|
{
|
||||||
|
dependee = dependee.substr(0, pos+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert dependee to a full path.
|
||||||
|
if(!cmSystemTools::FileIsFullPath(dependee.c_str()))
|
||||||
|
{
|
||||||
|
dependee = cmSystemTools::CollapseFullPath(dependee.c_str(),
|
||||||
|
m_Directory.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip whitespace from the depender.
|
||||||
|
if((pos = depender.find_last_not_of(" \t\r\n")) != std::string::npos)
|
||||||
|
{
|
||||||
|
depender = depender.substr(0, pos+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert depender to a full path.
|
||||||
|
if(!cmSystemTools::FileIsFullPath(depender.c_str()))
|
||||||
|
{
|
||||||
|
depender = cmSystemTools::CollapseFullPath(depender.c_str(),
|
||||||
|
m_Directory.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dependencies must be regenerated if the dependee does not exist
|
||||||
|
// or if the depender exists and is older than the dependee.
|
||||||
|
int result = 0;
|
||||||
|
if(!cmSystemTools::FileExists(dependee.c_str()) ||
|
||||||
|
(cmSystemTools::FileExists(depender.c_str()) &&
|
||||||
|
(!cmSystemTools::FileTimeCompare(depender.c_str(), dependee.c_str(),
|
||||||
|
&result) || result < 0)))
|
||||||
|
{
|
||||||
|
// Dependencies must be regenerated.
|
||||||
|
okay = false;
|
||||||
|
|
||||||
|
// Remove the depender to be sure it is rebuilt.
|
||||||
|
cmSystemTools::RemoveFile(depender.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return okay;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmDependsC::Scan(std::istream& is)
|
||||||
|
{
|
||||||
|
// Read one line at a time.
|
||||||
|
std::string line;
|
||||||
|
while(cmSystemTools::GetLineFromStream(is, line))
|
||||||
|
{
|
||||||
|
// Match include directives. TODO: Support include regex and
|
||||||
|
// ignore regex. Possibly also support directory-based inclusion
|
||||||
|
// in dependencies.
|
||||||
|
if(m_IncludeLineRegex.find(line.c_str()))
|
||||||
|
{
|
||||||
|
// Get the file being included.
|
||||||
|
std::string includeFile = m_IncludeLineRegex.match(1);
|
||||||
|
|
||||||
|
// Queue the file if it has not yet been encountered.
|
||||||
|
if(m_Encountered.find(includeFile) == m_Encountered.end())
|
||||||
|
{
|
||||||
|
m_Encountered.insert(includeFile);
|
||||||
|
m_Unscanned.push(includeFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*=========================================================================
|
||||||
|
|
||||||
|
Program: CMake - Cross-Platform Makefile Generator
|
||||||
|
Module: $RCSfile$
|
||||||
|
Language: C++
|
||||||
|
Date: $Date$
|
||||||
|
Version: $Revision$
|
||||||
|
|
||||||
|
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||||
|
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||||
|
|
||||||
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||||
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. See the above copyright notices for more information.
|
||||||
|
|
||||||
|
=========================================================================*/
|
||||||
|
#ifndef cmDependsC_h
|
||||||
|
#define cmDependsC_h
|
||||||
|
|
||||||
|
#include "cmDepends.h"
|
||||||
|
#include <cmsys/RegularExpression.hxx>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
/** \class cmDependsC
|
||||||
|
* \brief Dependency scanner for C and C++ object files.
|
||||||
|
*/
|
||||||
|
class cmDependsC: public cmDepends
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Checking instances need to know the build directory name and the
|
||||||
|
relative path from the build directory to the target file. */
|
||||||
|
cmDependsC(const char* dir, const char* targetFile);
|
||||||
|
|
||||||
|
/** Scanning need to know the build directory name, the relative
|
||||||
|
path from the build directory to the target file, the source
|
||||||
|
file from which to start scanning, and the include file search
|
||||||
|
path. */
|
||||||
|
cmDependsC(const char* dir, const char* targetFile,
|
||||||
|
const char* sourceFile, std::vector<std::string> const& includes);
|
||||||
|
|
||||||
|
/** Virtual destructor to cleanup subclasses properly. */
|
||||||
|
virtual ~cmDependsC();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Implement writing/checking methods required by superclass.
|
||||||
|
virtual bool WriteDependencies(std::ostream& os);
|
||||||
|
virtual bool CheckDependencies(std::istream& is);
|
||||||
|
|
||||||
|
// Method to scan a single file.
|
||||||
|
void Scan(std::istream& is);
|
||||||
|
|
||||||
|
// The source file from which to start scanning.
|
||||||
|
std::string m_SourceFile;
|
||||||
|
|
||||||
|
// The include file search path.
|
||||||
|
std::vector<std::string> const* m_IncludePath;
|
||||||
|
|
||||||
|
// Regular expression to identify C preprocessor include directives.
|
||||||
|
cmsys::RegularExpression m_IncludeLineRegex;
|
||||||
|
|
||||||
|
// Data structures for dependency graph walk.
|
||||||
|
std::set<cmStdString> m_Encountered;
|
||||||
|
std::queue<cmStdString> m_Unscanned;
|
||||||
|
|
||||||
|
private:
|
||||||
|
cmDependsC(cmDependsC const&); // Purposely not implemented.
|
||||||
|
void operator=(cmDependsC const&); // Purposely not implemented.
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -16,17 +16,20 @@
|
||||||
=========================================================================*/
|
=========================================================================*/
|
||||||
#include "cmLocalUnixMakefileGenerator2.h"
|
#include "cmLocalUnixMakefileGenerator2.h"
|
||||||
|
|
||||||
|
#include "cmDepends.h"
|
||||||
|
#include "cmDependsC.h"
|
||||||
#include "cmGeneratedFileStream.h"
|
#include "cmGeneratedFileStream.h"
|
||||||
#include "cmGlobalGenerator.h"
|
#include "cmGlobalGenerator.h"
|
||||||
#include "cmMakefile.h"
|
#include "cmMakefile.h"
|
||||||
#include "cmSourceFile.h"
|
#include "cmSourceFile.h"
|
||||||
|
|
||||||
|
#include <memory> // auto_ptr
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
// Quick-switch for generating old makefiles.
|
// Quick-switch for generating old makefiles.
|
||||||
#if 0
|
#if 1
|
||||||
# define CMLUMG_MAKEFILE_NAME "Makefile"
|
# define CMLUMG_MAKEFILE_NAME "Makefile"
|
||||||
#else
|
#else
|
||||||
# define CMLUMG_WRITE_OLD_MAKEFILE
|
# define CMLUMG_WRITE_OLD_MAKEFILE
|
||||||
|
@ -237,10 +240,26 @@ void cmLocalUnixMakefileGenerator2::GenerateCMakefile()
|
||||||
|
|
||||||
// Set the set of files to check for dependency integrity.
|
// Set the set of files to check for dependency integrity.
|
||||||
cmakefileStream
|
cmakefileStream
|
||||||
<< "# The set of files whose dependency integrity should be checked:\n"
|
<< "# The set of files whose dependency integrity should be checked:\n";
|
||||||
<< "SET(CMAKE_DEPENDS_CHECK\n";
|
cmakefileStream
|
||||||
for(std::set<cmStdString>::const_iterator i = m_CheckDependFiles.begin();
|
<< "SET(CMAKE_DEPENDS_LANGUAGES\n";
|
||||||
i != m_CheckDependFiles.end(); ++i)
|
for(std::map<cmStdString, IntegrityCheckSet>::const_iterator
|
||||||
|
l = m_CheckDependFiles.begin();
|
||||||
|
l != m_CheckDependFiles.end(); ++l)
|
||||||
|
{
|
||||||
|
cmakefileStream
|
||||||
|
<< " \"" << l->first.c_str() << "\"\n";
|
||||||
|
}
|
||||||
|
cmakefileStream
|
||||||
|
<< " )\n";
|
||||||
|
for(std::map<cmStdString, IntegrityCheckSet>::const_iterator
|
||||||
|
l = m_CheckDependFiles.begin();
|
||||||
|
l != m_CheckDependFiles.end(); ++l)
|
||||||
|
{
|
||||||
|
cmakefileStream
|
||||||
|
<< "SET(CMAKE_DEPENDS_CHECK_" << l->first.c_str() << "\n";
|
||||||
|
for(std::set<cmStdString>::const_iterator i = l->second.begin();
|
||||||
|
i != l->second.end(); ++i)
|
||||||
{
|
{
|
||||||
cmakefileStream
|
cmakefileStream
|
||||||
<< " \"" << this->ConvertToRelativePath(i->c_str()).c_str() << "\"\n";
|
<< " \"" << this->ConvertToRelativePath(i->c_str()).c_str() << "\"\n";
|
||||||
|
@ -248,6 +267,7 @@ void cmLocalUnixMakefileGenerator2::GenerateCMakefile()
|
||||||
cmakefileStream
|
cmakefileStream
|
||||||
<< " )\n";
|
<< " )\n";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
|
@ -278,7 +298,6 @@ cmLocalUnixMakefileGenerator2
|
||||||
std::string depBase = dir;
|
std::string depBase = dir;
|
||||||
depBase += "/";
|
depBase += "/";
|
||||||
depBase += target.GetName();
|
depBase += target.GetName();
|
||||||
std::string depMakeFile = this->GenerateDependsMakeFile(depBase.c_str());
|
|
||||||
|
|
||||||
// Construct the rule file name.
|
// Construct the rule file name.
|
||||||
std::string ruleFileName = dir;
|
std::string ruleFileName = dir;
|
||||||
|
@ -302,13 +321,6 @@ cmLocalUnixMakefileGenerator2
|
||||||
ruleFileStream
|
ruleFileStream
|
||||||
<< "# Rule file for target " << target.GetName() << ".\n\n";
|
<< "# Rule file for target " << target.GetName() << ".\n\n";
|
||||||
|
|
||||||
// Include the dependencies for the target.
|
|
||||||
ruleFileStream
|
|
||||||
<< "# Include any dependencies generated for this rule.\n"
|
|
||||||
<< m_IncludeDirective << " "
|
|
||||||
<< this->ConvertToOutputForExisting(depMakeFile.c_str()).c_str()
|
|
||||||
<< "\n\n";
|
|
||||||
|
|
||||||
// Include the rule file for each object.
|
// Include the rule file for each object.
|
||||||
if(!objects.empty())
|
if(!objects.empty())
|
||||||
{
|
{
|
||||||
|
@ -371,19 +383,27 @@ cmLocalUnixMakefileGenerator2
|
||||||
// Get the full path name of the object file.
|
// Get the full path name of the object file.
|
||||||
std::string obj = this->GetObjectFileName(target, source);
|
std::string obj = this->GetObjectFileName(target, source);
|
||||||
|
|
||||||
// Save this in the target's list of object files.
|
|
||||||
objects.push_back(obj);
|
|
||||||
|
|
||||||
// The object file should be checked for dependency integrity.
|
|
||||||
m_CheckDependFiles.insert(obj);
|
|
||||||
|
|
||||||
// Create the directory containing the object file. This may be a
|
// Create the directory containing the object file. This may be a
|
||||||
// subdirectory under the target's directory.
|
// subdirectory under the target's directory.
|
||||||
std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
|
std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
|
||||||
cmSystemTools::MakeDirectory(this->ConvertToFullPath(dir).c_str());
|
cmSystemTools::MakeDirectory(this->ConvertToFullPath(dir).c_str());
|
||||||
|
|
||||||
// Generate the build-time dependencies file for this object file.
|
// Generate the build-time dependencies file for this object file.
|
||||||
std::string depMakeFile = this->GenerateDependsMakeFile(obj.c_str());
|
std::string depMakeFile;
|
||||||
|
std::string depMarkFile;
|
||||||
|
if(!this->GenerateDependsMakeFile(lang, obj.c_str(),
|
||||||
|
depMakeFile, depMarkFile))
|
||||||
|
{
|
||||||
|
cmSystemTools::Error("No dependency checker available for language \"",
|
||||||
|
lang, "\".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save this in the target's list of object files.
|
||||||
|
objects.push_back(obj);
|
||||||
|
|
||||||
|
// The object file should be checked for dependency integrity.
|
||||||
|
m_CheckDependFiles[lang].insert(obj);
|
||||||
|
|
||||||
// Open the rule file for writing. This should be copy-if-different
|
// Open the rule file for writing. This should be copy-if-different
|
||||||
// because the rules may depend on this file itself.
|
// because the rules may depend on this file itself.
|
||||||
|
@ -424,8 +444,6 @@ cmLocalUnixMakefileGenerator2
|
||||||
depends.push_back(ruleFileName);
|
depends.push_back(ruleFileName);
|
||||||
|
|
||||||
// Write the dependency generation rule.
|
// Write the dependency generation rule.
|
||||||
std::string depTarget = obj;
|
|
||||||
depTarget += ".depends";
|
|
||||||
{
|
{
|
||||||
std::string depEcho = "Scanning ";
|
std::string depEcho = "Scanning ";
|
||||||
depEcho += lang;
|
depEcho += lang;
|
||||||
|
@ -453,7 +471,7 @@ cmLocalUnixMakefileGenerator2
|
||||||
|
|
||||||
// Write the rule.
|
// Write the rule.
|
||||||
this->WriteMakeRule(ruleFileStream, 0, depEcho.c_str(),
|
this->WriteMakeRule(ruleFileStream, 0, depEcho.c_str(),
|
||||||
depTarget.c_str(), depends, commands);
|
depMarkFile.c_str(), depends, commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the build rule.
|
// Write the build rule.
|
||||||
|
@ -676,30 +694,28 @@ cmLocalUnixMakefileGenerator2
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
std::string
|
bool
|
||||||
cmLocalUnixMakefileGenerator2
|
cmLocalUnixMakefileGenerator2
|
||||||
::GenerateDependsMakeFile(const char* file)
|
::GenerateDependsMakeFile(const std::string& lang, const char* objFile,
|
||||||
|
std::string& depMakeFile, std::string& depMarkFile)
|
||||||
{
|
{
|
||||||
// Check if the build-time dependencies file exists.
|
// Construct a checker for the given language.
|
||||||
std::string depMarkFile = file;
|
std::auto_ptr<cmDepends>
|
||||||
depMarkFile += ".depends";
|
checker(this->GetDependsChecker(lang,
|
||||||
std::string depMakeFile = depMarkFile;
|
m_Makefile->GetStartOutputDirectory(),
|
||||||
depMakeFile += ".make";
|
objFile));
|
||||||
std::string depMakeFileFull = this->ConvertToFullPath(depMakeFile);
|
if(checker.get())
|
||||||
if(cmSystemTools::FileExists(depMakeFileFull.c_str()))
|
|
||||||
{
|
{
|
||||||
// The build-time dependencies file already exists. Check it.
|
// Save the make and mark file names.
|
||||||
this->CheckDependencies(m_Makefile->GetStartOutputDirectory(), file);
|
depMakeFile = checker->GetMakeFileName();
|
||||||
|
depMarkFile = checker->GetMarkFileName();
|
||||||
|
|
||||||
|
// Check the dependencies.
|
||||||
|
checker->Check();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else
|
return false;
|
||||||
{
|
|
||||||
// The build-time dependencies file does not exist. Create an
|
|
||||||
// empty one.
|
|
||||||
std::string depMarkFileFull = this->ConvertToFullPath(depMarkFile);
|
|
||||||
this->WriteEmptyDependMakeFile(file, depMarkFileFull.c_str(),
|
|
||||||
depMakeFileFull.c_str());
|
|
||||||
}
|
|
||||||
return depMakeFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -2686,6 +2702,19 @@ cmLocalUnixMakefileGenerator2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
cmDepends*
|
||||||
|
cmLocalUnixMakefileGenerator2::GetDependsChecker(const std::string& lang,
|
||||||
|
const char* dir,
|
||||||
|
const char* objFile)
|
||||||
|
{
|
||||||
|
if(lang == "C" || lang == "CXX" || lang == "RC")
|
||||||
|
{
|
||||||
|
return new cmDependsC(dir, objFile);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
cmLocalUnixMakefileGenerator2
|
cmLocalUnixMakefileGenerator2
|
||||||
|
@ -2718,292 +2747,49 @@ cmLocalUnixMakefileGenerator2
|
||||||
if(lang == "C" || lang == "CXX" || lang == "RC")
|
if(lang == "C" || lang == "CXX" || lang == "RC")
|
||||||
{
|
{
|
||||||
// TODO: Handle RC (resource files) dependencies correctly.
|
// TODO: Handle RC (resource files) dependencies correctly.
|
||||||
return cmLocalUnixMakefileGenerator2::ScanDependenciesC(objFile, srcFile,
|
cmDependsC scanner(".", objFile, srcFile, includes);
|
||||||
includes);
|
scanner.Write();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void
|
void cmLocalUnixMakefileGenerator2::CheckDependencies(cmMakefile* mf)
|
||||||
cmLocalUnixMakefileGenerator2ScanDependenciesC(
|
|
||||||
std::ifstream& fin,
|
|
||||||
std::set<cmStdString>& encountered,
|
|
||||||
std::queue<cmStdString>& unscanned)
|
|
||||||
{
|
{
|
||||||
// Regular expression to identify C preprocessor include directives.
|
// Get the list of languages that may have sources to check.
|
||||||
cmsys::RegularExpression
|
const char* langDef = mf->GetDefinition("CMAKE_DEPENDS_LANGUAGES");
|
||||||
includeLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)[\">]");
|
if(!langDef)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::vector<std::string> languages;
|
||||||
|
cmSystemTools::ExpandListArgument(langDef, languages);
|
||||||
|
|
||||||
// Read one line at a time.
|
// For each language get the set of files to check.
|
||||||
std::string line;
|
for(std::vector<std::string>::iterator l = languages.begin();
|
||||||
while(cmSystemTools::GetLineFromStream(fin, line))
|
l != languages.end(); ++l)
|
||||||
{
|
{
|
||||||
// Match include directives. TODO: Support include regex and
|
std::string depCheck = "CMAKE_DEPENDS_CHECK_";
|
||||||
// ignore regex. Possibly also support directory-based inclusion
|
depCheck += *l;
|
||||||
// in dependencies.
|
if(const char* fileDef = mf->GetDefinition(depCheck.c_str()))
|
||||||
if(includeLine.find(line.c_str()))
|
|
||||||
{
|
{
|
||||||
// Get the file being included.
|
|
||||||
std::string includeFile = includeLine.match(1);
|
|
||||||
|
|
||||||
// Queue the file if it has not yet been encountered.
|
|
||||||
if(encountered.find(includeFile) == encountered.end())
|
|
||||||
{
|
|
||||||
encountered.insert(includeFile);
|
|
||||||
unscanned.push(includeFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
cmLocalUnixMakefileGenerator2
|
|
||||||
::ScanDependenciesC(const char* objFile, const char* srcFile,
|
|
||||||
std::vector<std::string> const& includes)
|
|
||||||
{
|
|
||||||
// Walk the dependency graph starting with the source file.
|
|
||||||
std::set<cmStdString> dependencies;
|
|
||||||
std::set<cmStdString> encountered;
|
|
||||||
std::set<cmStdString> scanned;
|
|
||||||
std::queue<cmStdString> unscanned;
|
|
||||||
unscanned.push(srcFile);
|
|
||||||
encountered.insert(srcFile);
|
|
||||||
while(!unscanned.empty())
|
|
||||||
{
|
|
||||||
// Get the next file to scan.
|
|
||||||
std::string fname = unscanned.front();
|
|
||||||
unscanned.pop();
|
|
||||||
|
|
||||||
// If not a full path, find the file in the include path.
|
|
||||||
std::string fullName;
|
|
||||||
if(cmSystemTools::FileIsFullPath(fname.c_str()))
|
|
||||||
{
|
|
||||||
fullName = fname;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(std::vector<std::string>::const_iterator i = includes.begin();
|
|
||||||
i != includes.end(); ++i)
|
|
||||||
{
|
|
||||||
std::string temp = *i;
|
|
||||||
temp += "/";
|
|
||||||
temp += fname;
|
|
||||||
if(cmSystemTools::FileExists(temp.c_str()))
|
|
||||||
{
|
|
||||||
fullName = temp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan the file if it was found and has not been scanned already.
|
|
||||||
if(fullName.size() && (scanned.find(fullName) == scanned.end()))
|
|
||||||
{
|
|
||||||
// Record scanned files.
|
|
||||||
scanned.insert(fullName);
|
|
||||||
|
|
||||||
// Try to scan the file. Just leave it out if we cannot find
|
|
||||||
// it.
|
|
||||||
std::ifstream fin(fullName.c_str());
|
|
||||||
if(fin)
|
|
||||||
{
|
|
||||||
// Add this file as a dependency.
|
|
||||||
dependencies.insert(fullName);
|
|
||||||
|
|
||||||
// Scan this file for new dependencies.
|
|
||||||
cmLocalUnixMakefileGenerator2ScanDependenciesC(fin, encountered,
|
|
||||||
unscanned);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the dependencies to the output file.
|
|
||||||
std::string depMarkFile = objFile;
|
|
||||||
std::string depMakeFile = objFile;
|
|
||||||
depMarkFile += ".depends";
|
|
||||||
depMakeFile += ".depends.make";
|
|
||||||
cmGeneratedFileStream fout(depMakeFile.c_str());
|
|
||||||
fout << "# Dependencies for " << objFile << std::endl;
|
|
||||||
for(std::set<cmStdString>::iterator i=dependencies.begin();
|
|
||||||
i != dependencies.end(); ++i)
|
|
||||||
{
|
|
||||||
fout << objFile << ": "
|
|
||||||
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
fout << std::endl;
|
|
||||||
fout << "# Dependencies for " << depMarkFile.c_str() << std::endl;
|
|
||||||
for(std::set<cmStdString>::iterator i=dependencies.begin();
|
|
||||||
i != dependencies.end(); ++i)
|
|
||||||
{
|
|
||||||
fout << depMarkFile.c_str() << ": "
|
|
||||||
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we could write the dependencies, touch the corresponding
|
|
||||||
// depends file to mark dependencies up to date.
|
|
||||||
if(fout)
|
|
||||||
{
|
|
||||||
std::ofstream fmark(depMarkFile.c_str());
|
|
||||||
fmark << "Dependencies updated for " << objFile << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void
|
|
||||||
cmLocalUnixMakefileGenerator2
|
|
||||||
::CheckDependencies(const char* depCheck)
|
|
||||||
{
|
|
||||||
// Get the list of files to scan. This is given through the command
|
|
||||||
// line hook cmake file.
|
|
||||||
std::vector<std::string> files;
|
|
||||||
cmSystemTools::ExpandListArgument(depCheck, files);
|
|
||||||
|
|
||||||
// Check each file. The current working directory is already
|
// Check each file. The current working directory is already
|
||||||
// correct.
|
// correct.
|
||||||
|
std::vector<std::string> files;
|
||||||
|
cmSystemTools::ExpandListArgument(fileDef, files);
|
||||||
for(std::vector<std::string>::iterator f = files.begin();
|
for(std::vector<std::string>::iterator f = files.begin();
|
||||||
f != files.end(); ++f)
|
f != files.end(); ++f)
|
||||||
{
|
{
|
||||||
cmLocalUnixMakefileGenerator2::CheckDependencies(".", f->c_str());
|
// Construct a checker for the given language.
|
||||||
}
|
std::auto_ptr<cmDepends>
|
||||||
}
|
checker(cmLocalUnixMakefileGenerator2
|
||||||
|
::GetDependsChecker(*l, ".", f->c_str()));
|
||||||
//----------------------------------------------------------------------------
|
if(checker.get())
|
||||||
void
|
|
||||||
cmLocalUnixMakefileGenerator2
|
|
||||||
::CheckDependencies(const char* dir, const char* file)
|
|
||||||
{
|
{
|
||||||
// Check the dependencies associated with the given file whose path
|
checker->Check();
|
||||||
// is specified relative to the given directory. If any dependency
|
|
||||||
// is missing then dependencies should be regenerated.
|
|
||||||
bool regenerate = false;
|
|
||||||
|
|
||||||
// Construct the names of the mark and make files.
|
|
||||||
std::string depMarkFileFull = dir;
|
|
||||||
depMarkFileFull += "/";
|
|
||||||
depMarkFileFull += file;
|
|
||||||
depMarkFileFull += ".depends";
|
|
||||||
std::string depMakeFileFull = depMarkFileFull;
|
|
||||||
depMakeFileFull += ".make";
|
|
||||||
|
|
||||||
// Open the dependency makefile.
|
|
||||||
std::ifstream fin(depMakeFileFull.c_str());
|
|
||||||
if(fin)
|
|
||||||
{
|
|
||||||
// Parse dependencies.
|
|
||||||
std::string line;
|
|
||||||
std::string depender;
|
|
||||||
std::string dependee;
|
|
||||||
while(cmSystemTools::GetLineFromStream(fin, line))
|
|
||||||
{
|
|
||||||
// Skip empty lines and comments.
|
|
||||||
std::string::size_type pos = line.find_first_not_of(" \t\r\n");
|
|
||||||
if(pos == std::string::npos || line[pos] == '#')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strip leading whitespace.
|
|
||||||
if(pos > 0)
|
|
||||||
{
|
|
||||||
line = line.substr(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip lines too short to have a dependency.
|
|
||||||
if(line.size() < 3)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the colon on the line. Skip the first two characters to
|
|
||||||
// avoid finding the colon in a drive letter on Windows. Ignore
|
|
||||||
// the line if a colon cannot be found.
|
|
||||||
if((pos = line.find(':', 2)) == std::string::npos)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split the line into depender and dependee.
|
|
||||||
depender = line.substr(0, pos);
|
|
||||||
dependee = line.substr(pos+1);
|
|
||||||
|
|
||||||
// Strip whitespace from the dependee.
|
|
||||||
if((pos = dependee.find_first_not_of(" \t\r\n")) != std::string::npos &&
|
|
||||||
pos > 0)
|
|
||||||
{
|
|
||||||
dependee = dependee.substr(pos);
|
|
||||||
}
|
|
||||||
if((pos = dependee.find_last_not_of(" \t\r\n")) != std::string::npos)
|
|
||||||
{
|
|
||||||
dependee = dependee.substr(0, pos+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert dependee to a full path.
|
|
||||||
if(!cmSystemTools::FileIsFullPath(dependee.c_str()))
|
|
||||||
{
|
|
||||||
dependee = cmSystemTools::CollapseFullPath(dependee.c_str(), dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the dependee does not exist, we need to regenerate
|
|
||||||
// dependencies and the depender should be removed.
|
|
||||||
if(!cmSystemTools::FileExists(dependee.c_str()))
|
|
||||||
{
|
|
||||||
// Strip whitespace from the depender.
|
|
||||||
if((pos = depender.find_last_not_of(" \t\r\n")) != std::string::npos)
|
|
||||||
{
|
|
||||||
depender = depender.substr(0, pos+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert depender to a full path.
|
|
||||||
if(!cmSystemTools::FileIsFullPath(depender.c_str()))
|
|
||||||
{
|
|
||||||
depender = cmSystemTools::CollapseFullPath(depender.c_str(), dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the depender.
|
|
||||||
cmSystemTools::RemoveFile(depender.c_str());
|
|
||||||
|
|
||||||
// Mark the need for regeneration.
|
|
||||||
regenerate = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Could not open the dependencies file. It needs to be
|
|
||||||
// regenerated.
|
|
||||||
regenerate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the dependencies file needs to be regenerated, create an empty
|
|
||||||
// one and delete the mark file.
|
|
||||||
if(regenerate)
|
|
||||||
{
|
|
||||||
cmLocalUnixMakefileGenerator2
|
|
||||||
::WriteEmptyDependMakeFile(file, depMarkFileFull.c_str(),
|
|
||||||
depMakeFileFull.c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void
|
|
||||||
cmLocalUnixMakefileGenerator2
|
|
||||||
::WriteEmptyDependMakeFile(const char* file,
|
|
||||||
const char* depMarkFileFull,
|
|
||||||
const char* depMakeFileFull)
|
|
||||||
{
|
|
||||||
// Remove the dependency mark file to be sure dependencies will be
|
|
||||||
// regenerated.
|
|
||||||
cmSystemTools::RemoveFile(depMarkFileFull);
|
|
||||||
|
|
||||||
// Write an empty dependency file.
|
|
||||||
cmGeneratedFileStream depFileStream(depMakeFileFull);
|
|
||||||
depFileStream
|
|
||||||
<< "# Empty dependencies file for " << file << ".\n"
|
|
||||||
<< "# This may be replaced when dependencies are built.\n";
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
class cmCustomCommand;
|
class cmCustomCommand;
|
||||||
class cmDependInformation;
|
class cmDependInformation;
|
||||||
|
class cmDepends;
|
||||||
class cmMakeDepend;
|
class cmMakeDepend;
|
||||||
class cmTarget;
|
class cmTarget;
|
||||||
class cmSourceFile;
|
class cmSourceFile;
|
||||||
|
@ -57,7 +58,7 @@ public:
|
||||||
static bool ScanDependencies(std::vector<std::string> const& args);
|
static bool ScanDependencies(std::vector<std::string> const& args);
|
||||||
|
|
||||||
/** Called from command-line hook to check dependencies. */
|
/** Called from command-line hook to check dependencies. */
|
||||||
static void CheckDependencies(const char* depCheck);
|
static void CheckDependencies(cmMakefile* mf);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -69,7 +70,10 @@ protected:
|
||||||
std::vector<std::string>& objects);
|
std::vector<std::string>& objects);
|
||||||
void GenerateCustomRuleFile(const cmCustomCommand& cc);
|
void GenerateCustomRuleFile(const cmCustomCommand& cc);
|
||||||
void GenerateUtilityRuleFile(const cmTarget& target);
|
void GenerateUtilityRuleFile(const cmTarget& target);
|
||||||
std::string GenerateDependsMakeFile(const char* file);
|
bool GenerateDependsMakeFile(const std::string& lang,
|
||||||
|
const char* objFile,
|
||||||
|
std::string& depMakeFile,
|
||||||
|
std::string& depMarkFile);
|
||||||
void WriteMakeRule(std::ostream& os,
|
void WriteMakeRule(std::ostream& os,
|
||||||
const char* comment,
|
const char* comment,
|
||||||
const char* preEcho,
|
const char* preEcho,
|
||||||
|
@ -163,12 +167,10 @@ protected:
|
||||||
std::string GetRecursiveMakeCall(const char* tgt);
|
std::string GetRecursiveMakeCall(const char* tgt);
|
||||||
void WriteJumpAndBuildRules(std::ostream& makefileStream);
|
void WriteJumpAndBuildRules(std::ostream& makefileStream);
|
||||||
|
|
||||||
static bool ScanDependenciesC(const char* objFile, const char* srcFile,
|
static cmDepends* GetDependsChecker(const std::string& lang,
|
||||||
std::vector<std::string> const& includes);
|
const char* dir,
|
||||||
static void CheckDependencies(const char* dir, const char* file);
|
const char* objFile);
|
||||||
static void WriteEmptyDependMakeFile(const char* file,
|
|
||||||
const char* depMarkFileFull,
|
|
||||||
const char* depMakeFileFull);
|
|
||||||
private:
|
private:
|
||||||
// Map from target name to build directory containing it for
|
// Map from target name to build directory containing it for
|
||||||
// jump-and-build targets.
|
// jump-and-build targets.
|
||||||
|
@ -179,8 +181,11 @@ private:
|
||||||
};
|
};
|
||||||
std::map<cmStdString, RemoteTarget> m_JumpAndBuild;
|
std::map<cmStdString, RemoteTarget> m_JumpAndBuild;
|
||||||
|
|
||||||
// List the files for which to check dependency integrity.
|
// List the files for which to check dependency integrity. Each
|
||||||
std::set<cmStdString> m_CheckDependFiles;
|
// language has its own list because integrity may be checked
|
||||||
|
// differently.
|
||||||
|
struct IntegrityCheckSet: public std::set<cmStdString> {};
|
||||||
|
std::map<cmStdString, IntegrityCheckSet> m_CheckDependFiles;
|
||||||
|
|
||||||
// Command used when a rule has no dependencies or commands.
|
// Command used when a rule has no dependencies or commands.
|
||||||
std::vector<std::string> m_EmptyCommands;
|
std::vector<std::string> m_EmptyCommands;
|
||||||
|
|
|
@ -1635,10 +1635,7 @@ int cmake::CheckBuildSystem()
|
||||||
|
|
||||||
#if defined(CMAKE_BUILD_WITH_CMAKE)
|
#if defined(CMAKE_BUILD_WITH_CMAKE)
|
||||||
// We do not need to rerun CMake. Check dependency integrity.
|
// We do not need to rerun CMake. Check dependency integrity.
|
||||||
if(const char* depCheck = mf->GetDefinition("CMAKE_DEPENDS_CHECK"))
|
cmLocalUnixMakefileGenerator2::CheckDependencies(mf);
|
||||||
{
|
|
||||||
cmLocalUnixMakefileGenerator2::CheckDependencies(depCheck);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// No need to rerun.
|
// No need to rerun.
|
||||||
|
|
Loading…
Reference in New Issue