From c790b1fabbc7b160bd67e1654a34964fd897a36c Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 17 Jun 2009 13:40:09 -0400 Subject: [PATCH] ENH: Create CMP0013 to disallow duplicate dirs In CMake 2.6.3 and below we silently accepted duplicate build directories whose build files would then conflict. At first this was considured purely a bug that confused beginners but would not be used in a real project. In CMake 2.6.4 we explicitly made it an error. However, some real projects took advantage of this as a "feature" and got lucky that the subtle build errors it can cause did not occur. Therefore we need a policy to deal with the case more gracefully. See issue #9173. --- Source/cmMakefile.cxx | 59 +++++++++++++++++++++++++++++++++++-------- Source/cmMakefile.h | 2 ++ Source/cmPolicies.cxx | 17 +++++++++++++ Source/cmPolicies.h | 1 + 4 files changed, 69 insertions(+), 10 deletions(-) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index fc572767f..57904b4c5 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1545,17 +1545,8 @@ void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath, } // Make sure the binary directory is unique. - cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator(); - if(!gg->BinaryDirectoryIsNew(binPath)) + if(!this->EnforceUniqueDir(srcPath, binPath)) { - cmOStringStream e; - e << "The binary directory\n" - << " " << binPath << "\n" - << "is already used to build another source directory, so it cannot " - << "be used to build source directory\n" - << " " << srcPath << "\n" - << "Specify a unique binary directory name."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } @@ -3719,6 +3710,54 @@ bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg, return true; } +//---------------------------------------------------------------------------- +bool cmMakefile::EnforceUniqueDir(const char* srcPath, const char* binPath) +{ + // Make sure the binary directory is unique. + cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator(); + if(gg->BinaryDirectoryIsNew(binPath)) + { + return true; + } + cmOStringStream e; + switch (this->GetPolicyStatus(cmPolicies::CMP0013)) + { + case cmPolicies::WARN: + // Print the warning. + e << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0013) + << "\n" + << "The binary directory\n" + << " " << binPath << "\n" + << "is already used to build a source directory. " + << "This command uses it to build source directory\n" + << " " << srcPath << "\n" + << "which can generate conflicting build files. " + << "CMake does not support this use case but it used " + << "to work accidentally and is being allowed for " + << "compatibility."; + this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + case cmPolicies::OLD: + // OLD behavior does not warn. + return true; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + e << this->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0013) + << "\n"; + case cmPolicies::NEW: + // NEW behavior prints the error. + e << "The binary directory\n" + << " " << binPath << "\n" + << "is already used to build a source directory. " + << "It cannot be used to build source directory\n" + << " " << srcPath << "\n" + << "Specify a unique binary directory name."; + this->IssueMessage(cmake::FATAL_ERROR, e.str()); + break; + } + + return false; +} + //---------------------------------------------------------------------------- cmPolicies::PolicyStatus cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id) diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 5efe2d948..7a235f9bb 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -900,6 +900,8 @@ private: bool ParseDefineFlag(std::string const& definition, bool remove); + bool EnforceUniqueDir(const char* srcPath, const char* binPath); + void ReadSources(std::ifstream& fin, bool t); friend class cmMakeDepend; // make depend needs direct access // to the Sources array diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 5e80e2fad..1f8bb8928 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -369,6 +369,23 @@ cmPolicies::cmPolicies() "The NEW behavior for this policy is to treat strings like true as a " "boolean constant.", 2,6,5, cmPolicies::WARN); + + this->DefinePolicy( + CMP0013, "CMP0013", + "Duplicate binary directories are not allowed.", + "CMake 2.6.3 and below silently permitted add_subdirectory() calls " + "to create the same binary directory multiple times. " + "During build system generation files would be written and then " + "overwritten in the build tree and could lead to strange behavior. " + "CMake 2.6.4 and above explicitly detect duplicate binary directories. " + "CMake 2.6.4 always considers this case an error. " + "In CMake 2.6.5 and above this policy determines whether or not " + "the case is an error. " + "The OLD behavior for this policy is to allow duplicate binary " + "directories. " + "The NEW behavior for this policy is to disallow duplicate binary " + "directories with an error.", + 2,6,5, cmPolicies::WARN); } cmPolicies::~cmPolicies() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 43b193411..391b91c44 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -53,6 +53,7 @@ public: CMP0010, // Bad variable reference syntax is an error CMP0011, // Strong policy scope for include and find_package CMP0012, // Strong handling of boolean constants + CMP0013, // Duplicate binary directories not allowed // Always the last entry. Useful mostly to avoid adding a comma // the last policy when adding a new one.