Makefile: Optionally scan only source and build trees for dependencies

Add a `CMAKE_DEPENDS_IN_PROJECT_ONLY` variable to activate the behavior.
This commit is contained in:
Attila Krasznahorkay 2016-03-22 13:18:42 +01:00 committed by Brad King
parent 208524b822
commit b1e1aa1e6a
3 changed files with 72 additions and 0 deletions

View File

@ -114,6 +114,7 @@ Variables that Change Behavior
/variable/CMAKE_COLOR_MAKEFILE
/variable/CMAKE_CONFIGURATION_TYPES
/variable/CMAKE_DEBUG_TARGET_PROPERTIES
/variable/CMAKE_DEPENDS_IN_PROJECT_ONLY
/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName
/variable/CMAKE_ERROR_DEPRECATED
/variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION

View File

@ -0,0 +1,10 @@
CMAKE_DEPENDS_IN_PROJECT_ONLY
-----------------------------
When set to ``TRUE`` in a directory, the build system produced by the
:ref:`Makefile Generators` is set up to only consider dependencies on source
files that appear either in the source or in the binary directories. Changes
to source files outside of these directories will not cause rebuilds.
This should be used carefully in cases where some source files are picked up
through external headers during the build.

View File

@ -34,6 +34,7 @@
#include <cmsys/Terminal.h>
#include <queue>
#include <algorithm>
//----------------------------------------------------------------------------
// Escape special characters in Makefile dependency lines
@ -1971,6 +1972,57 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
}
namespace
{
// Helper predicate for removing absolute paths that don't point to the
// source or binary directory. It is used when CMAKE_DEPENDS_IN_PROJECT_ONLY
// is set ON, to only consider in-project dependencies during the build.
class NotInProjectDir
{
public:
// Constructor with the source and binary directory's path
NotInProjectDir(const std::string& sourceDir,
const std::string& binaryDir)
: SourceDir(sourceDir), BinaryDir(binaryDir) {}
// Operator evaluating the predicate
bool operator()(const std::string& path) const
{
// Keep all relative paths:
if(!cmSystemTools::FileIsFullPath(path))
{
return false;
}
// If it's an absolute path, check if it starts with the source
// direcotory:
return (!(IsInDirectory(SourceDir, path)||
IsInDirectory(BinaryDir, path)));
}
private:
// Helper function used by the predicate
static bool IsInDirectory(const std::string& baseDir,
const std::string& testDir)
{
// First check if the test directory "starts with" the base directory:
if (testDir.find(baseDir) != 0)
{
return false;
}
// If it does, then check that it's either the same string, or that the
// next character is a slash:
return ((testDir.size() == baseDir.size())||
(testDir[baseDir.size()] == '/'));
}
// The path to the source directory
std::string SourceDir;
// The path to the binary directory
std::string BinaryDir;
};
}
void cmLocalUnixMakefileGenerator3
::WriteDependLanguageInfo(std::ostream& cmakefileStream,
cmGeneratorTarget* target)
@ -2058,6 +2110,15 @@ void cmLocalUnixMakefileGenerator3
this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
this->GetIncludeDirectories(includes, target,
l->first, config);
if(this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY"))
{
const char* sourceDir = this->GetState()->GetSourceDirectory();
const char* binaryDir = this->GetState()->GetBinaryDirectory();
std::vector<std::string>::iterator itr =
std::remove_if(includes.begin(), includes.end(),
::NotInProjectDir(sourceDir, binaryDir));
includes.erase(itr, includes.end());
}
for(std::vector<std::string>::iterator i = includes.begin();
i != includes.end(); ++i)
{