diff options
author | Yurii Batrak <yuriib@met.no> | 2017-11-24 12:01:18 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2017-12-14 13:13:42 (GMT) |
commit | 5f2e2c387deb7f798cbc54d0980503e05873eaaa (patch) | |
tree | 95a65992d8754c8d1b96bf0ad2073753244fa8b1 | |
parent | eea976e930fcb7e8f92968c241d50ed49a1f1f0b (diff) | |
download | CMake-5f2e2c387deb7f798cbc54d0980503e05873eaaa.zip CMake-5f2e2c387deb7f798cbc54d0980503e05873eaaa.tar.gz CMake-5f2e2c387deb7f798cbc54d0980503e05873eaaa.tar.bz2 |
Makefiles: Avoid nested make calls for Fortran module dependencies
Makefiles generated by cmake use a series of nested calls to build
`*.provides.build` targets that are used when the 'requires' step is
needed. That leads to significant degradation of the build time for
incremental builds. Re-arrange dependencies to eliminate the nested
calls.
Explicit `.mod.stamp` targets introduced by this commit could lead to
situation when a stamp file always older than its dependency. This
happens during the incremental build when building of an updated Fortran
source produces a module file that has no differences from the stored
stamp file. In such case `cmake_copy_f90_mod` will be triggered on each
new build to compare a module file with the corresponding stamp file.
This behavior is expected and can not be changed without nested calls
that slow down the build. The copy-if-different check is much cheaper
than an entire nested make call.
-rw-r--r-- | Source/cmDependsFortran.cxx | 24 | ||||
-rw-r--r-- | Source/cmLocalUnixMakefileGenerator3.cxx | 2 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 6 |
3 files changed, 22 insertions, 10 deletions
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index fdbc086..8b4fafd 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -388,7 +388,6 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, if (!info.Provides.empty()) { // Create a target to copy the module after the object file // changes. - makeDepends << obj_m << ".provides.build:\n"; for (std::string const& i : info.Provides) { // Include this module in the set provided by this target. this->Internal->TargetProvides.insert(i); @@ -407,11 +406,25 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, stampFile += "/"; stampFile += m; stampFile += ".mod.stamp"; - stampFile = this->LocalGenerator->ConvertToOutputFormat( - this->MaybeConvertToRelativePath(binDir, stampFile), - cmOutputConverter::SHELL); + stampFile = this->MaybeConvertToRelativePath(binDir, stampFile); + std::string const stampFileForShell = + this->LocalGenerator->ConvertToOutputFormat(stampFile, + cmOutputConverter::SHELL); + std::string const stampFileForMake = + cmSystemTools::ConvertToOutputPath(stampFile.c_str()); + + makeDepends << obj_m << ".provides.build" + << ": " << stampFileForMake << "\n"; + // Note that when cmake_copy_f90_mod finds that a module file + // and the corresponding stamp file have no differences, the stamp + // file is not updated. In such case the stamp file will be always + // older than its prerequisite and trigger cmake_copy_f90_mod + // on each new build. This is expected behavior for incremental + // builds and can not be changed without preforming recursive make + // calls that would considerably slow down the building process. + makeDepends << stampFileForMake << ": " << obj_m << "\n"; makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod " << modFile - << " " << stampFile; + << " " << stampFileForShell; cmMakefile* mf = this->LocalGenerator->GetMakefile(); const char* cid = mf->GetDefinition("CMAKE_Fortran_COMPILER_ID"); if (cid && *cid) { @@ -419,6 +432,7 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, } makeDepends << "\n"; } + makeDepends << obj_m << ".provides.build:\n"; // After copying the modules update the timestamp file so that // copying will not be done again until the source rebuilds. makeDepends << "\t$(CMAKE_COMMAND) -E touch " << obj_m diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index e26182a..a389ad0 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1444,6 +1444,8 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( } #ifdef CMAKE_BUILD_WITH_CMAKE else if (lang == "Fortran") { + ruleFileStream << "# Note that incremental build could trigger " + << "a call to cmake_copy_f90_mod on each re-build\n"; scanner = new cmDependsFortran(this); } else if (lang == "Java") { scanner = new cmDependsJava(); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 7db010c..ae0b61c 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -835,14 +835,10 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( std::string temp = relativeObj; temp += ".provides.build"; std::vector<std::string> r_commands; - std::string tgtMakefileName = - this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget); - tgtMakefileName += "/build.make"; - r_commands.push_back( - this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(), temp)); p_depends.clear(); p_depends.push_back(objectRequires); + p_depends.push_back(temp); this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr, objectProvides, p_depends, r_commands, true); |