Support running KoreBuild on full msbuild (#869)

These changes support using "MSBuild.exe" instead of "dotnet msbuild" when building a repo with KoreBuild.  The default still remains `dotnet msbuild`, so this is an opt-in change for repos.

### Usage:

In korebuild.json, add the following:

```json
{
  "msbuildType": "full"
}
```

_This only applies to Windows builds._

## Changes in this PR:
* Remove unused tasks and targets (reduces what we had to port to .NET Framework)
* Invoke VSWhere to find MSBuild.exe
* Back-port improvements to SourceLink and VSWhere tasks to reduce dependency on Json.Net
This commit is contained in:
Nate McMaster 2018-11-13 10:17:28 -08:00 коммит произвёл GitHub
Родитель c808c3c16c
Коммит 2444fbdf4f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
41 изменённых файлов: 379 добавлений и 780 удалений

Просмотреть файл

@ -90,8 +90,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiCheckForwardDestination"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Internal.AspNetCore.SiteExtension.Sdk", "src\Internal.AspNetCore.SiteExtension.Sdk\Internal.AspNetCore.SiteExtension.Sdk.csproj", "{418F99A5-5EC4-4895-B8EB-7F8BBA241DB2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.DotNet.GlobalTools.Sdk", "src\Microsoft.DotNet.GlobalTools.Sdk\Microsoft.DotNet.GlobalTools.Sdk.csproj", "{449E2FD8-AE30-4C4E-8FC2-E797B99CF339}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -162,10 +160,6 @@ Global
{418F99A5-5EC4-4895-B8EB-7F8BBA241DB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{418F99A5-5EC4-4895-B8EB-7F8BBA241DB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{418F99A5-5EC4-4895-B8EB-7F8BBA241DB2}.Release|Any CPU.Build.0 = Release|Any CPU
{449E2FD8-AE30-4C4E-8FC2-E797B99CF339}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{449E2FD8-AE30-4C4E-8FC2-E797B99CF339}.Debug|Any CPU.Build.0 = Debug|Any CPU
{449E2FD8-AE30-4C4E-8FC2-E797B99CF339}.Release|Any CPU.ActiveCfg = Release|Any CPU
{449E2FD8-AE30-4C4E-8FC2-E797B99CF339}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -188,7 +182,6 @@ Global
{02F548A6-B0E9-4F09-BC03-812FC3C8F0D2} = {B16B5072-3A0B-4527-8AB5-1C73A51684F7}
{605F0478-A9D2-4A8A-BB38-9D5DC132FBB5} = {60A938B2-D95A-403C-AA7A-3683AD64DFA0}
{418F99A5-5EC4-4895-B8EB-7F8BBA241DB2} = {A4F4353B-C3D2-40B0-909A-5B48A748EA76}
{449E2FD8-AE30-4C4E-8FC2-E797B99CF339} = {A4F4353B-C3D2-40B0-909A-5B48A748EA76}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1B8809C8-A6C3-4761-BC91-B12841F49AE1}

Просмотреть файл

@ -12,8 +12,6 @@
<NewtonsoftJsonPackageVersion>10.0.1</NewtonsoftJsonPackageVersion>
<NuGetPackagingPackageVersion>4.3.0</NuGetPackagingPackageVersion>
<NuGetProjectModelPackageVersion>4.3.0</NuGetProjectModelPackageVersion>
<SystemCollectionsImmutablePackageVersion>1.5.0</SystemCollectionsImmutablePackageVersion>
<SystemReflectionMetadataPackageVersion>1.5.0</SystemReflectionMetadataPackageVersion>
<VSWherePackageVersion>2.2.7</VSWherePackageVersion>
<XunitPackageVersion>2.3.1</XunitPackageVersion>
<XunitRunnerVisualStudioPackageVersion>2.3.1</XunitRunnerVisualStudioPackageVersion>

Просмотреть файл

@ -2,7 +2,8 @@
<Import Project="$(RepoTasksSdkPath)\Sdk.props" Condition="'$(RepoTasksSdkPath)' != '' "/>
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework Condition=" '$(MSBuildRuntimeType)' == 'core' ">netcoreapp2.1</TargetFramework>
<TargetFramework Condition=" '$(MSBuildRuntimeType)' != 'core' ">net46</TargetFramework>
<DefineConstants>$(DefineConstants);BuildTools</DefineConstants>
<NoWarn>$(NoWarn);NU1603</NoWarn>
</PropertyGroup>

Просмотреть файл

@ -18,6 +18,11 @@ FYI: targets, properties, and items that begin with an underscore are meant to b
<GetArtifactInfoDependsOn>$(GetArtifactInfoDependsOn);GetProjectArtifactInfo</GetArtifactInfoDependsOn>
</PropertyGroup>
<PropertyGroup>
<NuGetRestoreTargets Condition="'$(NuGetRestoreTargets)'=='' and '$([MSBuild]::IsRunningFromVisualStudio())'=='true'">$(MSBuildToolsPath32)\..\..\..\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.targets</NuGetRestoreTargets>
<NuGetRestoreTargets Condition="'$(NuGetRestoreTargets)'==''">$(MSBuildToolsPath)\NuGet.targets</NuGetRestoreTargets>
</PropertyGroup>
<!--
###################################################################
Targets: {Target}Projects
@ -57,7 +62,7 @@ Executes /t:{Target} on all projects
<!--
Invoke NuGet.targets directly. This avoids redundant calls the restore task.
-->
<MSBuild Projects="$(MSBuildToolsPath)\NuGet.targets"
<MSBuild Projects="$(NuGetRestoreTargets)"
Targets="Restore"
Properties="$(BuildProperties);RestoreGraphProjectInput=$(ProjectToBuildList);__BuildTarget=Restore"
RemoveProperties="$(_BuildPropertiesToRemove)"

Просмотреть файл

@ -2,7 +2,7 @@
<PropertyGroup>
<SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
<GenerateFullPaths Condition="'$(VSCODE_PID)' != ''">true</GenerateFullPaths>
<GenerateFullPaths Condition="'$(VSCODE_CWD)' != ''">true</GenerateFullPaths>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<!-- Set explicitly to make it clear that this is not a console app, even though it targets netcoreapp2.1 -->

Просмотреть файл

@ -1,25 +1,40 @@
<Project>
<PropertyGroup Condition="'$(MicrosoftBuildVersion)' == ''">
<!--
The dependency versions here don't matter as long as the version is binary compatible with the version of MSBuild and NuGet
already embedded in Microsoft.NET.Sdk. These are essentially reference assemblies.
<Choose>
<When Condition=" '$(MSBuildRuntimeType)' == 'Core' ">
Between MSBuild 15.6 and 15.8, the ref packages dropped .NET Standard 1.x suppport.
Use the netstandard2.0 packages if possible, otherwise fallback to 15.6.
-->
<MicrosoftBuildVersion Condition="$(TargetFramework.StartsWith('netstandard1'))">15.6.82</MicrosoftBuildVersion>
<MicrosoftBuildVersion Condition="'$(MicrosoftBuildVersion)' == ''">15.8.166</MicrosoftBuildVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(MicrosoftBuildVersion)' == ''">
<!--
The dependency versions here don't matter as long as the version is binary compatible with the version of MSBuild and NuGet
already embedded in Microsoft.NET.Sdk. These are essentially reference assemblies.
<ItemGroup Condition="'$(DisableImplicitFrameworkReferences)' != 'true'">
<!-- set as private assets all since we don't need this in the publish output folder -->
<PackageReference Include="Microsoft.Build" Version="$(MicrosoftBuildVersion)" IsImplicitlyDefined="true" PrivateAssets="All" />
<PackageReference Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildVersion)" IsImplicitlyDefined="true" PrivateAssets="All" />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="$(MicrosoftBuildVersion)" IsImplicitlyDefined="true" PrivateAssets="All" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildVersion)" IsImplicitlyDefined="true" PrivateAssets="All" />
<!-- because almost everyone ends up using JSON in repo tasks -->
<PackageReference Include="Newtonsoft.Json" Version="$(JsonInMSBuildVersion)" IsImplicitlyDefined="true" PrivateAssets="All" />
</ItemGroup>
Between MSBuild 15.6 and 15.8, the ref packages dropped .NET Standard 1.x suppport.
Use the netstandard2.0 packages if possible, otherwise fallback to 15.6.
-->
<MicrosoftBuildVersion Condition="$(TargetFramework.StartsWith('netstandard1'))">15.6.82</MicrosoftBuildVersion>
<MicrosoftBuildVersion Condition="'$(MicrosoftBuildVersion)' == ''">15.8.166</MicrosoftBuildVersion>
</PropertyGroup>
<ItemGroup Condition="'$(DisableImplicitFrameworkReferences)' != 'true'">
<!-- set as private assets all since we don't need this in the publish output folder -->
<PackageReference Include="Microsoft.Build" Version="$(MicrosoftBuildVersion)" IsImplicitlyDefined="true" PrivateAssets="All" />
<PackageReference Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildVersion)" IsImplicitlyDefined="true" PrivateAssets="All" />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="$(MicrosoftBuildVersion)" IsImplicitlyDefined="true" PrivateAssets="All" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildVersion)" IsImplicitlyDefined="true" PrivateAssets="All" />
<!-- because almost everyone ends up using JSON in repo tasks -->
<PackageReference Include="Newtonsoft.Json" Version="$(JsonInMSBuildVersion)" IsImplicitlyDefined="true" PrivateAssets="All" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup Condition="'$(DisableImplicitFrameworkReferences)' != 'true'">
<Reference Include="Microsoft.Build" />
<Reference Include="Microsoft.Build.Framework" />
<Reference Include="Microsoft.Build.Tasks.v4.0" />
<Reference Include="Microsoft.Build.Utilities.v4.0" />
<!-- because almost everyone ends up using JSON in repo tasks -->
<PackageReference Include="Newtonsoft.Json" Version="$(JsonInMSBuildVersion)" IsImplicitlyDefined="true" PrivateAssets="All" />
</ItemGroup>
</Otherwise>
</Choose>
</Project>

