From eb9fc21543a48d3b842da09d5653d8ca1c58b196 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Mon, 22 Dec 2003 12:24:26 -0500 Subject: [PATCH] ENH: add support for relative paths in makefiles --- Source/cmLocalUnixMakefileGenerator.cxx | 211 +++++++++++++++++------- Source/cmLocalUnixMakefileGenerator.h | 10 +- Source/cmSystemTools.cxx | 64 +++++++ Source/cmSystemTools.h | 5 + Source/cmake.cxx | 8 + 5 files changed, 234 insertions(+), 64 deletions(-) diff --git a/Source/cmLocalUnixMakefileGenerator.cxx b/Source/cmLocalUnixMakefileGenerator.cxx index 6fafac285..967ccaab8 100644 --- a/Source/cmLocalUnixMakefileGenerator.cxx +++ b/Source/cmLocalUnixMakefileGenerator.cxx @@ -41,6 +41,40 @@ cmLocalUnixMakefileGenerator::~cmLocalUnixMakefileGenerator() void cmLocalUnixMakefileGenerator::Generate(bool fromTheTop) { + if(m_CurrentOutputDirectory.size() == 0) + { + m_CurrentOutputDirectory = m_Makefile->GetCurrentOutputDirectory(); + m_HomeOutputDirectory = m_Makefile->GetHomeOutputDirectory(); + m_HomeDirectory = m_Makefile->GetHomeDirectory(); +#if defined(_WIN32) || defined(__APPLE__) + m_CurrentOutputDirectory = cmSystemTools::LowerCase(m_CurrentOutputDirectory); + m_HomeOutputDirectory = cmSystemTools::LowerCase(m_HomeOutputDirectory); + m_HomeDirectory = cmSystemTools::LowerCase(m_HomeDirectory); +#endif + if(m_RelativePathToSourceDir.size() == 0) + { + m_RelativePathToSourceDir = cmSystemTools::RelativePath( + m_CurrentOutputDirectory.c_str(), + m_HomeDirectory.c_str()); + std::string path = m_CurrentOutputDirectory; + cmSystemTools::ReplaceString(path, m_HomeOutputDirectory.c_str(), ""); + unsigned i; + m_RelativePathToBinaryDir = ""; + for(i =0; i < path.size(); ++i) + { + if(path[i] == '/') + { + m_RelativePathToBinaryDir += "../"; + } + } + } + m_HomeOutputDirectoryNoSlash = m_HomeOutputDirectory; + m_HomeOutputDirectory += "/"; + m_CurrentOutputDirectory += "/"; + } + + + // suppoirt override in output directories if (m_Makefile->GetDefinition("LIBRARY_OUTPUT_PATH")) { @@ -222,17 +256,18 @@ void cmLocalUnixMakefileGenerator::OutputMakefile(const char* file, for(std::vector::const_iterator i = lfiles.begin(); i != lfiles.end(); ++i) { - fout << " " << cmSystemTools::ConvertToOutputPath(i->c_str()); + fout << " " << this->ConvertToMakefilePath(i->c_str()); } // Add the cache to the list std::string cacheFile = m_Makefile->GetHomeOutputDirectory(); cacheFile += "/CMakeCache.txt"; - fout << " " << cmSystemTools::ConvertToOutputPath(cacheFile.c_str()); + fout << " " << this->ConvertToMakefilePath(cacheFile.c_str()); fout << "\n\n\n"; + this->OutputMakeVariables(fout); std::string checkCache = m_Makefile->GetHomeOutputDirectory(); checkCache += "/cmake.check_cache"; - checkCache = cmSystemTools::ConvertToOutputPath(checkCache.c_str()); + checkCache = this->ConvertToMakefilePath(checkCache.c_str()); // most unix makes will pass the command line flags to make down // to sub invoked makes via an environment variable. However, some // makes do not support that, so you have to pass the flags explicitly @@ -445,7 +480,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout) std::string path2 = m_LibraryOutputPath; path2 += this->GetFullTargetName(l->first.c_str(), l->second); path = "... "; - path += cmSystemTools::ConvertToOutputPath(path2.c_str()); + path += this->ConvertToMakefilePath(path2.c_str()); this->OutputEcho(fout,path.c_str()); } } @@ -490,7 +525,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout) path = m_LibraryOutputPath; path += this->GetFullTargetName(l->first.c_str(), l->second); fout << " \\\n" - << cmSystemTools::ConvertToOutputPath(path.c_str()); + << this->ConvertToMakefilePath(path.c_str()); } } } @@ -504,7 +539,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout) { path = m_ExecutableOutputPath; path += this->GetFullTargetName(l->first.c_str(), l->second); - fout << " \\\n" << cmSystemTools::ConvertToOutputPath(path.c_str()); + fout << " \\\n" << this->ConvertToMakefilePath(path.c_str()); } } // list utilities last @@ -537,7 +572,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout) if(outExt.size()) { fout << "\\\n" - << cmSystemTools::ConvertToOutputPath((*i)->GetSourceName().c_str()) + << this->ConvertToMakefilePath((*i)->GetSourceName().c_str()) << outExt.c_str() << " "; } } @@ -553,7 +588,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout) std::string outExt(this->GetOutputExtension((*i)->GetSourceExtension().c_str())); if(outExt.size()) { - fout << "\\\n\"" << cmSystemTools::ConvertToOutputPath((*i)->GetSourceName().c_str()) + fout << "\\\n\"" << this->ConvertToMakefilePath((*i)->GetSourceName().c_str()) << outExt.c_str() << "\" "; } } @@ -585,7 +620,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout) path = m_LibraryOutputPath; path += targetNameSO; fout << " \\\n" - << cmSystemTools::ConvertToOutputPath(path.c_str()); + << this->ConvertToMakefilePath(path.c_str()); } if(targetNameReal != targetName && targetNameReal != targetNameSO) @@ -593,7 +628,7 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout) path = m_LibraryOutputPath; path += targetNameReal; fout << " \\\n" - << cmSystemTools::ConvertToOutputPath(path.c_str()); + << this->ConvertToMakefilePath(path.c_str()); } } } @@ -861,7 +896,7 @@ std::string cmLocalUnixMakefileGenerator::CreatePreBuildRules( { initNext = true; } - std::string command = cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str()); + std::string command = this->ConvertToMakefilePath(cc.GetCommand().c_str()); customRuleCode += command + " " + cc.GetArguments(); } return customRuleCode; @@ -886,7 +921,7 @@ std::string cmLocalUnixMakefileGenerator::CreatePreLinkRules( { initNext = true; } - std::string command = cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str()); + std::string command = this->ConvertToMakefilePath(cc.GetCommand().c_str()); customRuleCode += command + " " + cc.GetArguments(); } return customRuleCode; @@ -911,7 +946,7 @@ std::string cmLocalUnixMakefileGenerator::CreatePostBuildRules( { initNext = true; } - std::string command = cmSystemTools::ConvertToOutputPath(cc.GetCommand().c_str()); + std::string command = this->ConvertToMakefilePath(cc.GetCommand().c_str()); customRuleCode += command + " " + cc.GetArguments(); } return customRuleCode; @@ -1066,10 +1101,10 @@ void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout, std::string targetFullPathSO = m_LibraryOutputPath + targetNameSO; std::string targetFullPathReal = m_LibraryOutputPath + targetNameReal; std::string targetFullPathBase = m_LibraryOutputPath + targetNameBase; - targetFullPath = cmSystemTools::ConvertToOutputPath(targetFullPath.c_str()); - targetFullPathSO = cmSystemTools::ConvertToOutputPath(targetFullPathSO.c_str()); - targetFullPathReal = cmSystemTools::ConvertToOutputPath(targetFullPathReal.c_str()); - targetFullPathBase = cmSystemTools::ConvertToOutputPath(targetFullPathBase.c_str()); + targetFullPath = this->ConvertToMakefilePath(targetFullPath.c_str()); + targetFullPathSO = this->ConvertToMakefilePath(targetFullPathSO.c_str()); + targetFullPathReal = this->ConvertToMakefilePath(targetFullPathReal.c_str()); + targetFullPathBase = this->ConvertToMakefilePath(targetFullPathBase.c_str()); // get the objects that are used to link this library std::string objs = "$(" + this->CreateMakeVariable(name, "_SRC_OBJS") + ") "; @@ -1193,7 +1228,7 @@ void cmLocalUnixMakefileGenerator::OutputSharedLibraryRule(std::ostream& fout, if((*i)->GetSourceExtension() == "def") { linkFlags += this->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG"); - linkFlags += cmSystemTools::ConvertToOutputPath((*i)->GetFullPath().c_str()); + linkFlags += this->ConvertToMakefilePath((*i)->GetFullPath().c_str()); linkFlags += " "; } } @@ -1296,8 +1331,13 @@ void cmLocalUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout, } } target += name; - target += cmSystemTools::GetExecutableExtension(); - target = cmSystemTools::ConvertToOutputPath(target.c_str()); + target += cmSystemTools::GetExecutableExtension(); + target = this->ConvertToMakefilePath(target.c_str()); + bool needsLocalTarget = false; + if(target.find('/') != target.npos) + { + needsLocalTarget = true; + } std::string objs = "$(" + this->CreateMakeVariable(name, "_SRC_OBJS") + ") "; std::string depend = "$("; @@ -1397,16 +1437,19 @@ void cmLocalUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout, // If there is no executable output path, add a rule with the // relative path to the executable. This is necessary for // try-compile to work in this case. - depend = target; - target = name; - target += cmSystemTools::GetExecutableExtension(); - target = cmSystemTools::ConvertToOutputPath(target.c_str()); - commands.resize(0); - this->OutputMakeRule(fout, - comment.c_str(), - target.c_str(), - depend.c_str(), - commands); + if(needsLocalTarget) + { + depend = target; + target = name; + target += cmSystemTools::GetExecutableExtension(); + target = this->ConvertToMakefilePath(target.c_str()); + commands.resize(0); + this->OutputMakeRule(fout, + comment.c_str(), + target.c_str(), + depend.c_str(), + commands); + } } @@ -1446,7 +1489,7 @@ void cmLocalUnixMakefileGenerator::OutputUtilityRule(std::ostream& fout, depends += " \\\n"; replaceVars = *d; m_Makefile->ExpandVariablesInString(replaceVars); - depends += cmSystemTools::ConvertToOutputPath(replaceVars.c_str()); + depends += this->ConvertToMakefilePath(replaceVars.c_str()); } } this->OutputMakeRule(fout, comment.c_str(), name, @@ -1662,10 +1705,13 @@ void cmLocalUnixMakefileGenerator::OutputBuildTargetInDirWindows(std::ostream& f const char* libOutPath) { const char* makeTarget = library; - std::string currentDir = - cmSystemTools::ConvertToOutputPath(m_Makefile->GetCurrentOutputDirectory()); + std::string jumpBack = + cmSystemTools::RelativePath(cmSystemTools::GetProgramPath(fullpath).c_str(), + m_Makefile->GetCurrentOutputDirectory()); + jumpBack = this->ConvertToOutputForExisting(jumpBack.c_str()); std::string wpath = this->ConvertToOutputForExisting(path); std::string wfullpath = this->ConvertToOutputForExisting(fullpath); + if(libOutPath && strcmp( libOutPath, "" ) != 0) { makeTarget = wfullpath.c_str(); @@ -1676,7 +1722,7 @@ void cmLocalUnixMakefileGenerator::OutputBuildTargetInDirWindows(std::ostream& f << "\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) cmake.check_depends\n" << "\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) -f cmake.check_depends\n" << "\t$(MAKE) $(MAKESILENT) " << makeTarget - << "\n\tcd " << currentDir << "\n"; + << "\n\tcd " << jumpBack << "\n"; } void cmLocalUnixMakefileGenerator::OutputBuildTargetInDir(std::ostream& fout, @@ -1701,7 +1747,7 @@ void cmLocalUnixMakefileGenerator::OutputBuildTargetInDir(std::ostream& fout, << "; $(MAKE) $(MAKESILENT) cmake.check_depends" << "; $(MAKE) $(MAKESILENT) -f cmake.check_depends" << "; $(MAKE) $(MAKESILENT) " - << cmSystemTools::ConvertToOutputPath(makeTarget) << "\n\n"; + << this->ConvertToMakefilePath(makeTarget) << "\n\n"; } @@ -1772,7 +1818,7 @@ void cmLocalUnixMakefileGenerator::OutputLibDepend(std::ostream& fout, libpath += name; libpath += this->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"); } - fout << cmSystemTools::ConvertToOutputPath(libpath.c_str()) << " "; + fout << this->ConvertToMakefilePath(libpath.c_str()) << " "; } } @@ -1811,7 +1857,7 @@ void cmLocalUnixMakefileGenerator::OutputExeDepend(std::ostream& fout, exepath += name; // add the correct extension exepath += cmSystemTools::GetExecutableExtension(); - fout << cmSystemTools::ConvertToOutputPath(exepath.c_str()) << " "; + fout << this->ConvertToMakefilePath(exepath.c_str()) << " "; } // if it isn't in the cache, it might still be a utility target // so check for that @@ -1857,9 +1903,10 @@ BuildInSubDirectoryWindows(std::ostream& fout, const char* target2, bool silent) { + std::string dir; if(target1) { - std::string dir = this->ConvertToOutputForExisting(directory); + dir = this->ConvertToOutputForExisting(directory); if(dir[0] == '\"') { dir = dir.substr(1, dir.size()-2); @@ -1881,9 +1928,19 @@ BuildInSubDirectoryWindows(std::ostream& fout, fout << "\t@echo " << directory << ": building " << target2 << "\n"; } fout << "\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) " << target2 << "\n"; + } + std::string currentDir = dir; + cmSystemTools::ConvertToUnixSlashes(currentDir); + std::string cdback = ".."; + for(unsigned int i =0; i < currentDir.size(); ++i) + { + if(currentDir[i] == '/') + { + cdback += "/.."; + } } - std::string currentDir = m_Makefile->GetCurrentOutputDirectory(); - fout << "\tcd " << this->ConvertToOutputForExisting(currentDir.c_str()) << "\n\n"; + fout << "\tcd " << this->ConvertToOutputForExisting(cdback.c_str()) << "\n\n"; + } @@ -1899,7 +1956,7 @@ void cmLocalUnixMakefileGenerator::BuildInSubDirectory(std::ostream& fout, return; } - std::string directory = cmSystemTools::ConvertToOutputPath(dir); + std::string directory = this->ConvertToMakefilePath(dir); if(target1) { fout << "\t@if test ! -d " << directory @@ -2046,8 +2103,8 @@ bool cmLocalUnixMakefileGenerator::OutputObjectDepends(std::ostream& fout) { std::string s = (*source)->GetSourceName(); s += this->GetOutputExtension((*source)->GetSourceExtension().c_str()); - fout << cmSystemTools::ConvertToOutputPath(s.c_str()) << " : " - << cmSystemTools::ConvertToOutputPath(dep->c_str()) << "\n"; + fout << this->ConvertToMakefilePath(s.c_str()) << " : " + << this->ConvertToMakefilePath(dep->c_str()) << "\n"; ret = true; } fout << "\n\n"; @@ -2098,7 +2155,7 @@ void cmLocalUnixMakefileGenerator::OutputCheckDepends(std::ostream& fout) // has been done because m_FullPath on cmDependInformation // always is it called. If it is called here, network builds are // very slow because of the number of stats - std::string dependfile = cmSystemTools::ConvertToOutputPath(dep->c_str()); + std::string dependfile = this->ConvertToMakefilePath(dep->c_str()); // use the lower path function to create uniqe names std::string lowerpath = this->LowerCasePath(dependfile.c_str()); if(emittedLowerPath.insert(lowerpath).second) @@ -2152,7 +2209,7 @@ void cmLocalUnixMakefileGenerator::OutputCustomRules(std::ostream& fout) std::string comment = c->GetComment(); std::string command = c->GetCommand(); cmSystemTools::ReplaceString(command, "/./", "/"); - command = cmSystemTools::ConvertToOutputPath(command.c_str()); + command = this->ConvertToMakefilePath(command.c_str()); command += " "; // now add the arguments command += c->GetArguments(); @@ -2183,7 +2240,7 @@ void cmLocalUnixMakefileGenerator::OutputCustomRules(std::ostream& fout) } cmSystemTools::ReplaceString(dep, "/./", "/"); cmSystemTools::ReplaceString(dep, "/$(IntDir)/", "/"); - dep = cmSystemTools::ConvertToOutputPath(dep.c_str()); + dep = this->ConvertToMakefilePath(dep.c_str()); depends += " "; depends += dep; } @@ -2209,7 +2266,7 @@ void cmLocalUnixMakefileGenerator::OutputCustomRules(std::ostream& fout) std::string cmLocalUnixMakefileGenerator::ConvertToOutputForExisting(const char* p) { - std::string ret = cmSystemTools::ConvertToOutputPath(p); + std::string ret = this->ConvertToMakefilePath(p); // if there are spaces in the path, then get the short path version // if there is one if(ret.find(' ') != std::string::npos) @@ -2218,7 +2275,7 @@ cmLocalUnixMakefileGenerator::ConvertToOutputForExisting(const char* p) { if(!cmSystemTools::GetShortPath(ret.c_str(), ret)) { - ret = cmSystemTools::ConvertToOutputPath(p); + ret = this->ConvertToMakefilePath(p); } } } @@ -2265,16 +2322,16 @@ void cmLocalUnixMakefileGenerator::OutputMakeVariables(std::ostream& fout) } fout << "CMAKE_CURRENT_SOURCE = " << - cmSystemTools::ConvertToOutputPath(m_Makefile->GetStartDirectory()) + this->ConvertToMakefilePath(m_Makefile->GetStartDirectory()) << "\n"; fout << "CMAKE_CURRENT_BINARY = " << - cmSystemTools::ConvertToOutputPath(m_Makefile->GetStartOutputDirectory()) + this->ConvertToMakefilePath(m_Makefile->GetStartOutputDirectory()) << "\n"; fout << "CMAKE_SOURCE_DIR = " << - cmSystemTools::ConvertToOutputPath(m_Makefile->GetHomeDirectory()) + this->ConvertToMakefilePath(m_Makefile->GetHomeDirectory()) << "\n"; fout << "CMAKE_BINARY_DIR = " << - cmSystemTools::ConvertToOutputPath(m_Makefile->GetHomeOutputDirectory()) + this->ConvertToMakefilePath(m_Makefile->GetHomeOutputDirectory()) << "\n"; // Output Include paths fout << "INCLUDE_FLAGS = "; @@ -2367,7 +2424,7 @@ void cmLocalUnixMakefileGenerator::OutputInstallRules(std::ostream& fout) installNameReal += targetNameReal; fname = m_LibraryOutputPath; fname += targetNameReal; - fout << "\t$(INSTALL_DATA) " << cmSystemTools::ConvertToOutputPath(fname.c_str()) + fout << "\t$(INSTALL_DATA) " << this->ConvertToMakefilePath(fname.c_str()) << " \"$(DESTDIR)" << prefix << l->second.GetInstallPath() << "\"\n"; fout << "\t" << cmakecommand << " -E cmake_symlink_library \"" << installNameReal << "\" \"" << installNameSO << "\" \"" << installName @@ -2377,7 +2434,7 @@ void cmLocalUnixMakefileGenerator::OutputInstallRules(std::ostream& fout) case cmTarget::EXECUTABLE: fname = m_ExecutableOutputPath; fname += this->GetFullTargetName(l->first.c_str(), l->second); - fout << "\t$(INSTALL_PROGRAM) " << cmSystemTools::ConvertToOutputPath(fname.c_str()) + fout << "\t$(INSTALL_PROGRAM) " << this->ConvertToMakefilePath(fname.c_str()) << " \"$(DESTDIR)" << prefix << l->second.GetInstallPath() << "\"\n"; break; case cmTarget::INSTALL_FILES: @@ -2411,7 +2468,7 @@ void cmLocalUnixMakefileGenerator::OutputInstallRules(std::ostream& fout) fout << "\t$(INSTALL_DATA) "; } - fout << cmSystemTools::ConvertToOutputPath(i->c_str()) + fout << this->ConvertToMakefilePath(i->c_str()) << " \"$(DESTDIR)" << prefix << l->second.GetInstallPath() << "\"\n"; } } @@ -2446,7 +2503,7 @@ void cmLocalUnixMakefileGenerator::OutputInstallRules(std::ostream& fout) { fout << "\t @$(INSTALL_PROGRAM) "; } - fout << cmSystemTools::ConvertToOutputPath(i->c_str()) + fout << this->ConvertToMakefilePath(i->c_str()) << " \"$(DESTDIR)" << prefix << l->second.GetInstallPath() << "\"\n"; } } @@ -2486,14 +2543,14 @@ void cmLocalUnixMakefileGenerator::OutputMakeRules(std::ostream& fout) { if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY")) { - allsources.push_back(cmSystemTools::ConvertToOutputPath((*source)->GetFullPath().c_str())); + allsources.push_back(this->ConvertToMakefilePath((*source)->GetFullPath().c_str())); } } } std::string checkCache = m_Makefile->GetHomeOutputDirectory(); checkCache += "/cmake.check_cache"; - checkCache = cmSystemTools::ConvertToOutputPath(checkCache.c_str()); + checkCache = this->ConvertToMakefilePath(checkCache.c_str()); std::vector cmake_depends; cmake_depends.push_back(checkCache); cmake_depends.push_back("$(CMAKE_MAKEFILE_SOURCES)"); @@ -2538,7 +2595,7 @@ void cmLocalUnixMakefileGenerator::OutputMakeRules(std::ostream& fout) std::vector check_cache_depends; std::string CMakeCache = m_Makefile->GetHomeOutputDirectory(); CMakeCache += "/CMakeCache.txt"; - CMakeCache = cmSystemTools::ConvertToOutputPath(CMakeCache.c_str()); + CMakeCache = this->ConvertToMakefilePath(CMakeCache.c_str()); check_cache_depends.push_back(CMakeCache); check_cache_depends.push_back("$(CMAKE_MAKEFILE_SOURCES)"); @@ -2643,7 +2700,7 @@ OutputBuildObjectFromSource(std::ostream& fout, std::string comment = "object file"; std::string objectFile = std::string(shortName) + this->GetOutputExtension(source.GetSourceExtension().c_str()); - objectFile = cmSystemTools::ConvertToOutputPath(objectFile.c_str()); + objectFile = this->ConvertToMakefilePath(objectFile.c_str()); cmSystemTools::FileFormat format = cmSystemTools::GetFileFormat(source.GetSourceExtension().c_str()); std::vector rules; @@ -2653,7 +2710,7 @@ OutputBuildObjectFromSource(std::ostream& fout, flags += extraCompileFlags; } std::string sourceFile = - cmSystemTools::ConvertToOutputPath(source.GetFullPath().c_str()); + this->ConvertToMakefilePath(source.GetFullPath().c_str()); std::string buildType = this->GetSafeDefinition("CMAKE_BUILD_TYPE"); buildType = cmSystemTools::UpperCase(buildType); switch(format) @@ -2761,7 +2818,7 @@ OutputBuildObjectFromSource(std::ostream& fout, for(std::vector::iterator i = depends.begin(); i != depends.end(); ++i) { - sourceAndDeps.push_back(cmSystemTools::ConvertToOutputPath(i->c_str())); + sourceAndDeps.push_back(this->ConvertToMakefilePath(i->c_str())); } } @@ -2957,7 +3014,7 @@ void cmLocalUnixMakefileGenerator::OutputMakeRule(std::ostream& fout, replace = target; m_Makefile->ExpandVariablesInString(replace); - std::string tgt = cmSystemTools::ConvertToOutputPath(replace.c_str()); + std::string tgt = this->ConvertToMakefilePath(replace.c_str()); if(depends.empty()) { fout << tgt.c_str() << ":\n"; @@ -3156,3 +3213,31 @@ void cmLocalUnixMakefileGenerator::GetLibraryNames(const char* n, // The library name without extension. baseName = this->GetBaseTargetName(n, t); } + +std::string cmLocalUnixMakefileGenerator::ConvertToMakefilePath(const char* p) +{ + std::string pathIn = p; +#if defined(_WIN32) || defined(__APPLE__) + pathIn = cmSystemTools::LowerCase(pathIn); +#endif + + std::string ret = pathIn; + cmSystemTools::ReplaceString(ret, m_CurrentOutputDirectory.c_str(), ""); + cmSystemTools::ReplaceString(ret, m_HomeDirectory.c_str(), + m_RelativePathToSourceDir.c_str()); + cmSystemTools::ReplaceString(ret, m_HomeOutputDirectory.c_str(), + m_RelativePathToBinaryDir.c_str()); + std::string relpath = m_RelativePathToBinaryDir; + if(relpath.size()) + { + relpath.erase(relpath.size()-1, 1); + } + else + { + relpath = "."; + } + cmSystemTools::ReplaceString(ret, m_HomeOutputDirectoryNoSlash.c_str(), + relpath.c_str()); + ret = cmSystemTools::ConvertToOutputPath(ret.c_str()); + return ret; +} diff --git a/Source/cmLocalUnixMakefileGenerator.h b/Source/cmLocalUnixMakefileGenerator.h index e6ca2cfec..7878552a4 100644 --- a/Source/cmLocalUnixMakefileGenerator.h +++ b/Source/cmLocalUnixMakefileGenerator.h @@ -231,7 +231,9 @@ protected: /** Output an echo command to the Makefile */ void OutputEcho(std::ostream& fout, const char *msg); - + + ///! final processing for a path to be put in a makefile + std::string ConvertToMakefilePath(const char* p); protected: int m_MakefileVariableSize; std::map m_MakeVariableMap; @@ -241,6 +243,12 @@ protected: std::string m_MakeSilentFlag; std::string m_ExecutableOutputPath; std::string m_LibraryOutputPath; + std::string m_RelativePathToSourceDir; + std::string m_RelativePathToBinaryDir; + std::string m_CurrentOutputDirectory; + std::string m_HomeOutputDirectory; + std::string m_HomeDirectory; + std::string m_HomeOutputDirectoryNoSlash; bool m_WindowsShell; bool m_PassMakeflags; private: diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 3046abcc9..72a2593a8 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -438,6 +438,7 @@ bool cmSystemTools::RunSingleCommand( } else { + std::cerr << cmsysProcess_GetErrorString(cp) << "\n"; result = false; } @@ -1063,3 +1064,66 @@ bool cmSystemTools::CreateSymlink(const char* origName, const char* newName) return (symlink(origName, newName) >= 0); } #endif + + +std::vector cmSystemTools::SplitString(const char* p, char sep) +{ + std::string path = p; + std::vector paths; + std::string::size_type pos1 = 0; + std::string::size_type pos2 = path.find(sep, pos1+1); + while(pos2 != std::string::npos) + { + paths.push_back(path.substr(pos1+1, pos2-pos1-1)); + pos1 = pos2; + pos2 = path.find(sep, pos1+1); + } + paths.push_back(path.substr(pos1+1, pos2-pos1-1)); + + return paths; +} + + +// compute the relative path from here to there +std::string cmSystemTools::RelativePath(const char* local, const char* remote) +{ +#ifdef _WIN32 + std::string lowerCaseLocal = cmSystemTools::LowerCase(std::string(local)); + std::string lowerCaseRemote = cmSystemTools::LowerCase(std::string(remote)); + remote = lowerCaseRemote.c_str(); + local = lowerCaseLocal.c_str(); +#endif + // check for driveletter: as the start of the path + // if not on the same drive then full path to remote must be used. + if(local[0] && local[0] != '/') + { + if(remote[0] && local[0] != remote[0]) + { + return remote; + } + } + std::string relativePath; // result string + // split up both paths into arrays of strings using / as a separator + std::vector fileSplit = cmSystemTools::SplitString(local); + std::vector relativeSplit = cmSystemTools::SplitString(remote); + // count up how many mathing directory names there are from the start + int sameCount = 0; + while(sameCount < fileSplit.size()-1 && sameCount < relativeSplit.size()-1 && + fileSplit[sameCount] == relativeSplit[sameCount]) + { + sameCount++; + } + // put in sameCount number of ../ into the path + int i; + for(i = sameCount; i < fileSplit.size(); ++i) + { + relativePath += "../"; + } + // now put the rest of path that did not match back + for(i = sameCount; i < relativeSplit.size()-1; ++i) + { + relativePath += relativeSplit[i] + "/"; + } + relativePath += relativeSplit[i]; + return relativePath; +} diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 5d484a838..4aeaf18b0 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -245,6 +245,11 @@ public: static bool StringEndsWith(const char* str1, const char* str2); static bool CreateSymlink(const char* origName, const char* newName); + + ///! compute the relative path from local to remote + static std::string RelativePath(const char* local, const char* remote); + ///! split a path by separator into an array of strings, default is / + static std::vector SplitString(const char* s, char separator = '/'); private: static bool s_ForceUnixPaths; static bool s_RunCommandHideConsole; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index b1e2eea14..bba8a382b 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -275,6 +275,8 @@ void cmake::SetArgs(const std::vector& args) { directoriesSet = true; std::string path = arg.substr(2); + path = cmSystemTools::CollapseFullPath(path.c_str()); + cmSystemTools::ConvertToUnixSlashes(path); this->SetHomeDirectory(path.c_str()); } else if(arg.find("-S",0) == 0) @@ -282,18 +284,24 @@ void cmake::SetArgs(const std::vector& args) directoriesSet = true; m_Local = true; std::string path = arg.substr(2); + path = cmSystemTools::CollapseFullPath(path.c_str()); + cmSystemTools::ConvertToUnixSlashes(path); this->SetStartDirectory(path.c_str()); } else if(arg.find("-O",0) == 0) { directoriesSet = true; std::string path = arg.substr(2); + path = cmSystemTools::CollapseFullPath(path.c_str()); + cmSystemTools::ConvertToUnixSlashes(path); this->SetStartOutputDirectory(path.c_str()); } else if(arg.find("-B",0) == 0) { directoriesSet = true; std::string path = arg.substr(2); + path = cmSystemTools::CollapseFullPath(path.c_str()); + cmSystemTools::ConvertToUnixSlashes(path); this->SetHomeOutputDirectory(path.c_str()); } else if(arg.find("-V",0) == 0)