From ad44a41a187fc3a1b829397e1c9f7c5f305c084b Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 9 Oct 2008 15:30:07 -0400 Subject: ENH: Fix optional use of relative paths. These changes refactor cmLocalGenerator methods Convert and ConvertToOutputForExisting to support references inside the build tree using relative paths. After this commit, all tests pass with Makefile generators when relative paths are enabled by default. See issue #7779. --- Source/cmLocalGenerator.cxx | 110 ++++++++++++++++++++++--- Source/cmLocalGenerator.h | 23 +++++- Source/cmLocalUnixMakefileGenerator3.cxx | 55 ++++++------- Source/cmLocalUnixMakefileGenerator3.h | 11 ++- Source/cmMakefileExecutableTargetGenerator.cxx | 4 +- Source/cmMakefileLibraryTargetGenerator.cxx | 6 +- Source/cmMakefileTargetGenerator.cxx | 10 +-- 7 files changed, 164 insertions(+), 55 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index f87924b..fd8da18 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1074,22 +1074,54 @@ cmLocalGenerator::ExpandRuleVariables(std::string& s, s = expandedInput; } - -std::string -cmLocalGenerator::ConvertToOutputForExisting(const char* p) +//---------------------------------------------------------------------------- +std::string +cmLocalGenerator::ConvertToOutputForExistingCommon(const char* remote, + std::string const& result) { - std::string ret = p; - if(this->WindowsShell && ret.find(' ') != ret.npos - && cmSystemTools::FileExists(p)) + // If this is a windows shell, the result has a space, and the path + // already exists, we can use a short-path to reference it without a + // space. + if(this->WindowsShell && result.find(' ') != result.npos && + cmSystemTools::FileExists(remote)) { - if(cmSystemTools::GetShortPath(p, ret)) + std::string tmp; + if(cmSystemTools::GetShortPath(remote, tmp)) { - return this->Convert(ret.c_str(), NONE, SHELL, true); + return this->Convert(tmp.c_str(), NONE, SHELL, true); } } - return this->Convert(p, START_OUTPUT, SHELL, true); + + // Otherwise, leave it unchanged. + return result; +} + +//---------------------------------------------------------------------------- +std::string +cmLocalGenerator::ConvertToOutputForExisting(const char* remote, + RelativeRoot local) +{ + // Perform standard conversion. + std::string result = this->Convert(remote, local, SHELL, true); + + // Consider short-path. + return this->ConvertToOutputForExistingCommon(remote, result); +} + +//---------------------------------------------------------------------------- +std::string +cmLocalGenerator::ConvertToOutputForExisting(RelativeRoot remote, + const char* local) +{ + // Perform standard conversion. + std::string result = this->Convert(remote, local, SHELL, true); + + // Consider short-path. + const char* remotePath = this->GetRelativeRootPath(remote); + return this->ConvertToOutputForExistingCommon(remotePath, result); } +//---------------------------------------------------------------------------- const char* cmLocalGenerator::GetIncludeFlags(const char* lang) { if(!lang) @@ -1985,7 +2017,21 @@ cmLocalGenerator::ConvertToOptionallyRelativeOutputPath(const char* remote) } //---------------------------------------------------------------------------- -std::string cmLocalGenerator::Convert(const char* source, +const char* cmLocalGenerator::GetRelativeRootPath(RelativeRoot relroot) +{ + switch (relroot) + { + case HOME: return this->Makefile->GetHomeDirectory(); + case START: return this->Makefile->GetStartDirectory(); + case HOME_OUTPUT: return this->Makefile->GetHomeOutputDirectory(); + case START_OUTPUT: return this->Makefile->GetStartOutputDirectory(); + default: break; + } + return 0; +} + +//---------------------------------------------------------------------------- +std::string cmLocalGenerator::Convert(const char* source, RelativeRoot relative, OutputFormat output, bool optional) @@ -2033,7 +2079,15 @@ std::string cmLocalGenerator::Convert(const char* source, break; } } - // Now convert it to an output path. + return this->ConvertToOutputFormat(result.c_str(), output); +} + +//---------------------------------------------------------------------------- +std::string cmLocalGenerator::ConvertToOutputFormat(const char* source, + OutputFormat output) +{ + std::string result = source; + // Convert it to an output path. if (output == MAKEFILE) { result = cmSystemTools::ConvertToOutputPath(result.c_str()); @@ -2066,6 +2120,40 @@ std::string cmLocalGenerator::Convert(const char* source, } //---------------------------------------------------------------------------- +std::string cmLocalGenerator::Convert(RelativeRoot remote, + const char* local, + OutputFormat output, + bool optional) +{ + const char* remotePath = this->GetRelativeRootPath(remote); + if(local && (!optional || this->UseRelativePaths)) + { + std::vector components; + std::string result; + switch(remote) + { + case HOME: + case HOME_OUTPUT: + case START: + case START_OUTPUT: + cmSystemTools::SplitPath(local, components); + result = this->ConvertToRelativePath(components, remotePath); + break; + case FULL: + result = remotePath; + break; + case NONE: + break; + } + return this->ConvertToOutputFormat(result.c_str(), output); + } + else + { + return this->ConvertToOutputFormat(remotePath, output); + } +} + +//---------------------------------------------------------------------------- std::string cmLocalGenerator::FindRelativePathTopSource() { // Relative path conversion within a single tree managed by CMake is diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index d528d2f..9af44c9 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -108,10 +108,18 @@ public: */ enum RelativeRoot { NONE, FULL, HOME, START, HOME_OUTPUT, START_OUTPUT }; enum OutputFormat { UNCHANGED, MAKEFILE, SHELL }; - std::string Convert(const char* source, - RelativeRoot relative, + std::string ConvertToOutputFormat(const char* source, OutputFormat output); + std::string Convert(const char* remote, RelativeRoot local, OutputFormat output = UNCHANGED, bool optional = false); + std::string Convert(RelativeRoot remote, const char* local, + OutputFormat output = UNCHANGED, + bool optional = false); + + /** + * Get path for the specified relative root. + */ + const char* GetRelativeRootPath(RelativeRoot relroot); /** * Convert the given path to an output path that is optionally @@ -162,7 +170,13 @@ public: std::string GetRealLocation(const char* inName, const char* config); ///! for existing files convert to output path and short path if spaces - std::string ConvertToOutputForExisting(const char* p); + std::string ConvertToOutputForExisting(const char* remote, + RelativeRoot local = START_OUTPUT); + + /** For existing path identified by RelativeRoot convert to output + path and short path if spaces. */ + std::string ConvertToOutputForExisting(RelativeRoot remote, + const char* local = 0); /** Called from command-line hook to clear dependencies. */ virtual void ClearDependencies(cmMakefile* /* mf */, @@ -386,6 +400,9 @@ protected: unsigned int BackwardsCompatibility; bool BackwardsCompatibilityFinal; +private: + std::string ConvertToOutputForExistingCommon(const char* remote, + std::string const& result); }; #endif diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index a2595d9..aae96ab 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -361,7 +361,7 @@ cmLocalUnixMakefileGenerator3 } this->CreateCDCommand(commands, this->Makefile->GetHomeOutputDirectory(), - this->Makefile->GetStartOutputDirectory()); + cmLocalGenerator::START_OUTPUT); // Write the rule to the makefile. std::vector no_depends; @@ -404,7 +404,7 @@ void cmLocalUnixMakefileGenerator3 (makefile2.c_str(),localName.c_str())); this->CreateCDCommand(commands, this->Makefile->GetHomeOutputDirectory(), - this->Makefile->GetStartOutputDirectory()); + cmLocalGenerator::START_OUTPUT); this->WriteMakeRule(ruleFileStream, "Convenience name for target.", localName.c_str(), depends, commands, true); @@ -432,7 +432,7 @@ void cmLocalUnixMakefileGenerator3 (makefileName.c_str(), makeTargetName.c_str())); this->CreateCDCommand(commands, this->Makefile->GetHomeOutputDirectory(), - this->Makefile->GetStartOutputDirectory()); + cmLocalGenerator::START_OUTPUT); this->WriteMakeRule(ruleFileStream, "fast build rule for target.", localName.c_str(), depends, commands, true); @@ -450,7 +450,7 @@ void cmLocalUnixMakefileGenerator3 (makefile2.c_str(), makeTargetName.c_str())); this->CreateCDCommand(commands, this->Makefile->GetHomeOutputDirectory(), - this->Makefile->GetStartOutputDirectory()); + cmLocalGenerator::START_OUTPUT); this->WriteMakeRule(ruleFileStream, "Manual pre-install relink rule for target.", localName.c_str(), depends, commands, true); @@ -835,7 +835,7 @@ void cmLocalUnixMakefileGenerator3 { this->CreateCDCommand(commands, this->Makefile->GetHomeOutputDirectory(), - this->Makefile->GetStartOutputDirectory()); + cmLocalGenerator::START_OUTPUT); } this->WriteMakeRule(makefileStream, "Special rule to run CMake to check the build system " @@ -953,12 +953,13 @@ cmLocalUnixMakefileGenerator3 void cmLocalUnixMakefileGenerator3 ::AppendCustomCommands(std::vector& commands, - const std::vector& ccs) + const std::vector& ccs, + cmLocalGenerator::RelativeRoot relative) { for(std::vector::const_iterator i = ccs.begin(); i != ccs.end(); ++i) { - this->AppendCustomCommand(commands, *i, true); + this->AppendCustomCommand(commands, *i, true, relative); } } @@ -966,7 +967,8 @@ cmLocalUnixMakefileGenerator3 void cmLocalUnixMakefileGenerator3 ::AppendCustomCommand(std::vector& commands, - const cmCustomCommand& cc, bool echo_comment) + const cmCustomCommand& cc, bool echo_comment, + cmLocalGenerator::RelativeRoot relative) { // Optionally create a command to display the custom command's // comment text. This is used for pre-build, pre-link, and @@ -1072,8 +1074,7 @@ cmLocalUnixMakefileGenerator3 } // Setup the proper working directory for the commands. - this->CreateCDCommand(commands1, dir, - this->Makefile->GetHomeOutputDirectory()); + this->CreateCDCommand(commands1, dir, relative); // push back the custom commands commands.insert(commands.end(), commands1.begin(), commands1.end()); @@ -1610,9 +1611,11 @@ void cmLocalUnixMakefileGenerator3 this->AppendCustomDepends(depends, glIt->second.GetPostBuildCommands()); this->AppendCustomCommands(commands, - glIt->second.GetPreBuildCommands()); + glIt->second.GetPreBuildCommands(), + cmLocalGenerator::START_OUTPUT); this->AppendCustomCommands(commands, - glIt->second.GetPostBuildCommands()); + glIt->second.GetPostBuildCommands(), + cmLocalGenerator::START_OUTPUT); std::string targetName = glIt->second.GetName(); this->WriteMakeRule(ruleFileStream, targetString.c_str(), targetName.c_str(), depends, commands, true); @@ -1674,7 +1677,7 @@ void cmLocalUnixMakefileGenerator3 recursiveTarget.c_str())); this->CreateCDCommand(commands, this->Makefile->GetHomeOutputDirectory(), - this->Makefile->GetStartOutputDirectory()); + cmLocalGenerator::START_OUTPUT); { cmOStringStream progCmd; progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0 @@ -1696,7 +1699,7 @@ void cmLocalUnixMakefileGenerator3 recursiveTarget.c_str())); this->CreateCDCommand(commands, this->Makefile->GetHomeOutputDirectory(), - this->Makefile->GetStartOutputDirectory()); + cmLocalGenerator::START_OUTPUT); this->WriteMakeRule(ruleFileStream, "The main clean target", "clean", depends, commands, true); commands.clear(); @@ -1726,7 +1729,7 @@ void cmLocalUnixMakefileGenerator3 (this->GetRecursiveMakeCall(mf2Dir.c_str(), recursiveTarget.c_str())); this->CreateCDCommand(commands, this->Makefile->GetHomeOutputDirectory(), - this->Makefile->GetStartOutputDirectory()); + cmLocalGenerator::START_OUTPUT); this->WriteMakeRule(ruleFileStream, "Prepare targets for installation.", "preinstall", depends, commands, true); depends.clear(); @@ -1747,7 +1750,7 @@ void cmLocalUnixMakefileGenerator3 commands.push_back(runRule); this->CreateCDCommand(commands, this->Makefile->GetHomeOutputDirectory(), - this->Makefile->GetStartOutputDirectory()); + cmLocalGenerator::START_OUTPUT); this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends, commands, true); @@ -2126,8 +2129,10 @@ cmLocalUnixMakefileGenerator3::AddImplicitDepends(cmTarget const& tgt, //---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator3 ::CreateCDCommand(std::vector& commands, const char *tgtDir, - const char *retDir) + cmLocalGenerator::RelativeRoot relRetDir) { + const char* retDir = this->GetRelativeRootPath(relRetDir); + // do we need to cd? if (!strcmp(tgtDir,retDir)) { @@ -2140,18 +2145,12 @@ void cmLocalUnixMakefileGenerator3 // back because the shell keeps the working directory between // commands. std::string cmd = "cd "; - cmd += this->ConvertToOutputForExisting(tgtDir); + cmd += this->ConvertToOutputForExisting(tgtDir, relRetDir); commands.insert(commands.begin(),cmd); - - // Change back to the starting directory. Any trailing slash must be - // removed to avoid problems with Borland Make. - std::string back = retDir; - if(back.size() && back[back.size()-1] == '/') - { - back = back.substr(0, back.size()-1); - } + + // Change back to the starting directory. cmd = "cd "; - cmd += this->ConvertToOutputForExisting(back.c_str()); + cmd += this->ConvertToOutputForExisting(relRetDir, tgtDir); commands.push_back(cmd); } else @@ -2163,7 +2162,7 @@ void cmLocalUnixMakefileGenerator3 for (; i != commands.end(); ++i) { std::string cmd = "cd "; - cmd += this->ConvertToOutputForExisting(tgtDir); + cmd += this->ConvertToOutputForExisting(tgtDir, relRetDir); cmd += " && "; cmd += *i; *i = cmd; diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index d321643..220aaa8 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -197,7 +197,8 @@ public: // create a command that cds to the start dir then runs the commands void CreateCDCommand(std::vector& commands, - const char *targetDir, const char *returnDir); + const char *targetDir, + cmLocalGenerator::RelativeRoot returnDir); static std::string ConvertToQuotedOutputPath(const char* p); @@ -321,10 +322,14 @@ protected: void AppendCustomDepend(std::vector& depends, const cmCustomCommand& cc); void AppendCustomCommands(std::vector& commands, - const std::vector& ccs); + const std::vector& ccs, + cmLocalGenerator::RelativeRoot relative = + cmLocalGenerator::HOME_OUTPUT); void AppendCustomCommand(std::vector& commands, const cmCustomCommand& cc, - bool echo_comment=false); + bool echo_comment=false, + cmLocalGenerator::RelativeRoot relative = + cmLocalGenerator::HOME_OUTPUT); void AppendCleanCommand(std::vector& commands, const std::vector& files, cmTarget& target, const char* filename =0); diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index ed7e7bc..06305d0 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -440,7 +440,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->CreateCDCommand (commands1, this->Makefile->GetStartOutputDirectory(), - this->Makefile->GetHomeOutputDirectory()); + cmLocalGenerator::HOME_OUTPUT); commands.insert(commands.end(), commands1.begin(), commands1.end()); commands1.clear(); @@ -454,7 +454,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) commands1.push_back(symlink); this->LocalGenerator->CreateCDCommand(commands1, this->Makefile->GetStartOutputDirectory(), - this->Makefile->GetHomeOutputDirectory()); + cmLocalGenerator::HOME_OUTPUT); commands.insert(commands.end(), commands1.begin(), commands1.end()); commands1.clear(); } diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 9c0cc38..1a43831 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -591,7 +591,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules this->LocalGenerator->CreateCDCommand (commands1, this->Makefile->GetStartOutputDirectory(), - this->Makefile->GetHomeOutputDirectory()); + cmLocalGenerator::HOME_OUTPUT); commands.insert(commands.end(), commands1.begin(), commands1.end()); commands1.clear(); } @@ -872,7 +872,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules this->LocalGenerator->CreateCDCommand (commands1, this->Makefile->GetStartOutputDirectory(), - this->Makefile->GetHomeOutputDirectory()); + cmLocalGenerator::HOME_OUTPUT); commands.insert(commands.end(), commands1.begin(), commands1.end()); commands1.clear(); @@ -888,7 +888,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules commands1.push_back(symlink); this->LocalGenerator->CreateCDCommand(commands1, this->Makefile->GetStartOutputDirectory(), - this->Makefile->GetHomeOutputDirectory()); + cmLocalGenerator::HOME_OUTPUT); commands.insert(commands.end(), commands1.begin(), commands1.end()); commands1.clear(); } diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index f50bd31..0374373 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -567,7 +567,7 @@ cmMakefileTargetGenerator if(this->LocalGenerator->UseRelativePaths) { sourceFile = this->Convert(sourceFile.c_str(), - cmLocalGenerator::HOME_OUTPUT); + cmLocalGenerator::START_OUTPUT); } sourceFile = this->Convert(sourceFile.c_str(), cmLocalGenerator::NONE, @@ -614,7 +614,7 @@ cmMakefileTargetGenerator this->LocalGenerator->CreateCDCommand (compileCommands, this->Makefile->GetStartOutputDirectory(), - this->Makefile->GetHomeOutputDirectory()); + cmLocalGenerator::HOME_OUTPUT); commands.insert(commands.end(), compileCommands.begin(), compileCommands.end()); @@ -725,7 +725,7 @@ cmMakefileTargetGenerator this->LocalGenerator->CreateCDCommand (preprocessCommands, this->Makefile->GetStartOutputDirectory(), - this->Makefile->GetHomeOutputDirectory()); + cmLocalGenerator::HOME_OUTPUT); commands.insert(commands.end(), preprocessCommands.begin(), preprocessCommands.end()); @@ -781,7 +781,7 @@ cmMakefileTargetGenerator this->LocalGenerator->CreateCDCommand (assemblyCommands, this->Makefile->GetStartOutputDirectory(), - this->Makefile->GetHomeOutputDirectory()); + cmLocalGenerator::HOME_OUTPUT); commands.insert(commands.end(), assemblyCommands.begin(), assemblyCommands.end()); @@ -895,7 +895,7 @@ void cmMakefileTargetGenerator::WriteTargetCleanRules() this->LocalGenerator->CreateCDCommand (commands, this->Makefile->GetStartOutputDirectory(), - this->Makefile->GetHomeOutputDirectory()); + cmLocalGenerator::HOME_OUTPUT); // Write the rule. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0, -- cgit v0.12