VS: Teach cmake --build to reconfigure if needed before building

Visual Studio's build system does not cleanly handle itself being
re-generated during the build.  Teach `cmake --build` to check whether
the build system needs to be re-generated before launching the native
build tool.
This commit is contained in:
Yves Frederix
2016-09-16 17:50:06 +02:00
committed by Brad King
parent ab4a9a9826
commit 427b6da9e5
4 changed files with 65 additions and 11 deletions

View File

@@ -161,6 +161,11 @@ void cmGlobalVisualStudio8Generator::GetDocumentation(
entry.Brief = "Generates Visual Studio 8 2005 project files.";
}
std::string cmGlobalVisualStudio8Generator::GetGenerateStampList()
{
return "generate.stamp.list";
}
void cmGlobalVisualStudio8Generator::Configure()
{
this->cmGlobalVisualStudio7Generator::Configure();
@@ -244,7 +249,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
// Create a list of all stamp files for this project.
std::vector<std::string> stamps;
std::string stampList = cmake::GetCMakeFilesDirectoryPostSlash();
stampList += "generate.stamp.list";
stampList += cmGlobalVisualStudio8Generator::GetGenerateStampList();
{
std::string stampListFile =
generators[0]->GetMakefile()->GetCurrentBinaryDirectory();

View File

@@ -23,6 +23,9 @@ public:
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
/** Get the name of the main stamp list file. */
static std::string GetGenerateStampList();
virtual void EnableLanguage(std::vector<std::string> const& languages,
cmMakefile*, bool optional);
virtual void AddPlatformDefinitions(cmMakefile* mf);

View File

@@ -129,8 +129,8 @@ typedef CM_UNORDERED_MAP<std::string, Json::Value> JsonValueMapType;
} // namespace
static bool cmakeCheckStampFile(const char* stampName);
static bool cmakeCheckStampList(const char* stampName);
static bool cmakeCheckStampFile(const char* stampName, bool verbose = true);
static bool cmakeCheckStampList(const char* stampList, bool verbose = true);
void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/,
void* ctx, const char* /*unused*/,
@@ -2233,7 +2233,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
return 0;
}
static bool cmakeCheckStampFile(const char* stampName)
static bool cmakeCheckStampFile(const char* stampName, bool verbose)
{
// The stamp file does not exist. Use the stamp dependencies to
// determine whether it is really out of date. This works in
@@ -2287,11 +2287,13 @@ static bool cmakeCheckStampFile(const char* stampName)
stamp << "# CMake generation timestamp file for this directory.\n";
}
if (cmSystemTools::RenameFile(stampTemp, stampName)) {
// Notify the user why CMake is not re-running. It is safe to
// just print to stdout here because this code is only reachable
// through an undocumented flag used by the VS generator.
std::cout << "CMake does not need to re-run because " << stampName
<< " is up-to-date.\n";
if (verbose) {
// Notify the user why CMake is not re-running. It is safe to
// just print to stdout here because this code is only reachable
// through an undocumented flag used by the VS generator.
std::cout << "CMake does not need to re-run because " << stampName
<< " is up-to-date.\n";
}
return true;
}
cmSystemTools::RemoveFile(stampTemp);
@@ -2299,7 +2301,7 @@ static bool cmakeCheckStampFile(const char* stampName)
return false;
}
static bool cmakeCheckStampList(const char* stampList)
static bool cmakeCheckStampList(const char* stampList, bool verbose)
{
// If the stamp list does not exist CMake must rerun to generate it.
if (!cmSystemTools::FileExists(stampList)) {
@@ -2317,7 +2319,7 @@ static bool cmakeCheckStampList(const char* stampList)
// Check each stamp.
std::string stampName;
while (cmSystemTools::GetLineFromStream(fin, stampName)) {
if (!cmakeCheckStampFile(stampName.c_str())) {
if (!cmakeCheckStampFile(stampName.c_str(), verbose)) {
return false;
}
}
@@ -2397,6 +2399,48 @@ int cmake::Build(const std::string& dir, const std::string& target,
if (cachedVerbose) {
verbose = cmSystemTools::IsOn(cachedVerbose);
}
#ifdef CMAKE_HAVE_VS_GENERATORS
// For VS generators, explicitly check if regeneration is necessary before
// actually starting the build. If not done separately from the build
// itself, there is the risk of building an out-of-date solution file due
// to limitations of the underlying build system.
std::string const stampList = cachePath + "/" +
GetCMakeFilesDirectoryPostSlash() +
cmGlobalVisualStudio8Generator::GetGenerateStampList();
// Note that the stampList file only exists for VS generators.
if (cmSystemTools::FileExists(stampList.c_str()) &&
!cmakeCheckStampList(stampList.c_str(), false)) {
// Correctly initialize the home (=source) and home output (=binary)
// directories, which is required for running the generation step.
std::string homeOrig = this->GetHomeDirectory();
std::string homeOutputOrig = this->GetHomeOutputDirectory();
this->SetDirectoriesFromFile(cachePath.c_str());
int ret = this->Configure();
if (ret) {
cmSystemTools::Message("CMake Configure step failed. "
"Build files cannot be regenerated correctly.");
return ret;
}
ret = this->Generate();
if (ret) {
cmSystemTools::Message("CMake Generate step failed. "
"Build files cannot be regenerated correctly.");
return ret;
}
std::string message = "Build files have been written to: ";
message += this->GetHomeOutputDirectory();
this->UpdateProgress(message.c_str(), -1);
// Restore the previously set directories to their original value.
this->SetHomeDirectory(homeOrig);
this->SetHomeOutputDirectory(homeOutputOrig);
}
#endif
return gen->Build("", dir, projName, target, output, "", config, clean,
false, verbose, 0, cmSystemTools::OUTPUT_PASSTHROUGH,
nativeOptions);

View File

@@ -407,6 +407,8 @@ static int do_build(int ac, char const* const* av)
}
cmake cm;
cmSystemTools::SetMessageCallback(cmakemainMessageCallback, (void*)&cm);
cm.SetProgressCallback(cmakemainProgressCallback, (void*)&cm);
return cm.Build(dir, target, config, nativeOptions, clean);
#endif
}