forked from dotnet/sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathValidateExecutableReferences.cs
102 lines (86 loc) · 5.1 KB
/
ValidateExecutableReferences.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Build.Framework;
namespace Microsoft.NET.Build.Tasks
{
public class ValidateExecutableReferences : TaskBase
{
public bool SelfContained { get; set; }
public bool IsExecutable { get; set; }
public ITaskItem[] ReferencedProjects { get; set; } = Array.Empty<ITaskItem>();
public bool UseAttributeForTargetFrameworkInfoPropertyNames { get; set; }
protected override void ExecuteCore()
{
if (!IsExecutable)
{
// If current project is not executable, then we don't need to check its references
return;
}
foreach (ITaskItem project in ReferencedProjects)
{
string nearestTargetFramework = project.GetMetadata("NearestTargetFramework");
if (string.IsNullOrEmpty(nearestTargetFramework) || !project.HasMetadataValue("AdditionalPropertiesFromProject"))
{
// Referenced project doesn't have the right metadata. This may be because it's a different project type (C++, for example)
// In this case just skip the checks
continue;
}
var additionalPropertiesXml = XElement.Parse(project.GetMetadata("AdditionalPropertiesFromProject"));
XElement targetFrameworkElement = UseAttributeForTargetFrameworkInfoPropertyNames ?
additionalPropertiesXml.Elements().Where(el => el.HasAttributes && el.FirstAttribute.Value.Equals(nearestTargetFramework)).Single() :
additionalPropertiesXml.Element(nearestTargetFramework);
Dictionary<string, string> projectAdditionalProperties = new(StringComparer.OrdinalIgnoreCase);
foreach (XElement propertyElement in targetFrameworkElement.Elements())
{
projectAdditionalProperties[propertyElement.Name.LocalName] = propertyElement.Value;
}
bool shouldBeValidatedAsExecutableReference = MSBuildUtilities.ConvertStringToBool(projectAdditionalProperties["ShouldBeValidatedAsExecutableReference"], true);
bool referencedProjectIsExecutable = MSBuildUtilities.ConvertStringToBool(projectAdditionalProperties["_IsExecutable"]);
bool referencedProjectIsSelfContained = MSBuildUtilities.ConvertStringToBool(projectAdditionalProperties["SelfContained"]);
bool referencedProjectHadSelfContainedSpecified = MSBuildUtilities.ConvertStringToBool(projectAdditionalProperties["_SelfContainedWasSpecified"]);
var globalProperties = BuildEngine6.GetGlobalProperties();
bool selfContainedIsGlobalProperty = globalProperties.ContainsKey("SelfContained");
bool runtimeIdentifierIsGlobalProperty = globalProperties.ContainsKey("RuntimeIdentifier");
bool projectIsRidAgnostic = true;
if (projectAdditionalProperties.TryGetValue("IsRidAgnostic", out string isRidAgnostic) &&
bool.TryParse(isRidAgnostic, out bool isRidAgnosticParseResult))
{
projectIsRidAgnostic = isRidAgnosticParseResult;
}
if (!projectIsRidAgnostic)
{
// If the project is NOT RID agnostic, and SelfContained was set as a global property,
// then SelfContained will flow across the project reference when we go to build it,
// despite the fact that we ignored it when doing the GetTargetFrameworks negotiation
if (selfContainedIsGlobalProperty && SelfContained)
{
referencedProjectIsSelfContained = true;
}
// If the project is NOT RID agnostic, then a global RuntimeIdentifier will flow to it.
// If the project didn't explicitly specify a value for SelfContained, then this will
// set SelfContained to true
if (runtimeIdentifierIsGlobalProperty && !referencedProjectHadSelfContainedSpecified)
{
referencedProjectIsSelfContained = true;
}
}
if (referencedProjectIsExecutable && shouldBeValidatedAsExecutableReference)
{
if (SelfContained && !referencedProjectIsSelfContained)
{
Log.LogError(Strings.SelfContainedExeCannotReferenceNonSelfContained, project.ItemSpec);
}
else if (!SelfContained && referencedProjectIsSelfContained)
{
Log.LogError(Strings.NonSelfContainedExeCannotReferenceSelfContained, project.ItemSpec);
}
}
}
}
}
}