Просмотреть файл

@ -92,6 +92,7 @@ function Invoke-RepositoryBuild(
/nologo
/m
/nodeReuse:false
/verbosity:minimal
/p:KoreBuildVersion=$koreBuildVersion
/p:SuppressNETCoreSdkPreviewMessage=true
/p:RepositoryRoot="$Path/"
@ -131,7 +132,7 @@ function Invoke-RepositoryBuild(
Write-Verbose "Invoking msbuild with '$(Get-Content $msBuildResponseFile)'"
__exec $global:dotnet msbuild `@"$msBuildResponseFile" `@"$msBuildLogRspFile"
Invoke-MSBuild `@"$msBuildResponseFile" `@"$msBuildLogRspFile"
}
finally {
Pop-Location
@ -324,14 +325,35 @@ function Set-KoreBuildSettings(
$arch = __get_dotnet_arch
$env:DOTNET_ROOT = if ($IS_WINDOWS) { Join-Path $DotNetHome $arch } else { $DotNetHome }
$MSBuildType = 'core'
$toolsets = $Null
if (Test-Path $ConfigFile) {
try {
$config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json
if (__has_member $config msbuildType) {
[string] $MSBuildType = $config.msbuildType
}
if (__has_member $config toolsets) {
$toolsets = $config.toolsets
}
}
catch {
Write-Host -ForegroundColor Red $Error[0]
Write-Error "$ConfigFile contains invalid JSON."
exit 1
}
}
# Workaround perpetual issues in node reuse and custom task assemblies
$env:MSBUILDDISABLENODEREUSE = 1
$global:KoreBuildSettings = @{
MSBuildType = $MSBuildType
ToolsSource = $ToolsSource
DotNetHome = $DotNetHome
RepoPath = $RepoPath
CI = $CI
Toolsets = $toolsets
}
}
@ -364,7 +386,7 @@ function Invoke-KoreBuildCommand(
$sdkVersion = __get_dotnet_sdk_version
$korebuildVersion = Get-KoreBuildVersion
if ($sdkVersion -ne 'latest') {
"{ `"sdk`": { `n`"version`": `"$sdkVersion`" },`n`"msbuild-sdks`": {`n`"Microsoft.DotNet.GlobalTools.Sdk`": `"$korebuildVersion`"}`n }" | Out-File (Join-Path $global:KoreBuildSettings.RepoPath 'global.json') -Encoding ascii
"{ `"sdk`": { `n`"version`": `"$sdkVersion`" }`n }" | Out-File (Join-Path $global:KoreBuildSettings.RepoPath 'global.json') -Encoding ascii
}
else {
Write-Verbose "Skipping global.json generation because the `$sdkVersion = $sdkVersion"
@ -397,13 +419,87 @@ function Invoke-KoreBuildCommand(
}
}
#
# Private functions
#
function Get-KoreBuildConsole() {
return Join-Paths $PSScriptRoot ("..", "tools", "KoreBuild.Console.dll")
}
#
# Private functions
#
function Invoke-MSBuild {
if ($global:KoreBuildSettings.MSBuildType -eq 'full') {
if (-not (Test-Path 'Variable:\script:msbuild')) {
$script:msbuild = Get-MSBuildPath
}
__exec $script:msbuild @args
}
else {
__exec $global:dotnet msbuild @args
}
}
function Get-MSBuildPath() {
$vswherePath = "${env:ProgramFiles(x86)}/Microsoft Visual Studio/Installer/vswhere.exe"
if (-not (Test-Path $vswherePath)) {
$vswherePath = "$PSScriptRoot/../modules/KoreBuild.Tasks/vswhere.exe"
}
if (-not (Test-Path $vswherePath)) {
# Couldn't use vswhere, return 'msbuild.exe' and let PATH do its thing.
Write-Verbose "Could not find VSWhere. Relying on MSBuild to exist on PATH"
return 'msbuild.exe'
}
[string[]] $vswhereArgs = @('-latest', '-format', 'json', '-products', '*')
if ($global:KoreBuildSettings.Toolsets -and (__has_member $global:KoreBuildSettings.Toolsets visualstudio)) {
$vs = $global:KoreBuildSettings.Toolsets.visualstudio
if ((__has_member $vs includePrerelease) -and $vs.includePrerelease) {
$vswhereArgs += '-prerelease'
}
if (__has_member $vs minVersion) {
$vswhereArgs += '-version', $vs.minVersion
}
if (__has_member $vs versionRange) {
$vswhereArgs += '-version', $vs.versionRange
}
if (__has_member $vs requiredWorkloads) {
foreach ($workload in $vs.requiredWorkloads) {
$vswhereArgs += '-requires', $workload
}
}
}
Write-Verbose "vswhere = $vswherePath $vswhereArgs"
$installations = & $vswherePath @vswhereArgs | ConvertFrom-Json
$latest = $null
if ($installations) {
$latest = $installations | Select-Object -first 1
}
if ($latest -and (__has_member $latest installationPath)) {
Write-Host "Detected $($latest.displayName) ($($latest.installationVersion)) in '$($latest.installationPath)'"
$msbuildVersions = @('Current', '16.0', '15.0')
foreach ($msbuildVersion in $msbuildVersions) {
$msbuildPath = Join-Paths $latest.installationPath ('MSBuild', $msbuildVersion, 'Bin', 'msbuild.exe')
if (Test-Path $msbuildPath) {
Write-Verbose "Using MSBuild.exe = $msbuildPath"
return $msbuildPath
}
}
}
return 'msbuild.exe'
}
function __has_member($obj, $name) {
return [bool](Get-Member -Name $name -InputObject $obj)
}
function __get_dotnet_arch {
if ($env:KOREBUILD_DOTNET_ARCH) {
@ -430,7 +526,7 @@ function __build_task_project($RepoPath, [string[]]$msbuildArgs) {
$sdkPath = "-p:RepoTasksSdkPath=$(Join-Paths $PSScriptRoot ('..', 'msbuild', 'KoreBuild.RepoTasks.Sdk', 'Sdk'))"
__exec $global:dotnet publish $taskProj --configuration Release --output $publishFolder -nologo $sdkPath @msbuildArgs
Invoke-MSBuild $taskProj '-v:m' -restore '-t:Publish' '-p:Configuration=Release' "-p:PublishDir=$publishFolder" -nologo $sdkPath @msbuildArgs
}
function Get-KoreBuildVersion {

Просмотреть файл

@ -62,13 +62,10 @@ sdk_version="$(__get_dotnet_sdk_version)"
korebuild_version="$(__get_korebuild_version)"
if [ "$sdk_version" != 'latest' ]; then
echo "{
\"sdk\": {
\"version\": \"${sdk_version}\"
},
\"msbuild-sdks\": {
\"Microsoft.DotNet.GlobalTools.Sdk\": \"${korebuild_version}\"
}
}" > "$repo_path/global.json"
\"sdk\": {
\"version\": \"${sdk_version}\"
}
}" > "$repo_path/global.json"
else
__verbose "Skipping global.json generation because the \$sdk_version = $sdk_version"
fi

Просмотреть файл

@ -1,27 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<DefineConstants>$(DefineConstants);BuildTools</DefineConstants>
<Description>MSBuild tasks. This package is intended for Microsoft use only</Description>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFrameworks>netcoreapp2.1;net46</TargetFrameworks>
<RootNamespace>Microsoft.AspNetCore.BuildTools</RootNamespace>
<AssemblyName>Internal.AspNetCore.BuildTools.Tasks</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\shared\Utilities\MSBuildListSplitter.cs" />
<Compile Include="..\..\shared\Microsoft.Extensions.CommandLineUtils.Sources\**\*.cs" />
<None Include="module.props" CopyToPublishDirectory="PreserveNewest" />
<None Include="BuildTools.Tasks.props" CopyToPublishDirectory="PreserveNewest" />
<None Include="*.targets" CopyToPublishDirectory="PreserveNewest" />
<Compile Include="..\..\shared\Microsoft.Extensions.CommandLineUtils.Sources\Utilities\*.cs" />
</ItemGroup>
<ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
<PackageReference Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildFrameworkPackageVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildUtilitiesCorePackageVersion)" PrivateAssets="All" />
<PackageReference Include="Newtonsoft.Json" Version="$(Tooling_NewtonsoftJsonPackageVersion)" />
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutablePackageVersion)" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataPackageVersion)" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net46'">
<Reference Include="System.IO.Compression" />
<Reference Include="Microsoft.Build.Framework" />
<Reference Include="Microsoft.Build.Utilities.v4.0" />
</ItemGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
<Import Project="Publish.targets" Condition=" '$(TargetFramework)' == '' " />
</Project>

