mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 02:08:27 +08:00
VS: Add support for add_custom_command DEPFILE
Transform the depfile into MSBuild `AdditionalInputs` content. Add MSBuild Targets to update `AdditionalInputs` and the `.tlog` files for future builds without actually modifying the `.vcxproj` file. Fixes: #20286
This commit is contained in:
@@ -282,17 +282,19 @@ The options are:
|
|||||||
:generator:`Xcode` or :ref:`Makefile <Makefile Generators>` is an error.
|
:generator:`Xcode` or :ref:`Makefile <Makefile Generators>` is an error.
|
||||||
|
|
||||||
.. versionadded:: 3.20
|
.. versionadded:: 3.20
|
||||||
Added the support of :ref:`Makefile Generators`.
|
Added support for :ref:`Makefile Generators`.
|
||||||
|
|
||||||
.. versionadded:: 3.21
|
.. versionadded:: 3.21
|
||||||
Added the support of :generator:`Xcode` generator and
|
Added support for :ref:`Visual Studio Generators` with VS 2012 and above,
|
||||||
|
for the :generator:`Xcode` generator, and for
|
||||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||||
|
|
||||||
If the ``DEPFILE`` argument is relative, it should be relative to
|
If the ``DEPFILE`` argument is relative, it should be relative to
|
||||||
:variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the
|
:variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the
|
||||||
``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`
|
``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`
|
||||||
(see policy :policy:`CMP0116`. This policy is always ``NEW`` for
|
(see policy :policy:`CMP0116`. This policy is always ``NEW`` for
|
||||||
:ref:`Makefile <Makefile Generators>` and :generator:`Xcode` generators).
|
:ref:`Makefile Generators`, :ref:`Visual Studio Generators`,
|
||||||
|
and the :generator:`Xcode` generator).
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@@ -2,4 +2,5 @@ add_custom_command-DEPFILE
|
|||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
* The :command:`add_custom_command` command gained ``DEPFILE`` support on
|
* The :command:`add_custom_command` command gained ``DEPFILE`` support on
|
||||||
the :generator:`Xcode` generator.
|
the :generator:`Xcode` generator, and on :ref:`Visual Studio Generators`
|
||||||
|
for VS 2012 and above.
|
||||||
|
@@ -24,6 +24,13 @@ public:
|
|||||||
|
|
||||||
bool MatchesGeneratorName(const std::string& name) const override;
|
bool MatchesGeneratorName(const std::string& name) const override;
|
||||||
|
|
||||||
|
bool SupportsCustomCommandDepfile() const override { return true; }
|
||||||
|
|
||||||
|
cm::optional<cmDepfileFormat> DepfileFormat() const override
|
||||||
|
{
|
||||||
|
return cmDepfileFormat::MSBuildAdditionalInputs;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
cmGlobalVisualStudio11Generator(cmake* cm, const std::string& name,
|
cmGlobalVisualStudio11Generator(cmake* cm, const std::string& name,
|
||||||
std::string const& platformInGeneratorName);
|
std::string const& platformInGeneratorName);
|
||||||
|
@@ -768,6 +768,11 @@ void cmVisualStudio10TargetGenerator::Generate()
|
|||||||
Elem(e1, "Import").Attribute("Project", nasmTargets);
|
Elem(e1, "Import").Attribute("Project", nasmTargets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this->ProjectType == vcxproj && this->HaveCustomCommandDepfile) {
|
||||||
|
std::string depfileTargets =
|
||||||
|
GetCMakeFilePath("Templates/MSBuild/CustomBuildDepFile.targets");
|
||||||
|
Elem(e0, "Import").Attribute("Project", depfileTargets);
|
||||||
|
}
|
||||||
if (this->ProjectType == csproj) {
|
if (this->ProjectType == csproj) {
|
||||||
for (std::string const& c : this->Configurations) {
|
for (std::string const& c : this->Configurations) {
|
||||||
Elem e1(e0, "PropertyGroup");
|
Elem e1(e0, "PropertyGroup");
|
||||||
@@ -1460,7 +1465,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
|
|||||||
e2.SetHasElements();
|
e2.SetHasElements();
|
||||||
}
|
}
|
||||||
for (std::string const& c : this->Configurations) {
|
for (std::string const& c : this->Configurations) {
|
||||||
cmCustomCommandGenerator ccg(command, c, lg);
|
cmCustomCommandGenerator ccg(command, c, lg, true);
|
||||||
std::string comment = lg->ConstructComment(ccg);
|
std::string comment = lg->ConstructComment(ccg);
|
||||||
comment = cmVS10EscapeComment(comment);
|
comment = cmVS10EscapeComment(comment);
|
||||||
std::string script = lg->ConstructScript(ccg);
|
std::string script = lg->ConstructScript(ccg);
|
||||||
@@ -1524,10 +1529,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
|
|||||||
std::string name = "CustomCommand_" + c + "_" +
|
std::string name = "CustomCommand_" + c + "_" +
|
||||||
cmSystemTools::ComputeStringMD5(sourcePath);
|
cmSystemTools::ComputeStringMD5(sourcePath);
|
||||||
this->WriteCustomRuleCSharp(e0, c, name, script, additional_inputs.str(),
|
this->WriteCustomRuleCSharp(e0, c, name, script, additional_inputs.str(),
|
||||||
outputs.str(), comment);
|
outputs.str(), comment, ccg);
|
||||||
} else {
|
} else {
|
||||||
this->WriteCustomRuleCpp(*spe2, c, script, additional_inputs.str(),
|
this->WriteCustomRuleCpp(*spe2, c, script, additional_inputs.str(),
|
||||||
outputs.str(), comment, symbolic);
|
outputs.str(), comment, ccg, symbolic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1535,7 +1540,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
|
|||||||
void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
|
void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
|
||||||
Elem& e2, std::string const& config, std::string const& script,
|
Elem& e2, std::string const& config, std::string const& script,
|
||||||
std::string const& additional_inputs, std::string const& outputs,
|
std::string const& additional_inputs, std::string const& outputs,
|
||||||
std::string const& comment, bool symbolic)
|
std::string const& comment, cmCustomCommandGenerator const& ccg,
|
||||||
|
bool symbolic)
|
||||||
{
|
{
|
||||||
const std::string cond = this->CalcCondition(config);
|
const std::string cond = this->CalcCondition(config);
|
||||||
e2.WritePlatformConfigTag("Message", cond, comment);
|
e2.WritePlatformConfigTag("Message", cond, comment);
|
||||||
@@ -1554,13 +1560,29 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
|
|||||||
// outputs is marked SYMBOLIC and not expected to be created.
|
// outputs is marked SYMBOLIC and not expected to be created.
|
||||||
e2.WritePlatformConfigTag("VerifyInputsAndOutputsExist", cond, "false");
|
e2.WritePlatformConfigTag("VerifyInputsAndOutputsExist", cond, "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string depfile = ccg.GetFullDepfile();
|
||||||
|
if (!depfile.empty()) {
|
||||||
|
this->HaveCustomCommandDepfile = true;
|
||||||
|
std::string internal_depfile = ccg.GetInternalDepfile();
|
||||||
|
ConvertToWindowsSlash(internal_depfile);
|
||||||
|
e2.WritePlatformConfigTag("DepFileAdditionalInputsFile", cond,
|
||||||
|
internal_depfile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmVisualStudio10TargetGenerator::WriteCustomRuleCSharp(
|
void cmVisualStudio10TargetGenerator::WriteCustomRuleCSharp(
|
||||||
Elem& e0, std::string const& config, std::string const& name,
|
Elem& e0, std::string const& config, std::string const& name,
|
||||||
std::string const& script, std::string const& inputs,
|
std::string const& script, std::string const& inputs,
|
||||||
std::string const& outputs, std::string const& comment)
|
std::string const& outputs, std::string const& comment,
|
||||||
|
cmCustomCommandGenerator const& ccg)
|
||||||
{
|
{
|
||||||
|
if (!ccg.GetFullDepfile().empty()) {
|
||||||
|
this->Makefile->IssueMessage(
|
||||||
|
MessageType::FATAL_ERROR,
|
||||||
|
cmStrCat("CSharp target \"", this->GeneratorTarget->GetName(),
|
||||||
|
"\" does not support add_custom_command DEPFILE."));
|
||||||
|
}
|
||||||
this->CSharpCustomCommandNames.insert(name);
|
this->CSharpCustomCommandNames.insert(name);
|
||||||
Elem e1(e0, "Target");
|
Elem e1(e0, "Target");
|
||||||
e1.Attribute("Condition", this->CalcCondition(config));
|
e1.Attribute("Condition", this->CalcCondition(config));
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
class cmComputeLinkInformation;
|
class cmComputeLinkInformation;
|
||||||
class cmCustomCommand;
|
class cmCustomCommand;
|
||||||
|
class cmCustomCommandGenerator;
|
||||||
class cmGeneratedFileStream;
|
class cmGeneratedFileStream;
|
||||||
class cmGlobalVisualStudio10Generator;
|
class cmGlobalVisualStudio10Generator;
|
||||||
class cmLocalVisualStudio10Generator;
|
class cmLocalVisualStudio10Generator;
|
||||||
@@ -143,13 +144,15 @@ private:
|
|||||||
std::string const& script,
|
std::string const& script,
|
||||||
std::string const& additional_inputs,
|
std::string const& additional_inputs,
|
||||||
std::string const& outputs,
|
std::string const& outputs,
|
||||||
std::string const& comment, bool symbolic);
|
std::string const& comment,
|
||||||
|
cmCustomCommandGenerator const& ccg, bool symbolic);
|
||||||
void WriteCustomRuleCSharp(Elem& e0, std::string const& config,
|
void WriteCustomRuleCSharp(Elem& e0, std::string const& config,
|
||||||
std::string const& commandName,
|
std::string const& commandName,
|
||||||
std::string const& script,
|
std::string const& script,
|
||||||
std::string const& inputs,
|
std::string const& inputs,
|
||||||
std::string const& outputs,
|
std::string const& outputs,
|
||||||
std::string const& comment);
|
std::string const& comment,
|
||||||
|
cmCustomCommandGenerator const& ccg);
|
||||||
void WriteCustomCommands(Elem& e0);
|
void WriteCustomCommands(Elem& e0);
|
||||||
void WriteCustomCommand(Elem& e0, cmSourceFile const* sf);
|
void WriteCustomCommand(Elem& e0, cmSourceFile const* sf);
|
||||||
void WriteGroups();
|
void WriteGroups();
|
||||||
@@ -216,6 +219,7 @@ private:
|
|||||||
bool Managed;
|
bool Managed;
|
||||||
bool NsightTegra;
|
bool NsightTegra;
|
||||||
bool Android;
|
bool Android;
|
||||||
|
bool HaveCustomCommandDepfile = false;
|
||||||
unsigned int NsightTegraVersion[4];
|
unsigned int NsightTegraVersion[4];
|
||||||
bool TargetCompileAsWinRT;
|
bool TargetCompileAsWinRT;
|
||||||
std::set<std::string> IPOEnabledConfigurations;
|
std::set<std::string> IPOEnabledConfigurations;
|
||||||
|
48
Templates/MSBuild/CustomBuildDepFile.targets
Normal file
48
Templates/MSBuild/CustomBuildDepFile.targets
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<!-- Update AdditionalInputs with depfile-discovered inputs. -->
|
||||||
|
<Target Name="CMakeCustomBuildDepFileAdditionalInputs" BeforeTargets="CustomBuild" Condition="'@(CustomBuild)' != ''">
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- Save original AdditionalInputs generated by CMake. -->
|
||||||
|
<CustomBuild>
|
||||||
|
<CMakeAdditionalInputs>%(CustomBuild.AdditionalInputs)</CMakeAdditionalInputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<!-- Read depfile-discovered inputs. -->
|
||||||
|
<CustomBuild Condition="Exists('%(CustomBuild.DepFileAdditionalInputsFile)')">
|
||||||
|
<DepFileAdditionalInputs>$([System.IO.File]::ReadAllText('%(CustomBuild.DepFileAdditionalInputsFile)').TrimEnd())</DepFileAdditionalInputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<!-- Add depfile-discovered inputs to AdditionalInputs. -->
|
||||||
|
<CustomBuild Condition="'%(CustomBuild.DepFileAdditionalInputs)' != ''">
|
||||||
|
<AdditionalInputs Condition="'%(CustomBuild.AdditionalInputs)' == ''">%(CustomBuild.DepFileAdditionalInputs)</AdditionalInputs>
|
||||||
|
<AdditionalInputs Condition="'%(CustomBuild.AdditionalInputs)' != ''">%(CustomBuild.AdditionalInputs);%(CustomBuild.DepFileAdditionalInputs)</AdditionalInputs>
|
||||||
|
</CustomBuild>
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!-- Update the tracking log with depfile-discovered inputs. -->
|
||||||
|
<Target Name="CMakeCustomBuildDepFileTrackingLog" AfterTargets="CustomBuild" Condition="'@(CustomBuild)' != ''">
|
||||||
|
<!-- Compute the tracking log content for each CustomBuild item individually. -->
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- Read depfile-discovered inputs. -->
|
||||||
|
<CustomBuild Condition="Exists('%(CustomBuild.DepFileAdditionalInputsFile)')">
|
||||||
|
<DepFileAdditionalInputs>$([System.IO.File]::ReadAllText('%(CustomBuild.DepFileAdditionalInputsFile)').TrimEnd())</DepFileAdditionalInputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<!-- Generate tracking log representation of all inputs. -->
|
||||||
|
<CustomBuild>
|
||||||
|
<ReadTLog>^%(CustomBuild.Identity)
</ReadTLog>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Condition="'%(CustomBuild.CMakeAdditionalInputs)' != ''">
|
||||||
|
<ReadTLog>%(ReadTLog)$([System.String]::Copy('%(CustomBuild.CMakeAdditionalInputs)').Trim(';').Replace(';', '
'))
</ReadTLog>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Condition="'%(CustomBuild.DepFileAdditionalInputs)' != ''">
|
||||||
|
<ReadTLog>%(ReadTLog)$([System.String]::Copy('%(CustomBuild.DepFileAdditionalInputs)').Trim(';').Replace(';', '
'))
</ReadTLog>
|
||||||
|
</CustomBuild>
|
||||||
|
</ItemGroup>
|
||||||
|
<!-- Compute the combined tracking log for all CustomBuild items together. -->
|
||||||
|
<PropertyGroup>
|
||||||
|
<CustomBuildReadTLog>@(CustomBuild->'%(ReadTLog)','')</CustomBuildReadTLog>
|
||||||
|
</PropertyGroup>
|
||||||
|
<!-- Replace the combined tracking log on disk. -->
|
||||||
|
<WriteLinesToFile File="$(TLogLocation)CustomBuild.read.1.tlog" Overwrite="true" Lines="$(CustomBuildReadTLog.ToUpper())" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
@@ -172,7 +172,8 @@ if (RunCMake_GENERATOR MATCHES "Makefiles")
|
|||||||
run_cmake(CustomCommandDependencies-BadArgs)
|
run_cmake(CustomCommandDependencies-BadArgs)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(RunCMake_GENERATOR MATCHES "Make|Ninja|Xcode")
|
if(RunCMake_GENERATOR MATCHES "Make|Ninja|Visual Studio|Xcode" AND
|
||||||
|
NOT RunCMake_GENERATOR MATCHES "Visual Studio (9|10)( |$)")
|
||||||
unset(run_BuildDepends_skip_step_3)
|
unset(run_BuildDepends_skip_step_3)
|
||||||
run_BuildDepends(CustomCommandDepfile)
|
run_BuildDepends(CustomCommandDepfile)
|
||||||
set(run_BuildDepends_skip_step_3 1)
|
set(run_BuildDepends_skip_step_3 1)
|
||||||
|
Reference in New Issue
Block a user