ENH: Makefile performance improvements

This commit is contained in:
Ken Martin 2006-05-02 09:56:42 -04:00
parent 2324e7ec5d
commit 3023eb7ccb
6 changed files with 206 additions and 123 deletions

View File

@ -91,7 +91,7 @@ ENDIF(NOT CMAKE_COMPILER_IS_GNUCC_RUN)
# configure variables set in this file for fast reload later on # configure variables set in this file for fast reload later on
CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeCCompiler.cmake.in CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeCCompiler.cmake.in
${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCCompiler.cmake IMMEDIATE) "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCCompiler.cmake" IMMEDIATE)
MARK_AS_ADVANCED(CMAKE_AR) MARK_AS_ADVANCED(CMAKE_AR)
SET(CMAKE_C_COMPILER_ENV_VAR "CC") SET(CMAKE_C_COMPILER_ENV_VAR "CC")

View File

@ -1,7 +1,7 @@
# try to load any previously computed information for C on this platform # try to load any previously computed information for C on this platform
INCLUDE( ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCPlatform.cmake OPTIONAL) INCLUDE( ${CMAKE_PLATFORM_ROOT_BIN}/CMakeCPlatform.cmake OPTIONAL)
# try to load any previously computed information for CXX on this platform # try to load any previously computed information for CXX on this platform
INCLUDE( ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCXXPlatform.cmake OPTIONAL) INCLUDE( ${CMAKE_PLATFORM_ROOT_BIN}/CMakeCXXPlatform.cmake OPTIONAL)
SET(CMAKE_LIBRARY_PATH_FLAG "-LIBPATH:") SET(CMAKE_LIBRARY_PATH_FLAG "-LIBPATH:")
SET(CMAKE_LINK_LIBRARY_FLAG "") SET(CMAKE_LINK_LIBRARY_FLAG "")
@ -273,14 +273,14 @@ SET (CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO_INIT ${CMAKE_EXE_LINKER_FLAGS_RELW
# save computed information for this platform # save computed information for this platform
IF(NOT EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCPlatform.cmake") IF(NOT EXISTS "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCPlatform.cmake")
CONFIGURE_FILE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake.in CONFIGURE_FILE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake.in
${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCPlatform.cmake IMMEDIATE) ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCPlatform.cmake IMMEDIATE)
ENDIF(NOT EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCPlatform.cmake") ENDIF(NOT EXISTS "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCPlatform.cmake")
IF(NOT EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCXXPlatform.cmake") IF(NOT EXISTS "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCXXPlatform.cmake")
CONFIGURE_FILE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake.in CONFIGURE_FILE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake.in
${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCXXPlatform.cmake IMMEDIATE) ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCXXPlatform.cmake IMMEDIATE)
ENDIF(NOT EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeCXXPlatform.cmake") ENDIF(NOT EXISTS "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCXXPlatform.cmake")
INCLUDE(Platform/WindowsPaths) INCLUDE(Platform/WindowsPaths)

View File

@ -169,42 +169,21 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
// files from the parent cmake bin dir, into the try compile bin dir // files from the parent cmake bin dir, into the try compile bin dir
if(this->ConfiguredFilesPath.size()) if(this->ConfiguredFilesPath.size())
{ {
std::string src = this->ConfiguredFilesPath;
src += "/CMakeSystem.cmake";
std::string dst = rootBin;
dst += "/CMakeSystem.cmake";
cmSystemTools::CopyFileIfDifferent(src.c_str(), dst.c_str());
for(std::vector<std::string>::const_iterator l = languages.begin(); for(std::vector<std::string>::const_iterator l = languages.begin();
l != languages.end(); ++l) l != languages.end(); ++l)
{ {
if(*l == "NONE") if(*l == "NONE")
{ {
this->SetLanguageEnabled("NONE", mf); this->SetLanguageEnabled("NONE", mf);
continue; break;
} }
const char* lang = l->c_str();
std::string src2 = this->ConfiguredFilesPath;
src2 += "/CMake";
src2 += lang;
src2 += "Compiler.cmake";
std::string dst2 = rootBin;
dst2 += "/CMake";
dst2 += lang;
dst2 += "Compiler.cmake";
cmSystemTools::CopyFileIfDifferent(src2.c_str(), dst2.c_str());
src2 = this->ConfiguredFilesPath;
src2 += "/CMake";
src2 += lang;
src2 += "Platform.cmake";
dst2 = rootBin;
dst2 += "/CMake";
dst2 += lang;
dst2 += "Platform.cmake";
cmSystemTools::CopyFileIfDifferent(src2.c_str(), dst2.c_str());
} }
rootBin = this->ConfiguredFilesPath; rootBin = this->ConfiguredFilesPath;
} }
// set the dir for parent files so they can be used by modules
mf->AddDefinition("CMAKE_PLATFORM_ROOT_BIN",rootBin.c_str());
// find and make sure CMAKE_MAKE_PROGRAM is defined // find and make sure CMAKE_MAKE_PROGRAM is defined
this->FindMakeProgram(mf); this->FindMakeProgram(mf);

View File

@ -501,6 +501,66 @@ cmGlobalUnixMakefileGenerator3
this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", false, true); this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", false, true);
} }
std::string cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(const char* makeProgram,
const char *projectName, const char* additionalOptions, const char *targetName,
const char* config, bool ignoreErrors)
{
// Project name and config are not used yet.
(void)projectName;
(void)config;
std::string makeCommand = cmSystemTools::ConvertToUnixOutputPath(makeProgram);
// Since we have full control over the invocation of nmake, let us
// make it quiet.
if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
{
makeCommand += " /NOLOGO ";
}
if ( ignoreErrors )
{
makeCommand += " -i";
}
if ( additionalOptions )
{
makeCommand += " ";
makeCommand += additionalOptions;
}
if ( targetName && strlen(targetName))
{
cmLocalUnixMakefileGenerator3 *lg;
if (this->LocalGenerators.size())
{
lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
}
else
{
lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->CreateLocalGenerator());
// set the Start directories
lg->GetMakefile()->SetStartDirectory
(this->CMakeInstance->GetStartDirectory());
lg->GetMakefile()->SetStartOutputDirectory
(this->CMakeInstance->GetStartOutputDirectory());
lg->GetMakefile()->MakeStartDirectoriesCurrent();
}
makeCommand += "\"";
std::string tname = targetName;
tname += "/fast";
tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
cmLocalGenerator::SHELL);
tname = lg->ConvertToMakeTarget(tname.c_str());
makeCommand += tname.c_str();
makeCommand += "\"";
if (!this->LocalGenerators.size())
{
delete lg;
}
}
return makeCommand;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmGlobalUnixMakefileGenerator3 cmGlobalUnixMakefileGenerator3
@ -550,8 +610,35 @@ cmGlobalUnixMakefileGenerator3
"Build rule for target.", "Build rule for target.",
t->second.GetName(), depends, commands, t->second.GetName(), depends, commands,
true); true);
// Add a fast rule to build the target
std::string localName = lg->GetRelativeTargetDirectory(t->second);
std::string makefileName;
makefileName = localName;
makefileName += "/build.make";
depends.clear();
commands.clear();
std::string makeTargetName = localName;
makeTargetName += "/build";
localName = t->second.GetName();
localName += "/fast";
commands.push_back(lg->GetRecursiveMakeCall
(makefileName.c_str(), makeTargetName.c_str()));
lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
localName.c_str(), depends, commands, true);
} }
} }
else
{
// Add a fast rule to build the target
depends.clear();
commands.clear();
std::string localName = t->second.GetName();
depends.push_back(localName);
localName += "/fast";
lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
localName.c_str(), depends, commands, true);
}
} }
} }
} }
@ -578,117 +665,120 @@ cmGlobalUnixMakefileGenerator3
cmTargets& targets = lg->GetMakefile()->GetTargets(); cmTargets& targets = lg->GetMakefile()->GetTargets();
for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t) for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
{ {
if (((t->second.GetType() == cmTarget::EXECUTABLE) || if (t->second.GetName() && strlen(t->second.GetName()))
(t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
(t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
(t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
(t->second.GetType() == cmTarget::UTILITY)) &&
t->second.GetName() &&
strlen(t->second.GetName()))
{ {
bool needRequiresStep = std::string makefileName;
this->NeedRequiresStep(lg,t->second.GetName());
// Add a rule to build the target by name. // Add a rule to build the target by name.
localName = lg->GetRelativeTargetDirectory(t->second); localName = lg->GetRelativeTargetDirectory(t->second);
std::string makefileName = localName; makefileName = localName;
makefileName += "/build.make"; makefileName += "/build.make";
lg->WriteDivider(ruleFileStream); if (((t->second.GetType() == cmTarget::EXECUTABLE) ||
ruleFileStream (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
<< "# Target rules for target " (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
<< localName << "\n\n"; (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
(t->second.GetType() == cmTarget::UTILITY)))
commands.clear();
if (t->second.GetType() != cmTarget::UTILITY)
{ {
bool needRequiresStep =
this->NeedRequiresStep(lg,t->second.GetName());
lg->WriteDivider(ruleFileStream);
ruleFileStream
<< "# Target rules for target "
<< localName << "\n\n";
commands.clear();
if (t->second.GetType() != cmTarget::UTILITY)
{
makeTargetName = localName;
makeTargetName += "/depend";
commands.push_back(lg->GetRecursiveMakeCall
(makefileName.c_str(),makeTargetName.c_str()));
// add requires if we need it for this generator
if (needRequiresStep)
{
makeTargetName = localName;
makeTargetName += "/requires";
commands.push_back(lg->GetRecursiveMakeCall
(makefileName.c_str(),makeTargetName.c_str()));
}
}
makeTargetName = localName; makeTargetName = localName;
makeTargetName += "/depend"; makeTargetName += "/build";
commands.push_back(lg->GetRecursiveMakeCall commands.push_back(lg->GetRecursiveMakeCall
(makefileName.c_str(),makeTargetName.c_str())); (makefileName.c_str(),makeTargetName.c_str()));
// add requires if we need it for this generator // Write the rule.
if (needRequiresStep) localName += "/all";
depends.clear();
this->AppendGlobalTargetDepends(depends,t->second);
lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
localName.c_str(), depends, commands, true);
// add the all/all dependency
if (!exclude && t->second.IsInAll())
{ {
makeTargetName = localName; depends.clear();
makeTargetName += "/requires"; depends.push_back(localName);
commands.push_back(lg->GetRecursiveMakeCall commands.clear();
(makefileName.c_str(),makeTargetName.c_str())); lg->WriteMakeRule(ruleFileStream, "Include target in all.",
"all", depends, commands, true);
} }
}
makeTargetName = localName;
makeTargetName += "/build";
commands.push_back(lg->GetRecursiveMakeCall
(makefileName.c_str(),makeTargetName.c_str()));
// Write the rule. // Write the rule.
localName += "/all"; commands.clear();
depends.clear(); commands.push_back(lg->GetRecursiveMakeCall
this->AppendGlobalTargetDepends(depends,t->second); ("CMakeFiles/Makefile2",localName.c_str()));
lg->WriteMakeRule(ruleFileStream, "All Build rule for target.", depends.clear();
localName.c_str(), depends, commands, true); depends.push_back("cmake_check_build_system");
localName = lg->GetRelativeTargetDirectory(t->second);
localName += "/rule";
lg->WriteMakeRule(ruleFileStream,
"Build rule for subdir invocation for target.",
localName.c_str(), depends, commands, true);
// add the all/all dependency // Add a target with the canonical name (no prefix, suffix or path).
if (!exclude && t->second.IsInAll()) commands.clear();
{
depends.clear(); depends.clear();
depends.push_back(localName); depends.push_back(localName);
commands.clear(); lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
lg->WriteMakeRule(ruleFileStream, "Include target in all.", t->second.GetName(), depends, commands, true);
"all", depends, commands, true);
}
// Write the rule. // Add rules to prepare the target for installation.
commands.clear(); if(t->second.NeedRelinkBeforeInstall())
commands.push_back(lg->GetRecursiveMakeCall {
("CMakeFiles/Makefile2",localName.c_str())); localName = lg->GetRelativeTargetDirectory(t->second);
depends.clear(); localName += "/preinstall";
depends.push_back("cmake_check_build_system"); depends.clear();
localName = lg->GetRelativeTargetDirectory(t->second); commands.clear();
localName += "/rule"; commands.push_back(lg->GetRecursiveMakeCall
lg->WriteMakeRule(ruleFileStream, (makefileName.c_str(), localName.c_str()));
"Build rule for subdir invocation for target.", this->AppendGlobalTargetDepends(depends,t->second);
localName.c_str(), depends, commands, true); lg->WriteMakeRule(ruleFileStream, "Pre-install relink rule for target.",
localName.c_str(), depends, commands, true);
depends.clear();
depends.push_back(localName);
commands.clear();
lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
"preinstall", depends, commands, true);
}
// Add a target with the canonical name (no prefix, suffix or path). // add the clean rule
commands.clear();
depends.clear();
depends.push_back(localName);
lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
t->second.GetName(), depends, commands, true);
// Add rules to prepare the target for installation.
if(t->second.NeedRelinkBeforeInstall())
{
localName = lg->GetRelativeTargetDirectory(t->second); localName = lg->GetRelativeTargetDirectory(t->second);
localName += "/preinstall"; makeTargetName = localName;
makeTargetName += "/clean";
depends.clear(); depends.clear();
commands.clear(); commands.clear();
commands.push_back(lg->GetRecursiveMakeCall commands.push_back(lg->GetRecursiveMakeCall
(makefileName.c_str(), localName.c_str())); (makefileName.c_str(), makeTargetName.c_str()));
this->AppendGlobalTargetDepends(depends,t->second); lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
lg->WriteMakeRule(ruleFileStream, "Pre-install relink rule for target.", makeTargetName.c_str(), depends, commands, true);
localName.c_str(), depends, commands, true);
depends.clear();
depends.push_back(localName);
commands.clear(); commands.clear();
lg->WriteMakeRule(ruleFileStream, "Prepare target for install.", depends.push_back(makeTargetName);
"preinstall", depends, commands, true); lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
"clean", depends, commands, true);
} }
// add the clean rule
localName = lg->GetRelativeTargetDirectory(t->second);
makeTargetName = localName;
makeTargetName += "/clean";
depends.clear();
commands.clear();
commands.push_back(lg->GetRecursiveMakeCall
(makefileName.c_str(), makeTargetName.c_str()));
lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
makeTargetName.c_str(), depends, commands, true);
commands.clear();
depends.push_back(makeTargetName);
lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
"clean", depends, commands, true);
} }
} }
} }

