Merge topic 'vs10-rule-files'

72333a4 VS10: Avoid creating .rule files next to outputs (#13141)
369e346 Factor out custom command .rule file path generation
f9b758e Cleanup custom command .rule file internal handling
This commit is contained in:
David Cole 2012-04-25 14:03:01 -04:00 committed by CMake Topic Stage
commit 728cbd19e3
9 changed files with 87 additions and 52 deletions

View File

@ -2091,6 +2091,21 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(
return target; return target;
} }
//----------------------------------------------------------------------------
std::string
cmGlobalGenerator::GenerateRuleFile(std::string const& output) const
{
std::string ruleFile = output;
ruleFile += ".rule";
const char* dir = this->GetCMakeCFGIntDir();
if(dir && dir[0] == '$')
{
cmSystemTools::ReplaceString(ruleFile, dir,
cmake::GetCMakeFilesDirectory());
}
return ruleFile;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*, void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
const char*, std::string&) const char*, std::string&)

View File

@ -277,6 +277,9 @@ public:
i.e. "Can I build Debug and Release in the same tree?" */ i.e. "Can I build Debug and Release in the same tree?" */
virtual bool IsMultiConfig() { return false; } virtual bool IsMultiConfig() { return false; }
/** Generate an <output>.rule file path for a given command output. */
virtual std::string GenerateRuleFile(std::string const& output) const;
protected: protected:
typedef std::vector<cmLocalGenerator*> GeneratorVector; typedef std::vector<cmLocalGenerator*> GeneratorVector;
// for a project collect all its targets by following depend // for a project collect all its targets by following depend

View File

@ -212,3 +212,21 @@ bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf)
return false; return false;
} }
} }
//----------------------------------------------------------------------------
std::string
cmGlobalVisualStudio10Generator
::GenerateRuleFile(std::string const& output) const
{
// The VS 10 generator needs to create the .rule files on disk.
// Hide them away under the CMakeFiles directory.
std::string ruleDir = this->GetCMakeInstance()->GetHomeOutputDirectory();
ruleDir += cmake::GetCMakeFilesDirectory();
ruleDir += "/";
ruleDir += cmSystemTools::ComputeStringMD5(
cmSystemTools::GetFilenamePath(output).c_str());
std::string ruleFile = ruleDir + "/";
ruleFile += cmSystemTools::GetFilenameName(output);
ruleFile += ".rule";
return ruleFile;
}

View File

@ -75,6 +75,10 @@ public:
virtual const char* GetCMakeCFGIntDir() const virtual const char* GetCMakeCFGIntDir() const
{ return "$(Configuration)";} { return "$(Configuration)";}
bool Find64BitTools(cmMakefile* mf); bool Find64BitTools(cmMakefile* mf);
/** Generate an <output>.rule file path for a given command output. */
virtual std::string GenerateRuleFile(std::string const& output) const;
protected: protected:
virtual const char* GetIDEVersion() { return "10.0"; } virtual const char* GetIDEVersion() { return "10.0"; }

View File

@ -214,13 +214,11 @@ void cmGlobalVisualStudio8Generator::AddCheckTarget()
// (this could be avoided with per-target source files) // (this could be avoided with per-target source files)
const char* no_main_dependency = 0; const char* no_main_dependency = 0;
const char* no_working_directory = 0; const char* no_working_directory = 0;
if(cmSourceFile* file =
mf->AddCustomCommandToOutput( mf->AddCustomCommandToOutput(
stamps, listFiles, stamps, listFiles,
no_main_dependency, commandLines, "Checking Build System", no_main_dependency, commandLines, "Checking Build System",
no_working_directory, true); no_working_directory, true))
std::string ruleName = stamps[0];
ruleName += ".rule";
if(cmSourceFile* file = mf->GetSource(ruleName.c_str()))
{ {
tgt->AddSourceFile(file); tgt->AddSourceFile(file);
} }

View File

