forked from dotnet/sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
GenerateShims.cs
163 lines (140 loc) · 6.93 KB
/
GenerateShims.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// 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.IO;
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.NET.HostModel;
using Microsoft.NET.HostModel.AppHost;
using NuGet.Frameworks;
using NuGet.ProjectModel;
using NuGet.Versioning;
namespace Microsoft.NET.Build.Tasks
{
public sealed class GenerateShims : TaskWithAssemblyResolveHooks
{
/// <summary>
/// Relative paths for Apphost for different ShimRuntimeIdentifiers with RuntimeIdentifier as meta data
/// </summary>
[Required]
public ITaskItem[] ApphostsForShimRuntimeIdentifiers { get; private set; }
[Required]
public string IntermediateAssembly { get; set; }
public string OutputType { get; set; }
/// <summary>
/// PackageId of the dotnet tool NuGet Package.
/// </summary>
[Required]
public string PackageId { get; set; }
/// <summary>
/// Package Version of the dotnet tool NuGet Package.
/// </summary>
[Required]
public string PackageVersion { get; set; }
/// <summary>
/// TFM to use for compile-time assets.
/// </summary>
[Required]
public string TargetFrameworkMoniker { get; set; }
/// <summary>
/// The command name of the dotnet tool.
/// </summary>
[Required]
public string ToolCommandName { get; set; }
/// <summary>
/// The entry point of the dotnet tool which will be run by Apphost
/// </summary>
[Required]
public string ToolEntryPoint { get; set; }
/// <summary>
/// The output directory path of generated shims.
/// </summary>
[Required]
public string PackagedShimOutputDirectory { get; set; }
/// <summary>
/// The RuntimeIdentifiers that shims will be generated for.
/// </summary>
[Required]
public ITaskItem[] ShimRuntimeIdentifiers { get; set; }
/// <summary>
/// Path of generated shims. metadata "ShimRuntimeIdentifier" is used to map back to input ShimRuntimeIdentifiers.
/// </summary>
[Output]
public ITaskItem[] EmbeddedApphostPaths { get; private set; }
private const ushort WindowsGUISubsystem = 0x2;
protected override void ExecuteCore()
{
var embeddedApphostPaths = new List<ITaskItem>();
foreach (var runtimeIdentifier in ShimRuntimeIdentifiers.Select(r => r.ItemSpec))
{
var resolvedApphostAssetPath = GetApphostAsset(ApphostsForShimRuntimeIdentifiers, runtimeIdentifier);
var packagedShimOutputDirectoryAndRid = Path.Combine(
PackagedShimOutputDirectory,
runtimeIdentifier);
var appHostDestinationFilePath = Path.Combine(
packagedShimOutputDirectoryAndRid,
ToolCommandName + ExecutableExtension.ForRuntimeIdentifier(runtimeIdentifier));
Directory.CreateDirectory(packagedShimOutputDirectoryAndRid);
// per https://github.com/dotnet/cli/issues/9870 nuget layout (as in {packageid}/{packageversion}/tools/)is normalized version
var normalizedPackageVersion = NuGetVersion.Parse(PackageVersion).ToNormalizedString();
// This is the embedded string. We should normalize it on forward slash, so the file won't be different according to
// build machine.
var appBinaryFilePath = string.Join("/",
new[] {
".store",
PackageId.ToLowerInvariant(),
normalizedPackageVersion,
PackageId.ToLowerInvariant(),
normalizedPackageVersion,
"tools",
NuGetUtils.ParseFrameworkName(TargetFrameworkMoniker).GetShortFolderName(),
"any",
ToolEntryPoint});
try
{
var windowsGraphicalUserInterface = runtimeIdentifier.StartsWith("win") && "WinExe".Equals(OutputType, StringComparison.OrdinalIgnoreCase);
if (ResourceUpdater.IsSupportedOS() && runtimeIdentifier.StartsWith("win"))
{
HostWriter.CreateAppHost(appHostSourceFilePath: resolvedApphostAssetPath,
appHostDestinationFilePath: appHostDestinationFilePath,
appBinaryFilePath: appBinaryFilePath,
windowsGraphicalUserInterface: windowsGraphicalUserInterface,
assemblyToCopyResourcesFrom: IntermediateAssembly);
}
else
{
// by passing null to assemblyToCopyResourcesFrom, it will skip copying resources,
// which is only supported on Windows
if (windowsGraphicalUserInterface)
{
Log.LogWarning(Strings.AppHostCustomizationRequiresWindowsHostWarning);
}
HostWriter.CreateAppHost(appHostSourceFilePath: resolvedApphostAssetPath,
appHostDestinationFilePath: appHostDestinationFilePath,
appBinaryFilePath: appBinaryFilePath,
windowsGraphicalUserInterface: false,
assemblyToCopyResourcesFrom: null);
}
}
catch (AppNameTooLongException ex)
{
throw new BuildErrorException(Strings.FileNameIsTooLong, ex.LongName);
}
catch (PlaceHolderNotFoundInAppHostException ex)
{
throw new BuildErrorException(Strings.AppHostHasBeenModified, resolvedApphostAssetPath, BitConverter.ToString(ex.MissingPattern));
}
var item = new TaskItem(appHostDestinationFilePath);
item.SetMetadata(MetadataKeys.ShimRuntimeIdentifier, runtimeIdentifier);
embeddedApphostPaths.Add(item);
}
EmbeddedApphostPaths = embeddedApphostPaths.ToArray();
}
private string GetApphostAsset(ITaskItem[] apphostsForShimRuntimeIdentifiers, string runtimeIdentifier)
{
return apphostsForShimRuntimeIdentifiers.Single(i => i.GetMetadata(MetadataKeys.RuntimeIdentifier) == runtimeIdentifier).ItemSpec;
}
}
}