Enforce that DLL/EXEs in platform manifest have a FileVersion (dotnet/core-setup...
authorDavis Goodin <dagood@users.noreply.github.com>
Fri, 5 Apr 2019 17:06:18 +0000 (12:06 -0500)
committerGitHub <noreply@github.com>
Fri, 5 Apr 2019 17:06:18 +0000 (12:06 -0500)
* Enforce DLL/EXEs in platform manifest have version

* Allow zero/missing versions on non-Windows

Commit migrated from https://github.com/dotnet/core-setup/commit/851859e9e07eda7adb2dcf129b0d6fb3cab411e3

src/installer/pkg/projects/dir.targets
src/installer/pkg/projects/windowsdesktop/dir.props
tools-local/tasks/GenerateFileVersionProps.cs

index f8ca13a..3719ef4 100644 (file)
       <Output TaskParameter="TargetOutputs" ItemName="SharedFrameworkRuntimeFiles" />
     </MSBuild>
 
+    <!--
+      Workaround: zero-versioned Microsoft.VisualBasic.dll in non-Windows CoreFX transport package.
+      See https://github.com/dotnet/corefx/issues/36630
+    -->
+    <PropertyGroup Condition="'$(OSGroup)' != 'Windows_NT'">
+      <PermitDllAndExeFilesLackingFileVersion>true</PermitDllAndExeFilesLackingFileVersion>
+    </PropertyGroup>
+
     <GenerateFileVersionProps Files="@(SharedFrameworkRuntimeFiles)"
                               PackageId="$(Id)"
                               PackageVersion="$(Version)"
                               PlatformManifestFile="$(PlatformManifestFile)"
                               PropsFile="$(PropsFile)"
-                              PreferredPackages="$(Id);@(RuntimeDependency)" />
+                              PreferredPackages="$(Id);@(RuntimeDependency)"
+                              PermitDllAndExeFilesLackingFileVersion="$(PermitDllAndExeFilesLackingFileVersion)" />
   </Target>
 
   <Target Name="IncludeFileVersionPropsFile"
index 6a02ce6..cf941f3 100644 (file)
@@ -4,5 +4,16 @@
 
   <PropertyGroup>
     <FrameworkPackageName>Microsoft.WindowsDesktop.App</FrameworkPackageName>
+
+    <!--
+      Disable FileVersion check for WindowsDesktop. Files with no FileVersion, as of writing:
+
+      runtimes\win-x86\native\PenImc_cor3.dll
+      runtimes\win-x86\native\PresentationNative_cor3.dll
+      runtimes\win-x86\native\wpfgfx_cor3.dll
+      runtimes\win-x86\lib\netcoreapp3.0\DirectWriteForwarder.dll
+      runtimes\win-x86\lib\netcoreapp3.0\System.Printing.dll
+    -->
+    <PermitDllAndExeFilesLackingFileVersion>true</PermitDllAndExeFilesLackingFileVersion>
   </PropertyGroup>
 </Project>
index b306d4d..a8cfdb8 100644 (file)
@@ -2,18 +2,21 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-using System;
+using Microsoft.Build.Construction;
 using Microsoft.Build.Framework;
-using System.IO;
+using System;
 using System.Collections.Generic;
-using Microsoft.Build.Construction;
+using System.IO;
+using System.Linq;
 
 namespace Microsoft.DotNet.Build.Tasks
 {
     public partial class GenerateFileVersionProps : BuildTask
     {
-        const string PlatformManifestsItem = "PackageConflictPlatformManifests";
-        const string PreferredPackagesProperty = "PackageConflictPreferredPackages";
+        private const string PlatformManifestsItem = "PackageConflictPlatformManifests";
+        private const string PreferredPackagesProperty = "PackageConflictPreferredPackages";
+        private static readonly Version ZeroVersion = new Version(0, 0, 0, 0);
+
 
         [Required]
         public ITaskItem[] Files { get; set; }
@@ -33,6 +36,12 @@ namespace Microsoft.DotNet.Build.Tasks
         [Required]
         public string PreferredPackages { get; set; }
 
+        /// <summary>
+        /// The task normally enforces that all DLL and EXE files have a non-0.0.0.0 FileVersion.
+        /// This flag disables the check.
+        /// </summary>
+        public bool PermitDllAndExeFilesLackingFileVersion { get; set; }
+
         public override bool Execute()
         {
             var fileVersions = new Dictionary<string, FileVersionData>(StringComparer.OrdinalIgnoreCase);
@@ -90,6 +99,28 @@ namespace Microsoft.DotNet.Build.Tasks
                 }
             }
 
+            // Check for versionless files after all duplicate filenames are resolved, rather than
+            // logging errors immediately upon encountering a versionless file. There may be
+            // duplicate filenames where only one has a version, and this is ok. The highest version
+            // is used.
+            if (!PermitDllAndExeFilesLackingFileVersion)
+            {
+                var versionlessFiles = fileVersions
+                    .Where(p =>
+                        p.Key.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) ||
+                        p.Key.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
+                    .Where(p => (p.Value.FileVersion ?? ZeroVersion) == ZeroVersion)
+                    .Select(p => p.Value.File.ItemSpec)
+                    .ToArray();
+
+                if (versionlessFiles.Any())
+                {
+                    Log.LogError(
+                        $"Missing FileVersion in {versionlessFiles.Length} shared framework files:" +
+                        string.Concat(versionlessFiles.Select(f => Environment.NewLine + f)));
+                }
+            }
+
             var props = ProjectRootElement.Create();
             var itemGroup = props.AddItemGroup();
             // set the platform manifest when the platform is not being published as part of the app
@@ -132,7 +163,8 @@ namespace Microsoft.DotNet.Build.Tasks
                 return new FileVersionData()
                 {
                     AssemblyVersion = FileUtilities.GetAssemblyName(filePath)?.Version,
-                    FileVersion = FileUtilities.GetFileVersion(filePath)
+                    FileVersion = FileUtilities.GetFileVersion(filePath),
+                    File = file
                 };
             }
             else
@@ -147,13 +179,14 @@ namespace Microsoft.DotNet.Build.Tasks
                 {
                     // FileVersionInfo will return 0.0.0.0 if a file doesn't have a version.
                     // match that behavior
-                    fileVersion = new Version(0, 0, 0, 0);
+                    fileVersion = ZeroVersion;
                 }
 
                 return new FileVersionData()
                 {
                     AssemblyVersion = assemblyVersion,
-                    FileVersion = fileVersion
+                    FileVersion = fileVersion,
+                    File = file
                 };
             }
         }
@@ -162,6 +195,7 @@ namespace Microsoft.DotNet.Build.Tasks
         {
             public Version AssemblyVersion { get; set; }
             public Version FileVersion { get; set; }
+            public ITaskItem File { get; set; }
         }
     }
 }