@ -320,7 +320,7 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
sourceGroup.AssignSource(*i); sourceGroup.AssignSource(*i);
// while we are at it, if it is a .rule file then for visual studio 6 we // while we are at it, if it is a .rule file then for visual studio 6 we
// must generate it // must generate it
if ((*i)->GetExtension() == "rule") if ((*i)->GetPropertyAsBool("__CMAKE_RULE"))
{ {
if(!cmSystemTools::FileExists(source.c_str())) if(!cmSystemTools::FileExists(source.c_str()))
{ {

View File

@ -883,7 +883,7 @@ cmMakefile::AddCustomCommandToTarget(const char* target,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmSourceFile*
cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs, cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
const std::vector<std::string>& depends, const std::vector<std::string>& depends,
const char* main_dependency, const char* main_dependency,
@ -897,7 +897,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
if(outputs.empty()) if(outputs.empty())
{ {
cmSystemTools::Error("Attempt to add a custom rule with no output!"); cmSystemTools::Error("Attempt to add a custom rule with no output!");
return; return 0;
} }
// Validate custom commands. TODO: More strict? // Validate custom commands. TODO: More strict?
@ -910,7 +910,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
cmOStringStream e; cmOStringStream e;
e << "COMMAND may not contain literal quotes:\n " << cl[0] << "\n"; e << "COMMAND may not contain literal quotes:\n " << cl[0] << "\n";
this->IssueMessage(cmake::FATAL_ERROR, e.str()); this->IssueMessage(cmake::FATAL_ERROR, e.str());
return; return 0;
} }
} }
@ -928,7 +928,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
{ {
// The existing custom command is identical. Silently ignore // The existing custom command is identical. Silently ignore
// the duplicate. // the duplicate.
return; return file;
} }
else else
{ {
@ -948,17 +948,11 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
// Generate a rule file if the main dependency is not available. // Generate a rule file if the main dependency is not available.
if(!file) if(!file)
{ {
cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator();
// Construct a rule file associated with the first output produced. // Construct a rule file associated with the first output produced.
std::string outName = outputs[0]; std::string outName = gg->GenerateRuleFile(outputs[0]);
outName += ".rule";
const char* dir =
this->LocalGenerator->GetGlobalGenerator()->
GetCMakeCFGIntDir();
if(dir && dir[0] == '$')
{
cmSystemTools::ReplaceString(outName, dir,
cmake::GetCMakeFilesDirectory());
}
// Check if the rule file already exists. // Check if the rule file already exists.
file = this->GetSource(outName.c_str()); file = this->GetSource(outName.c_str());
if(file && file->GetCustomCommand() && !replace) if(file && file->GetCustomCommand() && !replace)
@ -970,11 +964,12 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
outName.c_str(), outName.c_str(),
"\" which already has a custom rule."); "\" which already has a custom rule.");
} }
return; return file;
} }
// Create a cmSourceFile for the rule file. // Create a cmSourceFile for the rule file.
file = this->GetOrCreateSource(outName.c_str(), true); file = this->GetOrCreateSource(outName.c_str(), true);
file->SetProperty("__CMAKE_RULE", "1");
} }
// Always create the output sources and mark them generated. // Always create the output sources and mark them generated.
@ -1004,10 +999,11 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
cc->SetEscapeAllowMakeVars(true); cc->SetEscapeAllowMakeVars(true);
file->SetCustomCommand(cc); file->SetCustomCommand(cc);
} }
return file;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmSourceFile*
cmMakefile::AddCustomCommandToOutput(const char* output, cmMakefile::AddCustomCommandToOutput(const char* output,
const std::vector<std::string>& depends, const std::vector<std::string>& depends,
const char* main_dependency, const char* main_dependency,
@ -1019,7 +1015,7 @@ cmMakefile::AddCustomCommandToOutput(const char* output,
{ {
std::vector<std::string> outputs; std::vector<std::string> outputs;
outputs.push_back(output); outputs.push_back(output);
this->AddCustomCommandToOutput(outputs, depends, main_dependency, return this->AddCustomCommandToOutput(outputs, depends, main_dependency,
commandLines, comment, workingDir, commandLines, comment, workingDir,
replace, escapeOldStyle); replace, escapeOldStyle);
} }
@ -1054,12 +1050,13 @@ cmMakefile::AddCustomCommandOldStyle(const char* target,
{ {
// Get the name of this output. // Get the name of this output.
const char* output = oi->c_str(); const char* output = oi->c_str();
cmSourceFile* sf;
// Choose whether to use a main dependency. // Choose whether to use a main dependency.
if(sourceFiles.find(source)) if(sourceFiles.find(source))
{ {
// The source looks like a real file. Use it as the main dependency. // The source looks like a real file. Use it as the main dependency.
this->AddCustomCommandToOutput(output, depends, source, sf = this->AddCustomCommandToOutput(output, depends, source,
commandLines, comment, 0); commandLines, comment, 0);
} }
else else
@ -1068,20 +1065,18 @@ cmMakefile::AddCustomCommandOldStyle(const char* target,
const char* no_main_dependency = 0; const char* no_main_dependency = 0;
std::vector<std::string> depends2 = depends; std::vector<std::string> depends2 = depends;
depends2.push_back(source); depends2.push_back(source);
this->AddCustomCommandToOutput(output, depends2, no_main_dependency, sf = this->AddCustomCommandToOutput(output, depends2, no_main_dependency,
commandLines, comment, 0); commandLines, comment, 0);
} }
// If the rule was added to the source (and not a .rule file), // If the rule was added to the source (and not a .rule file),
// then add the source to the target to make sure the rule is // then add the source to the target to make sure the rule is
// included. // included.
std::string sname = output; if(sf && !sf->GetPropertyAsBool("__CMAKE_RULE"))
sname += ".rule";
if(!this->GetSource(sname.c_str()))
{ {
if (this->Targets.find(target) != this->Targets.end()) if (this->Targets.find(target) != this->Targets.end())
{ {
this->Targets[target].AddSource(source); this->Targets[target].AddSourceFile(sf);
} }
else else
{ {
@ -1976,7 +1971,6 @@ cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname)
// look through all the source files that have custom commands // look through all the source files that have custom commands
// and see if the custom command has the passed source file as an output // and see if the custom command has the passed source file as an output
// keep in mind the possible .rule extension that may be tacked on
for(std::vector<cmSourceFile*>::const_iterator i = for(std::vector<cmSourceFile*>::const_iterator i =
this->SourceFiles.begin(); i != this->SourceFiles.end(); ++i) this->SourceFiles.begin(); i != this->SourceFiles.end(); ++i)
{ {

View File

@ -175,14 +175,16 @@ public:
cmTarget::CustomCommandType type, cmTarget::CustomCommandType type,
const char* comment, const char* workingDir, const char* comment, const char* workingDir,
bool escapeOldStyle = true); bool escapeOldStyle = true);
void AddCustomCommandToOutput(const std::vector<std::string>& outputs, cmSourceFile* AddCustomCommandToOutput(
const std::vector<std::string>& outputs,
const std::vector<std::string>& depends, const std::vector<std::string>& depends,
const char* main_dependency, const char* main_dependency,
const cmCustomCommandLines& commandLines, const cmCustomCommandLines& commandLines,
const char* comment, const char* workingDir, const char* comment, const char* workingDir,
bool replace = false, bool replace = false,
bool escapeOldStyle = true); bool escapeOldStyle = true);
void AddCustomCommandToOutput(const char* output, cmSourceFile* AddCustomCommandToOutput(
const char* output,
const std::vector<std::string>& depends, const std::vector<std::string>& depends,
const char* main_dependency, const char* main_dependency,
const cmCustomCommandLines& commandLines, const cmCustomCommandLines& commandLines,

View File

@ -459,8 +459,9 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
command) command)
{ {
std::string sourcePath = source->GetFullPath(); std::string sourcePath = source->GetFullPath();
// the rule file seems to need to exist for vs10 // VS 10 will always rebuild a custom command attached to a .rule
if (source->GetExtension() == "rule") // file that doesn't exist so create the file explicitly.
if (source->GetPropertyAsBool("__CMAKE_RULE"))
{ {
if(!cmSystemTools::FileExists(sourcePath.c_str())) if(!cmSystemTools::FileExists(sourcePath.c_str()))
{ {