forked from dotnet/sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
GenerateShims.cs
176 lines (145 loc) · 6.15 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
164
165
166
167
168
169
170
171
172
173
174
175
176
// 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.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using NuGet.Frameworks;
using NuGet.ProjectModel;
namespace Microsoft.NET.Build.Tasks
{
public sealed class GenerateShims : TaskBase
{
private NuGetPackageResolver _packageResolver;
/// <summary>
/// Path to assets.json.
/// </summary>
[Required]
public string ProjectAssetsFile { get; set; }
/// <summary>
/// The file name of Apphost asset.
/// </summary>
[Required]
public string DotNetAppHostExecutableNameWithoutExtension { get; set; }
/// <summary>
/// Path to project file (.csproj|.vbproj|.fsproj)
/// </summary>
[Required]
public string ProjectPath { get; set; }
/// <summary>
/// TFM to use for compile-time assets.
/// </summary>
[Required]
public string TargetFrameworkMoniker { 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>
/// 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; }
protected override void ExecuteCore()
{
NuGetFramework targetFramework = NuGetUtils.ParseFrameworkName(TargetFrameworkMoniker);
LockFile lockFile = new LockFileCache(this).GetLockFile(ProjectAssetsFile);
_packageResolver = NuGetPackageResolver.CreateResolver(lockFile, ProjectPath);
var embeddedApphostPaths = new List<ITaskItem>();
foreach (var runtimeIdentifier in ShimRuntimeIdentifiers.Select(r => r.ItemSpec))
{
var resolvedApphostAssetPath = GetApphostAsset(targetFramework, lockFile, runtimeIdentifier);
var packagedShimOutputDirectoryAndRid = Path.Combine(
PackagedShimOutputDirectory,
runtimeIdentifier);
var appHostDestinationFilePath = Path.Combine(
packagedShimOutputDirectoryAndRid,
ToolCommandName + Path.GetExtension(resolvedApphostAssetPath));
Directory.CreateDirectory(packagedShimOutputDirectoryAndRid);
// 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(),
PackageVersion,
PackageId.ToLowerInvariant(),
PackageVersion,
"tools",
targetFramework.GetShortFolderName(),
"any",
ToolEntryPoint});
AppHost.Create(
resolvedApphostAssetPath,
appHostDestinationFilePath,
appBinaryFilePath,
overwriteExisting: true
);
var item = new TaskItem(appHostDestinationFilePath);
item.SetMetadata("ShimRuntimeIdentifier", runtimeIdentifier);
embeddedApphostPaths.Add(item);
}
EmbeddedApphostPaths = embeddedApphostPaths.ToArray();
}
private string GetApphostAsset(NuGetFramework targetFramework, LockFile lockFile, string runtimeIdentifier)
{
var apphostName = DotNetAppHostExecutableNameWithoutExtension;
if (runtimeIdentifier.StartsWith("win"))
{
apphostName += ".exe";
}
LockFileTarget runtimeTarget = lockFile.GetTargetAndThrowIfNotFound(targetFramework, runtimeIdentifier);
return FindApphostInRuntimeTarget(apphostName, runtimeTarget);
}
private string FindApphostInRuntimeTarget(string apphostName, LockFileTarget runtimeTarget)
{
foreach (LockFileTargetLibrary library in runtimeTarget.Libraries)
{
if (!library.IsPackage())
{
continue;
}
foreach (LockFileItem asset in library.NativeLibraries)
{
if (asset.IsPlaceholderFile())
{
continue;
}
var resolvedPackageAssetPath = _packageResolver.ResolvePackageAssetPath(library, asset.Path);
if (Path.GetFileName(resolvedPackageAssetPath) == apphostName)
{
return resolvedPackageAssetPath;
}
}
}
throw new BuildErrorException(Strings.CannotFindApphostForRid, runtimeTarget.RuntimeIdentifier);
}
}
}