diff options
author | Ken Martin <ken.martin@kitware.com> | 2008-02-29 20:28:46 (GMT) |
---|---|---|
committer | Ken Martin <ken.martin@kitware.com> | 2008-02-29 20:28:46 (GMT) |
commit | ab851bf36b3d32d5f5284718d1c660356e4c56fb (patch) | |
tree | 2c795be6435360d455593a2d956424929b8954c2 | |
parent | 22dc873ef07bdb31ee80b6117a781b1253ae7f94 (diff) | |
download | CMake-ab851bf36b3d32d5f5284718d1c660356e4c56fb.zip CMake-ab851bf36b3d32d5f5284718d1c660356e4c56fb.tar.gz CMake-ab851bf36b3d32d5f5284718d1c660356e4c56fb.tar.bz2 |
ENH: just getting somethng checked in, still work to do
-rw-r--r-- | Source/cmCMakePolicyCommand.h | 98 | ||||
-rw-r--r-- | Source/cmCmakePolicyCOmmand.cxx | 59 | ||||
-rw-r--r-- | Source/cmPolicies.cxx | 410 | ||||
-rw-r--r-- | Source/cmPolicies.h | 85 |
4 files changed, 652 insertions, 0 deletions
diff --git a/Source/cmCMakePolicyCommand.h b/Source/cmCMakePolicyCommand.h new file mode 100644 index 0000000..19ff393 --- /dev/null +++ b/Source/cmCMakePolicyCommand.h @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef cmCMakePolicyCommand_h +#define cmCMakePolicyCommand_h + +#include "cmCommand.h" + +/** \class cmCMakePolicyCommand + * \brief Set how CMake should handle policies + * + * cmCMakePolicyCommand sets how CMake should deal with backwards + * compatibility policies. + */ +class cmCMakePolicyCommand : public cmCommand +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmCMakePolicyCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector<std::string> const& args, + cmExecutionStatus &status); + + /** + * This determines if the command is invoked when in script mode. + */ + virtual bool IsScriptable() { return true; } + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() {return "cmake_policy";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() + { + return "Set how CMake should handle policies."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() + { + return + " cmake_policy(NEW id)\n" + " cmake_policy(OLD id)\n" + " cmake_policy(VERSION version)\n" + " cmake_policy(PUSH)\n" + " cmake_policy(POP)\n" + "The first two forms of this command sets a specified policy to " + "use the OLD or NEW implementation respectively. For example " + "if a new policy is created in CMake 2.6 then you could use " + "this command to tell the running CMake to use the OLD behavior " + "(before the change in 2.6) or the NEW behavior.\n" + "The third form of this command indicates that the CMake List file " + "has been written to the specified version of CMake and to the " + "policies of that version of CMake. All policies introduced in " + "the specified version of CMake or earlier will be set to NEW. " + "All policies introduced after the specified version of CMake will " + "be set to WARN (WARN is like OLD but also produces a warning) if " + "that is possible.\n" + "The last two forms of this command push and pop the current " + "handling of policies in CMake. This is useful when mixing multiple " + "projects that may have been written to different versions of CMake." + ; + } + + cmTypeMacro(cmCMakePolicyCommand, cmCommand); +}; + + + +#endif diff --git a/Source/cmCmakePolicyCOmmand.cxx b/Source/cmCmakePolicyCOmmand.cxx new file mode 100644 index 0000000..b87e7ae --- /dev/null +++ b/Source/cmCmakePolicyCOmmand.cxx @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "cmCMakePolicyCommand.h" + +#include "cmVersion.h" + +// cmCMakePolicyCommand +bool cmCMakePolicyCommand +::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) +{ + if (args.size() < 1) + { + this->SetError("cmake_policy requires at least one argument."); + return false; + } + + if (args[0] == "OLD" && args.size() == 2) + { + return this->Makefile->SetPolicy(args[1].c_str(),cmPolicies::OLD); + } + + if (args[0] == "NEW" && args.size() == 2) + { + return this->Makefile->SetPolicy(args[1].c_str(),cmPolicies::NEW); + } + + if (args[0] == "VERSION" && args.size() == 2) + { + return this->Makefile->SetPolicyVersion(args[1].c_str()); + } + + if (args[0] == "PUSH" && args.size() == 1) + { + return this->Makefile->PushPolicy(); + } + + if (args[0] == "POP" && args.size() == 1) + { + return this->Makefile->PopPolicy(); + } + + this->SetError("incorrect arguments for cmake_policy."); + return false; +} + diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx new file mode 100644 index 0000000..3a05e4b --- /dev/null +++ b/Source/cmPolicies.cxx @@ -0,0 +1,410 @@ +#include "cmPolicies.h" +#include "cmake.h" +#include "cmMakefile.h" +#include "cmSourceFile.h" +#include <map> +#include <set> +#include <queue> +#include <assert.h> + +const char* cmPolicies::PolicyStatusNames[] = { + "OLD", "WARN", "NEW", "REQUIRED_IF_USED", "REQUIRED_ALWAYS" +}; + +class cmPolicy +{ +public: + cmPolicy(cmPolicies::PolicyID iD, + const char *idString, + const char *shortDescription, + const char *longDescription, + unsigned int majorVersionIntroduced, + unsigned int minorVersionIntroduced, + unsigned int patchVersionIntroduced, + cmPolicies::PolicyStatus status) + { + if (!idString || !shortDescription || ! longDescription) + { + cmSystemTools::Error("Attempt to define a policy without " + "all parameters being specified!"); + return; + } + this->ID = iD; + this->IDString = idString; + this->ShortDescription = shortDescription; + this->LongDescription = longDescription; + this->MajorVersionIntroduced = majorVersionIntroduced; + this->MinorVersionIntroduced = minorVersionIntroduced; + this->PatchVersionIntroduced = patchVersionIntroduced; + this->Status = status; + } + + std::string GetVersionString() + { + cmOStringStream error; + error << this->MajorVersionIntroduced << "." << + this->MinorVersionIntroduced << "." << + this->PatchVersionIntroduced; + return error.str(); + } + + bool IsPolicyNewerThan(unsigned int majorV, + unsigned int minorV, + unsigned int patchV) + { + if (majorV < this->MajorVersionIntroduced) + { + return true; + } + if (majorV > this->MajorVersionIntroduced) + { + return false; + } + if (minorV < this->MinorVersionIntroduced) + { + return true; + } + if (minorV > this->MinorVersionIntroduced) + { + return false; + } + return (patchV < this->PatchVersionIntroduced); + } + + cmPolicies::PolicyID ID; + std::string IDString; + std::string ShortDescription; + std::string LongDescription; + unsigned int MajorVersionIntroduced; + unsigned int MinorVersionIntroduced; + unsigned int PatchVersionIntroduced; + cmPolicies::PolicyStatus Status; +}; + +cmPolicies::cmPolicies() +{ + // define all the policies + this->DefinePolicy(CMP_0000, "CMP_0000", + "Missing a CMake version specification. You must have a cmake_policy " + "or cmake_minimum_required call.", + "CMake requires that projects specify what version of CMake they have " + "been written to. The easiest way to do this is by placing a call to " + "cmake_policy such as the following cmake_policy(VERSION 2.6) Replace " + "2.6 in that example with the verison of CMake you are writing to. " + "This policy is being put in place because it aids us in detecting " + "and maintaining backwards compatibility.", + 2,6,0, cmPolicies::WARN); + this->PolicyStringMap["CMP_POLICY_SPECIFICATION"] = CMP_0000; + + this->DefinePolicy(CMP_0001, "CMP_0001", + "CMake does not allow target names to include slash characters.", + "CMake requires that target names not include any / or \\ characters " + "please change the name of any targets to not use such characters." + , + 2,4,0, cmPolicies::REQUIRED_IF_USED); + this->PolicyStringMap["CMP_TARGET_NAMES_WITH_SLASHES"] = CMP_0001; + + this->DefinePolicy(CMP_0002, "CMP_0002", + "CMake requires that target names be globaly unique.", + "CMake requires that target names not include any / or \\ characters " + "please change the name of any targets to not use such characters." + , + 2,6,0, cmPolicies::WARN); + this->PolicyStringMap["CMP_REQUIRE_UNIQUE_TARGET_NAMES"] = CMP_0002; + +} + +cmPolicies::~cmPolicies() +{ + // free the policies + std::map<cmPolicies::PolicyID,cmPolicy *>::iterator i + = this->Policies.begin(); + for (;i != this->Policies.end(); ++i) + { + delete i->second; + } +} + +void cmPolicies::DefinePolicy(cmPolicies::PolicyID iD, + const char *idString, + const char *shortDescription, + const char *longDescription, + unsigned int majorVersionIntroduced, + unsigned int minorVersionIntroduced, + unsigned int patchVersionIntroduced, + cmPolicies::PolicyStatus status) +{ + // a policy must be unique and can only be defined once + if (this->Policies.find(iD) != this->Policies.end()) + { + cmSystemTools::Error("Attempt to redefine a CMake policy for policy " + "ID ", this->GetPolicyIDString(iD).c_str()); + return; + } + + this->Policies[iD] = new cmPolicy(iD, idString, + shortDescription, + longDescription, + majorVersionIntroduced, + minorVersionIntroduced, + patchVersionIntroduced, + status); + this->PolicyStringMap[idString] = iD; +} + +bool cmPolicies::ApplyPolicyVersion(cmMakefile *mf, + const char *version) +{ + std::string ver = "2.4.0"; + + if (version && strlen(version) > 0) + { + ver = version; + } + + unsigned int majorVer = 2; + unsigned int minorVer = 0; + unsigned int patchVer = 0; + + // parse the string + std::string major = ver.substr(0,ver.find('.')); + std::string patch = ver.substr(ver.find('.')); + std::string minor = patch.substr(0,patch.find('.')); + patch = patch.substr(patch.find('.')); + + if (major.size()) + { + majorVer = atoi(major.c_str()); + } + if (minor.size()) + { + minorVer = atoi(minor.c_str()); + } + if (patch.size()) + { + patchVer = atoi(patch.c_str()); + } + + // now loop over all the policies and set them as appropriate + std::map<cmPolicies::PolicyID,cmPolicy *>::iterator i = this->Policies.begin(); + for (;i != this->Policies.end(); ++i) + { + if (i->second->IsPolicyNewerThan(majorVer,minorVer,patchVer)) + { + if (!mf->SetPolicy(i->second->ID, cmPolicies::WARN)) + { + return false; + } + } + else + { + if (!mf->SetPolicy(i->second->ID, cmPolicies::NEW)) + { + return false; + } + } + } + return true; +} + +// is this a valid status the listfile can set this policy to? +bool cmPolicies::IsValidPolicyStatus(cmPolicies::PolicyID id, + cmPolicies::PolicyStatus status) +{ + // if they are setting a feature to anything other than OLD or WARN and the feature is not known about + // then that is an error + if (this->Policies.find(id) == this->Policies.end()) + { + if (status == cmPolicies::WARN || + status == cmPolicies::OLD) + { + return true; + } + cmOStringStream error; + error << + "Error: an attempt was made to enable the new behavior for " << + "a new feature that is in a later version of CMake than " + "what you are runing, please upgrade to a newer version " + "of CMake."; + cmSystemTools::Error(error.str().c_str()); + return false; + } + + // now we know the feature is defined, so the only issue is if someone is setting it to + // WARN or OLD when the feature is REQUIRED_ALWAYS + if ((status == cmPolicies::WARN || + status == cmPolicies::OLD) && + this->Policies[id]->Status == cmPolicies::REQUIRED_ALWAYS) + { + cmOStringStream error; + error << + "Error: an attempt was made to enable the old behavior for " << + "a feature that is no longer supported. The feature in " << + "question is feature " << + id << + " which had new behavior introduced in CMake version " << + this->Policies[id]->GetVersionString() << + " please either update your CMakeLists files to conform to " << + "the new behavior " << + "or use an older version of CMake that still supports " << + "the old behavior. Run cmake --help-policies " << + id << " for more information."; + cmSystemTools::Error(error.str().c_str()); + return false; + } + + return true; +} + +// is this a valid status the listfile can set this policy to? +bool cmPolicies::IsValidUsedPolicyStatus(cmPolicies::PolicyID id, + cmPolicies::PolicyStatus status) +{ + // if they are setting a feature to anything other than OLD or WARN and the feature is not known about + // then that is an error + if (this->Policies.find(id) == this->Policies.end()) + { + if (status == cmPolicies::WARN || + status == cmPolicies::OLD) + { + return true; + } + cmOStringStream error; + error << + "Error: an attempt was made to enable the new behavior for " << + "a new feature that is in a later version of CMake than " + "what you are runing, please upgrade to a newer version " + "of CMake."; + cmSystemTools::Error(error.str().c_str()); + return false; + } + + // now we know the feature is defined, so the only issue is if someone is setting it to + // WARN or OLD when the feature is REQUIRED_ALWAYS + if ((status == cmPolicies::WARN || + status == cmPolicies::OLD) && + (this->Policies[id]->Status == cmPolicies::REQUIRED_ALWAYS || + this->Policies[id]->Status == cmPolicies::REQUIRED_IF_USED)) + { + cmOStringStream error; + error << + "Error: an attempt was made to enable the old behavior for " << + "a feature that is no longer supported. The feature in " << + "question is feature " << + id << + " which had new behavior introduced in CMake version " << + this->Policies[id]->GetVersionString() << + " please either update your CMakeLists files to conform to " << + "the new behavior " << + "or use an older version of CMake that still supports " << + "the old behavior. Run cmake --help-policies " << + id << " for more information."; + cmSystemTools::Error(error.str().c_str()); + return false; + } + + return true; +} + +bool cmPolicies::GetPolicyID(const char *id, cmPolicies::PolicyID &pid) +{ + if (!id || strlen(id) < 1) + { + return false; + } + std::map<std::string,cmPolicies::PolicyID>::iterator pos = + this->PolicyStringMap.find(id); + if (pos == this->PolicyStringMap.end()) + { + return false; + } + pid = pos->second; + return true; +} + +std::string cmPolicies::GetPolicyIDString(cmPolicies::PolicyID pid) +{ + std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos = + this->Policies.find(pid); + if (pos == this->Policies.end()) + { + return ""; + } + return pos->second->IDString; +} + + +///! return a warning string for a given policy +std::string cmPolicies::GetPolicyWarning(cmPolicies::PolicyID id) +{ + std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos = + this->Policies.find(id); + if (pos == this->Policies.end()) + { + cmSystemTools::Error( + "Request for warning text for undefined policy!"); + return "Request for warning text for undefined policy!"; + } + + cmOStringStream error; + error << + "Warning " << + pos->second->IDString << ": " << + pos->second->ShortDescription << + " You can suppress this warning by adding either\n" << + "cmake_policy (OLD " << + pos->second->IDString << ") for the old behavior or " << + "cmake_policy(NEW " << + pos->second->IDString << ") for the new behavior. " << + "Run cmake --help-policy " << + pos->second->IDString << " for more information."; + return error.str(); +} + + +///! return an error string for when a required policy is unspecified +std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id) +{ + std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos = + this->Policies.find(id); + if (pos == this->Policies.end()) + { + cmSystemTools::Error( + "Request for error text for undefined policy!"); + return "Request for warning text for undefined policy!"; + } + + cmOStringStream error; + error << + "Error " << + pos->second->IDString << ": " << + pos->second->ShortDescription << + " This behavior is required now. You can suppress this message by " + "specifying that your listfile is written to handle this new " + "behavior by adding either\n" << + "cmake_policy (NEW " << + pos->second->IDString << ")\n or \n. " << + "cmake_policy (VERSION " << + pos->second->GetVersionString() << " ) or later." + "Run cmake --help-policy " << + pos->second->IDString << " for more information."; + return error.str(); + +} + +///! Get the default status for a policy +cmPolicies::PolicyStatus +cmPolicies::GetPolicyStatus(cmPolicies::PolicyID id) +{ + // if the policy is not know then what? + std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos = + this->Policies.find(id); + if (pos == this->Policies.end()) + { + // TODO is this right? + return cmPolicies::WARN; + } + + return pos->second->Status; +} + diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h new file mode 100644 index 0000000..81d5c05 --- /dev/null +++ b/Source/cmPolicies.h @@ -0,0 +1,85 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef cmPolicies_h +#define cmPolicies_h + +#include "cmCustomCommand.h" + +class cmake; +class cmMakefile; +class cmPolicy; + +/** \class cmPolicies + * \brief Handles changes in CMake behavior and policies + * + * See the cmake wiki section on policies for an overview of this class's purpose + */ +class cmPolicies +{ +public: + cmPolicies(); + ~cmPolicies(); + + enum PolicyStatus { OLD, WARN, NEW, REQUIRED_IF_USED, REQUIRED_ALWAYS }; + static const char* PolicyStatusNames[]; + + enum PolicyID {CMP_0000, CMP_POLICY_SPECIFICATION = CMP_0000, + CMP_0001, CMP_TARGET_NAMES_WITH_SLASHES = CMP_0001, + CMP_0002, CMP_REQUIRE_UNIQUE_TARGET_NAMES = CMP_0002}; + + + ///! convert a string policy ID into a number + bool GetPolicyID(const char *id, /* out */ cmPolicies::PolicyID &pid); + std::string GetPolicyIDString(cmPolicies::PolicyID pid); + + ///! Get the default status for a policy + cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id); + + ///! Define a Policy for CMake + void DefinePolicy(cmPolicies::PolicyID id, + const char *stringID, + const char *shortDescription, + const char *longDescription, + unsigned int majorVersionIntroduced, + unsigned int minorVersionIntroduced, + unsigned int patchVersionIntroduced, + cmPolicies::PolicyStatus status); + + ///! Set a policy level for this listfile + bool ApplyPolicyVersion(cmMakefile *mf, const char *version); + + ///! test to see if setting a policy to a specific value is valid + bool IsValidPolicyStatus(cmPolicies::PolicyID id, + cmPolicies::PolicyStatus status); + + ///! test to see if setting a policy to a specific value is valid, when used + bool IsValidUsedPolicyStatus(cmPolicies::PolicyID id, + cmPolicies::PolicyStatus status); + + ///! return a warning string for a given policy + std::string GetPolicyWarning(cmPolicies::PolicyID id); + + ///! return an error string for when a required policy is unspecified + std::string GetRequiredPolicyError(cmPolicies::PolicyID id); + + private: + std::map<cmPolicies::PolicyID,cmPolicy *> Policies; + std::map<std::string,cmPolicies::PolicyID> PolicyStringMap; + +}; + +#endif |