From b1e1aa1e6a2aa4c0da9d39f2e9f2a80d093f1dc7 Mon Sep 17 00:00:00 2001 From: Attila Krasznahorkay Date: Tue, 22 Mar 2016 13:18:42 +0100 Subject: Makefile: Optionally scan only source and build trees for dependencies Add a `CMAKE_DEPENDS_IN_PROJECT_ONLY` variable to activate the behavior. --- Help/manual/cmake-variables.7.rst | 1 + Help/variable/CMAKE_DEPENDS_IN_PROJECT_ONLY.rst | 10 ++++ Source/cmLocalUnixMakefileGenerator3.cxx | 61 +++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 Help/variable/CMAKE_DEPENDS_IN_PROJECT_ONLY.rst diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index cb50051..5fd5c5c 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 0000000..7179071 --- /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 62fea3d..afdff33 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) { -- cgit v0.12 From 525402450a1ccde0e9187c9613752f728a96149b Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 22 Mar 2016 16:03:28 -0400 Subject: Tests: Add test for CMAKE_DEPENDS_IN_PROJECT_ONLY variable --- Tests/RunCMake/BuildDepends/MakeInProjectOnly.c | 2 ++ Tests/RunCMake/BuildDepends/MakeInProjectOnly.cmake | 16 ++++++++++++++++ .../RunCMake/BuildDepends/MakeInProjectOnly.step1.cmake | 3 +++ .../RunCMake/BuildDepends/MakeInProjectOnly.step2.cmake | 3 +++ Tests/RunCMake/BuildDepends/RunCMakeTest.cmake | 5 +++++ 5 files changed, 29 insertions(+) create mode 100644 Tests/RunCMake/BuildDepends/MakeInProjectOnly.c create mode 100644 Tests/RunCMake/BuildDepends/MakeInProjectOnly.cmake create mode 100644 Tests/RunCMake/BuildDepends/MakeInProjectOnly.step1.cmake create mode 100644 Tests/RunCMake/BuildDepends/MakeInProjectOnly.step2.cmake diff --git a/Tests/RunCMake/BuildDepends/MakeInProjectOnly.c b/Tests/RunCMake/BuildDepends/MakeInProjectOnly.c new file mode 100644 index 0000000..bcb8745 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/MakeInProjectOnly.c @@ -0,0 +1,2 @@ +#include +int main() { return MakeInProjectOnly(); } diff --git a/Tests/RunCMake/BuildDepends/MakeInProjectOnly.cmake b/Tests/RunCMake/BuildDepends/MakeInProjectOnly.cmake new file mode 100644 index 0000000..add9aeb --- /dev/null +++ b/Tests/RunCMake/BuildDepends/MakeInProjectOnly.cmake @@ -0,0 +1,16 @@ +enable_language(C) +get_filename_component(include_dir "${CMAKE_BINARY_DIR}" PATH) +include_directories("${include_dir}") +add_executable(MakeInProjectOnly MakeInProjectOnly.c) +set(CMAKE_DEPENDS_IN_PROJECT_ONLY 1) +file(GENERATE OUTPUT check-$>.cmake CONTENT " +if (check_step EQUAL 1) + set(check_pairs + \"$|${include_dir}/MakeInProjectOnly.h\" + ) +else() + set(check_pairs + \"${include_dir}/MakeInProjectOnly.h|\$\" + ) +endif() +") diff --git a/Tests/RunCMake/BuildDepends/MakeInProjectOnly.step1.cmake b/Tests/RunCMake/BuildDepends/MakeInProjectOnly.step1.cmake new file mode 100644 index 0000000..d6551ab --- /dev/null +++ b/Tests/RunCMake/BuildDepends/MakeInProjectOnly.step1.cmake @@ -0,0 +1,3 @@ +file(WRITE "${RunCMake_TEST_BINARY_DIR}/../MakeInProjectOnly.h" [[ +int MakeInProjectOnly(void) { return 0; } +]]) diff --git a/Tests/RunCMake/BuildDepends/MakeInProjectOnly.step2.cmake b/Tests/RunCMake/BuildDepends/MakeInProjectOnly.step2.cmake new file mode 100644 index 0000000..145605b --- /dev/null +++ b/Tests/RunCMake/BuildDepends/MakeInProjectOnly.step2.cmake @@ -0,0 +1,3 @@ +file(WRITE "${RunCMake_TEST_BINARY_DIR}/../MakeInProjectOnly.h" [[ +int MakeInProjectOnly(void) { return 1; } +]]) diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index 26ffcc0..6b2b85a 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -41,6 +41,11 @@ endif() run_BuildDepends(Custom-Always) +if(RunCMake_GENERATOR MATCHES "Make" AND + NOT "${RunCMake_BINARY_DIR}" STREQUAL "${RunCMake_SOURCE_DIR}") + run_BuildDepends(MakeInProjectOnly) +endif() + function(run_ReGeneration) # test re-generation of project even if CMakeLists.txt files disappeared -- cgit v0.12 From b06e17da7b4137d22ae7cfcf14c6aa3205577822 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 22 Mar 2016 16:04:25 -0400 Subject: Help: Add notes for topic 'cmake-depend-in-project-only' --- Help/release/dev/cmake-depend-in-project-only.rst | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Help/release/dev/cmake-depend-in-project-only.rst diff --git a/Help/release/dev/cmake-depend-in-project-only.rst b/Help/release/dev/cmake-depend-in-project-only.rst new file mode 100644 index 0000000..8553e80 --- /dev/null +++ b/Help/release/dev/cmake-depend-in-project-only.rst @@ -0,0 +1,6 @@ +cmake-depend-in-project-only +---------------------------- + +* The :ref:`Makefile Generators` learned to optionally limit dependency + scanning only to files in the project source and build trees. + See the :variable:`CMAKE_DEPENDS_IN_PROJECT_ONLY` variable. -- cgit v0.12