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
This commit is contained in:
Alexander Neundorf 2007-05-09 08:25:45 -04:00
parent 5af3105021
commit 7f11536704
28 changed files with 400 additions and 205 deletions

View File

@ -69,8 +69,8 @@ public:
void SetEscapeAllowMakeVars(bool b); void SetEscapeAllowMakeVars(bool b);
/** set get the used status of the command */ /** set get the used status of the command */
void SetUsed() { this->Used = true;}; void SetUsed() { this->Used = true;}
bool IsUsed() { return this->Used;}; bool IsUsed() const { return this->Used;}
private: private:
std::vector<std::string> Outputs; std::vector<std::string> Outputs;

View File

@ -718,6 +718,13 @@ void cmGlobalGenerator::Configure()
// at this point this->LocalGenerators has been filled, // at this point this->LocalGenerators has been filled,
// so create the map from project name to vector of local generators // so create the map from project name to vector of local generators
this->FillProjectMap(); 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() ) if ( !this->CMakeInstance->GetScriptMode() )
{ {
this->CMakeInstance->UpdateProgress("Configuring done", -1); this->CMakeInstance->UpdateProgress("Configuring done", -1);
@ -1036,6 +1043,13 @@ const char* cmGlobalGenerator::GetLinkerPreference(const char* lang)
return "None"; return "None";
} }
void cmGlobalGenerator::TraceDependencies()
{
for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
{
this->LocalGenerators[i]->TraceDependencies();
}
}
void cmGlobalGenerator::FillProjectMap() void cmGlobalGenerator::FillProjectMap()
{ {
@ -1057,10 +1071,6 @@ void cmGlobalGenerator::FillProjectMap()
} }
while (lg); 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();
} }

View File