Просмотреть файл

@ -6,18 +6,12 @@
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)GetGitBranch" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)GetGitCommitHash" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)GetGitCommitInfo" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)GetDotNetHost" AssemblyFile="$(_BuildToolsAssembly)"
Condition="'$(MSBuildRuntimeType)' == 'Core'"/>
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)GetOSPlatform" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)GenerateSvgBadge" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)JsonPeek" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)SetEnvironmentVariable" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)UpdatePackageSource" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)WaitForDebugger" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)ZipArchive" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)UnzipArchive" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)FindUnusedReferences" AssemblyFile="$(_BuildToolsAssembly)"
Condition="'$(MSBuildRuntimeType)' == 'Core'" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)CreateSourceLink" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)Run" AssemblyFile="$(_BuildToolsAssembly)" />
<UsingTask TaskName="Microsoft.AspNetCore.BuildTools.$(_BuildTasksPrefix)RunDotNet" AssemblyFile="$(_BuildToolsAssembly)" />

Просмотреть файл

@ -2,11 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Microsoft.AspNetCore.BuildTools
{
@ -51,20 +51,51 @@ namespace Microsoft.AspNetCore.BuildTools
SourceLinkRoot += '*';
var codeSource = ConvertUrl();
var data = new JObject
var mappings = new List<Mapping>
{
["documents"] = new JObject
{
[SourceLinkRoot] = codeSource
}
new Mapping { LocalPath = SourceLinkRoot, Url = codeSource },
};
File.WriteAllText(DestinationFile, data.ToString(Formatting.None));
GenerateSourceLink(DestinationFile, mappings);
SourceLinkFile = DestinationFile;
return true;
}
private static void GenerateSourceLink(string filePath, List<Mapping> mappings)
{
var data = new StringBuilder();
data.Append("{\"documents\":{");
// not bullet-proof, but should be good enough for escaping paths
string JsonEscape(string str)
=> str.Replace(@"\", @"\\").Replace("\"", "\\\"");
var first = true;
foreach (var mapping in mappings)
{
if (first)
{
first = false;
}
else
{
data.Append(",");
}
data
.Append('"')
.Append(JsonEscape(mapping.LocalPath))
.Append("\":\"")
.Append(JsonEscape(mapping.Url))
.Append('"');
}
data.Append("}}");
File.WriteAllText(filePath, data.ToString());
}
private string ConvertUrl()
{
if (!OriginUrl.Contains("github.com"))
@ -82,5 +113,11 @@ namespace Microsoft.AspNetCore.BuildTools
return $"https://raw.githubusercontent.com/{repoName}/{Commit}/*";
}
private struct Mapping
{
public string LocalPath;
public string Url;
}
}
}

