diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index cb500519d..5fd5c5c05 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -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 diff --git a/Help/variable/CMAKE_DEPENDS_IN_PROJECT_ONLY.rst b/Help/variable/CMAKE_DEPENDS_IN_PROJECT_ONLY.rst new file mode 100644 index 000000000..717907145 --- /dev/null +++ b/Help/variable/CMAKE_DEPENDS_IN_PROJECT_ONLY.rst @@ -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. diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 62fea3d84..afdff337e 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -34,6 +34,7 @@ #include #include +#include //---------------------------------------------------------------------------- // 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::iterator itr = + std::remove_if(includes.begin(), includes.end(), + ::NotInProjectDir(sourceDir, binaryDir)); + includes.erase(itr, includes.end()); + } for(std::vector::iterator i = includes.begin(); i != includes.end(); ++i) {