View File

@ -113,6 +113,15 @@ public:
/** Get the command to use for a non-symbolic target file that has /** Get the command to use for a non-symbolic target file that has
no rule. This is used for multiple output dependencies. */ no rule. This is used for multiple output dependencies. */
std::string GetEmptyCommandHack() { return this->EmptyCommandsHack; } std::string GetEmptyCommandHack() { return this->EmptyCommandsHack; }
// change the build command for speed
virtual std::string GenerateBuildCommand
(const char* makeProgram,
const char *projectName, const char* additionalOptions,
const char *targetName,
const char* config, bool ignoreErrors);
protected: protected:
void WriteMainMakefile2(); void WriteMainMakefile2();
void WriteMainCMakefile(); void WriteMainCMakefile();

View File

@ -1418,6 +1418,11 @@ void cmLocalUnixMakefileGenerator3
this->Makefile->GetStartOutputDirectory()); this->Makefile->GetStartOutputDirectory());
this->WriteMakeRule(ruleFileStream, "The main clean target", "clean", this->WriteMakeRule(ruleFileStream, "The main clean target", "clean",
depends, commands, true); depends, commands, true);
commands.clear();
depends.clear();
depends.push_back("clean");
this->WriteMakeRule(ruleFileStream, "The main clean target", "clean/fast",
depends, commands, true);
// Write the preinstall rule. // Write the preinstall rule.
dir = this->Makefile->GetStartOutputDirectory(); dir = this->Makefile->GetStartOutputDirectory();