Просмотреть файл

@ -1,87 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#if NETCOREAPP2_1
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.AspNetCore.BuildTools
{
#if SDK
public class Sdk_FindUnusedReferences : Task
#elif BuildTools
public class FindUnusedReferences : Task
#else
#error This must be built either for an SDK or for BuildTools
#endif
{
/// <summary>
/// IntermediateAssembly from CoreCompile
/// </summary>
[Required]
public string Assembly { get; set; }
/// <summary>
/// ReferencePath from CoreCompile
/// </summary>
[Required]
public ITaskItem[] References { get; set; }
/// <summary>
/// FileDefinitions from RunResolvePackageDependencies
/// </summary>
[Required]
public ITaskItem[] Packages { get; set; }
/// <summary>
/// PackageDependencies from RunResolvePackageDependencies
/// </summary>
[Required]
public ITaskItem[] Files { get; set; }
[Output]
public ITaskItem[] UnusedReferences { get; set; }
public override bool Execute()
{
var references = new HashSet<string>(References.Select(item => item.ItemSpec), StringComparer.OrdinalIgnoreCase);
var referenceFiles = Files.Where(file => references.Contains(file.GetMetadata("ResolvedPath")))
.ToDictionary(item => Path.GetFileNameWithoutExtension(item.GetMetadata("ResolvedPath")), StringComparer.OrdinalIgnoreCase);
var directReferences = new HashSet<string>(
Packages.Where(p => string.IsNullOrEmpty(p.GetMetadata("ParentPackage"))).Select(i => i.ItemSpec),
StringComparer.OrdinalIgnoreCase);
using (var fileStream = File.OpenRead(Assembly))
using (var reader = new PEReader(fileStream))
{
var metadataReader = reader.GetMetadataReader();
foreach (AssemblyReferenceHandle assemblyReferenceHandle in metadataReader.AssemblyReferences)
{
var assemblyReference = metadataReader.GetAssemblyReference(assemblyReferenceHandle);
var name = metadataReader.GetString(assemblyReference.Name);
if (referenceFiles.TryGetValue(name, out var fileItem))
{
var packageName = fileItem.GetMetadata("PackageName") + "/" + fileItem.GetMetadata("PackageVersion");
directReferences.Remove(packageName);
referenceFiles.Remove(name);
}
}
}
UnusedReferences = referenceFiles.Values.Where(f => directReferences.Any(r => f.ItemSpec.StartsWith(r))).ToArray();
return true;
}
}
}
#elif NET46
#else
#error Target frameworks should be updated
#endif

Просмотреть файл

@ -1,71 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#if NETCOREAPP2_1
using System.IO;
using Microsoft.AspNetCore.BuildTools.Utilities;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.Extensions.CommandLineUtils;
namespace Microsoft.AspNetCore.BuildTools
{
/// <summary>
/// <para>
/// Uses the current runtime information to find the "dotnet.exe" path.
/// This requires that MSBuild itself execute on top of Microsoft.NETCore.App.
/// </para>
/// <para>
/// This code is modeled of this API: https://github.com/dotnet/cli/blob/rel/1.0.0/src/Microsoft.DotNet.Cli.Utils/Muxer.cs.
/// We don't use this API directly as using Microsoft.DotNet.Cli.Utils with MSBuild causes assembly loading issues.
/// </para>
/// <para>
/// Also, this task may be not be necessary in future releases. At the time of writing, however, this
/// feature does not exist in MSBuild of the .NET Core SDK. See https://github.com/Microsoft/msbuild/issues/1669
/// and https://github.com/dotnet/sdk/issues/20
/// </para>
/// </summary>
#if SDK
public class Sdk_GetDotNetHost : Task
#elif BuildTools
public class GetDotNetHost : Task
#else
#error This must be built either for an SDK or for BuildTools
#endif
{
/// <summary>
/// The full path to "dotnet.exe"
/// </summary>
[Output]
public string ExecutablePath { get; set; }
/// <summary>
/// The folder containing "dotnet.exe". This is the directory also contains shared frameworks and SDKs.
/// </summary>
[Output]
public string DotNetDirectory { get; set; }
public override bool Execute()
{
ExecutablePath = DotNetMuxer.MuxerPath;
if (ExecutablePath == null)
{
Log.LogError("Failed to find the .NET Core installation");
return false;
}
DotNetDirectory = FileHelpers.EnsureTrailingSlash(Path.GetDirectoryName(ExecutablePath));
Log.LogMessage(MessageImportance.Low, "Found dotnet muxer in '{0}'", DotNetDirectory);
return File.Exists(ExecutablePath);
}
}
}
#elif NET46
#else
#error Target frameworks should be updated
#endif

Просмотреть файл

@ -1,52 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#if !NET46
using System.Runtime.InteropServices;
#endif
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.AspNetCore.BuildTools
{
#if SDK
public class Sdk_GetOSPlatform : Task
#elif BuildTools
public class GetOSPlatform : Task
#else
#error This must be built either for an SDK or for BuildTools
#endif
{
[Output]
public string PlatformName { get; set; }
public override bool Execute()
{
#if NET46
// MSBuild.exe only runs on Windows. This task doesn't support xbuild, only dotnet-msbuild and MSBuild.exe.
PlatformName = "Windows";
#elif NETCOREAPP2_1
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
PlatformName = "Windows";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
PlatformName = "Linux";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
PlatformName = "macOS";
}
else
{
Log.LogError("Failed to determine the platform on which the build is running");
return false;
}
#else
#error Target frameworks should be updated
#endif
return true;
}
}
}

Просмотреть файл