@ -202,6 +202,8 @@ protected:
void FillProjectMap(); void FillProjectMap();
bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen); bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen);
void FillProjectToTargetMap(); void FillProjectToTargetMap();
// Calls TraceVSDependencies() on all targets
void TraceDependencies();
void CreateDefaultGlobalTargets(cmTargets* targets); void CreateDefaultGlobalTargets(cmTargets* targets);
cmTarget CreateGlobalTarget(const char* name, const char* message, cmTarget CreateGlobalTarget(const char* name, const char* message,
const cmCustomCommandLines* commandLines, const cmCustomCommandLines* commandLines,

View File

@ -208,9 +208,8 @@ void cmGlobalVisualStudio6Generator
static_cast<cmLocalVisualStudio6Generator *>(generators[i]) static_cast<cmLocalVisualStudio6Generator *>(generators[i])
->GetCreatedProjectNames(); ->GetCreatedProjectNames();
cmTargets &tgts = generators[i]->GetMakefile()->GetTargets(); cmTargets &tgts = generators[i]->GetMakefile()->GetTargets();
cmTargets::iterator l = tgts.begin(); std::vector<std::string>::iterator si = dspnames.begin();
for(std::vector<std::string>::iterator si = dspnames.begin(); for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
l != tgts.end(); ++l)
{ {
// special handling for the current makefile // special handling for the current makefile
if(mf == generators[0]->GetMakefile()) if(mf == generators[0]->GetMakefile())

View File

@ -294,8 +294,7 @@ void cmGlobalVisualStudio7Generator
// than one dsp could have been created per input CMakeLists.txt file // than one dsp could have been created per input CMakeLists.txt file
// for each target // for each target
cmTargets &tgts = generators[i]->GetMakefile()->GetTargets(); cmTargets &tgts = generators[i]->GetMakefile()->GetTargets();
cmTargets::iterator l = tgts.begin(); for (cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
for(; l != tgts.end(); ++l)
{ {
// special handling for the current makefile // special handling for the current makefile
if(mf == generators[0]->GetMakefile()) if(mf == generators[0]->GetMakefile())

View File

@ -577,16 +577,17 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
{ {
continue; continue;
} }
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 || if(cmtarget.GetType() == cmTarget::UTILITY ||
cmtarget.GetType() == cmTarget::GLOBAL_TARGET) cmtarget.GetType() == cmTarget::GLOBAL_TARGET)
{ {
targets.push_back(this->CreateUtilityTarget(cmtarget)); 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)
{
continue; continue;
} }
@ -849,6 +850,7 @@ std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
} }
return retFlag; return retFlag;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
@ -872,7 +874,30 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
return; return;
} }
// collect multiple outputs of custom commands into a set
// which will be used for every configuration
std::map<cmStdString, cmStdString> multipleOutputPairs; 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(); std::string dir = this->CurrentMakefile->GetCurrentOutputDirectory();
dir += "/CMakeScripts"; dir += "/CMakeScripts";
@ -883,7 +908,48 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
makefile += "_"; makefile += "_";
makefile += name; makefile += name;
makefile += ".make"; 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) if(!makefileStream)
{ {
return; return;
@ -939,21 +1005,9 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
const std::vector<std::string>& outputs = cc.GetOutputs(); const std::vector<std::string>& outputs = cc.GetOutputs();
if(!outputs.empty()) if(!outputs.empty())
{ {
// There is at least one output. If there is more than one treat the // There is at least one output, start the rule for it
// first as the primary output and make the rest depend on it.
std::vector<std::string>::const_iterator o = outputs.begin();
std::string primary_output = std::string primary_output =
this->ConvertToRelativeForMake(o->c_str()); this->ConvertToRelativeForMake(outputs.begin()->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.
makefileStream << primary_output << ": "; makefileStream << primary_output << ": ";
} }
else else
@ -994,7 +1048,9 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
{ {
// Build the command line in a single string. // Build the command line in a single string.
const cmCustomCommandLine& commandLine = *cl; const cmCustomCommandLine& commandLine = *cl;
std::string cmd2 = commandLine[0]; std::string cmd2 = this->CurrentLocalGenerator
->GetRealLocation(commandLine[0].c_str(), configName);
cmSystemTools::ReplaceString(cmd2, "/./", "/"); cmSystemTools::ReplaceString(cmd2, "/./", "/");
cmd2 = this->ConvertToRelativeForMake(cmd2.c_str()); cmd2 = this->ConvertToRelativeForMake(cmd2.c_str());
std::string cmd; std::string cmd;
@ -1025,9 +1081,18 @@ 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()) 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 << makefileStream <<
"\n" "\n"
"cmake_check_multiple_outputs:\n"; "cmake_check_multiple_outputs:\n";
@ -1039,24 +1104,8 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
<< o->second << "; fi\n"; << 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, void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
cmXCodeObject* buildSettings, cmXCodeObject* buildSettings,
@ -2406,20 +2455,6 @@ cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator* root,
cmMakefile* mf = (*g)->GetMakefile(); cmMakefile* mf = (*g)->GetMakefile();
std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups(); std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups();
cmTargets &tgts = mf->GetTargets(); 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 // now for all custom commands that are not used directly in a
// target, add them to all targets in the current directory or // target, add them to all targets in the current directory or
// makefile // makefile

View File

@ -106,6 +106,15 @@ private:
std::vector<cmCustomCommand> std::vector<cmCustomCommand>
const & commands, const & commands,
const char* commandFileName); 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*); cmXCodeObject* FindXCodeTarget(cmTarget*);
// create cmXCodeObject from these functions so that memory can be managed // create cmXCodeObject from these functions so that memory can be managed
// correctly. All objects created are stored in this->XCodeObjects. // correctly. All objects created are stored in this->XCodeObjects.

View File

@ -52,6 +52,7 @@ cmLocalGenerator::cmLocalGenerator()
this->UseRelativePaths = false; this->UseRelativePaths = false;
this->Configured = false; this->Configured = false;
this->EmitUniversalBinaryFlags = true; this->EmitUniversalBinaryFlags = true;
this->IsMakefileGenerator = false;
this->RelativePathsConfigured = false; this->RelativePathsConfigured = false;
this->PathConversionsSetup = false; this->PathConversionsSetup = false;
} }
@ -135,6 +136,30 @@ void cmLocalGenerator::ConfigureFinalPass()
this->Makefile->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() void cmLocalGenerator::GenerateTestFiles()
{ {
if ( !this->Makefile->IsOn("CMAKE_TESTING_ENABLED") ) if ( !this->Makefile->IsOn("CMAKE_TESTING_ENABLED") )
@ -1986,6 +2011,20 @@ std::string cmLocalGenerator::GetRealDependency(const char* inName,
return name; return name;
} }
//----------------------------------------------------------------------------
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, void cmLocalGenerator::AddSharedFlags(std::string& flags,
const char* lang, const char* lang,

View File

@ -42,7 +42,7 @@ public:
/** /**
* Generate the makefile for this directory. * Generate the makefile for this directory.
*/ */
virtual void Generate() {}; virtual void Generate() {}
/** /**
* Process the CMakeLists files for this directory to fill in the * Process the CMakeLists files for this directory to fill in the
@ -50,6 +50,11 @@ public:
*/ */
virtual void Configure(); virtual void Configure();
/**
* Calls TraceVSDependencies() on all targets of this generator.
*/
virtual void TraceDependencies();
/** /**
* Perform any final calculations prior to generation * Perform any final calculations prior to generation
*/ */
@ -138,6 +143,11 @@ public:
used for dependencies of custom commands. */ used for dependencies of custom commands. */
std::string GetRealDependency(const char* name, const char* config); 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 ///! for existing files convert to output path and short path if spaces
std::string ConvertToOutputForExisting(const char* p); std::string ConvertToOutputForExisting(const char* p);
@ -298,6 +308,8 @@ protected:
bool IgnoreLibPrefix; bool IgnoreLibPrefix;
bool Configured; bool Configured;
bool EmitUniversalBinaryFlags; bool EmitUniversalBinaryFlags;
// A type flag is not nice. It's used only in TraceDependencies().
bool IsMakefileGenerator;
// Hack for ExpandRuleVariable until object-oriented version is // Hack for ExpandRuleVariable until object-oriented version is
// committed. // committed.
std::string TargetImplib; std::string TargetImplib;

View File

@ -54,6 +54,7 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3()
this->NativeEchoCommand = "@echo "; this->NativeEchoCommand = "@echo ";
this->NativeEchoWindows = true; this->NativeEchoWindows = true;
this->MakeCommandEscapeTargetTwice = false; this->MakeCommandEscapeTargetTwice = false;
this->IsMakefileGenerator = true;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -112,7 +113,7 @@ void cmLocalUnixMakefileGenerator3::Generate()
if (tg) if (tg)
{ {
this->TargetGenerators.push_back(tg); this->TargetGenerators.push_back(tg);
t->second.TraceVSDependencies(empty, this->Makefile); // t->second.TraceVSDependencies(empty, this->Makefile);
tg->WriteRuleFiles(); tg->WriteRuleFiles();
} }
} }
@ -885,7 +886,8 @@ cmLocalUnixMakefileGenerator3
{ {
// Build the command line in a single string. // Build the command line in a single string.
const cmCustomCommandLine& commandLine = *cl; const cmCustomCommandLine& commandLine = *cl;
std::string cmd = commandLine[0]; std::string cmd = GetRealLocation(commandLine[0].c_str(),
this->ConfigurationName.c_str());
if (cmd.size()) if (cmd.size())
{ {
cmSystemTools::ReplaceString(cmd, "/./", "/"); cmSystemTools::ReplaceString(cmd, "/./", "/");

View File

@ -116,16 +116,6 @@ void cmLocalVisualStudio6Generator::OutputDSPFile()
{ {
this->AddDSPBuildRule(l->second); 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 // build any targets
@ -490,23 +480,8 @@ void cmLocalVisualStudio6Generator
} }
if (command) 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; const char* flags = compileFlags.size() ? compileFlags.c_str(): 0;
this->WriteCustomRule(fout, source.c_str(), script.c_str(), this->WriteCustomRule(fout, source.c_str(), *command, flags);
comment.c_str(), command->GetDepends(),
command->GetOutputs(), flags);
} }
else if(!compileFlags.empty() || !objectNameDir.empty()) else if(!compileFlags.empty() || !objectNameDir.empty())
{ {
@ -603,16 +578,29 @@ void
cmLocalVisualStudio6Generator cmLocalVisualStudio6Generator
::WriteCustomRule(std::ostream& fout, ::WriteCustomRule(std::ostream& fout,
const char* source, const char* source,
const char* command, const cmCustomCommand& command,
const char* comment,
const std::vector<std::string>& depends,
const std::vector<std::string>& outputs,
const char* flags) const char* flags)
{ {
std::string comment =
this->ConstructComment(command, "Building Custom Rule $(InputPath)");
if(comment == "<hack>")
{
comment = "";
}
// Write the rule for each configuration. // Write the rule for each configuration.
std::vector<std::string>::iterator i; std::vector<std::string>::iterator i;
for(i = this->Configurations.begin(); i != this->Configurations.end(); ++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()) if (i == this->Configurations.begin())
{ {
fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl; fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl;
@ -627,8 +615,9 @@ cmLocalVisualStudio6Generator
} }
// Write out the dependencies for the rule. // Write out the dependencies for the rule.
fout << "USERDEP__HACK="; fout << "USERDEP__HACK=";
for(std::vector<std::string>::const_iterator d = depends.begin(); for(std::vector<std::string>::const_iterator d=command.GetDepends().begin();
d != depends.end(); ++d) d != command.GetDepends().end();
++d)
{ {
// Lookup the real name of the dependency in case it is a CMake target. // 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()); std::string dep = this->GetRealDependency(d->c_str(), i->c_str());
@ -639,26 +628,28 @@ cmLocalVisualStudio6Generator
fout << "# PROP Ignore_Default_Tool 1\n"; fout << "# PROP Ignore_Default_Tool 1\n";
fout << "# Begin Custom Build -"; fout << "# Begin Custom Build -";
if(comment && *comment) if(!comment.empty())
{ {
fout << " " << comment; fout << " " << comment.c_str();
} }
fout << "\n\n"; fout << "\n\n";
if(outputs.empty()) if(command.GetOutputs().empty())
{ {
fout << source fout << source
<< "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t"; << "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
fout << command << "\n\n"; fout << script.c_str() << "\n\n";
} }
else else
{ {
for(std::vector<std::string>::const_iterator o = outputs.begin(); for(std::vector<std::string>::const_iterator o =
o != outputs.end(); ++o) command.GetOutputs().begin();
o != command.GetOutputs().end();
++o)
{ {
// Write a rule for every output generated by this command. // Write a rule for every output generated by this command.
fout << this->ConvertToOptionallyRelativeOutputPath(o->c_str()) fout << this->ConvertToOptionallyRelativeOutputPath(o->c_str())
<< " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t"; << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
fout << command << "\n\n"; fout << script.c_str() << "\n\n";
} }
} }
fout << "# End Custom Build\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 // look for custom rules on a target and collect them together
std::string std::string
cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target, cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target,
const char* configName,
const char * /* libName */) const char * /* libName */)
{ {
std::string customRuleCode = ""; std::string customRuleCode = "";
@ -808,6 +800,7 @@ cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target,
} }
customRuleCode += this->ConstructScript(cr->GetCommandLines(), customRuleCode += this->ConstructScript(cr->GetCommandLines(),
cr->GetWorkingDirectory(), cr->GetWorkingDirectory(),
configName,
cr->GetEscapeOldStyle(), cr->GetEscapeOldStyle(),
cr->GetEscapeAllowMakeVars(), cr->GetEscapeAllowMakeVars(),
"\\\n\t"); "\\\n\t");
@ -822,6 +815,7 @@ cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target,
} }
customRuleCode += this->ConstructScript(cr->GetCommandLines(), customRuleCode += this->ConstructScript(cr->GetCommandLines(),
cr->GetWorkingDirectory(), cr->GetWorkingDirectory(),
configName,
cr->GetEscapeOldStyle(), cr->GetEscapeOldStyle(),
cr->GetEscapeAllowMakeVars(), cr->GetEscapeAllowMakeVars(),
"\\\n\t"); "\\\n\t");
@ -850,6 +844,7 @@ cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target,
} }
customRuleCode += this->ConstructScript(cr->GetCommandLines(), customRuleCode += this->ConstructScript(cr->GetCommandLines(),
cr->GetWorkingDirectory(), cr->GetWorkingDirectory(),
configName,
cr->GetEscapeOldStyle(), cr->GetEscapeOldStyle(),
cr->GetEscapeAllowMakeVars(), cr->GetEscapeAllowMakeVars(),
"\\\n\t"); "\\\n\t");
@ -1274,7 +1269,14 @@ void cmLocalVisualStudio6Generator
// are there any custom rules on the target itself // are there any custom rules on the target itself
// only if the target is a lib or exe // 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()); std::ifstream fin(this->DSPHeaderTemplate.c_str());
if(!fin) if(!fin)
@ -1307,8 +1309,6 @@ void cmLocalVisualStudio6Generator
} }
cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS", cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS",
exportSymbol.c_str()); exportSymbol.c_str());
cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE",
customRuleCode.c_str());
cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG", cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG",
mfcFlag); mfcFlag);
if(target.GetType() == cmTarget::STATIC_LIBRARY ) if(target.GetType() == cmTarget::STATIC_LIBRARY )
@ -1338,6 +1338,18 @@ void cmLocalVisualStudio6Generator
libMultiLineOptimizedOptions.c_str()); libMultiLineOptimizedOptions.c_str());
#endif #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. // Substitute the real output name into the template.
cmSystemTools::ReplaceString(line, "OUTPUT_NAME_DEBUG", cmSystemTools::ReplaceString(line, "OUTPUT_NAME_DEBUG",
outputNameDebug.c_str()); outputNameDebug.c_str());

