diff options
author | Brad King <brad.king@kitware.com> | 2007-03-07 20:15:46 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2007-03-07 20:15:46 (GMT) |
commit | fc19882e8f85516c4f774083b6d9f57f843fb941 (patch) | |
tree | 0e673dc5a8b7dfe6eedeb01bfe8f2ec123e3d7bb | |
parent | 3bd9d67488b98cb1141b7aaadbffb6550935f2aa (diff) | |
download | CMake-fc19882e8f85516c4f774083b6d9f57f843fb941.zip CMake-fc19882e8f85516c4f774083b6d9f57f843fb941.tar.gz CMake-fc19882e8f85516c4f774083b6d9f57f843fb941.tar.bz2 |
ENH: Moved ConvertToRelativePath from cmGlobalGenerator to cmLocalGenerator. This is in preparation for setting up each local generator to have its own RelativePathTopSource and RelativePathTopBinary based on its ancestor directories.
-rw-r--r-- | Source/cmGlobalGenerator.cxx | 160 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.h | 21 | ||||
-rw-r--r-- | Source/cmLocalGenerator.cxx | 182 | ||||
-rw-r--r-- | Source/cmLocalGenerator.h | 21 |
4 files changed, 191 insertions, 193 deletions
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 92f6420..36d6fba 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -42,9 +42,6 @@ cmGlobalGenerator::cmGlobalGenerator() // By default do not use link scripts. this->UseLinkScript = false; - // Relative paths are not configured in the constructor. - this->RelativePathsConfigured = false; - // Whether an install target is needed. this->InstallTargetEnabled = false; @@ -1107,163 +1104,6 @@ cmTarget* cmGlobalGenerator::FindTarget(const char* project, return 0; } -//---------------------------------------------------------------------------- -void cmGlobalGenerator::ConfigureRelativePaths() -{ - // The current working directory on Windows cannot be a network - // path. Therefore relative paths cannot work when the build tree - // is a network path. - std::string source = this->CMakeInstance->GetHomeDirectory(); - std::string binary = this->CMakeInstance->GetHomeOutputDirectory(); - if(binary.size() < 2 || binary.substr(0, 2) != "//") - { - this->RelativePathTopSource = source; - this->RelativePathTopBinary = binary; - } - else - { - this->RelativePathTopSource = ""; - this->RelativePathTopBinary = ""; - } -} - -//---------------------------------------------------------------------------- -std::string cmGlobalGenerator -::ConvertToRelativePath(const std::vector<std::string>& local, - const char* in_remote) -{ - // The path should never be quoted. - assert(in_remote[0] != '\"'); - - // The local path should never have a trailing slash. - assert(local.size() > 0 && !(local[local.size()-1] == "")); - - // If the path is already relative then just return the path. - if(!cmSystemTools::FileIsFullPath(in_remote)) - { - return in_remote; - } - - // Make sure relative path conversion is configured. - if(!this->RelativePathsConfigured) - { - this->ConfigureRelativePaths(); - this->RelativePathsConfigured = true; - } - - std::string original = in_remote; - - // Skip conversion if the path and local are not both in the source or both - // in the binary tree - std::string local_path = cmSystemTools::JoinPath(local); - bool should_convert = false; - - // is the root in the binary tree? - if (local_path.size() >= this->RelativePathTopBinary.size() && - cmSystemTools::ComparePath - (local_path.substr(0, this->RelativePathTopBinary.size()).c_str(), - this->RelativePathTopBinary.c_str())) - { - // is the source also in the binary tree? - if (original.size() >= this->RelativePathTopBinary.size() && - cmSystemTools::ComparePath - (original.substr(0, this->RelativePathTopBinary.size()).c_str(), - this->RelativePathTopBinary.c_str())) - { - should_convert = true; - } - } - - if (local_path.size() >= this->RelativePathTopSource.size() && - cmSystemTools::ComparePath - (local_path.substr(0, this->RelativePathTopSource.size()).c_str(), - this->RelativePathTopSource.c_str())) - { - // is the source also in the binary tree? - if (original.size() >= this->RelativePathTopSource.size() && - cmSystemTools::ComparePath - (original.substr(0, this->RelativePathTopSource.size()).c_str(), - this->RelativePathTopSource.c_str())) - { - should_convert = true; - } - } - - if (!should_convert) - { - return in_remote; - } - - // Identify the longest shared path component between the remote - // path and the local path. - std::vector<std::string> remote; - cmSystemTools::SplitPath(in_remote, remote); - unsigned int common=0; - while(common < remote.size() && - common < local.size() && - cmSystemTools::ComparePath(remote[common].c_str(), - local[common].c_str())) - { - ++common; - } - - // If no part of the path is in common then return the full path. - if(common == 0) - { - return in_remote; - } - - // If the entire path is in common then just return a ".". - if(common == remote.size() && - common == local.size()) - { - return "."; - } - - // If the entire path is in common except for a trailing slash then - // just return a "./". - if(common+1 == remote.size() && - remote[common].size() == 0 && - common == local.size()) - { - return "./"; - } - - // Construct the relative path. - std::string relative; - - // First add enough ../ to get up to the level of the shared portion - // of the path. Leave off the trailing slash. Note that the last - // component of local will never be empty because local should never - // have a trailing slash. - for(unsigned int i=common; i < local.size(); ++i) - { - relative += ".."; - if(i < local.size()-1) - { - relative += "/"; - } - } - - // Now add the portion of the destination path that is not included - // in the shared portion of the path. Add a slash the first time - // only if there was already something in the path. If there was a - // trailing slash in the input then the last iteration of the loop - // will add a slash followed by an empty string which will preserve - // the trailing slash in the output. - for(unsigned int i=common; i < remote.size(); ++i) - { - if(relative.size() > 0) - { - relative += "/"; - } - relative += remote[i]; - } - - // Finally return the path. - return relative; -} - inline std::string removeQuotes(const std::string& s) { if(s[0] == '\"' && s[s.size()-1] == '\"') diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index da98f52..7072f26 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -144,16 +144,6 @@ public: ///! What is the configurations directory variable called? virtual const char* GetCMakeCFGInitDirectory() { return "."; } - /** - * Convert the given remote path to a relative path with respect to - * the given local path. The local path must be given in component - * form (see SystemTools::SplitPath) without a trailing slash. The - * remote path must use forward slashes and not already be escaped - * or quoted. - */ - std::string ConvertToRelativePath(const std::vector<std::string>& local, - const char* remote); - /** Get whether the generator should use a script for link commands. */ bool GetUseLinkScript() { return this->UseLinkScript; } @@ -209,9 +199,6 @@ protected: void FillProjectMap(); bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen); - void ConfigureRelativePaths(); - bool RelativePathsConfigured; - void CreateDefaultGlobalTargets(cmTargets* targets); cmTarget CreateGlobalTarget(const char* name, const char* message, const cmCustomCommandLines* commandLines, @@ -246,14 +233,6 @@ private: std::map<cmStdString, cmStdString> ExtensionToLanguage; std::map<cmStdString, cmStdString> LanguageToLinkerPreference; - // The paths to the tops of the source and binary trees used for - // relative path computation. A path must be either in the source - // tree or the build tree to be converted to a relative path. The - // ConfigureRelativePaths method may set these to be empty when - // using relative paths is unsafe. - std::string RelativePathTopSource; - std::string RelativePathTopBinary; - // this is used to improve performance std::map<cmStdString,cmTarget *> TotalTargets; }; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 1a68871..559482f 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -45,6 +45,7 @@ cmLocalGenerator::cmLocalGenerator() this->UseRelativePaths = false; this->Configured = false; this->EmitUniversalBinaryFlags = true; + this->RelativePathsConfigured = false; } cmLocalGenerator::~cmLocalGenerator() @@ -2020,27 +2021,25 @@ std::string cmLocalGenerator::Convert(const char* source, { case HOME: //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->GlobalGenerator-> - ConvertToRelativePath(this->HomeDirectoryComponents, - result.c_str()); + result = this->ConvertToRelativePath(this->HomeDirectoryComponents, + result.c_str()); break; case START: //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->GlobalGenerator-> - ConvertToRelativePath(this->StartDirectoryComponents, - result.c_str()); + result = this->ConvertToRelativePath(this->StartDirectoryComponents, + result.c_str()); break; case HOME_OUTPUT: //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->GlobalGenerator-> - ConvertToRelativePath(this->HomeOutputDirectoryComponents, - result.c_str()); + result = + this->ConvertToRelativePath(this->HomeOutputDirectoryComponents, + result.c_str()); break; case START_OUTPUT: //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->GlobalGenerator-> - ConvertToRelativePath(this->StartOutputDirectoryComponents, - result.c_str()); + result = + this->ConvertToRelativePath(this->StartOutputDirectoryComponents, + result.c_str()); break; case FULL: result = cmSystemTools::CollapseFullPath(result.c_str()); @@ -2082,6 +2081,165 @@ std::string cmLocalGenerator::Convert(const char* source, return result; } +//---------------------------------------------------------------------------- +void cmLocalGenerator::ConfigureRelativePaths() +{ + // The current working directory on Windows cannot be a network + // path. Therefore relative paths cannot work when the build tree + // is a network path. + std::string source = this->Makefile->GetHomeDirectory(); + std::string binary = this->Makefile->GetHomeOutputDirectory(); + if(binary.size() < 2 || binary.substr(0, 2) != "//") + { + this->RelativePathTopSource = source; + this->RelativePathTopBinary = binary; + } + else + { + this->RelativePathTopSource = ""; + this->RelativePathTopBinary = ""; + } +} + +//---------------------------------------------------------------------------- +std::string +cmLocalGenerator +::ConvertToRelativePath(const std::vector<std::string>& local, + const char* in_remote) +{ + // The path should never be quoted. + assert(in_remote[0] != '\"'); + + // The local path should never have a trailing slash. + assert(local.size() > 0 && !(local[local.size()-1] == "")); + + // If the path is already relative then just return the path. + if(!cmSystemTools::FileIsFullPath(in_remote)) + { + return in_remote; + } + + // Make sure relative path conversion is configured. + if(!this->RelativePathsConfigured) + { + this->ConfigureRelativePaths(); + this->RelativePathsConfigured = true; + } + + std::string original = in_remote; + + // Skip conversion if the path and local are not both in the source or both + // in the binary tree + std::string local_path = cmSystemTools::JoinPath(local); + bool should_convert = false; + + // A relative path is safe if both the local and remote locations + // are underneath the current relative path top in the binary tree. + if (local_path.size() >= this->RelativePathTopBinary.size() && + cmSystemTools::ComparePath + (local_path.substr(0, this->RelativePathTopBinary.size()).c_str(), + this->RelativePathTopBinary.c_str())) + { + if (original.size() >= this->RelativePathTopBinary.size() && + cmSystemTools::ComparePath + (original.substr(0, this->RelativePathTopBinary.size()).c_str(), + this->RelativePathTopBinary.c_str())) + { + should_convert = true; + } + } + + // A relative path is safe if both the local and remote locations + // are underneath the current relative path top in the source tree. + if (local_path.size() >= this->RelativePathTopSource.size() && + cmSystemTools::ComparePath + (local_path.substr(0, this->RelativePathTopSource.size()).c_str(), + this->RelativePathTopSource.c_str())) + { + if (original.size() >= this->RelativePathTopSource.size() && + cmSystemTools::ComparePath + (original.substr(0, this->RelativePathTopSource.size()).c_str(), + this->RelativePathTopSource.c_str())) + { + should_convert = true; + } + } + + // Do not convert if it is not safe. + if(!should_convert) + { + return in_remote; + } + + // Identify the longest shared path component between the remote + // path and the local path. + std::vector<std::string> remote; + cmSystemTools::SplitPath(in_remote, remote); + unsigned int common=0; + while(common < remote.size() && + common < local.size() && + cmSystemTools::ComparePath(remote[common].c_str(), + local[common].c_str())) + { + ++common; + } + + // If no part of the path is in common then return the full path. + if(common == 0) + { + return in_remote; + } + + // If the entire path is in common then just return a ".". + if(common == remote.size() && + common == local.size()) + { + return "."; + } + + // If the entire path is in common except for a trailing slash then + // just return a "./". + if(common+1 == remote.size() && + remote[common].size() == 0 && + common == local.size()) + { + return "./"; + } + + // Construct the relative path. + std::string relative; + + // First add enough ../ to get up to the level of the shared portion + // of the path. Leave off the trailing slash. Note that the last + // component of local will never be empty because local should never + // have a trailing slash. + for(unsigned int i=common; i < local.size(); ++i) + { + relative += ".."; + if(i < local.size()-1) + { + relative += "/"; + } + } + + // Now add the portion of the destination path that is not included + // in the shared portion of the path. Add a slash the first time + // only if there was already something in the path. If there was a + // trailing slash in the input then the last iteration of the loop + // will add a slash followed by an empty string which will preserve + // the trailing slash in the output. + for(unsigned int i=common; i < remote.size(); ++i) + { + if(relative.size() > 0) + { + relative += "/"; + } + relative += remote[i]; + } + + // Finally return the path. + return relative; +} //---------------------------------------------------------------------------- void diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 1b8f124..6b4d7dc 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -266,6 +266,18 @@ protected: std::string GetObjectFileNameWithoutTarget(const cmSourceFile& source); std::string& CreateSafeUniqueObjectFileName(const char* sin); + void ConfigureRelativePaths(); + + /** + * Convert the given remote path to a relative path with respect to + * the given local path. The local path must be given in component + * form (see SystemTools::SplitPath) without a trailing slash. The + * remote path must use forward slashes and not already be escaped + * or quoted. + */ + std::string ConvertToRelativePath(const std::vector<std::string>& local, + const char* remote); + cmMakefile *Makefile; cmGlobalGenerator *GlobalGenerator; // members used for relative path function ConvertToMakefilePath @@ -291,6 +303,15 @@ protected: // Hack for ExpandRuleVariable until object-oriented version is // committed. std::string TargetImplib; + + // The top-most directories for relative path conversion. Both the + // source and destination location of a relative path conversion + // must be underneath one of these directories (both under source or + // both under binary) in order for the relative path to be evaluated + // safely by the build tools. + std::string RelativePathTopSource; + std::string RelativePathTopBinary; + bool RelativePathsConfigured; }; #endif |