|
|
@@ -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
|