mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-04 04:40:56 -06:00
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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user