@ -1,96 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Microsoft.AspNetCore.BuildTools
{
#if SDK
public class Sdk_JsonPeek : Task
#elif BuildTools
public class JsonPeek : Task
#else
#error This must be built either for an SDK or for BuildTools
#endif
{
/// <summary>
/// Specifies the JSONPath query.
/// </summary>
[Required]
public string Query { get; set; }
/// <summary>
/// Specifies the JSON input as a file path.
/// </summary>
public string JsonInputPath { get; set; }
/// <summary>
/// Specifies the JSON input as a string.
/// </summary>
public string JsonContent { get; set; }
/// <summary>
/// Contains the results that are returned by this task.
/// </summary>
[Output]
public ITaskItem[] Result { get; set; }
public override bool Execute()
{
// pre-set the result in case we exit early
Result = Array.Empty<ITaskItem>();
if (!string.IsNullOrEmpty(JsonInputPath) && !string.IsNullOrEmpty(JsonContent))
{
Log.LogError($"Cannot specify both {nameof(JsonInputPath)} and {nameof(JsonContent)}.");
return false;
}
try
{
JToken token;
if (!string.IsNullOrEmpty(JsonContent))
{
token = JToken.Parse(JsonContent);
}
else
{
if (!File.Exists(JsonInputPath))
{
Log.LogError("File does not exist: {path}", JsonInputPath);
return false;
}
using (var stream = File.OpenRead(JsonInputPath))
using (var reader = new StreamReader(stream))
using (var json = new JsonTextReader(reader))
{
token = JToken.ReadFrom(json);
}
}
var results = new List<ITaskItem>();
foreach (var result in token.SelectTokens(Query))
{
var item = new TaskItem(result.ToString());
item.SetMetadata("Type", result.Type.ToString());
results.Add(item);
}
Result = results.ToArray();
return true;
}
catch (JsonException ex)
{
Log.LogErrorFromException(ex, showStackTrace: false);
return false;
}
}
}
}

Просмотреть файл

@ -0,0 +1,19 @@
<Project>
<Target Name="Publish">
<ItemGroup>
<ContentFiles Include="module.props" />
<ContentFiles Include="module.targets" />
<ContentFiles Include="BuildTools.Tasks.props" />
<ContentFiles Include="Project.CSharp.Resx.targets" />
<_TargetFramework Remove="@(_TargetFramework)" />
<_TargetFramework Include="$(TargetFrameworks)" />
</ItemGroup>
<Copy SourceFiles="@(ContentFiles)" DestinationFolder="$(PublishDir)" />
<MSBuild Projects="$(MSBuildProjectFullPath)"
Targets="Publish"
Properties="PublishDir=$(PublishDir)%(_TargetFramework.Identity)\;TargetFramework=%(_TargetFramework.Identity)" />
</Target>
</Project>

Просмотреть файл

@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.BuildTools
var entry = zip.CreateEntryFromFile(file.ItemSpec, entryName);
#if NET46
#elif NETCOREAPP2_1
#elif NETCOREAPP2_1 || NETSTANDARD2_0
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// This isn't required when creating a zip on Windows. unzip will check which

Просмотреть файл

@ -1,7 +1,8 @@
<Project>
<PropertyGroup>
<_BuildToolsAssembly>$(MSBuildThisFileDirectory)Internal.AspNetCore.BuildTools.Tasks.dll</_BuildToolsAssembly>
<_BuildToolsAssembly Condition="'$(MSBuildRuntimeType)' == 'core' ">$(MSBuildThisFileDirectory)netcoreapp2.1\Internal.AspNetCore.BuildTools.Tasks.dll</_BuildToolsAssembly>
<_BuildToolsAssembly Condition="'$(MSBuildRuntimeType)' != 'core' ">$(MSBuildThisFileDirectory)net46\Internal.AspNetCore.BuildTools.Tasks.dll</_BuildToolsAssembly>
<_BuildTasksPrefix></_BuildTasksPrefix>
</PropertyGroup>

Просмотреть файл

@ -6,7 +6,6 @@
<ItemGroup>
<Projects Include="$(MSBuildThisFileDirectory)..\..\src\Internal.AspNetCore.Sdk\Internal.AspNetCore.Sdk.csproj" />
<Projects Include="$(MSBuildThisFileDirectory)..\..\src\ApiCheck.Console\ApiCheck.Console.csproj" />
<Projects Include="$(MSBuildThisFileDirectory)..\..\src\Microsoft.DotNet.GlobalTools.Sdk\Microsoft.DotNet.GlobalTools.Sdk.csproj" />
</ItemGroup>
<MSBuild Projects="@(Projects)"
@ -31,8 +30,6 @@
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<Sdk Name="Microsoft.DotNet.GlobalTools.Sdk" Version="$(Version)" />
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Internal.AspNetCore.KoreBuild.Tasks</AssemblyName>
</PropertyGroup>
@ -25,7 +25,7 @@
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="$(MicrosoftBuildTasksCorePackageVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildUtilitiesCorePackageVersion)" PrivateAssets="All" />
<PackageReference Include="NuGet.Build.Tasks" Version="$(Tooling_NuGetBuildTasksPackageVersion)" PrivateAssets="All" />
<PackageReference Include="Newtonsoft.Json" Version="$(Tooling_NewtonsoftJsonPackageVersion)" PrivateAssets="All" />
<PackageReference Include="Newtonsoft.Json" Version="$(Tooling_NewtonsoftJsonPackageVersion)" />
<PackageReference Include="vswhere" Version="$(VSWherePackageVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.DotNet.SignTool" Version="$(MicrosoftDotNetSignToolPackageVersion)" ExcludeAssets="All" PrivateAssets="All" />
<PackageReference Include="Microsoft.DotNet.SignCheck" Version="$(MicrosoftDotNetSignCheckPackageVersion)" ExcludeAssets="All" PrivateAssets="All" />

Просмотреть файл