View File

@ -84,10 +84,7 @@ private:
void AddDSPBuildRule(cmTarget& tgt); void AddDSPBuildRule(cmTarget& tgt);
void WriteCustomRule(std::ostream& fout, void WriteCustomRule(std::ostream& fout,
const char* source, const char* source,
const char* command, const cmCustomCommand& command,
const char* comment,
const std::vector<std::string>& depends,
const std::vector<std::string>& outputs,
const char* flags); const char* flags);
void AddUtilityCommandHack(cmTarget& target, int count, void AddUtilityCommandHack(cmTarget& target, int count,
std::vector<std::string>& depends, std::vector<std::string>& depends,
@ -95,6 +92,7 @@ private:
void WriteGroup(const cmSourceGroup *sg, cmTarget target, void WriteGroup(const cmSourceGroup *sg, cmTarget target,
std::ostream &fout, const char *libName); std::ostream &fout, const char *libName);
std::string CreateTargetRules(cmTarget &target, std::string CreateTargetRules(cmTarget &target,
const char* configName,
const char *libName); const char *libName);
void ComputeLinkOptions(cmTarget& target, const char* configName, void ComputeLinkOptions(cmTarget& target, const char* configName,
const std::string extraOptions, const std::string extraOptions,

View File

@ -124,16 +124,6 @@ void cmLocalVisualStudio7Generator::OutputVCProjFile()
{ {
this->AddVCProjBuildRule(l->second); 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(); for(cmTargets::iterator l = tgts.begin();
@ -623,7 +613,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
<< "\t\t\t/>\n"; << "\t\t\t/>\n";
} }
this->OutputTargetRules(fout, target, libName); this->OutputTargetRules(fout, configName, target, libName);
this->OutputBuildTool(fout, configName, target); this->OutputBuildTool(fout, configName, target);
fout << "\t\t</Configuration>\n"; fout << "\t\t</Configuration>\n";
} }
@ -1141,17 +1131,8 @@ void cmLocalVisualStudio7Generator
fout << "\t\t\t\tRelativePath=\"" << d << "\">\n"; fout << "\t\t\t\tRelativePath=\"" << d << "\">\n";
if (command) 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; const char* flags = compileFlags.size() ? compileFlags.c_str(): 0;
this->WriteCustomRule(fout, source.c_str(), script.c_str(), this->WriteCustomRule(fout, source.c_str(), *command, flags);
comment.c_str(), command->GetDepends(),
command->GetOutputs(), flags);
} }
else if(compileFlags.size() || additionalDeps.length() else if(compileFlags.size() || additionalDeps.length()
|| objectName.size() || excludedFromBuild) || objectName.size() || excludedFromBuild)
@ -1228,12 +1209,11 @@ void cmLocalVisualStudio7Generator
void cmLocalVisualStudio7Generator:: void cmLocalVisualStudio7Generator::
WriteCustomRule(std::ostream& fout, WriteCustomRule(std::ostream& fout,
const char* source, const char* source,
const char* command, const cmCustomCommand& command,
const char* comment,
const std::vector<std::string>& depends,
const std::vector<std::string>& outputs,
const char* compileFlags) const char* compileFlags)
{ {
std::string comment = this->ConstructComment(command);
// Write the rule for each configuration. // Write the rule for each configuration.
std::vector<std::string>::iterator i; std::vector<std::string>::iterator i;
std::vector<std::string> *configs = std::vector<std::string> *configs =
@ -1251,14 +1231,21 @@ WriteCustomRule(std::ostream& fout,
<< "\t\t\t\t\tAdditionalOptions=\"" << "\t\t\t\t\tAdditionalOptions=\""
<< this->EscapeForXML(compileFlags) << "\"/>\n"; << 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" fout << "\t\t\t\t\t<Tool\n"
<< "\t\t\t\t\tName=\"VCCustomBuildTool\"\n" << "\t\t\t\t\tName=\"VCCustomBuildTool\"\n"
<< "\t\t\t\t\tDescription=\"" << "\t\t\t\t\tDescription=\""
<< this->EscapeForXML(comment) << "\"\n" << this->EscapeForXML(comment.c_str()) << "\"\n"
<< "\t\t\t\t\tCommandLine=\"" << "\t\t\t\t\tCommandLine=\""
<< this->EscapeForXML(command) << "\"\n" << this->EscapeForXML(script.c_str()) << "\"\n"
<< "\t\t\t\t\tAdditionalDependencies=\""; << "\t\t\t\t\tAdditionalDependencies=\"";
if(depends.empty()) if(command.GetDepends().empty())
{ {
// There are no real dependencies. Produce an artificial one to // There are no real dependencies. Produce an artificial one to
// make sure the rule runs reliably. // make sure the rule runs reliably.
@ -1272,8 +1259,10 @@ WriteCustomRule(std::ostream& fout,
else else
{ {
// Write out the dependencies for the rule. // Write out the dependencies for the rule.
for(std::vector<std::string>::const_iterator d = depends.begin(); for(std::vector<std::string>::const_iterator d =
d != depends.end(); ++d) command.GetDepends().begin();
d != command.GetDepends().end();
++d)
{ {
// Get the real name of the dependency in case it is a CMake target. // 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()); std::string dep = this->GetRealDependency(d->c_str(), i->c_str());
@ -1283,7 +1272,7 @@ WriteCustomRule(std::ostream& fout,
} }
fout << "\"\n"; fout << "\"\n";
fout << "\t\t\t\t\tOutputs=\""; fout << "\t\t\t\t\tOutputs=\"";
if(outputs.empty()) if(command.GetOutputs().empty())
{ {
fout << source << "_force"; fout << source << "_force";
} }
@ -1291,8 +1280,9 @@ WriteCustomRule(std::ostream& fout,
{ {
// Write a rule for the output generated by this command. // Write a rule for the output generated by this command.
const char* sep = ""; const char* sep = "";
for(std::vector<std::string>::const_iterator o = outputs.begin(); for(std::vector<std::string>::const_iterator o = command.GetOutputs().begin();
o != outputs.end(); ++o) o != command.GetOutputs().end();
++o)
{ {
fout << sep << this->ConvertToXMLOutputPathSingle(o->c_str()); fout << sep << this->ConvertToXMLOutputPathSingle(o->c_str());
sep = ";"; sep = ";";
@ -1323,6 +1313,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjEndGroup(std::ostream& fout)
// look for custom rules on a target and collect them together // look for custom rules on a target and collect them together
void cmLocalVisualStudio7Generator void cmLocalVisualStudio7Generator
::OutputTargetRules(std::ostream& fout, ::OutputTargetRules(std::ostream& fout,
const char* configName,
cmTarget &target, cmTarget &target,
const char * /*libName*/) const char * /*libName*/)
{ {
@ -1350,6 +1341,7 @@ void cmLocalVisualStudio7Generator
std::string script = std::string script =
this->ConstructScript(cr->GetCommandLines(), this->ConstructScript(cr->GetCommandLines(),
cr->GetWorkingDirectory(), cr->GetWorkingDirectory(),
configName,
cr->GetEscapeOldStyle(), cr->GetEscapeOldStyle(),
cr->GetEscapeAllowMakeVars()); cr->GetEscapeAllowMakeVars());
fout << this->EscapeForXML(script.c_str()).c_str(); fout << this->EscapeForXML(script.c_str()).c_str();
@ -1379,6 +1371,7 @@ void cmLocalVisualStudio7Generator
std::string script = std::string script =
this->ConstructScript(cr->GetCommandLines(), this->ConstructScript(cr->GetCommandLines(),
cr->GetWorkingDirectory(), cr->GetWorkingDirectory(),
configName,
cr->GetEscapeOldStyle(), cr->GetEscapeOldStyle(),
cr->GetEscapeAllowMakeVars()); cr->GetEscapeAllowMakeVars());
fout << this->EscapeForXML(script.c_str()).c_str(); fout << this->EscapeForXML(script.c_str()).c_str();
@ -1408,6 +1401,7 @@ void cmLocalVisualStudio7Generator
std::string script = std::string script =
this->ConstructScript(cr->GetCommandLines(), this->ConstructScript(cr->GetCommandLines(),
cr->GetWorkingDirectory(), cr->GetWorkingDirectory(),
configName,
cr->GetEscapeOldStyle(), cr->GetEscapeOldStyle(),
cr->GetEscapeAllowMakeVars()); cr->GetEscapeAllowMakeVars());
fout << this->EscapeForXML(script.c_str()).c_str(); fout << this->EscapeForXML(script.c_str()).c_str();

View File

@ -89,8 +89,8 @@ private:
std::string EscapeForXML(const char* s); std::string EscapeForXML(const char* s);
std::string ConvertToXMLOutputPath(const char* path); std::string ConvertToXMLOutputPath(const char* path);
std::string ConvertToXMLOutputPathSingle(const char* path); std::string ConvertToXMLOutputPathSingle(const char* path);
void OutputTargetRules(std::ostream& fout, cmTarget &target, void OutputTargetRules(std::ostream& fout, const char* configName,
const char *libName); cmTarget &target, const char *libName);
void OutputBuildTool(std::ostream& fout, const char* configName, void OutputBuildTool(std::ostream& fout, const char* configName,
cmTarget& t); cmTarget& t);
void OutputLibraries(std::ostream& fout, void OutputLibraries(std::ostream& fout,
@ -104,12 +104,10 @@ private:
const char* group, const char* group,
const char* filter); const char* filter);
void WriteVCProjEndGroup(std::ostream& fout); void WriteVCProjEndGroup(std::ostream& fout);
void WriteCustomRule(std::ostream& fout, void WriteCustomRule(std::ostream& fout,
const char* source, const char* source,
const char* command, const cmCustomCommand& command,
const char* comment,
const std::vector<std::string>& depends,
const std::vector<std::string>& outputs,
const char* extraFlags); const char* extraFlags);
void WriteTargetVersionAttribute(std::ostream& fout, cmTarget& target); void WriteTargetVersionAttribute(std::ostream& fout, cmTarget& target);

View File

@ -111,6 +111,7 @@ std::string
cmLocalVisualStudioGenerator cmLocalVisualStudioGenerator
::ConstructScript(const cmCustomCommandLines& commandLines, ::ConstructScript(const cmCustomCommandLines& commandLines,
const char* workingDirectory, const char* workingDirectory,
const char* configName,
bool escapeOldStyle, bool escapeOldStyle,
bool escapeAllowMakeVars, bool escapeAllowMakeVars,
const char* newline_text) const char* newline_text)
@ -152,13 +153,15 @@ cmLocalVisualStudioGenerator
// Start with the command name. // Start with the command name.
const cmCustomCommandLine& commandLine = *cl; const cmCustomCommandLine& commandLine = *cl;
std::string commandName = this->GetRealLocation(commandLine[0].c_str(),
configName);
if(!workingDirectory) if(!workingDirectory)
{ {
script += this->Convert(commandLine[0].c_str(),START_OUTPUT,SHELL); script += this->Convert(commandName.c_str(),START_OUTPUT,SHELL);
} }
else else
{ {
script += this->Convert(commandLine[0].c_str(),NONE,SHELL); script += this->Convert(commandName.c_str(),NONE,SHELL);
} }
// Add the arguments. // Add the arguments.

View File

@ -41,6 +41,7 @@ protected:
/** Construct a script from the given list of command lines. */ /** Construct a script from the given list of command lines. */
std::string ConstructScript(const cmCustomCommandLines& commandLines, std::string ConstructScript(const cmCustomCommandLines& commandLines,
const char* workingDirectory, const char* workingDirectory,
const char* configName,
bool escapeOldStyle, bool escapeOldStyle,
bool escapeAllowMakeVars, bool escapeAllowMakeVars,
const char* newline = "\n"); const char* newline = "\n");

View File

@ -578,18 +578,6 @@ cmMakefile::AddCustomCommandToTarget(const char* target,
ti->second.GetPostBuildCommands().push_back(cc); ti->second.GetPostBuildCommands().push_back(cc);
break; 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);
}
}
} }
} }

View File

@ -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, void cmTarget::TraceVSDependencies(std::string projFile,
cmMakefile *makefile) cmMakefile *makefile)
{ {
@ -504,6 +529,11 @@ void cmTarget::TraceVSDependencies(std::string projFile,
} }
} }
} }
checkForTargetsAsCommand(this->GetPreBuildCommands());
checkForTargetsAsCommand(this->GetPreLinkCommands());
checkForTargetsAsCommand(this->GetPostBuildCommands());
while (!srcFilesToProcess.empty()) while (!srcFilesToProcess.empty())
{ {
// is this source the output of a custom command // is this source the output of a custom command
@ -533,9 +563,28 @@ void cmTarget::TraceVSDependencies(std::string projFile,
srcFilesQueued.insert(temp); 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 // add its dependencies to the list to check
unsigned int i; for (unsigned int i = 0; i < outsf->GetCustomCommand()->GetDepends().size(); ++i)
for (i = 0; i < outsf->GetCustomCommand()->GetDepends().size(); ++i)
{ {
const std::string& fullName const std::string& fullName
= outsf->GetCustomCommand()->GetDepends()[i]; = outsf->GetCustomCommand()->GetDepends()[i];
@ -590,6 +639,7 @@ void cmTarget::TraceVSDependencies(std::string projFile,
} }
} }
} }
} }
// finished with this SF move to the next // finished with this SF move to the next
srcFilesToProcess.pop(); srcFilesToProcess.pop();

View File

@ -55,7 +55,7 @@ public:
void SetType(TargetType f, const char* name); void SetType(TargetType f, const char* name);
///! Set/Get the name of the target ///! 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 ///! Set the cmMakefile that owns this target
void SetMakefile(cmMakefile *mf); void SetMakefile(cmMakefile *mf);
@ -180,7 +180,7 @@ public:
/** /**
* Trace through the source files in this target and add al source files * 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); void TraceVSDependencies(std::string projName, cmMakefile *mf);
@ -291,6 +291,13 @@ private:
const LibraryID& lib, const LibraryID& lib,
const LibraryID& dep); 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. * Emits the library \a lib and all its dependencies into link_line.
* \a emitted keeps track of the libraries that have been emitted to * \a emitted keeps track of the libraries that have been emitted to

View File

@ -74,7 +74,7 @@ LINK32=link.exe
# ADD LINK32 /nologo /dll TARGET_VERSION_FLAG /machine:I386 /out:"OUTPUT_DIRECTORY\Release/OUTPUT_NAME_RELEASE" TARGET_IMPLIB_FLAG_RELEASE # ADD LINK32 /nologo /dll TARGET_VERSION_FLAG /machine:I386 /out:"OUTPUT_DIRECTORY\Release/OUTPUT_NAME_RELEASE" TARGET_IMPLIB_FLAG_RELEASE
CM_MULTILINE_OPTIONS_RELEASE CM_MULTILINE_OPTIONS_RELEASE
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_RELEASE
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug"
@ -106,7 +106,7 @@ LINK32=link.exe
# ADD LINK32 /nologo /dll TARGET_VERSION_FLAG /debug /machine:I386 /out:"OUTPUT_DIRECTORY\Debug/OUTPUT_NAME_DEBUG" /pdbtype:sept TARGET_IMPLIB_FLAG_DEBUG # ADD LINK32 /nologo /dll TARGET_VERSION_FLAG /debug /machine:I386 /out:"OUTPUT_DIRECTORY\Debug/OUTPUT_NAME_DEBUG" /pdbtype:sept TARGET_IMPLIB_FLAG_DEBUG
CM_MULTILINE_OPTIONS_DEBUG CM_MULTILINE_OPTIONS_DEBUG
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_DEBUG
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel"
@ -140,7 +140,7 @@ LINK32=link.exe
# ADD LINK32 /nologo /dll TARGET_VERSION_FLAG /machine:I386 /out:"OUTPUT_DIRECTORY\MinSizeRel/OUTPUT_NAME_MINSIZEREL" TARGET_IMPLIB_FLAG_MINSIZEREL # ADD LINK32 /nologo /dll TARGET_VERSION_FLAG /machine:I386 /out:"OUTPUT_DIRECTORY\MinSizeRel/OUTPUT_NAME_MINSIZEREL" TARGET_IMPLIB_FLAG_MINSIZEREL
CM_MULTILINE_OPTIONS_MINSIZEREL CM_MULTILINE_OPTIONS_MINSIZEREL
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_MINSIZEREL
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo"
@ -172,7 +172,7 @@ LINK32=link.exe
# ADD LINK32 /nologo /dll TARGET_VERSION_FLAG /debug /machine:I386 /pdbtype:sept /out:"OUTPUT_DIRECTORY\RelWithDebInfo/OUTPUT_NAME_RELWITHDEBINFO" TARGET_IMPLIB_FLAG_RELWITHDEBINFO # ADD LINK32 /nologo /dll TARGET_VERSION_FLAG /debug /machine:I386 /pdbtype:sept /out:"OUTPUT_DIRECTORY\RelWithDebInfo/OUTPUT_NAME_RELWITHDEBINFO" TARGET_IMPLIB_FLAG_RELWITHDEBINFO
CM_MULTILINE_OPTIONS_RELWITHDEBINFO CM_MULTILINE_OPTIONS_RELWITHDEBINFO
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO
!ENDIF !ENDIF

View File

@ -72,7 +72,7 @@ LINK32=link.exe
# ADD LINK32 /out:"OUTPUT_DIRECTORY\Release\OUTPUT_NAME_RELEASE" TARGET_IMPLIB_FLAG_RELEASE # ADD LINK32 /out:"OUTPUT_DIRECTORY\Release\OUTPUT_NAME_RELEASE" TARGET_IMPLIB_FLAG_RELEASE
CM_MULTILINE_OPTIONS_RELEASE CM_MULTILINE_OPTIONS_RELEASE
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_RELEASE
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug"
@ -104,7 +104,7 @@ LINK32=link.exe
# ADD LINK32 /out:"OUTPUT_DIRECTORY\Debug\OUTPUT_NAME_DEBUG" TARGET_IMPLIB_FLAG_DEBUG # ADD LINK32 /out:"OUTPUT_DIRECTORY\Debug\OUTPUT_NAME_DEBUG" TARGET_IMPLIB_FLAG_DEBUG
CM_MULTILINE_OPTIONS_DEBUG CM_MULTILINE_OPTIONS_DEBUG
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_DEBUG
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel"
# PROP BASE Use_MFC CMAKE_MFC_FLAG # PROP BASE Use_MFC CMAKE_MFC_FLAG
@ -133,7 +133,7 @@ LINK32=link.exe
# ADD LINK32 /out:"OUTPUT_DIRECTORY\MinSizeRel\OUTPUT_NAME_MINSIZEREL" TARGET_IMPLIB_FLAG_MINSIZEREL # ADD LINK32 /out:"OUTPUT_DIRECTORY\MinSizeRel\OUTPUT_NAME_MINSIZEREL" TARGET_IMPLIB_FLAG_MINSIZEREL
CM_MULTILINE_OPTIONS_MINSIZEREL CM_MULTILINE_OPTIONS_MINSIZEREL
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_MINSIZEREL
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo"
@ -163,7 +163,7 @@ LINK32=link.exe
# ADD LINK32 /out:"OUTPUT_DIRECTORY\RelWithDebInfo\OUTPUT_NAME_RELWITHDEBINFO" TARGET_IMPLIB_FLAG_RELWITHDEBINFO # ADD LINK32 /out:"OUTPUT_DIRECTORY\RelWithDebInfo\OUTPUT_NAME_RELWITHDEBINFO" TARGET_IMPLIB_FLAG_RELWITHDEBINFO
CM_MULTILINE_OPTIONS_RELWITHDEBINFO CM_MULTILINE_OPTIONS_RELWITHDEBINFO
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO
!ENDIF !ENDIF

View File

@ -74,7 +74,7 @@ LINK32=link.exe
# ADD LINK32 /out:"OUTPUT_DIRECTORY\Release\OUTPUT_NAME_RELEASE" # ADD LINK32 /out:"OUTPUT_DIRECTORY\Release\OUTPUT_NAME_RELEASE"
CM_MULTILINE_OPTIONS_RELEASE CM_MULTILINE_OPTIONS_RELEASE
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_RELEASE
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug"
@ -106,7 +106,7 @@ LINK32=link.exe
# ADD LINK32 /out:"OUTPUT_DIRECTORY\Debug\OUTPUT_NAME_DEBUG" # ADD LINK32 /out:"OUTPUT_DIRECTORY\Debug\OUTPUT_NAME_DEBUG"
CM_MULTILINE_OPTIONS_DEBUG CM_MULTILINE_OPTIONS_DEBUG
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_DEBUG
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel"
# PROP BASE Use_MFC CMAKE_MFC_FLAG # PROP BASE Use_MFC CMAKE_MFC_FLAG
@ -135,7 +135,7 @@ LINK32=link.exe
# ADD LINK32 /out:"OUTPUT_DIRECTORY\MinSizeRel\OUTPUT_NAME_MINSIZEREL" # ADD LINK32 /out:"OUTPUT_DIRECTORY\MinSizeRel\OUTPUT_NAME_MINSIZEREL"
CM_MULTILINE_OPTIONS_MINSIZEREL CM_MULTILINE_OPTIONS_MINSIZEREL
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_MINSIZEREL
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo"
@ -167,7 +167,7 @@ LINK32=link.exe
# ADD LINK32 /out:"OUTPUT_DIRECTORY\RelWithDebInfo\OUTPUT_NAME_RELWITHDEBINFO" # ADD LINK32 /out:"OUTPUT_DIRECTORY\RelWithDebInfo\OUTPUT_NAME_RELWITHDEBINFO"
CM_MULTILINE_OPTIONS_RELWITHDEBINFO CM_MULTILINE_OPTIONS_RELWITHDEBINFO
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO
!ENDIF !ENDIF

View File

@ -42,7 +42,7 @@ MTL=midl.exe
# PROP Intermediate_Dir "Release" # PROP Intermediate_Dir "Release"
# PROP Target_Dir "" # PROP Target_Dir ""
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_RELEASE
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug"
@ -57,7 +57,7 @@ CMAKE_CUSTOM_RULE_CODE
# PROP Intermediate_Dir "Debug" # PROP Intermediate_Dir "Debug"
# PROP Target_Dir "" # PROP Target_Dir ""
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_DEBUG
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel"
@ -72,7 +72,7 @@ CMAKE_CUSTOM_RULE_CODE
# PROP Intermediate_Dir "MinSizeRel" # PROP Intermediate_Dir "MinSizeRel"
# PROP Target_Dir "" # PROP Target_Dir ""
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_MINSIZEREL
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo"
@ -87,7 +87,7 @@ CMAKE_CUSTOM_RULE_CODE
# PROP Intermediate_Dir "RelWithDebInfo" # PROP Intermediate_Dir "RelWithDebInfo"
# PROP Target_Dir "" # PROP Target_Dir ""
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO
!ENDIF !ENDIF

View File

@ -67,7 +67,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo # ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"OUTPUT_DIRECTORY\Release/OUTPUT_NAME_RELEASE" CM_STATIC_LIB_ARGS # ADD LIB32 /nologo /out:"OUTPUT_DIRECTORY\Release/OUTPUT_NAME_RELEASE" CM_STATIC_LIB_ARGS
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_RELEASE
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 Debug"
@ -95,7 +95,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo # ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"OUTPUT_DIRECTORY\Debug/OUTPUT_NAME_DEBUG" CM_STATIC_LIB_ARGS # ADD LIB32 /nologo /out:"OUTPUT_DIRECTORY\Debug/OUTPUT_NAME_DEBUG" CM_STATIC_LIB_ARGS
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_DEBUG
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 MinSizeRel"
@ -124,7 +124,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo # ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"OUTPUT_DIRECTORY\MinSizeRel/OUTPUT_NAME_MINSIZEREL" CM_STATIC_LIB_ARGS # ADD LIB32 /nologo /out:"OUTPUT_DIRECTORY\MinSizeRel/OUTPUT_NAME_MINSIZEREL" CM_STATIC_LIB_ARGS
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_MINSIZEREL
!ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo" !ELSEIF "$(CFG)" == "OUTPUT_LIBNAME - Win32 RelWithDebInfo"
@ -152,7 +152,7 @@ LIB32=link.exe -lib
# ADD BASE LIB32 /nologo # ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"OUTPUT_DIRECTORY\RelWithDebInfo/OUTPUT_NAME_RELWITHDEBINFO" CM_STATIC_LIB_ARGS # ADD LIB32 /nologo /out:"OUTPUT_DIRECTORY\RelWithDebInfo/OUTPUT_NAME_RELWITHDEBINFO" CM_STATIC_LIB_ARGS
CMAKE_CUSTOM_RULE_CODE CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO
!ENDIF !ENDIF

View File

@ -167,6 +167,31 @@ TARGET_LINK_LIBRARIES(CustomCommand GeneratedHeader)
# the CustomCommand executable really needs doc1.h # the CustomCommand executable really needs doc1.h
ADD_DEPENDENCIES(CustomCommand TDocument) ADD_DEPENDENCIES(CustomCommand TDocument)
##############################################################################
# Test for using just the target name as executable in the COMMAND
# section. Has to be recognized and replaced by CMake with the output
# actual location of the executable.
# Additionally the generator is created in an extra subdir after the
# ADD_CUSTOM_COMMAND() is used.
#
# Test the same for ADD_CUSTOM_TARGET()
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated_extern.cxx
COMMAND generator_extern ${CMAKE_CURRENT_BINARY_DIR}/generated_extern.cxx
)
ADD_EXECUTABLE(CustomCommandUsingTargetTest main.cxx ${CMAKE_CURRENT_BINARY_DIR}/generated_extern.cxx )
ADD_CUSTOM_TARGET(RunTarget
COMMAND generator_extern ${CMAKE_CURRENT_BINARY_DIR}/run_target.cxx
)
ADD_CUSTOM_COMMAND(TARGET CustomCommandUsingTargetTest POST_BUILD
COMMAND dummy_generator ${CMAKE_CURRENT_BINARY_DIR}/generated_dummy.cxx)
ADD_SUBDIRECTORY(GeneratorInExtraDir)
############################################################################## ##############################################################################
# Test non-trivial command line arguments in custom commands. # Test non-trivial command line arguments in custom commands.
SET(EXPECTED_ARGUMENTS) SET(EXPECTED_ARGUMENTS)

View File

@ -0,0 +1,6 @@
# add the executable which will be used for generating files
ADD_EXECUTABLE(generator_extern ../generator.cxx)
SET_TARGET_PROPERTIES(generator_extern PROPERTIES OUTPUT_NAME the_external_generator)
# add an executable which will be called from ADD_CUSTOM_COMMAND( ... POST_BUILD)
ADD_EXECUTABLE(dummy_generator ../generator.cxx)

View File

@ -0,0 +1,6 @@
extern int generated();
int main()
{
return generated();
}