未验证 提交 b31bcc32 编写于 作者: S Steve Pfister 提交者: GitHub

Mono toolchain workload (#51327)

First pass at a more comprehensive mono workload that includes wasm, the aot compilers, and the runtime config task.
Co-authored-by: NSteve Pfister <steve.pfister@microsoft.com>
Co-authored-by: NLarry Ewing <lewing@microsoft.com>
上级 212d2348
......@@ -206,5 +206,9 @@
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-optimization</Uri>
<Sha>511fc23bc9dc22f6d7c0d2433e936c5db6a1a797</Sha>
</Dependency>
<Dependency Name="Microsoft.NET.Runtime.Emscripten.2.0.12.Node.win-x64" Version="6.0.0-preview.4.21212.1">
<Uri>https://github.com/dotnet/emsdk</Uri>
<Sha>e51b2a920817aec200d7306b95f616f9451d47a3</Sha>
</Dependency>
</ToolsetDependencies>
</Dependencies>
......@@ -25,6 +25,8 @@
release, increase this number by one.
-->
<NETStandardPatchVersion>0</NETStandardPatchVersion>
<MicrosoftNETRuntimeEmscripten2012Nodewinx64Version>6.0.0-preview.4.21212.1</MicrosoftNETRuntimeEmscripten2012Nodewinx64Version>
<MicrosoftNETRuntimeEmscriptenVersion>$(MicrosoftNETRuntimeEmscripten2012Nodewinx64Version)</MicrosoftNETRuntimeEmscriptenVersion>
</PropertyGroup>
<!--
Servicing build settings for Setup/Installer packages. Instructions:
......
......@@ -3,6 +3,9 @@
<Import Project="..\Directory.Build.props" />
<Import Project="$(NuGetPackageRoot)\microsoft.dotnet.build.tasks.packaging\$(MicrosoftDotNetBuildTasksPackagingVersion)\build\Microsoft.DotNet.Build.Tasks.Packaging.props" />
<PropertyGroup>
<WorkloadTasksAssemblyPath>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WorkloadBuildTasks', 'Debug', '$(NetCoreAppToolCurrent)'))WorkloadBuildTasks.dll</WorkloadTasksAssemblyPath>
</PropertyGroup>
<PropertyGroup>
<PackageIndexFile>$(MSBuildThisFileDirectory)packageIndex.json</PackageIndexFile>
<PackagePlatform>AnyCPU</PackagePlatform>
......
<Project>
<UsingTask TaskName="GenerateFileFromTemplate" AssemblyFile="$(WorkloadTasksAssemblyPath)" />
<Import Project="..\Directory.Build.targets" />
<Import Project="$(NuGetPackageRoot)\microsoft.dotnet.build.tasks.packaging\$(MicrosoftDotNetBuildTasksPackagingVersion)\build\Microsoft.DotNet.Build.Tasks.Packaging.targets" />
</Project>
<Project DefaultTargets="Build">
<Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.props))" />
<PropertyGroup>
<PackageDescription>Internal toolchain package not meant for direct consumption. Please do not reference directly.</PackageDescription>
</PropertyGroup>
<Target Name="_PrepareForPack" BeforeTargets="GetPackageFiles" Returns="@(PackageFile)">
<PropertyGroup>
<WorkloadManifestPath>$(IntermediateOutputPath)WorkloadManifest.json</WorkloadManifestPath>
<PackagePathVersion>PackageVersion=$(PackageVersion);</PackagePathVersion>
</PropertyGroup>
<ItemGroup>
<_WorkloadManifestValues Include="PackageVersion" Value="$(PackageVersion)" />
<_WorkloadManifestValues Include="EmscriptenVersion" Value="$(MicrosoftNETRuntimeEmscriptenVersion)" />
</ItemGroup>
<GenerateFileFromTemplate
TemplateFile="WorkloadManifest.json.in"
Properties="@(_WorkloadManifestValues)"
OutputPath="$(WorkloadManifestPath)" />
<ItemGroup>
<PackageFile Include="$(WorkloadManifestPath)" TargetPath="data" />
<PackageFile Include="WorkloadManifest.targets" TargetPath="data" />
</ItemGroup>
</Target>
<Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.targets))" />
</Project>
{
"version": 1,
"workloads": {
"microsoft-net-runtime-browser-native": {
"description": "Browser Runtime native performance tools",
"packs": [
"Microsoft.NETCore.App.Runtime.Mono.browser-wasm",
"Microsoft.NET.Runtime.MonoAOTCompiler.Task",
"Microsoft.NET.Runtime.WebAssembly.Sdk",
"Microsoft.NETCore.App.Runtime.AOT.Cross.browser-wasm",
"Microsoft.NET.Runtime.Emscripten.Node",
"Microsoft.NET.Runtime.Emscripten.Python",
"Microsoft.NET.Runtime.Emscripten.Sdk"
]
},
"microsoft-net-runtime-android": {
"abstract": true,
"description": "Android Mono Runtime and AOT Workload",
"packs": [
"Microsoft.NET.Runtime.MonoAOTCompiler.Task",
"Microsoft.NETCore.App.Runtime.Mono.android-arm",
"Microsoft.NETCore.App.Runtime.Mono.android-arm64",
"Microsoft.NETCore.App.Runtime.Mono.android-x64",
"Microsoft.NETCore.App.Runtime.Mono.android-x86",
"Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64",
"Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm",
"Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64"
]
},
"microsoft-net-runtime-ios": {
"abstract": true,
"description": "iOS Mono Runtime and AOT Workload",
"packs": [
"Microsoft.NET.Runtime.MonoAOTCompiler.Task",
"Microsoft.NETCore.App.Runtime.Mono.ios-arm",
"Microsoft.NETCore.App.Runtime.Mono.ios-arm64",
"Microsoft.NETCore.App.Runtime.Mono.iossimulator",
"Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86",
"Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm",
"Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm64",
"Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator",
"Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-x86"
],
"platforms": [ "osx-arm64", "osx-x64" ]
},
"microsoft-net-runtime-tvos": {
"abstract": true,
"description": "tvOS Mono Runtime and AOT Workload",
"packs": [
"Microsoft.NET.Runtime.MonoAOTCompiler.Task",
"Microsoft.NETCore.App.Runtime.Mono.tvos-arm64",
"Microsoft.NETCore.App.Runtime.Mono.tvos-x64",
"Microsoft.NETCore.App.Runtime.Mono.tvossimulator",
"Microsoft.NETCore.App.Runtime.AOT.Cross.tvos-arm64",
"Microsoft.NETCore.App.Runtime.AOT.Cross.tvossimulator"
],
"platforms": [ "osx-arm64", "osx-x64" ]
}
},
"packs": {
"Microsoft.NET.Runtime.RuntimeConfigParser.Task": {
"kind": "Sdk",
"version": "${PackageVersion}"
},
"Microsoft.NET.Runtime.MonoAOTCompiler.Task": {
"kind": "Sdk",
"version": "${PackageVersion}"
},
"Microsoft.NET.Runtime.WebAssembly.Sdk": {
"kind": "Sdk",
"version": "${PackageVersion}"
},
"Microsoft.NETCore.App.Runtime.Mono.android-arm": {
"kind": "framework",
"version": "${PackageVersion}"
},
"Microsoft.NETCore.App.Runtime.Mono.android-arm64": {
"kind": "framework",
"version": "${PackageVersion}"
},
"Microsoft.NETCore.App.Runtime.Mono.android-x64": {
"kind": "framework",
"version": "${PackageVersion}"
},
"Microsoft.NETCore.App.Runtime.Mono.android-x86": {
"kind": "framework",
"version": "${PackageVersion}"
},
"Microsoft.NETCore.App.Runtime.AOT.Cross.android-x86": {
"kind": "Sdk",
"version": "${PackageVersion}",
"alias-to": {
"win-x64": "Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.android-x86",
"linux-x64": "Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.android-x86",
"osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-x86",
"osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-x86"
}
},
"Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64": {
"kind": "Sdk",
"version": "${PackageVersion}",
"alias-to": {
"win-x64": "Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.android-x64",
"linux-x64": "Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.android-x64",
"osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-x64",
"osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-x64"
}
},
"Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm": {
"kind": "Sdk",
"version": "${PackageVersion}",
"alias-to": {
"win-x64": "Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.android-arm",
"linux-x64": "Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.android-arm",
"osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-arm",
"osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-arm"
}
},
"Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64": {
"kind": "Sdk",
"version": "${PackageVersion}",
"alias-to": {
"win-x64": "Microsoft.netcore.app.runtime.aot.win-x64.Cross.android-arm64",
"linux-x64": "Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.android-arm64",
"osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-arm64",
"osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.android-arm64"
}
},
"Microsoft.NETCore.App.Runtime.Mono.ios-arm" : {
"kind": "framework",
"version": "${PackageVersion}"
},
"Microsoft.NETCore.App.Runtime.Mono.ios-arm64" : {
"kind": "framework",
"version": "${PackageVersion}"
},
"Microsoft.NETCore.App.Runtime.Mono.iossimulator" : {
"kind": "framework",
"version": "${PackageVersion}",
"alias-to": {
"osx-arm64": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-arm64",
"osx-x64": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x64"
}
},
"Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86" : {
"kind": "framework",
"version": "${PackageVersion}",
"alias-to": {
"osx-x64": "Microsoft.NETCore.App.Runtime.Mono.iossimulator-x86"
}
},
"Microsoft.NETCore.App.Runtime.AOT.Cross.tvos-arm64": {
"kind": "Sdk",
"version": "${PackageVersion}",
"alias-to": {
"osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvos-arm64",
"osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvos-arm64",
}
},
"Microsoft.NETCore.App.Runtime.Mono.tvos-arm64" : {
"kind": "framework",
"version": "${PackageVersion}"
},
"Microsoft.NETCore.App.Runtime.Mono.tvossimulator" : {
"kind": "framework",
"version": "${PackageVersion}",
"alias-to": {
"osx-arm64": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-arm64",
"osx-x64": "Microsoft.NETCore.App.Runtime.Mono.tvossimulator-x64"
}
},
"Microsoft.NETCore.App.Runtime.AOT.Cross.tvossimulator": {
"kind": "Sdk",
"version": "${PackageVersion}",
"alias-to": {
"osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvossimulator-arm64",
"osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.tvossimulator-x64"
}
},
"Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm": {
"kind": "Sdk",
"version": "${PackageVersion}",
"alias-to": {
"osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm",
"osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm",
}
},
"Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm64": {
"kind": "Sdk",
"version": "${PackageVersion}",
"alias-to": {
"osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm64",
"osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.ios-arm64",
}
},
"Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator": {
"kind": "Sdk",
"version": "${PackageVersion}",
"alias-to": {
"osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.iossimulator-arm64",
"osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.iossimulator-x64"
}
},
"Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator-x86": {
"kind": "Sdk",
"version": "${PackageVersion}",
"alias-to": {
"osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.iossimulator-x86"
}
},
"Microsoft.NETCore.App.Runtime.AOT.Cross.browser-wasm": {
"kind": "Sdk",
"version": "${PackageVersion}",
"alias-to": {
"win-x86": "Microsoft.NETCore.App.Runtime.AOT.win-x86.Cross.browser-wasm",
"win-x64": "Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm",
"linux-x64": "Microsoft.NETCore.App.Runtime.AOT.linux-x64.Cross.browser-wasm",
"osx-x64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.browser-wasm",
"osx-arm64": "Microsoft.NETCore.App.Runtime.AOT.osx-x64.Cross.browser-wasm"
}
},
"Microsoft.NETCore.App.Runtime.Mono.browser-wasm" : {
"kind": "framework",
"version": "${PackageVersion}"
},
"Microsoft.NET.Runtime.Emscripten.Node" : {
"kind": "Sdk",
"version": "${EmscriptenVersion}",
"alias-to": {
"win-x64": "Microsoft.NET.Runtime.Emscripten.2.0.12.Node.win-x64",
"linux-x64": "Microsoft.NET.Runtime.Emscripten.2.0.12.Node.linux-x64",
"osx-x64": "Microsoft.NET.Runtime.Emscripten.2.0.12.Node.osx-x64",
"osx-arm64": "Microsoft.NET.Runtime.Emscripten.2.0.12.Node.osx-x64"
}
},
"Microsoft.NET.Runtime.Emscripten.Python" : {
"kind": "Sdk",
"version": "${EmscriptenVersion}",
"alias-to": {
"win-x64": "Microsoft.NET.Runtime.Emscripten.2.0.12.Python.win-x64",
"osx-x64": "Microsoft.NET.Runtime.Emscripten.2.0.12.Python.osx-x64",
"osx-arm64": "Microsoft.NET.Runtime.Emscripten.2.0.12.Python.osx-x64"
}
},
"Microsoft.NET.Runtime.Emscripten.Sdk" : {
"kind": "Sdk",
"version": "${EmscriptenVersion}",
"alias-to": {
"win-x64": "Microsoft.NET.Runtime.Emscripten.2.0.12.Sdk.win-x64",
"linux-x64": "Microsoft.NET.Runtime.Emscripten.2.0.12.Sdk.linux-x64",
"osx-x64": "Microsoft.NET.Runtime.Emscripten.2.0.12.Sdk.osx-x64",
"osx-arm64": "Microsoft.NET.Runtime.Emscripten.2.0.12.Sdk.osx-x64"
}
}
}
}
\ No newline at end of file
<Project>
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<UsingBrowserRuntimeWorkload Condition="'$(RunAOTCompilation)' == 'true' or '$(UsingMicrosoftNETSdkBlazorWebAssembly)' != 'true'" >true</UsingBrowserRuntimeWorkload>
<UsingBrowserRuntimeWorkload Condition="'$(UsingBrowserRuntimeWorkload)' == ''" >$(WasmNativeWorkload)</UsingBrowserRuntimeWorkload>
</PropertyGroup>
<PropertyGroup Condition="'$(UsingMicrosoftNETSdkBlazorWebAssembly)' == 'true' and '$(UsingBrowserRuntimeWorkload)' == 'true'">
<WasmGenerateAppBundle>false</WasmGenerateAppBundle>
<UsingBlazorAOTWorkloadManifest>true</UsingBlazorAOTWorkloadManifest>
</PropertyGroup>
<Import Condition="'$(RunAOTCompilation)' == 'true'" Project="Sdk.props" Sdk="Microsoft.NET.Runtime.MonoAOTCompiler.Task" />
<ImportGroup Condition="'$(TargetPlatformIdentifier)' == 'android' and '$(RunAOTCompilation)' == 'true'">
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-x86" />
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-x64" />
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm" />
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.android-arm64" />
</ImportGroup>
<ImportGroup Condition="'$(TargetPlatformIdentifier)' == 'ios' and '$(RunAOTCompilation)' == 'true'">
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm" />
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.ios-arm64" />
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.ios-x86" />
</ImportGroup>
<ImportGroup Condition="'$(TargetPlatformIdentifier)' == 'tvos' and '$(RunAOTCompilation)' == 'true'">
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.tvos-arm64" />
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.tvos-x64" />
</ImportGroup>
<ImportGroup Condition="'$(TargetPlatformIdentifier)' == 'iossimulator' and '$(RunAOTCompilation)' == 'true'">
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.iossimulator" />
</ImportGroup>
<ImportGroup Condition="'$(TargetPlatformIdentifier)' == 'tvossimulator' and '$(RunAOTCompilation)' == 'true'">
<Import Project="Sdk.props" Sdk="Microsoft.NETCore.App.Runtime.AOT.Cross.tvossimulator" />
</ImportGroup>
<ImportGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm' and '$(UsingBrowserRuntimeWorkload)' == 'true'">
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Runtime.WebAssembly.Sdk" />
<Import Project="Sdk.props" Sdk="Microsoft.NET.Runtime.Emscripten.Python" Condition="!$([MSBuild]::IsOsPlatform('Linux'))" />
<Import Project="Sdk.props" Sdk="Microsoft.NET.Runtime.Emscripten.Node" />
<Import Project="Sdk.props" Sdk="Microsoft.NET.Runtime.Emscripten.Sdk" />
<Import Project="Sdk.props" Sdk="Microsoft.NETcore.App.Runtime.AOT.Cross.browser-wasm" />
</ImportGroup>
</Project>
......@@ -18,6 +18,7 @@
</ItemGroup>
<ItemGroup Condition="'$(TargetsMobile)' == 'true'">
<ProjectReference Include="Microsoft.NET.Sdk.Mono.Toolchain.Manifest\Microsoft.NET.Sdk.Mono.Toolchain.Manifest.pkgproj" />
<ProjectReference Include="Microsoft.NET.Runtime.MonoAOTCompiler.Task\Microsoft.NET.Runtime.MonoAOTCompiler.Task.pkgproj" />
<ProjectReference Include="Microsoft.NET.Runtime.RuntimeConfigParser.Task\Microsoft.NET.Runtime.RuntimeConfigParser.Task.pkgproj" />
</ItemGroup>
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// <para>
/// Generates a new file at <see cref="OutputPath"/>.
/// </para>
/// <para>
/// The <see cref="TemplateFile"/> can define variables for substitution using <see cref="Properties"/>.
/// </para>
/// <example>
/// The input file might look like this:
/// <code>
/// 2 + 2 = ${Sum}
/// </code>
/// When the task is invoked like this, it will produce "2 + 2 = 4"
/// <code>
/// &lt;GenerateFileFromTemplate Properties="Sum=4;OtherValue=123;" ... &gt;
/// </code>
/// </example>
/// </summary>
public class GenerateFileFromTemplate : Task
{
/// <summary>
/// The template file.
/// Variable syntax: ${VarName}
/// If your template file needs to output this format, you can escape the dollar sign with a backtick, e.g. `${NotReplaced}
/// </summary>
[NotNull]
[Required]
public string? TemplateFile { get; set; }
/// <summary>
/// The destination for the generated file.
/// </summary>
[NotNull]
[Required]
public string? OutputPath { get; set; }
/// <summary>
/// Key=value pairs of values
/// </summary>
[NotNull]
[Required]
public ITaskItem[]? Properties { get; set; }
public override bool Execute()
{
string outputPath = Path.GetFullPath(OutputPath);
if (!File.Exists(TemplateFile))
{
Log.LogError($"File {TemplateFile} does not exist");
return false;
}
var template = File.ReadAllText(TemplateFile);
var values = new Dictionary<string, string>();
foreach (ITaskItem item in Properties)
values.Add(item.ItemSpec, item.GetMetadata("Value"));
var result = Replace(template, values);
string? dir = Path.GetDirectoryName(outputPath);
if (dir != null)
Directory.CreateDirectory(dir);
File.WriteAllText(outputPath, result);
return true;
}
public string Replace(string template, IDictionary<string, string> values)
{
var sb = new StringBuilder();
var varNameSb = new StringBuilder();
var line = 1;
for (var i = 0; i < template.Length; i++)
{
var ch = template[i];
var nextCh = i + 1 >= template.Length
? '\0'
: template[i + 1];
// count lines in the template file
if (ch == '\n')
{
line++;
}
if (ch == '`' && (nextCh == '$' || nextCh == '`'))
{
// skip the backtick for known escape characters
i++;
sb.Append(nextCh);
continue;
}
if (ch != '$' || nextCh != '{')
{
// variables begin with ${. Moving on.
sb.Append(ch);
continue;
}
varNameSb.Clear();
i += 2;
for (; i < template.Length; i++)
{
ch = template[i];
if (ch != '}')
{
varNameSb.Append(ch);
}
else
{
// Found the end of the variable substitution
var varName = varNameSb.ToString();
if (values.TryGetValue(varName, out var value))
{
sb.Append(value);
}
else
{
Log.LogWarning(null, null, null, TemplateFile,
line, 0, 0, 0,
message: $"No property value is available for '{varName}'");
}
varNameSb.Clear();
break;
}
}
if (varNameSb.Length > 0)
{
Log.LogWarning(null, null, null, TemplateFile,
line, 0, 0, 0,
message: "Expected closing bracket for variable placeholder. No substitution will be made.");
sb.Append("${").Append(varNameSb);
}
}
return sb.ToString();
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(NetCoreAppToolCurrent)</TargetFramework>
<OutputType>Library</OutputType>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn),CA1050</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build" Version="$(RefOnlyMicrosoftBuildVersion)" />
<PackageReference Include="Microsoft.Build.Framework" Version="$(RefOnlyMicrosoftBuildFrameworkVersion)" />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="$(RefOnlyMicrosoftBuildTasksCoreVersion)" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(RefOnlyMicrosoftBuildUtilitiesCoreVersion)" />
</ItemGroup>
<Target Name="PublishBuilder"
AfterTargets="Build"
DependsOnTargets="Publish" />
</Project>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册