@ -26,6 +26,25 @@ namespace KoreBuild.Tasks.Utilities
args.Add("-prerelease");
}
args.Add("-products");
args.Add("*");
return GetInstallations(args, log).FirstOrDefault();
}
public static VsInstallation FindLatestInstallation(bool includePrerelease, string vsProductVersion, TaskLoggingHelper log)
{
var args = new List<string>
{
"-latest",
};
if (includePrerelease)
{
args.Add("-prerelease");
}
args.Add("-products");
args.Add($"Microsoft.VisualStudio.Product.{vsProductVersion}");
return GetInstallations(args, log).FirstOrDefault();
}
@ -38,10 +57,10 @@ namespace KoreBuild.Tasks.Utilities
args.Add("-prerelease");
}
if (!string.IsNullOrEmpty(toolset.MinVersion))
if (TryGetVersion(toolset, out var version))
{
args.Add("-version");
args.Add(toolset.MinVersion);
args.Add(version);
}
if (toolset.RequiredWorkloads != null)
@ -56,6 +75,28 @@ namespace KoreBuild.Tasks.Utilities
return GetInstallations(args, log).FirstOrDefault();
}
// Internal for testing
internal static bool TryGetVersion(KoreBuildSettings.VisualStudioToolset toolset, out string version)
{
if (!string.IsNullOrEmpty(toolset.VersionRange))
{
// This is the same as MinVersion but the name indicates that a user can specify more than just
// a min version. For example: [15.0,16.0) will find versions 15.*.
version = toolset.VersionRange;
return true;
}
if (!string.IsNullOrEmpty(toolset.MinVersion))
{
// Here for back compatibility.
version = toolset.MinVersion;
return true;
}
version = null;
return false;
}
private static VsInstallation[] GetInstallations(List<string> args, TaskLoggingHelper log)
{
args.Add("-format");

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>NuGetPackageVerifier.Task</AssemblyName>
</PropertyGroup>

Просмотреть файл

@ -1,8 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// System.AppContext.GetData is not available in these frameworks
#if !NET451 && !NET452 && !NET46 && !NET461
using System;
using System.Diagnostics;
@ -39,10 +37,16 @@ namespace Microsoft.Extensions.CommandLineUtils
private static string TryFindMuxerPath()
{
var fileName = MuxerName;
#if NET46
fileName += ".exe";
#elif NETCOREAPP2_1 || NETSTANDARD2_0
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
fileName += ".exe";
}
#else
#error Update target frameworks
#endif
var mainModule = Process.GetCurrentProcess().MainModule;
if (!string.IsNullOrEmpty(mainModule?.FileName)
@ -51,8 +55,16 @@ namespace Microsoft.Extensions.CommandLineUtils
return mainModule.FileName;
}
var dotnetRoot = Environment.GetEnvironmentVariable("DOTNET_ROOT")
?? Environment.GetEnvironmentVariable("DOTNET_CLI_HOME")
?? Environment.GetEnvironmentVariable("DOTNET_HOME");
if (!string.IsNullOrEmpty(dotnetRoot))
{
return Path.Combine(dotnetRoot, fileName);
}
return null;
}
}
}
#endif

Просмотреть файл

@ -20,19 +20,15 @@
<Compile Include="..\..\shared\Utilities\MSBuildListSplitter.cs" />
</ItemGroup>
<ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
<PackageReference Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildFrameworkPackageVersion)" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildUtilitiesCorePackageVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(Tooling_NewtonsoftJsonPackageVersion)" />
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutablePackageVersion)" PrivateAssets="All" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataPackageVersion)" PrivateAssets="All" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net46'">
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="Microsoft.Build.Framework" />
<Reference Include="Microsoft.Build.Utilities.v4.0" />
</ItemGroup>
<Target Name="SetPackageDependencies" BeforeTargets="GenerateNuspec">

Просмотреть файл

@ -13,7 +13,6 @@ For single-tfm projects, this will be imported from build/Internal.AspNetCore.Sd
<PropertyGroup>
<!-- Suppress warnings about using semver 2.0 versions in packages -->
<NoWarn>$(NoWarn);NU5105</NoWarn>
<IncludeSymbols Condition="'$(NuspecFile)'!=''">false</IncludeSymbols>
</PropertyGroup>
<PropertyGroup Condition=" '$(IncludeSymbols)' != 'false' ">

Просмотреть файл

@ -1,15 +0,0 @@
<!--
WARNING: These targets are intended for building Microsoft's ASP.NET Core repos and are not intended
for use outside of Microsoft.
-->
<Project>
<Target Name="FindUnusedReferences"
AfterTargets="CoreCompile"
DependsOnTargets="RunResolvePackageDependencies"
Condition=" '$(EnableFindUnusedReferences)' == 'true' and '$(MSBuildRuntimeType)' == 'Core' ">
<Sdk_FindUnusedReferences Assembly="@(IntermediateAssembly)" References="@(ReferencePath)" Packages="@(PackageDependencies)" Files="@(FileDefinitions)" >
<Output TaskParameter="UnusedReferences" ItemName="UnusedReferences" />
</Sdk_FindUnusedReferences>
<Warning Condition="'@(UnusedReferences)' != ''" Text="Unused reference in $(MSBuildProjectFile)/$(TargetFramework) %(UnusedReferences.Identity) from package %(UnusedReferences.PackageName)" />
</Target>
</Project>

Просмотреть файл

@ -5,7 +5,6 @@ for use outside of Microsoft.
<Project>
<Import Project="$(MSBuildThisFileDirectory)Common.targets" />
<Import Project="$(MSBuildThisFileDirectory)ApiCheck.targets" />
<Import Project="$(MSBuildThisFileDirectory)FindUnusedReferences.targets" />
<Import Project="$(MSBuildThisFileDirectory)GenerateAssemblyInfo.targets" />
<Import Project="$(MSBuildThisFileDirectory)Git.targets" />

Просмотреть файл

@ -1,27 +0,0 @@
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<NuspecFile>$(MSBuildThisFileDirectory)$(MSBuildProjectName).nuspec</NuspecFile>
<Serviceable>false</Serviceable>
<NoPackageAnalysis>true</NoPackageAnalysis>
<IncludeBuildOutput>false</IncludeBuildOutput>
<IncludeSource>false</IncludeSource>
<IncludeSymbols>false</IncludeSymbols>
</PropertyGroup>
<Target Name="SetPackageProperties" BeforeTargets="GenerateNuspec">
<PropertyGroup>
<NuspecProperties>$(NuspecProperties);id=$(PackageId)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);version=$(PackageVersion)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);copyright=$(Copyright)</NuspecProperties>
</PropertyGroup>
</Target>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
<Target Name="Compile" />
<Target Name="CopyFilesToOutputDirectory" />
</Project>

Просмотреть файл

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>$id$</id>
<version>$version$</version>
<authors>Microsoft</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Provides additional support to .NET Core teams producing global CLI tools. This package is only intended for internal Microsoft use.</description>
<copyright>$copyright$</copyright>
<packageTypes>
<!-- This project needs to be MSBuildSdk because its targets need to influence the way /t:Restore works -->
<packageType name="MSBuildSdk" />
</packageTypes>
</metadata>
<files>
<file src="_._" target="lib/netstandard1.0/_._" />
<file src="sdk\**\*" target="sdk/" />
</files>
</package>

Просмотреть файл

@ -1,43 +0,0 @@
Microsoft.DotNet.GlobalTools.Sdk
================================
Provides additional support to .NET Core teams producing global CLI tools. This package is only intended for internal Microsoft use.
## Usage
Projects that need to bundle and sign the global CLI tool shim should add this to their .csproj file. This will include files in the .nupkg.
```xml
<!-- In MyTool.csproj -->
<Project>
<Sdk Name="Microsoft.NET.Sdk" />
<Sdk Name="Microsoft.DotNet.GlobalTools.Sdk" />
<PropertyGroup>
<PackAsTool>true</PackAsTool>
<GenerateToolShims>true</GenerateToolShims>
</PropertyGroup>
</Project>
```
```js
// in global.json
{
"msbuild-sdks": {
"Microsoft.DotNet.GlobalTools.Sdk": "2.1.0-rtm-12345"
}
}
```
### Additional options
#### `GenerateToolShims` (property)
A boolean flag. When `true`, tool shims will be generated for each RID listed in `GeneratedShimRuntimeIdentifiers` and included in the .nupkg.
Default value = `false`
#### `GeneratedShimRuntimeIdentifiers` (property)
A semi-colon separate list of RIDs for which to generate and pack the shim.
Default value = `win-x86;win-x64`

