summaryrefslogtreecommitdiffstats
path: root/Source/cmGlobalGenerator.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2005-02-24 21:04:54 (GMT)
committerBrad King <brad.king@kitware.com>2005-02-24 21:04:54 (GMT)
commitcb48e0c16178738c3d3bafd551f0f3e0b906c6c1 (patch)
treee6a6b05c3bf993e74eca255d6a00c70175956f1d /Source/cmGlobalGenerator.cxx
parent9bf0811e34e7d26eb4aaf7bb250b1fd8be5cbb87 (diff)
downloadCMake-cb48e0c16178738c3d3bafd551f0f3e0b906c6c1.zip
CMake-cb48e0c16178738c3d3bafd551f0f3e0b906c6c1.tar.gz
CMake-cb48e0c16178738c3d3bafd551f0f3e0b906c6c1.tar.bz2
ENH: Merged implementations of ConvertToRelative*Path methods. The main ConvertToRelativePath method is now in cmGlobalGenerator. It converts paths only if they are at least inside the deepest common directory between the top-level source and build trees. Each cmLocalGenerator instance calls this global method with its own output directory as the "local" argument from which paths are relative. Added separate ConvertToOptionallyRelative path that pays attention to the CMAKE_USE_RELATIVE_PATHS option.
Diffstat (limited to 'Source/cmGlobalGenerator.cxx')
-rw-r--r--Source/cmGlobalGenerator.cxx138
1 files changed, 137 insertions, 1 deletions
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 296a008..4b8d711 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -24,6 +24,8 @@
#include <windows.h>
#endif
+#include <assert.h>
+
int cmGlobalGenerator::s_TryCompileTimeout = 0;
cmGlobalGenerator::cmGlobalGenerator()
@@ -487,7 +489,10 @@ void cmGlobalGenerator::Configure()
delete m_LocalGenerators[i];
}
m_LocalGenerators.clear();
-
+
+ // Setup relative path generation.
+ this->ConfigureRelativePaths();
+
// start with this directory
cmLocalGenerator *lg = this->CreateLocalGenerator();
m_LocalGenerators.push_back(lg);
@@ -573,6 +578,7 @@ void cmGlobalGenerator::Configure()
}
}
+
// loop through the directories creating cmLocalGenerators and Configure()
void cmGlobalGenerator::RecursiveConfigure(cmLocalGenerator *lg,
float startProgress,
@@ -877,3 +883,133 @@ cmTarget* cmGlobalGenerator::FindTarget(const char* name)
return 0;
}
+//----------------------------------------------------------------------------
+void cmGlobalGenerator::ConfigureRelativePaths()
+{
+ // Identify the longest shared path component between the source
+ // directory and the build directory.
+ std::vector<std::string> source;
+ std::vector<std::string> binary;
+ cmSystemTools::SplitPath(m_CMakeInstance->GetHomeDirectory(), source);
+ cmSystemTools::SplitPath(m_CMakeInstance->GetHomeOutputDirectory(), binary);
+ unsigned int common=0;
+ while(common < source.size() && common < binary.size() &&
+ cmSystemTools::ComparePath(source[common].c_str(),
+ binary[common].c_str()))
+ {
+ ++common;
+ }
+
+ // Require more than just the root portion of the path to be in
+ // common before allowing relative paths. Also disallow relative
+ // paths if the build tree is a network path. The current working
+ // directory on Windows cannot be a network path. Therefore
+ // relative paths cannot work with network paths.
+ if(common > 1 && source[0] != "//")
+ {
+ // Build the minimum prefix required of a path to be converted to
+ // a relative path.
+ source.erase(source.begin()+common, source.end());
+ m_RelativePathTop = cmSystemTools::JoinPath(source);
+ }
+ else
+ {
+ // Disable relative paths.
+ m_RelativePathTop = "";
+ }
+}
+
+//----------------------------------------------------------------------------
+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 or relative paths are disabled
+ // then just return the path.
+ if(m_RelativePathTop.size() == 0 ||
+ !cmSystemTools::FileIsFullPath(in_remote))
+ {
+ return in_remote;
+ }
+
+ // If the path does not begin with the minimum relative path prefix
+ // then do not convert it.
+ std::string original = in_remote;
+ if(original.size() < m_RelativePathTop.size() ||
+ !cmSystemTools::ComparePath(
+ original.substr(0, m_RelativePathTop.size()).c_str(),
+ m_RelativePathTop.c_str()))
+ {
+ 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 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;
+}
+