From 166aa0f5556989a52b666b9876ab58855d3db507 Mon Sep 17 00:00:00 2001 From: Daniel Plaisted Date: Wed, 30 Dec 2020 18:50:36 -0800 Subject: [PATCH] Add validation that executable references match SelfContained Fixes #15117 --- .../ValidateExecutableReferences.cs | 59 +++++++++ .../targets/Microsoft.NET.Sdk.targets | 25 ++++ .../ReferenceExeTests.cs | 112 ++++++++++++------ .../ProjectConstruction/TestProject.cs | 7 ++ 4 files changed, 170 insertions(+), 33 deletions(-) create mode 100644 src/Tasks/Microsoft.NET.Build.Tasks/ValidateExecutableReferences.cs diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ValidateExecutableReferences.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ValidateExecutableReferences.cs new file mode 100644 index 000000000000..066bc18ae66b --- /dev/null +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ValidateExecutableReferences.cs @@ -0,0 +1,59 @@ +// 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.Text; +using System.Threading.Tasks; +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(); + + protected override void ExecuteCore() + { + if (!IsExecutable) + { + // If current project is not executable, then we don't need to check its references + return; + } + + foreach (var project in ReferencedProjects) + { + string nearestTargetFramework = project.GetMetadata("NearestTargetFramework"); + int targetFrameworkIndex = project.GetMetadata("TargetFrameworks").Split(';').ToList().IndexOf(nearestTargetFramework); + string projectAdditionalPropertiesMetadata = project.GetMetadata("AdditionalPropertiesFromProject").Split(new[] { ";;" }, StringSplitOptions.None)[targetFrameworkIndex]; + Dictionary projectAdditionalProperties = new(StringComparer.OrdinalIgnoreCase); + foreach (var propAndValue in projectAdditionalPropertiesMetadata.Split(';')) + { + var split = propAndValue.Split('='); + projectAdditionalProperties[split[0]] = split[1]; + } + + var referencedProjectIsExecutable = MSBuildUtilities.ConvertStringToBool(projectAdditionalProperties["_IsExecutable"]); + var referencedProjectIsSelfContained = MSBuildUtilities.ConvertStringToBool(projectAdditionalProperties["SelfContained"]); + + if (referencedProjectIsExecutable) + { + if (SelfContained && !referencedProjectIsSelfContained) + { + Log.LogError(Strings.SelfContainedExeCannotReferenceNonSelfContained, project.ItemSpec); + } + else if (!SelfContained && referencedProjectIsSelfContained) + { + Log.LogError(Strings.NonSelfContainedExeCannottReferenceSelfContained, project.ItemSpec); + } + } + } + } + } +} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets index 95bb30c86104..9b2bdb6afcff 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets @@ -1029,6 +1029,31 @@ Copyright (c) .NET Foundation. All rights reserved. + + + + + + + + + + + + + + +