VS: De-duplicate custom command dependencies

Avoid listing the same input more than once in custom commands generated
in `.vcxproj` and `.csproj` files.  In the case of a `.vcxproj` file
additionally avoid listing the source to which the command is attached
since it is already implicitly a dependency.

This is a nice cleanup and also works around a VS 2019 16.1 regression
in MSBuild dependency checking.  Starting with that version, MSBuild now
re-builds custom commands when the list of dependencies has changed.
However, its check is confused by duplicate dependencies.
De-duplicating them avoids this problem.

Co-Author: Brad King <brad.king@kitware.com>
Fixes: #19303
This commit is contained in:
Frans van Dorsselaer 2019-05-28 15:53:13 +02:00 committed by Brad King
parent d03a6fc857
commit 42bc67bd43

View File

@ -18,6 +18,7 @@
#include <iterator>
#include <memory> // IWYU pragma: keep
#include <set>
static void ConvertToWindowsSlash(std::string& s);
@ -1355,14 +1356,34 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
// input files for custom command
std::stringstream additional_inputs;
{
additional_inputs << source->GetFullPath();
const char* sep = "";
if (this->ProjectType == csproj) {
// csproj files do not attach the command to a specific file
// so the primary input must be listed explicitly.
additional_inputs << source->GetFullPath();
sep = ";";
}
// Avoid listing an input more than once.
std::set<std::string> unique_inputs;
// The source is either implicit an input or has been added above.
unique_inputs.insert(source->GetFullPath());
for (std::string const& d : ccg.GetDepends()) {
std::string dep;
if (lg->GetRealDependency(d, c, dep)) {
if (!unique_inputs.insert(dep).second) {
// already listed
continue;
}
ConvertToWindowsSlash(dep);
additional_inputs << ";" << dep;
additional_inputs << sep << dep;
sep = ";";
}
}
if (this->ProjectType != csproj) {
additional_inputs << sep << "%(AdditionalInputs)";
}
}
// output files for custom command
std::stringstream outputs;
@ -1395,8 +1416,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
const std::string cond = this->CalcCondition(config);
e2.WritePlatformConfigTag("Message", cond, comment);
e2.WritePlatformConfigTag("Command", cond, script);
e2.WritePlatformConfigTag("AdditionalInputs", cond,
additional_inputs + ";%(AdditionalInputs)");
e2.WritePlatformConfigTag("AdditionalInputs", cond, additional_inputs);
e2.WritePlatformConfigTag("Outputs", cond, outputs);
if (this->LocalGenerator->GetVersion() >
cmGlobalVisualStudioGenerator::VS10) {