diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 667d86f4c..e5b4057d2 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -573,22 +573,20 @@ cmLocalVisualStudio6Generator // Add the rule with the given dependencies and commands. const char* no_main_dependency = 0; - this->Makefile->AddCustomCommandToOutput(output, - depends, - no_main_dependency, - origCommand.GetCommandLines(), - comment.c_str(), - origCommand.GetWorkingDirectory()); + if(cmSourceFile* outsf = + this->Makefile->AddCustomCommandToOutput( + output, depends, no_main_dependency, + origCommand.GetCommandLines(), comment.c_str(), + origCommand.GetWorkingDirectory())) + { + target.AddSourceFile(outsf); + } // Replace the dependencies with the output of this rule so that the // next rule added will run after this one. depends.clear(); depends.push_back(output); - // Add a source file representing this output to the project. - cmSourceFile* outsf = this->Makefile->GetSourceFileWithOutput(output); - target.AddSourceFile(outsf); - // Free the fake output name. delete [] output; } diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index b7e30b360..58cc6f40a 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -146,11 +146,10 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets() force += "/"; force += tgt.GetName(); force += "_force"; - this->Makefile->AddCustomCommandToOutput(force.c_str(), no_depends, - no_main_dependency, - force_commands, " ", 0, true); if(cmSourceFile* file = - this->Makefile->GetSourceFileWithOutput(force.c_str())) + this->Makefile->AddCustomCommandToOutput( + force.c_str(), no_depends, no_main_dependency, + force_commands, " ", 0, true)) { tgt.AddSourceFile(file); } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index aae92dd89..08c97635e 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -150,6 +150,7 @@ cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals) this->Initialize(); this->CheckSystemVars = mf.CheckSystemVars; this->ListFileStack = mf.ListFileStack; + this->OutputToSource = mf.OutputToSource; } //---------------------------------------------------------------------------- @@ -1010,10 +1011,31 @@ cmMakefile::AddCustomCommandToOutput(const std::vector& outputs, cc->SetEscapeOldStyle(escapeOldStyle); cc->SetEscapeAllowMakeVars(true); file->SetCustomCommand(cc); + this->UpdateOutputToSourceMap(outputs, file); } return file; } +//---------------------------------------------------------------------------- +void +cmMakefile::UpdateOutputToSourceMap(std::vector const& outputs, + cmSourceFile* source) +{ + for(std::vector::const_iterator o = outputs.begin(); + o != outputs.end(); ++o) + { + this->UpdateOutputToSourceMap(*o, source); + } +} + +//---------------------------------------------------------------------------- +void +cmMakefile::UpdateOutputToSourceMap(std::string const& output, + cmSourceFile* source) +{ + this->OutputToSource[output] = source; +} + //---------------------------------------------------------------------------- cmSourceFile* cmMakefile::AddCustomCommandToOutput(const char* output, @@ -1994,7 +2016,7 @@ cmMakefile::AddNewTarget(cmTarget::TargetType type, const char* name) return &it->second; } -cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname) +cmSourceFile *cmMakefile::LinearGetSourceFileWithOutput(const char *cname) { std::string name = cname; std::string out; @@ -2030,6 +2052,25 @@ cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname) return 0; } +cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname) +{ + std::string name = cname; + + // If the queried path is not absolute we use the backward compatible + // linear-time search for an output with a matching suffix. + if(!cmSystemTools::FileIsFullPath(cname)) + { + return LinearGetSourceFileWithOutput(cname); + } + // Otherwise we use an efficient lookup map. + OutputToSourceMap::iterator o = this->OutputToSource.find(name); + if (o != this->OutputToSource.end()) + { + return (*o).second; + } + return 0; +} + #if defined(CMAKE_BUILD_WITH_CMAKE) cmSourceGroup* cmMakefile::GetSourceGroup(const std::vector&name) { diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 711a208fb..8bce9fd65 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -29,6 +29,9 @@ #include #include +#if defined(CMAKE_BUILD_WITH_CMAKE) +# include +#endif class cmFunctionBlocker; class cmCommand; @@ -1039,6 +1042,26 @@ private: bool GeneratingBuildSystem; + /** + * Old version of GetSourceFileWithOutput(const char*) kept for + * backward-compatibility. It implements a linear search and support + * relative file paths. It is used as a fall back by + * GetSourceFileWithOutput(const char*). + */ + cmSourceFile *LinearGetSourceFileWithOutput(const char *cname); + + // A map for fast output to input look up. +#if defined(CMAKE_BUILD_WITH_CMAKE) + typedef cmsys::hash_map OutputToSourceMap; +#else + typedef std::map OutputToSourceMap; +#endif + OutputToSourceMap OutputToSource; + + void UpdateOutputToSourceMap(std::vector const& outputs, + cmSourceFile* source); + void UpdateOutputToSourceMap(std::string const& output, + cmSourceFile* source); }; //----------------------------------------------------------------------------