Просмотреть файл

Просмотреть файл

@ -1,10 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<ItemGroup Condition="'$(DisableImplicitFrameworkReferences)' != 'true'">
<PackageReference Include="Microsoft.NETCore.DotNetAppHost" Version="$(MicrosoftNETCoreDotNetAppHostImplicitPackageVersion)" PrivateAssets="All" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,104 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);GetDotNetToolShimPackageContent</TargetsForTfmSpecificContentInPackage>
</PropertyGroup>
<PropertyGroup>
<!--
Define the package version of Microsoft.NETCore.DotNetAppHost to match the shared runtime version
-->
<MicrosoftNETCoreDotNetAppHostImplicitPackageVersion Condition="'$(MicrosoftNETCoreDotNetAppHostImplicitPackageVersion)' == ''">$(RuntimeFrameworkVersion)</MicrosoftNETCoreDotNetAppHostImplicitPackageVersion>
<!--
Only generate shims for these platforms.
-->
<GeneratedShimRuntimeIdentifiers Condition="'$(GeneratedShimRuntimeIdentifiers)' == ''">win-x86;win-x64</GeneratedShimRuntimeIdentifiers>
<!--
Define runtime identifiers to NuGet will restore the apphost for that RID.
-->
<RuntimeIdentifiers>$(RuntimeIdentifiers);$(GeneratedShimRuntimeIdentifiers)</RuntimeIdentifiers>
</PropertyGroup>
<!--
************************************************************
Target: GetDotNetToolShimPackageContent
Gets package content items for the global shim, without building anything.
************************************************************
-->
<Target Name="GetDotNetToolShimPackageContent" DependsOnTargets="_ComputeGeneratedDotNetToolShims">
<ItemGroup>
<!-- Add the file to the package -->
<TfmSpecificPackageFile Include="@(GeneratedDotNetToolShim)" />
</ItemGroup>
</Target>
<!--
************************************************************
Target: GenerateDotNetToolShims
Generates the dotnettool shims
************************************************************
-->
<Target Name="GenerateDotNetToolShims"
DependsOnTargets="_ComputeGeneratedDotNetToolShims;_CoreGenerateDotNetToolShim"
BeforeTargets="CoreCompile" />
<Target Name="_ComputeGeneratedDotNetToolShims">
<PropertyGroup>
<_NormalizedPackageVersion>$(PackageVersion)</_NormalizedPackageVersion>
<_NormalizedPackageVersion Condition="$(_NormalizedPackageVersion.Contains('+'))">$(_NormalizedPackageVersion.Substring($(_NormalizedPackageVersion.IndexOf('+'))))</_NormalizedPackageVersion>
</PropertyGroup>
<ItemGroup>
<_ShimRids Include="$(GeneratedShimRuntimeIdentifiers)" AppHostFileName="$(AssemblyName)" />
<_ShimRids Update="%(_ShimRids.Identity)" AppHostFileName="$(AssemblyName).exe" Condition="$([System.String]::new('%(_ShimRids.Identity)').StartsWith('win'))" />
<GeneratedDotNetToolShim Condition="'%(_ShimRids.Identity)' != ''" Include="$(IntermediateOutputPath)shims/%(_ShimRids.Identity)/%(_ShimRids.AppHostFileName)">
<RuntimeIdentifier>%(_ShimRids.Identity)</RuntimeIdentifier>
<OutputDir>$(IntermediateOutputPath)shims/%(_ShimRids.Identity)/</OutputDir>
<PackagePath>tools/$(TargetFramework)/any/shims/%(_ShimRids.Identity)/</PackagePath>
<RelativeAppBinaryFilePath>.store/$(PackageId.ToLowerInvariant())/$(_NormalizedPackageVersion)/$(PackageId.ToLowerInvariant())/$(_NormalizedPackageVersion)/tools/$(TargetFramework)/any/$(TargetFileName)</RelativeAppBinaryFilePath>
</GeneratedDotNetToolShim>
</ItemGroup>
</Target>
<!-- This task is defined in Microsoft.NET.Sdk -->
<UsingTask TaskName="EmbedAppNameInHost" AssemblyFile="$(MicrosoftNETBuildTasksAssembly)" />
<Target Name="_CoreGenerateDotNetToolShim"
DependsOnTargets="_ComputeGeneratedDotNetToolShims"
Inputs="$(MSBuildAllProjects);$(ProjectAssetsFile)"
Outputs="@(GeneratedDotNetToolShim)">
<MSBuild
Targets="_CoreGenerateDotNetToolShimForRid"
Projects="$(MSBuildProjectFullPath)"
Properties="
TargetFramework=$(TargetFramework);
RuntimeIdentifier=%(GeneratedDotNetToolShim.RuntimeIdentifier);
RuntimeFrameworkVersion=$(RuntimeFrameworkVersion);
_ShimRelativeAppBinaryFilePath=%(GeneratedDotNetToolShim.RelativeAppBinaryFilePath);
_ShimOutputDir=%(GeneratedDotNetToolShim.OutputDir)"
Condition="'%(GeneratedDotNetToolShim.Identity)' != ''" />
</Target>
<Target Name="_CoreGenerateDotNetToolShimForRid" DependsOnTargets="ResolvePackageAssets">
<ItemGroup>
<NativeRestoredAppHostNETCore Include="@(NativeCopyLocalItems)"
Condition="'%(NativeCopyLocalItems.FileName)%(NativeCopyLocalItems.Extension)' == '$(_DotNetAppHostExecutableName)'"/>
</ItemGroup>
<NETSdkError Condition="'@(NativeRestoredAppHostNETCore->Count())' &gt; 1"
ResourceName="MultipleFilesResolved"
FormatArguments="$(_DotNetAppHostExecutableName)" />
<EmbedAppNameInHost AppHostSourcePath="@(NativeRestoredAppHostNETCore)"
AppHostDestinationDirectoryPath="$(_ShimOutputDir)"
AppBinaryName="$(_ShimRelativeAppBinaryFilePath)"/>
</Target>
</Project>

Просмотреть файл

@ -1,10 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<Import
Project="Microsoft.DotNetTool.ShimGeneration.props"
Condition="'$(PackAsTool)' == 'true' AND '$(GenerateToolShims)' == 'true' AND '$(TargetFramework)' != ''" />
</Project>

Просмотреть файл

@ -1,10 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<Import
Project="Microsoft.DotNetTool.ShimGeneration.targets"
Condition="'$(PackAsTool)' == 'true' AND '$(GenerateToolShims)' == 'true' AND '$(TargetFramework)' != ''" />
</Project>

Просмотреть файл

