diff options
author | Alexander Neundorf <neundorf@kde.org> | 2007-05-09 08:25:45 -0400 |
---|---|---|
committer | Alexander Neundorf <neundorf@kde.org> | 2007-05-09 08:25:45 -0400 |
commit | 7f11536704d9f971cf5c8b0a2b490ccc6af58588 (patch) | |
tree | 05b5b24050a629bf9ceb59d743f77ca909448229 /Source | |
parent | 5af310502142252995ad5d74e66355be4094b7cc (diff) | |
download | cmake-7f11536704d9f971cf5c8b0a2b490ccc6af58588.tar.gz |
ENH: now target names can be used in add_custom_command() and
add_custom_target() as COMMAND, and cmake will recognize them and replace
them with the actual output path of these executables. Also the dependency
will be added automatically. Test included.
ENH: moved TraceVSDependencies() to the end of GlobalGenerator::Configure(),
so it is done now in one central place
Alex
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmCustomCommand.h | 4 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.cxx | 18 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.h | 2 | ||||
-rw-r--r-- | Source/cmGlobalUnixMakefileGenerator3.cxx | 2 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudio6Generator.cxx | 5 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudio7Generator.cxx | 3 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.cxx | 167 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.h | 9 | ||||
-rw-r--r-- | Source/cmLocalGenerator.cxx | 39 | ||||
-rw-r--r-- | Source/cmLocalGenerator.h | 14 | ||||
-rw-r--r-- | Source/cmLocalUnixMakefileGenerator3.cxx | 6 | ||||
-rw-r--r-- | Source/cmLocalVisualStudio6Generator.cxx | 96 | ||||
-rw-r--r-- | Source/cmLocalVisualStudio6Generator.h | 6 | ||||
-rw-r--r-- | Source/cmLocalVisualStudio7Generator.cxx | 60 | ||||
-rw-r--r-- | Source/cmLocalVisualStudio7Generator.h | 10 | ||||
-rw-r--r-- | Source/cmLocalVisualStudioGenerator.cxx | 7 | ||||
-rw-r--r-- | Source/cmLocalVisualStudioGenerator.h | 1 | ||||
-rw-r--r-- | Source/cmMakefile.cxx | 12 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 54 | ||||
-rw-r--r-- | Source/cmTarget.h | 11 |
20 files changed, 342 insertions, 184 deletions
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h index 5d59f0a97d..f7c6b5eeeb 100644 --- a/Source/cmCustomCommand.h +++ b/Source/cmCustomCommand.h @@ -69,8 +69,8 @@ public: void SetEscapeAllowMakeVars(bool b); /** set get the used status of the command */ - void SetUsed() { this->Used = true;}; - bool IsUsed() { return this->Used;}; + void SetUsed() { this->Used = true;} + bool IsUsed() const { return this->Used;} private: std::vector<std::string> Outputs; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index a0e66d3268..16913086b3 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -718,6 +718,13 @@ void cmGlobalGenerator::Configure() // at this point this->LocalGenerators has been filled, // so create the map from project name to vector of local generators this->FillProjectMap(); + // now create project to target map + // This will make sure that targets have all the + // targets they depend on as part of the build. + this->FillProjectToTargetMap(); + // now trace all dependencies + this->TraceDependencies(); + if ( !this->CMakeInstance->GetScriptMode() ) { this->CMakeInstance->UpdateProgress("Configuring done", -1); @@ -1036,6 +1043,13 @@ const char* cmGlobalGenerator::GetLinkerPreference(const char* lang) return "None"; } +void cmGlobalGenerator::TraceDependencies() +{ + for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) + { + this->LocalGenerators[i]->TraceDependencies(); + } +} void cmGlobalGenerator::FillProjectMap() { @@ -1057,10 +1071,6 @@ void cmGlobalGenerator::FillProjectMap() } while (lg); } - // now create project to target map - // This will make sure that targets have all the - // targets they depend on as part of the build. - this->FillProjectToTargetMap(); } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 65fe7159e8..0c0cd20f63 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -202,6 +202,8 @@ protected: void FillProjectMap(); bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen); void FillProjectToTargetMap(); + // Calls TraceVSDependencies() on all targets + void TraceDependencies(); void CreateDefaultGlobalTargets(cmTargets* targets); cmTarget CreateGlobalTarget(const char* name, const char* message, const cmCustomCommandLines* commandLines, diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index b4e05ede85..068cc517bd 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -1056,7 +1056,7 @@ cmGlobalUnixMakefileGenerator3 { cmTarget *result; cmLocalUnixMakefileGenerator3 *lg3; - + // first check the same dir as the current target lg3 = static_cast<cmLocalUnixMakefileGenerator3 *> (target.GetMakefile()->GetLocalGenerator()); diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx index 3b905c03e3..3829b3e090 100644 --- a/Source/cmGlobalVisualStudio6Generator.cxx +++ b/Source/cmGlobalVisualStudio6Generator.cxx @@ -208,9 +208,8 @@ void cmGlobalVisualStudio6Generator static_cast<cmLocalVisualStudio6Generator *>(generators[i]) ->GetCreatedProjectNames(); cmTargets &tgts = generators[i]->GetMakefile()->GetTargets(); - cmTargets::iterator l = tgts.begin(); - for(std::vector<std::string>::iterator si = dspnames.begin(); - l != tgts.end(); ++l) + std::vector<std::string>::iterator si = dspnames.begin(); + for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l) { // special handling for the current makefile if(mf == generators[0]->GetMakefile()) diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index afe96e7181..67fd7a3a12 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -294,8 +294,7 @@ void cmGlobalVisualStudio7Generator // than one dsp could have been created per input CMakeLists.txt file // for each target cmTargets &tgts = generators[i]->GetMakefile()->GetTargets(); - cmTargets::iterator l = tgts.begin(); - for(; l != tgts.end(); ++l) + for (cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l) { // special handling for the current makefile if(mf == generators[0]->GetMakefile()) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 7e6d506e2f..580aa5b3d7 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -577,16 +577,17 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, { continue; } + + if(cmtarget.GetType() == cmTarget::UTILITY || + cmtarget.GetType() == cmTarget::GLOBAL_TARGET) + { + targets.push_back(this->CreateUtilityTarget(cmtarget)); + } if(cmtarget.GetType() == cmTarget::UTILITY || cmtarget.GetType() == cmTarget::GLOBAL_TARGET || cmtarget.GetType() == cmTarget::INSTALL_FILES || cmtarget.GetType() == cmTarget::INSTALL_PROGRAMS) { - if(cmtarget.GetType() == cmTarget::UTILITY || - cmtarget.GetType() == cmTarget::GLOBAL_TARGET) - { - targets.push_back(this->CreateUtilityTarget(cmtarget)); - } continue; } @@ -849,6 +850,7 @@ std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag, } return retFlag; } + //---------------------------------------------------------------------------- void cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, @@ -872,8 +874,31 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, return; } + // collect multiple outputs of custom commands into a set + // which will be used for every configuration std::map<cmStdString, cmStdString> multipleOutputPairs; - + for(std::vector<cmCustomCommand>::const_iterator i = commands.begin(); + i != commands.end(); ++i) + { + cmCustomCommand const& cc = *i; + if(!cc.GetCommandLines().empty()) + { + const std::vector<std::string>& outputs = cc.GetOutputs(); + if(!outputs.empty()) + { + // If there are more than one outputs treat the + // first as the primary output and make the rest depend on it. + std::vector<std::string>::const_iterator o = outputs.begin(); + std::string primaryOutput = this->ConvertToRelativeForMake(o->c_str()); + for(++o; o != outputs.end(); ++o) + { + std::string currentOutput =this->ConvertToRelativeForMake(o->c_str()); + multipleOutputPairs[currentOutput] = primaryOutput; + } + } + } + } + std::string dir = this->CurrentMakefile->GetCurrentOutputDirectory(); dir += "/CMakeScripts"; cmSystemTools::MakeDirectory(dir.c_str()); @@ -883,7 +908,48 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, makefile += "_"; makefile += name; makefile += ".make"; - cmGeneratedFileStream makefileStream(makefile.c_str()); + + for (std::vector<std::string>::const_iterator currentConfig= + this->CurrentConfigurationTypes.begin(); + currentConfig!=this->CurrentConfigurationTypes.end(); + currentConfig++ ) + { + this->CreateCustomRulesMakefile(makefile.c_str(), + target, + commands, + currentConfig->c_str(), + multipleOutputPairs); + } + + std::string cdir = this->CurrentMakefile->GetCurrentOutputDirectory(); + cdir = this->ConvertToRelativeForXCode(cdir.c_str()); + std::string makecmd = "make -C "; + makecmd += cdir; + makecmd += " -f "; + makecmd += this->ConvertToRelativeForMake((makefile+"$CONFIGURATION").c_str()); + if(!multipleOutputPairs.empty()) + { + makecmd += " cmake_check_multiple_outputs"; + } + makecmd += " all"; + cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ "); + buildphase->AddAttribute("shellScript", + this->CreateString(makecmd.c_str())); +} + +//---------------------------------------------------------------------------- +void cmGlobalXCodeGenerator +::CreateCustomRulesMakefile(const char* makefileBasename, + cmTarget& target, + std::vector<cmCustomCommand> + const & commands, + const char* configName, + const std::map<cmStdString, cmStdString>& multipleOutputPairs + ) +{ + std::string makefileName=makefileBasename; + makefileName+=configName; + cmGeneratedFileStream makefileStream(makefileName.c_str()); if(!makefileStream) { return; @@ -909,7 +975,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, o != outputs.end(); ++o) { makefileStream - << "\\\n\t" << this->ConvertToRelativeForMake(o->c_str()); + << "\\\n\t" << this->ConvertToRelativeForMake(o->c_str()); } } else @@ -939,21 +1005,9 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, const std::vector<std::string>& outputs = cc.GetOutputs(); if(!outputs.empty()) { - // There is at least one output. If there is more than one treat the - // first as the primary output and make the rest depend on it. - std::vector<std::string>::const_iterator o = outputs.begin(); + // There is at least one output, start the rule for it std::string primary_output = - this->ConvertToRelativeForMake(o->c_str()); - for(++o; o != outputs.end(); ++o) - { - std::string current_output = - this->ConvertToRelativeForMake(o->c_str()); - makefileStream << current_output << ": " - << primary_output << "\n"; - multipleOutputPairs[current_output] = primary_output; - } - - // Start the rule for the primary output. + this->ConvertToRelativeForMake(outputs.begin()->c_str()); makefileStream << primary_output << ": "; } else @@ -962,11 +1016,11 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, makefileStream << tname[&cc] << ": "; } for(std::vector<std::string>::const_iterator d = - cc.GetDepends().begin(); + cc.GetDepends().begin(); d != cc.GetDepends().end(); ++d) { if(!this->FindTarget(this->CurrentProject.c_str(), - d->c_str())) + d->c_str())) { // if the depend is not a target but // is a full path then use it, if not then @@ -974,7 +1028,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, if(cmSystemTools::FileIsFullPath(d->c_str())) { makefileStream << "\\\n" << this - ->ConvertToRelativeForMake(d->c_str()); + ->ConvertToRelativeForMake(d->c_str()); } } else @@ -989,12 +1043,14 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, // Add each command line to the set of commands. for(cmCustomCommandLines::const_iterator cl = - cc.GetCommandLines().begin(); + cc.GetCommandLines().begin(); cl != cc.GetCommandLines().end(); ++cl) { // Build the command line in a single string. const cmCustomCommandLine& commandLine = *cl; - std::string cmd2 = commandLine[0]; + std::string cmd2 = this->CurrentLocalGenerator + ->GetRealLocation(commandLine[0].c_str(), configName); + cmSystemTools::ReplaceString(cmd2, "/./", "/"); cmd2 = this->ConvertToRelativeForMake(cmd2.c_str()); std::string cmd; @@ -1011,13 +1067,13 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, if(escapeOldStyle) { cmd += (this->CurrentLocalGenerator - ->EscapeForShellOldStyle(commandLine[j].c_str())); + ->EscapeForShellOldStyle(commandLine[j].c_str())); } else { cmd += (this->CurrentLocalGenerator-> - EscapeForShell(commandLine[j].c_str(), - escapeAllowMakeVars)); + EscapeForShell(commandLine[j].c_str(), + escapeAllowMakeVars)); } } makefileStream << "\t" << cmd.c_str() << "\n"; @@ -1025,38 +1081,31 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, } } - // Add a rule to deal with multiple outputs of custom commands. + // Add rules to deal with multiple outputs of custom commands. if(!multipleOutputPairs.empty()) { + makefileStream << + "\n# Dependencies of multiple outputs to their primary outputs \n"; + + for(std::map<cmStdString, cmStdString>::const_iterator o = + multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o) + { + makefileStream << o->first << ": " << o->second << "\n"; + } + makefileStream << - "\n" - "cmake_check_multiple_outputs:\n"; + "\n" + "cmake_check_multiple_outputs:\n"; for(std::map<cmStdString, cmStdString>::const_iterator o = - multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o) + multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o) { makefileStream << "\t@if [ ! -f " - << o->first << " ]; then rm -f " - << o->second << "; fi\n"; + << o->first << " ]; then rm -f " + << o->second << "; fi\n"; } } - - std::string cdir = this->CurrentMakefile->GetCurrentOutputDirectory(); - cdir = this->ConvertToRelativeForXCode(cdir.c_str()); - std::string makecmd = "make -C "; - makecmd += cdir; - makecmd += " -f "; - makecmd += this->ConvertToRelativeForMake(makefile.c_str()); - if(!multipleOutputPairs.empty()) - { - makecmd += " cmake_check_multiple_outputs"; - } - makecmd += " all"; - cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ "); - buildphase->AddAttribute("shellScript", - this->CreateString(makecmd.c_str())); } - //---------------------------------------------------------------------------- void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, cmXCodeObject* buildSettings, @@ -2406,20 +2455,6 @@ cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator* root, cmMakefile* mf = (*g)->GetMakefile(); std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups(); cmTargets &tgts = mf->GetTargets(); - // Call TraceVSDependencies on all targets - for(cmTargets::iterator l = tgts.begin(); - l != tgts.end(); l++) - { - // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace - // so don't build a projectfile for it - if ((l->second.GetType() != cmTarget::INSTALL_FILES) - && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS) - && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0)) - { - cmTarget& target = l->second; - target.TraceVSDependencies(target.GetName(), mf); - } - } // now for all custom commands that are not used directly in a // target, add them to all targets in the current directory or // makefile diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index e9091e42d2..4a08217454 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -106,6 +106,15 @@ private: std::vector<cmCustomCommand> const & commands, const char* commandFileName); + + void CreateCustomRulesMakefile(const char* makefileBasename, + cmTarget& target, + std::vector<cmCustomCommand> const & commands, + const char* configName, + const std::map<cmStdString, cmStdString>& + multipleOutputPairs + ); + cmXCodeObject* FindXCodeTarget(cmTarget*); // create cmXCodeObject from these functions so that memory can be managed // correctly. All objects created are stored in this->XCodeObjects. diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 05ba04d71f..ec78dafeb9 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -52,6 +52,7 @@ cmLocalGenerator::cmLocalGenerator() this->UseRelativePaths = false; this->Configured = false; this->EmitUniversalBinaryFlags = true; + this->IsMakefileGenerator = false; this->RelativePathsConfigured = false; this->PathConversionsSetup = false; } @@ -135,6 +136,30 @@ void cmLocalGenerator::ConfigureFinalPass() this->Makefile->ConfigureFinalPass(); } +void cmLocalGenerator::TraceDependencies() +{ + // Generate the rule files for each target. + cmTargets& targets = this->Makefile->GetTargets(); + for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t) + { + // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace + // so don't build a projectfile for it + if ((t->second.GetType() != cmTarget::INSTALL_FILES) + && (t->second.GetType() != cmTarget::INSTALL_PROGRAMS) + && (t->second.GetType() != cmTarget::INSTALL_DIRECTORY) + && (strncmp(t->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0) + && (t->second.GetPropertyAsBool("IMPORTED") == false)) + { + std::string projectFilename; + if (this->IsMakefileGenerator == false) // only use of this variable + { + projectFilename=t->second.GetName(); + } + t->second.TraceVSDependencies(projectFilename, this->Makefile); + } + } +} + void cmLocalGenerator::GenerateTestFiles() { if ( !this->Makefile->IsOn("CMAKE_TESTING_ENABLED") ) @@ -1987,6 +2012,20 @@ std::string cmLocalGenerator::GetRealDependency(const char* inName, } //---------------------------------------------------------------------------- +std::string cmLocalGenerator::GetRealLocation(const char* inName, + const char* config) +{ + std::string outName=inName; + // Look for a CMake target with the given name. + cmTarget* target = this->GlobalGenerator->FindTarget(0, inName); + if ((target!=0) && (target->GetType()==cmTarget::EXECUTABLE)) + { + outName = target->GetLocation( config ); + } + return outName; +} + +//---------------------------------------------------------------------------- void cmLocalGenerator::AddSharedFlags(std::string& flags, const char* lang, bool shared) diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 651988960e..a9f56822c3 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -42,7 +42,7 @@ public: /** * Generate the makefile for this directory. */ - virtual void Generate() {}; + virtual void Generate() {} /** * Process the CMakeLists files for this directory to fill in the @@ -50,6 +50,11 @@ public: */ virtual void Configure(); + /** + * Calls TraceVSDependencies() on all targets of this generator. + */ + virtual void TraceDependencies(); + /** * Perform any final calculations prior to generation */ @@ -137,6 +142,11 @@ public: the source directory of this generator. This should only be used for dependencies of custom commands. */ std::string GetRealDependency(const char* name, const char* config); + + /** Translate a command as given in CMake code to the location of the + executable if the command is the name of a CMake executable target. + If that's not the case, just return the original name. */ + 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); @@ -298,6 +308,8 @@ protected: bool IgnoreLibPrefix; bool Configured; bool EmitUniversalBinaryFlags; + // A type flag is not nice. It's used only in TraceDependencies(). + bool IsMakefileGenerator; // Hack for ExpandRuleVariable until object-oriented version is // committed. std::string TargetImplib; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 2b8f3466f9..a48bebbaa8 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -54,6 +54,7 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3() this->NativeEchoCommand = "@echo "; this->NativeEchoWindows = true; this->MakeCommandEscapeTargetTwice = false; + this->IsMakefileGenerator = true; } //---------------------------------------------------------------------------- @@ -112,7 +113,7 @@ void cmLocalUnixMakefileGenerator3::Generate() if (tg) { this->TargetGenerators.push_back(tg); - t->second.TraceVSDependencies(empty, this->Makefile); +// t->second.TraceVSDependencies(empty, this->Makefile); tg->WriteRuleFiles(); } } @@ -885,7 +886,8 @@ cmLocalUnixMakefileGenerator3 { // Build the command line in a single string. const cmCustomCommandLine& commandLine = *cl; - std::string cmd = commandLine[0]; + std::string cmd = GetRealLocation(commandLine[0].c_str(), + this->ConfigurationName.c_str()); if (cmd.size()) { cmSystemTools::ReplaceString(cmd, "/./", "/"); diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 24a381afd8..b3ae6e2199 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -116,16 +116,6 @@ void cmLocalVisualStudio6Generator::OutputDSPFile() { this->AddDSPBuildRule(l->second); } - - // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace - // so don't build a projectfile for it - if ((l->second.GetType() != cmTarget::INSTALL_FILES) - && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS) - && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0)) - { - cmTarget& target = l->second; - target.TraceVSDependencies(target.GetName(), this->Makefile); - } } // build any targets @@ -490,23 +480,8 @@ void cmLocalVisualStudio6Generator } if (command) { - std::string script = - this->ConstructScript(command->GetCommandLines(), - command->GetWorkingDirectory(), - command->GetEscapeOldStyle(), - command->GetEscapeAllowMakeVars(), - "\\\n\t"); - std::string comment = - this->ConstructComment(*command, - "Building Custom Rule $(InputPath)"); - if(comment == "<hack>") - { - comment = ""; - } const char* flags = compileFlags.size() ? compileFlags.c_str(): 0; - this->WriteCustomRule(fout, source.c_str(), script.c_str(), - comment.c_str(), command->GetDepends(), - command->GetOutputs(), flags); + this->WriteCustomRule(fout, source.c_str(), *command, flags); } else if(!compileFlags.empty() || !objectNameDir.empty()) { @@ -603,16 +578,29 @@ void cmLocalVisualStudio6Generator ::WriteCustomRule(std::ostream& fout, const char* source, - const char* command, - const char* comment, - const std::vector<std::string>& depends, - const std::vector<std::string>& outputs, + const cmCustomCommand& command, const char* flags) { + std::string comment = + this->ConstructComment(command, "Building Custom Rule $(InputPath)"); + if(comment == "<hack>") + { + comment = ""; + } + // Write the rule for each configuration. std::vector<std::string>::iterator i; for(i = this->Configurations.begin(); i != this->Configurations.end(); ++i) { + + std::string script = + this->ConstructScript(command.GetCommandLines(), + command.GetWorkingDirectory(), + i->c_str(), + command.GetEscapeOldStyle(), + command.GetEscapeAllowMakeVars(), + "\\\n\t"); + if (i == this->Configurations.begin()) { fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl; @@ -627,8 +615,9 @@ cmLocalVisualStudio6Generator } // Write out the dependencies for the rule. fout << "USERDEP__HACK="; - for(std::vector<std::string>::const_iterator d = depends.begin(); - d != depends.end(); ++d) + for(std::vector<std::string>::const_iterator d=command.GetDepends().begin(); + d != command.GetDepends().end(); + ++d) { // Lookup the real name of the dependency in case it is a CMake target. std::string dep = this->GetRealDependency(d->c_str(), i->c_str()); @@ -639,26 +628,28 @@ cmLocalVisualStudio6Generator fout << "# PROP Ignore_Default_Tool 1\n"; fout << "# Begin Custom Build -"; - if(comment && *comment) + if(!comment.empty()) { - fout << " " << comment; + fout << " " << comment.c_str(); } fout << "\n\n"; - if(outputs.empty()) + if(command.GetOutputs().empty()) { fout << source << "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t"; - fout << command << "\n\n"; + fout << script.c_str() << "\n\n"; } else { - for(std::vector<std::string>::const_iterator o = outputs.begin(); - o != outputs.end(); ++o) + for(std::vector<std::string>::const_iterator o = + command.GetOutputs().begin(); + o != command.GetOutputs().end(); + ++o) { // Write a rule for every output generated by this command. fout << this->ConvertToOptionallyRelativeOutputPath(o->c_str()) << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t"; - fout << command << "\n\n"; + fout << script.c_str() << "\n\n"; } } fout << "# End Custom Build\n\n"; @@ -768,6 +759,7 @@ void cmLocalVisualStudio6Generator::SetBuildType(BuildType b, // look for custom rules on a target and collect them together std::string cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target, + const char* configName, const char * /* libName */) { std::string customRuleCode = ""; @@ -808,6 +800,7 @@ cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target, } customRuleCode += this->ConstructScript(cr->GetCommandLines(), cr->GetWorkingDirectory(), + configName, cr->GetEscapeOldStyle(), cr->GetEscapeAllowMakeVars(), "\\\n\t"); @@ -822,6 +815,7 @@ cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target, } customRuleCode += this->ConstructScript(cr->GetCommandLines(), cr->GetWorkingDirectory(), + configName, cr->GetEscapeOldStyle(), cr->GetEscapeAllowMakeVars(), "\\\n\t"); @@ -850,6 +844,7 @@ cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target, } customRuleCode += this->ConstructScript(cr->GetCommandLines(), cr->GetWorkingDirectory(), + configName, cr->GetEscapeOldStyle(), cr->GetEscapeAllowMakeVars(), "\\\n\t"); @@ -1274,7 +1269,14 @@ void cmLocalVisualStudio6Generator // are there any custom rules on the target itself // only if the target is a lib or exe - std::string customRuleCode = this->CreateTargetRules(target, libName); + std::string customRuleCodeRelease + = this->CreateTargetRules(target, "RELEASE", libName); + std::string customRuleCodeDebug + = this->CreateTargetRules(target, "DEBUG", libName); + std::string customRuleCodeMinSizeRel + = this->CreateTargetRules(target, "MINSIZEREL", libName); + std::string customRuleCodeRelWithDebInfo + = this->CreateTargetRules(target, "RELWITHDEBINFO", libName); std::ifstream fin(this->DSPHeaderTemplate.c_str()); if(!fin) @@ -1307,8 +1309,6 @@ void cmLocalVisualStudio6Generator } cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS", exportSymbol.c_str()); - cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE", - customRuleCode.c_str()); cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG", mfcFlag); if(target.GetType() == cmTarget::STATIC_LIBRARY ) @@ -1337,6 +1337,18 @@ void cmLocalVisualStudio6Generator cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIMIZED_LIBRARIES", libMultiLineOptimizedOptions.c_str()); #endif + + // Substitute the rules for custom command. When specifying just the + // target name for the command the command can be different for + // different configs + cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_RELEASE", + customRuleCodeRelease.c_str()); + cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_DEBUG", + customRuleCodeDebug.c_str()); + cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_MINSIZEREL", + customRuleCodeMinSizeRel.c_str()); + cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO", + customRuleCodeRelWithDebInfo.c_str()); // Substitute the real output name into the template. cmSystemTools::ReplaceString(line, "OUTPUT_NAME_DEBUG", diff --git a/Source/cmLocalVisualStudio6Generator.h b/Source/cmLocalVisualStudio6Generator.h index 3b789f8f34..7ac84a43ec 100644 --- a/Source/cmLocalVisualStudio6Generator.h +++ b/Source/cmLocalVisualStudio6Generator.h @@ -84,10 +84,7 @@ private: void AddDSPBuildRule(cmTarget& tgt); void WriteCustomRule(std::ostream& fout, const char* source, - const char* command, - const char* comment, - const std::vector<std::string>& depends, - const std::vector<std::string>& outputs, + const cmCustomCommand& command, const char* flags); void AddUtilityCommandHack(cmTarget& target, int count, std::vector<std::string>& depends, @@ -95,6 +92,7 @@ private: void WriteGroup(const cmSourceGroup *sg, cmTarget target, std::ostream &fout, const char *libName); std::string CreateTargetRules(cmTarget &target, + const char* configName, const char *libName); void ComputeLinkOptions(cmTarget& target, const char* configName, const std::string extraOptions, diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index c40ca42988..6e2f1be010 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -124,16 +124,6 @@ void cmLocalVisualStudio7Generator::OutputVCProjFile() { this->AddVCProjBuildRule(l->second); } - - // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace - // so don't build a projectfile for it - if ((l->second.GetType() != cmTarget::INSTALL_FILES) - && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS) - && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0)) - { - cmTarget& target = l->second; - target.TraceVSDependencies(target.GetName(), this->Makefile); - } } for(cmTargets::iterator l = tgts.begin(); @@ -623,7 +613,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, << "\t\t\t/>\n"; } - this->OutputTargetRules(fout, target, libName); + this->OutputTargetRules(fout, configName, target, libName); this->OutputBuildTool(fout, configName, target); fout << "\t\t</Configuration>\n"; } @@ -1141,17 +1131,8 @@ void cmLocalVisualStudio7Generator fout << "\t\t\t\tRelativePath=\"" << d << "\">\n"; if (command) { - // Construct the entire set of commands in one string. - std::string script = - this->ConstructScript(command->GetCommandLines(), - command->GetWorkingDirectory(), - command->GetEscapeOldStyle(), - command->GetEscapeAllowMakeVars()); - std::string comment = this->ConstructComment(*command); const char* flags = compileFlags.size() ? compileFlags.c_str(): 0; - this->WriteCustomRule(fout, source.c_str(), script.c_str(), - comment.c_str(), command->GetDepends(), - command->GetOutputs(), flags); + this->WriteCustomRule(fout, source.c_str(), *command, flags); } else if(compileFlags.size() || additionalDeps.length() || objectName.size() || excludedFromBuild) @@ -1228,12 +1209,11 @@ void cmLocalVisualStudio7Generator void cmLocalVisualStudio7Generator:: WriteCustomRule(std::ostream& fout, const char* source, - const char* command, - const char* comment, - const std::vector<std::string>& depends, - const std::vector<std::string>& outputs, + const cmCustomCommand& command, const char* compileFlags) { + std::string comment = this->ConstructComment(command); + // Write the rule for each configuration. std::vector<std::string>::iterator i; std::vector<std::string> *configs = @@ -1251,14 +1231,21 @@ WriteCustomRule(std::ostream& fout, << "\t\t\t\t\tAdditionalOptions=\"" << this->EscapeForXML(compileFlags) << "\"/>\n"; } + + std::string script = + this->ConstructScript(command.GetCommandLines(), + command.GetWorkingDirectory(), + i->c_str(), + command.GetEscapeOldStyle(), + command.GetEscapeAllowMakeVars()); fout << "\t\t\t\t\t<Tool\n" << "\t\t\t\t\tName=\"VCCustomBuildTool\"\n" << "\t\t\t\t\tDescription=\"" - << this->EscapeForXML(comment) << "\"\n" + << this->EscapeForXML(comment.c_str()) << "\"\n" << "\t\t\t\t\tCommandLine=\"" - << this->EscapeForXML(command) << "\"\n" + << this->EscapeForXML(script.c_str()) << "\"\n" << "\t\t\t\t\tAdditionalDependencies=\""; - if(depends.empty()) + if(command.GetDepends().empty()) { // There are no real dependencies. Produce an artificial one to // make sure the rule runs reliably. @@ -1272,8 +1259,10 @@ WriteCustomRule(std::ostream& fout, else { // Write out the dependencies for the rule. - for(std::vector<std::string>::const_iterator d = depends.begin(); - d != depends.end(); ++d) + for(std::vector<std::string>::const_iterator d = + command.GetDepends().begin(); + d != command.GetDepends().end(); + ++d) { // Get the real name of the dependency in case it is a CMake target. std::string dep = this->GetRealDependency(d->c_str(), i->c_str()); @@ -1283,7 +1272,7 @@ WriteCustomRule(std::ostream& fout, } fout << "\"\n"; fout << "\t\t\t\t\tOutputs=\""; - if(outputs.empty()) + if(command.GetOutputs().empty()) { fout << source << "_force"; } @@ -1291,8 +1280,9 @@ WriteCustomRule(std::ostream& fout, { // Write a rule for the output generated by this command. const char* sep = ""; - for(std::vector<std::string>::const_iterator o = outputs.begin(); - o != outputs.end(); ++o) + for(std::vector<std::string>::const_iterator o = command.GetOutputs().begin(); + o != command.GetOutputs().end(); + ++o) { fout << sep << this->ConvertToXMLOutputPathSingle(o->c_str()); sep = ";"; @@ -1323,6 +1313,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjEndGroup(std::ostream& fout) // look for custom rules on a target and collect them together void cmLocalVisualStudio7Generator ::OutputTargetRules(std::ostream& fout, + const char* configName, cmTarget &target, const char * /*libName*/) { @@ -1350,6 +1341,7 @@ void cmLocalVisualStudio7Generator std::string script = this->ConstructScript(cr->GetCommandLines(), cr->GetWorkingDirectory(), + configName, cr->GetEscapeOldStyle(), cr->GetEscapeAllowMakeVars()); fout << this->EscapeForXML(script.c_str()).c_str(); @@ -1379,6 +1371,7 @@ void cmLocalVisualStudio7Generator std::string script = this->ConstructScript(cr->GetCommandLines(), cr->GetWorkingDirectory(), + configName, cr->GetEscapeOldStyle(), cr->GetEscapeAllowMakeVars()); fout << this->EscapeForXML(script.c_str()).c_str(); @@ -1408,6 +1401,7 @@ void cmLocalVisualStudio7Generator std::string script = this->ConstructScript(cr->GetCommandLines(), cr->GetWorkingDirectory(), + configName, cr->GetEscapeOldStyle(), cr->GetEscapeAllowMakeVars()); fout << this->EscapeForXML(script.c_str()).c_str(); diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index b983799055..1863ff9c3f 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -89,8 +89,8 @@ private: std::string EscapeForXML(const char* s); std::string ConvertToXMLOutputPath(const char* path); std::string ConvertToXMLOutputPathSingle(const char* path); - void OutputTargetRules(std::ostream& fout, cmTarget &target, - const char *libName); + void OutputTargetRules(std::ostream& fout, const char* configName, + cmTarget &target, const char *libName); void OutputBuildTool(std::ostream& fout, const char* configName, cmTarget& t); void OutputLibraries(std::ostream& fout, @@ -104,12 +104,10 @@ private: const char* group, const char* filter); void WriteVCProjEndGroup(std::ostream& fout); + void WriteCustomRule(std::ostream& fout, const char* source, - const char* command, - const char* comment, - const std::vector<std::string>& depends, - const std::vector<std::string>& outputs, + const cmCustomCommand& command, const char* extraFlags); void WriteTargetVersionAttribute(std::ostream& fout, cmTarget& target); diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 8ca677e01e..1d494c2abf 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -111,6 +111,7 @@ std::string cmLocalVisualStudioGenerator ::ConstructScript(const cmCustomCommandLines& commandLines, const char* workingDirectory, + const char* configName, bool escapeOldStyle, bool escapeAllowMakeVars, const char* newline_text) @@ -152,13 +153,15 @@ cmLocalVisualStudioGenerator // Start with the command name. const cmCustomCommandLine& commandLine = *cl; + std::string commandName = this->GetRealLocation(commandLine[0].c_str(), + configName); if(!workingDirectory) { - script += this->Convert(commandLine[0].c_str(),START_OUTPUT,SHELL); + script += this->Convert(commandName.c_str(),START_OUTPUT,SHELL); } else { - script += this->Convert(commandLine[0].c_str(),NONE,SHELL); + script += this->Convert(commandName.c_str(),NONE,SHELL); } // Add the arguments. diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index 8259474491..db03f8dfd5 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -41,6 +41,7 @@ protected: /** Construct a script from the given list of command lines. */ std::string ConstructScript(const cmCustomCommandLines& commandLines, const char* workingDirectory, + const char* configName, bool escapeOldStyle, bool escapeAllowMakeVars, const char* newline = "\n"); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index c1a65d7e9f..4cc265f214 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -578,18 +578,6 @@ cmMakefile::AddCustomCommandToTarget(const char* target, ti->second.GetPostBuildCommands().push_back(cc); break; } - - // Add dependencies on commands CMake knows how to build. - for(cmCustomCommandLines::const_iterator cli = commandLines.begin(); - cli != commandLines.end(); ++cli) - { - std::string cacheCommand = *cli->begin(); - if(const char* knownTarget = - this->GetCacheManager()->GetCacheValue(cacheCommand.c_str())) - { - ti->second.AddUtility(knownTarget); - } - } } } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 85f3d6e0bf..9f99266733 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -408,6 +408,31 @@ void cmTarget::SetMakefile(cmMakefile* mf) } } + +void +cmTarget::checkForTargetsAsCommand(const std::vector<cmCustomCommand>& commands) +{ + for ( std::vector<cmCustomCommand>::const_iterator cli = commands.begin(); + cli != commands.end(); + ++cli ) + { + for ( cmCustomCommandLines::const_iterator cit=cli->GetCommandLines().begin(); + cit!=cli->GetCommandLines().end(); + ++cit ) + { + std::string command = *cit->begin(); + // see if we can find a target with this name + cmTarget* t = this->Makefile->GetLocalGenerator()-> + GetGlobalGenerator()->FindTarget ( 0, command.c_str() ); + if ( ( t ) && ( t->GetType() ==cmTarget::EXECUTABLE ) ) + { + this->AddUtility ( command.c_str() ); + } + } + } +} + + void cmTarget::TraceVSDependencies(std::string projFile, cmMakefile *makefile) { @@ -504,6 +529,11 @@ void cmTarget::TraceVSDependencies(std::string projFile, } } } + + checkForTargetsAsCommand(this->GetPreBuildCommands()); + checkForTargetsAsCommand(this->GetPreLinkCommands()); + checkForTargetsAsCommand(this->GetPostBuildCommands()); + while (!srcFilesToProcess.empty()) { // is this source the output of a custom command @@ -533,9 +563,28 @@ void cmTarget::TraceVSDependencies(std::string projFile, srcFilesQueued.insert(temp); } } + + // check if commands for this custom commands are names of targets and + // if that's the case add these targets as dependencies + std::vector<std::string> automaticTargetDepends; + for(cmCustomCommandLines::const_iterator it= + outsf->GetCustomCommand()->GetCommandLines().begin(); + it!=outsf->GetCustomCommand()->GetCommandLines().end(); + ++it) + { + const std::string& currentCommand = (*it)[0]; + // see if we can find a target with this name + cmTarget* t = this->Makefile->GetLocalGenerator()-> + GetGlobalGenerator()->FindTarget(0, currentCommand.c_str()); + if (( t) && (t->GetType()==cmTarget::EXECUTABLE)) + { + automaticTargetDepends.push_back(currentCommand); + } + } + outsf->GetCustomCommand()->AppendDepends(automaticTargetDepends); + // add its dependencies to the list to check - unsigned int i; - for (i = 0; i < outsf->GetCustomCommand()->GetDepends().size(); ++i) + for (unsigned int i = 0; i < outsf->GetCustomCommand()->GetDepends().size(); ++i) { const std::string& fullName = outsf->GetCustomCommand()->GetDepends()[i]; @@ -590,6 +639,7 @@ void cmTarget::TraceVSDependencies(std::string projFile, } } } + } // finished with this SF move to the next srcFilesToProcess.pop(); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 5cda102f55..215d879be9 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -55,7 +55,7 @@ public: void SetType(TargetType f, const char* name); ///! Set/Get the name of the target - const char* GetName() {return this->Name.c_str();} + const char* GetName() const {return this->Name.c_str();} ///! Set the cmMakefile that owns this target void SetMakefile(cmMakefile *mf); @@ -180,7 +180,7 @@ public: /** * Trace through the source files in this target and add al source files - * that they depend on, used by the visual studio generators + * that they depend on, used by all generators */ void TraceVSDependencies(std::string projName, cmMakefile *mf); @@ -291,6 +291,13 @@ private: const LibraryID& lib, const LibraryID& dep); + /* + * Checks the prebuild, prelink and postbuild custom commands for known + * targets and adds them to the dependencies. + */ + void checkForTargetsAsCommand(const std::vector<cmCustomCommand>& commands); + + /** * Emits the library \a lib and all its dependencies into link_line. * \a emitted keeps track of the libraries that have been emitted to |