@ -1,27 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
using System.IO;
using Microsoft.AspNetCore.BuildTools;
using Xunit;
namespace BuildTools.Tasks.Tests
{
public class GetDotNetHostTest
{
[Fact]
public void FindsMuxer()
{
var task = new GetDotNetHost
{
BuildEngine = new MockEngine()
};
Assert.True(task.Execute(), "Task failed");
var muxer = Process.GetCurrentProcess().MainModule.FileName;
Assert.Equal(muxer, task.ExecutablePath);
Assert.Equal(Path.GetDirectoryName(muxer) + Path.DirectorySeparatorChar, task.DotNetDirectory);
}
}
}

Просмотреть файл

@ -1,111 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using Microsoft.AspNetCore.BuildTools;
using Xunit;
namespace BuildTools.Tasks.Tests
{
public class JsonPeekTests
{
[Fact]
public void CanReadJsonFile()
{
var filepath = Path.Combine(AppContext.BaseDirectory, "Resources", "sampledata.json");
var task = new JsonPeek
{
BuildEngine = new MockEngine(),
JsonInputPath = filepath,
Query = "$.sdk.version"
};
Assert.True(task.Execute(), "Task should pass");
var result = Assert.Single(task.Result);
Assert.Equal("1.2.3", result.ItemSpec);
Assert.Equal("String", result.GetMetadata("Type"));
}
[Fact]
public void CanReadContent()
{
var filepath = Path.Combine(AppContext.BaseDirectory, "Resources", "sampledata.json");
var content = File.ReadAllText(filepath);
var task = new JsonPeek
{
BuildEngine = new MockEngine(),
JsonContent = content,
Query = "$.runtimes[*].version"
};
Assert.True(task.Execute(), "Task should pass");
Assert.Collection(task.Result,
i => Assert.Equal("1.0.0-beta", i.ItemSpec),
i => Assert.Equal("1.0.0-alpha", i.ItemSpec));
}
[Fact]
public void HandlesEmptyQuery()
{
var task = new JsonPeek
{
BuildEngine = new MockEngine(),
JsonContent = "{}",
Query = "$.dne.property.notthere"
};
Assert.True(task.Execute(), "Task should pass");
Assert.Empty(task.Result);
}
[Fact]
public void HandlesBadQuery()
{
var engine = new MockEngine { ContinueOnError = true };
var task = new JsonPeek
{
BuildEngine = engine,
JsonContent = "{}",
Query = "this is bad JSONPath syntax"
};
Assert.False(task.Execute(), "Task should not pass");
var error = Assert.Single(engine.Errors);
Assert.Contains("Unexpected character while parsing path", error.Message);
Assert.NotNull(task.Result);
}
[Fact]
public void HandlesBadJson()
{
var engine = new MockEngine { ContinueOnError = true };
var task = new JsonPeek
{
BuildEngine = engine,
JsonContent = "{ obj: }",
Query = ""
};
Assert.False(task.Execute(), "Task should not pass");
var error = Assert.Single(engine.Errors);
Assert.Contains("Unexpected character encountered while parsing value", error.Message);
Assert.NotNull(task.Result);
}
[Fact]
public void InvalidToSpecifyContentAndPath()
{
var task = new JsonPeek
{
BuildEngine = new MockEngine { ContinueOnError = true },
JsonInputPath = Path.Combine(AppContext.BaseDirectory, "Resources", "sampledata.json"),
JsonContent = "{}",
Query = ""
};
Assert.False(task.Execute(), "Task should not pass");
Assert.NotNull(task.Result);
}
}
}

Просмотреть файл

@ -17,7 +17,6 @@ namespace KoreBuild.FunctionalTests
"Internal.AspNetCore.Sdk",
"Internal.AspNetCore.SiteExtension.Sdk",
"Microsoft.AspNetCore.BuildTools.ApiCheck",
"Microsoft.DotNet.GlobalTools.Sdk",
};
private static readonly string _solutionDir;

Просмотреть файл

@ -4,6 +4,7 @@
using System.IO;
using System.Runtime.InteropServices;
using BuildTools.Tasks.Tests;
using KoreBuild.Tasks.Utilities;
using Xunit;
using Xunit.Abstractions;
@ -18,6 +19,57 @@ namespace KoreBuild.Tasks.Tests
_output = output;
}
[Fact]
public void TryGetVersion_ReturnsFalseWhenNoVersionsProvided()
{
// Arrange
var toolset = new KoreBuildSettings.VisualStudioToolset();
// Act
var result = VsWhere.TryGetVersion(toolset, out var version);
// Assert
Assert.False(result);
Assert.Null(version);
}
[Fact]
public void TryGetVersion_PrioritizesVersionRangeOverMinRange()
{
// Arrange
var expectedVersion = "[15.0,16.0)";
var toolset = new KoreBuildSettings.VisualStudioToolset()
{
VersionRange = expectedVersion,
MinVersion = "unexpected",
};
// Act
var result = VsWhere.TryGetVersion(toolset, out var version);
// Assert
Assert.True(result);
Assert.Equal(expectedVersion, version);
}
[Fact]
public void TryGetVersion_ReturnsVersionRange()
{
// Arrange
var expectedVersion = "[15.0,16.0)";
var toolset = new KoreBuildSettings.VisualStudioToolset()
{
VersionRange = expectedVersion,
};
// Act
var result = VsWhere.TryGetVersion(toolset, out var version);
// Assert
Assert.True(result);
Assert.Equal(expectedVersion, version);
}
[Fact]
public void ItFindsVisualStudio()
{

Просмотреть файл

@ -41,6 +41,7 @@ namespace KoreBuild
{
public bool IncludePrerelease { get; set; } = true;
public string MinVersion { get; set; }
public string VersionRange { get; set; }
public string[] RequiredWorkloads { get; set; } = Array.Empty<string>();
}

Просмотреть файл

@ -74,12 +74,28 @@
"items": {
"type": "string"
}
},
"minVersion": {
"type": "string",
"description": "The minimum version of Visual Studio required."
}
}
},
{
"oneOf": [
{
"properties": {
"minVersion": {
"type": "string",
"description": "The minimum version of Visual Studio required."
}
}
},
{
"properties": {
"versionRange": {
"type": "string",
"description": "The version range of Visual Studio required."
}
}
}
]
}
]
}
@ -93,13 +109,23 @@
"channel": {
"description": "The channel of KoreBuild used to select a version when korebuild-lock.txt is not present.",
"type": "string",
"default": "dev",
"default": "master",
"enum": [
"dev",
"master",
"release/2.2",
"release/2.1",
"release/2.0"
]
},
"msbuildType": {
"description": "The type of MSBuild to use. 'core' = 'dotnet msbuild', 'full' = 'msbuild.exe'. (Only applies to Windows)",
"type": "string",
"default": "core",
"enum": [
"core",
"full"
]
},
"toolsets": {
"description": "Lists required toolsets for this repository.",
"type": "object",