Skip to content

Commit

Permalink
[build] bootstrap a local .\bin\dotnet\ with .NET Workloads
Browse files Browse the repository at this point in the history
Based on: https://github.com/jonathanpeppers/maui-workload

This adds a new `DotNet.csproj` that provisions a local .NET 6 install
into `.\bin\dotnet\`.

Next, it uses versions defined in `eng/Versions.props` as required by
.NET version bumping infrastructure (called Darc):

    <Project>
      <PropertyGroup>
        <MicrosoftNETSdkPackageVersion>6.0.100-preview.2.21155.3</MicrosoftNETSdkPackageVersion>
        <MicrosoftAndroidSdkPackageVersion>11.0.200-ci.main.148</MicrosoftAndroidSdkPackageVersion>
        <MicrosoftMacCatalystSdkPackageVersion>14.3.100-ci.main.337</MicrosoftMacCatalystSdkPackageVersion>
        <MicrosoftiOSSdkPackageVersion>14.4.100-ci.main.1192</MicrosoftiOSSdkPackageVersion>
      </PropertyGroup>
    </Project>

Next, we can use these versions to consume NuGet packages for workloads:

    <PackageDownload Include="Microsoft.NET.Workload.Android"     Version="[$(MicrosoftAndroidSdkPackageVersion)]" />
    <PackageDownload Include="Microsoft.NET.Workload.MacCatalyst" Version="[$(MicrosoftMacCatalystSdkPackageVersion)]" />
    <PackageDownload Include="Microsoft.NET.Workload.iOS"         Version="[$(MicrosoftiOSSdkPackageVersion)]" />

Then the other packs they depend on:

    <PackageDownload Include="Microsoft.Android.Ref"            Version="[$(MicrosoftAndroidSdkPackageVersion)]" />
    <PackageDownload Include="Microsoft.Android.Sdk.win-x64"    Version="[$(MicrosoftAndroidSdkPackageVersion)]" Condition="$([MSBuild]::IsOSPlatform('windows'))" />
    <PackageDownload Include="Microsoft.Android.Sdk.osx-x64"    Version="[$(MicrosoftAndroidSdkPackageVersion)]" Condition="$([MSBuild]::IsOSPlatform('osx'))" />
    <PackageDownload Include="Microsoft.Android.Sdk.BundleTool" Version="[$(MicrosoftAndroidSdkPackageVersion)]" />
    <PackageDownload Include="Microsoft.MacCatalyst.Ref"        Version="[$(MicrosoftMacCatalystSdkPackageVersion)]" />
    <PackageDownload Include="Microsoft.MacCatalyst.Sdk"        Version="[$(MicrosoftMacCatalystSdkPackageVersion)]" />
    <PackageDownload Include="Microsoft.iOS.Ref"                Version="[$(MicrosoftiOSSdkPackageVersion)]" />
    <PackageDownload Include="Microsoft.iOS.Sdk"                Version="[$(MicrosoftiOSSdkPackageVersion)]" />

After doing this, I can build .NET 6 projects with:

    > .\bin\dotnet\dotnet.exe build .\src\Controls\samples\Controls.Sample.SingleProject\Maui.Controls.Sample.SingleProject.csproj

I can even build MacCatalyst apps on Windows!

I updated `build.cake` so the following builds for .NET 6 and opens
Visual Studio:

    > dotnet cake --target=VS-NET6

This is the equivalent of these commands if you want to run them
individually:

    dotnet build src\DotNet\DotNet.csproj
    .\bin\dotnet\dotnet build Microsoft.Maui.BuildTasks-net6.sln
    .\bin\dotnet\dotnet build Microsoft.Maui-net6.sln
    .\eng\dogfood.ps1

~~ Other Changes ~~

* Rework CI setup to use .\bin\dotnet\dotnet
* We don't need boots or URLs anymore
* Fixed `MSBuildTests` to use .\bin\dotnet\dotnet if found and fall
  back to the system `dotnet`
* Moved `.nuspec\package.ps1` to `eng\package.ps1`

~~ What problems does this solve? ~~

* MacCatalyst builds on Windows! (offline build that checks C#)
* Building Maui always gets you the right things installed.
* Maui becoming a .NET workload will be a breeze. We can copy files
  into `.\bin\dotnet\sdk-manifests` and `.\bin\dotnet\packs`.
* We can use Darc to bump dependencies within .NET:

https://github.com/dotnet/arcade/blob/main/Documentation/Darc.md
  • Loading branch information
jonathanpeppers committed Mar 19, 2021
1 parent 6402f5c commit 64f93dc
Show file tree
Hide file tree
Showing 29 changed files with 361 additions and 129 deletions.
3 changes: 1 addition & 2 deletions .nuspec/Microsoft.Maui.Controls.targets
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
<Import Project="$(MSBuildThisFileDirectory)Microsoft.Maui.Controls.DefaultItems.targets" Condition="'$(MSBuildSDKsPath)'!=''" />

<ItemGroup>
<ProjectCapability Include="XamarinForms" />
<ProjectCapability Include="Maui" />
<ProjectCapability Include="Maui" Condition="'$(_ExcludeMauiProjectCapability)' != 'true'" />
</ItemGroup>

<!-- Check Tasks ABI and other validations -->
Expand Down
6 changes: 0 additions & 6 deletions .nuspec/package.ps1

This file was deleted.

1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<Project>
<Import Project="eng\Version.props" />
<PropertyGroup>
<_MauiBuildTasksLocation>$(_MauiBuildTasksLocation)</_MauiBuildTasksLocation>
<_MauiBuildTasksLocation Condition="'$(_MauiBuildTasksLocation)' == ''">$(MSBuildThisFileDirectory).nuspec\</_MauiBuildTasksLocation>
Expand Down
2 changes: 2 additions & 0 deletions Microsoft.Maui-net6.sln
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Global
{BE50FAEF-4096-48B5-B9CE-EE0C38F15A18}.Release|Any CPU.Build.0 = Release|Any CPU
{1C3439E6-73D7-4F8E-A64A-5448F5CB18DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1C3439E6-73D7-4F8E-A64A-5448F5CB18DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1C3439E6-73D7-4F8E-A64A-5448F5CB18DE}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{1C3439E6-73D7-4F8E-A64A-5448F5CB18DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1C3439E6-73D7-4F8E-A64A-5448F5CB18DE}.Release|Any CPU.Build.0 = Release|Any CPU
{D7FE9FD0-144A-4199-93FC-3AD62325F1D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
Expand All @@ -91,6 +92,7 @@ Global
{D7FE9FD0-144A-4199-93FC-3AD62325F1D6}.Release|Any CPU.Build.0 = Release|Any CPU
{CB495F62-CFE6-4975-AED8-F26B6C5D0113}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB495F62-CFE6-4975-AED8-F26B6C5D0113}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB495F62-CFE6-4975-AED8-F26B6C5D0113}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{CB495F62-CFE6-4975-AED8-F26B6C5D0113}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB495F62-CFE6-4975-AED8-F26B6C5D0113}.Release|Any CPU.Build.0 = Release|Any CPU
{75C380E0-CE53-4C01-B89F-CF685331DE18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
Expand Down
3 changes: 2 additions & 1 deletion Microsoft.Maui.sln
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuspec", ".nuspec", "{7E12
.nuspec\Microsoft.Maui.Controls.SingleProject.targets = .nuspec\Microsoft.Maui.Controls.SingleProject.targets
.nuspec\Microsoft.Maui.Controls.targets = .nuspec\Microsoft.Maui.Controls.targets
.nuspec\Microsoft.Maui.Resizetizer.targets = .nuspec\Microsoft.Maui.Resizetizer.targets
.nuspec\package.ps1 = .nuspec\package.ps1
.nuspec\proguard.cfg = .nuspec\proguard.cfg
eng\package.ps1 = eng\package.ps1
eng\dogfood.ps1 = eng\dogfood.ps1
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.Core", "src\Controls\src\Core\Controls.Core.csproj", "{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}"
Expand Down
35 changes: 32 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,42 @@ dotnet tool install Cake.Tool -g
#### IDE
- If you have Visual Studio 16.9 P4 installed you can open `Maui.sln` and run it from there.

#### Command Line
#### .NET 6

You can run a `Cake` target to bootstrap .NET 6 in `bin\dotnet` and launch Visual Studio:

```dotnetcli
dotnet cake --target=VS-NET6
```
_NOTE: VS Mac is not yet supported._

You can also run commands individually:
```dotnetcli
# Provision .NET 6 in bin\dotnet
dotnet build src\DotNet\DotNet.csproj
# Builds Maui MSBuild tasks
.\bin\dotnet\dotnet build Microsoft.Maui.BuildTasks-net6.sln
# Builds the rest of Maui
.\bin\dotnet\dotnet build Microsoft.Maui-net6.sln
# (Windows-only) to launch Visual Studio
.\eng\dogfood.ps1
```
dotnet build src\Controls\samples\Controls.Sample.Droid\Maui.Controls.Sample.Droid-net6.csproj -t:Run
dotnet build src\Controls\samples\Controls.Sample.iOS\Maui.Controls.Sample.iOS-net6.csproj -t:Run

To build & run .NET 6 sample apps, you will also need to use `.\bin\dotnet\dotnet`:
```dotnetcli
.\bin\dotnet\dotnet build src\Controls\samples\Controls.Sample.Droid\Maui.Controls.Sample.Droid-net6.csproj -t:Run
.\bin\dotnet\dotnet build src\Controls\samples\Controls.Sample.iOS\Maui.Controls.Sample.iOS-net6.csproj -t:Run
```

Try try out a "single project", you will need the `-f` switch to choose the platform:

```dotnetcli
.\bin\dotnet\dotnet build src\Controls\samples\Controls.Sample.SingleProject\Maui.Controls.Sample.SingleProject.csproj t:Run -f net6.0-android --no-restore
.\bin\dotnet\dotnet build src\Controls\samples\Controls.Sample.SingleProject\Maui.Controls.Sample.SingleProject.csproj t:Run -f net6.0-ios --no-restore
```

Note that `--no-restore` is a workaround until [dotnet#15485](https://github.com/dotnet/sdk/issues/15485) is fixed in a future preview.

## Current News

[March 11, 2021 - Announcing .NET 6 Preview 2](https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-2/)
Expand Down
26 changes: 21 additions & 5 deletions build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ Task("NuGetPack")
var settings = new DotNetCoreToolSettings
{
DiagnosticOutput = true,
ArgumentCustomization = args => args.Append($"./.nuspec/package.ps1 -configuration \"{configuration}\"")
ArgumentCustomization = args => args.Append($"./eng/package.ps1 -configuration \"{configuration}\"")
};

DotNetCoreTool("pwsh", settings);
Expand Down Expand Up @@ -886,12 +886,12 @@ Task("Android100")


Task("VS-NET6")
.IsDependentOn("Clean")
.Does(() =>
{
DotNetCoreRestore("Microsoft.Maui-net6.sln");
DotNetCoreBuild("Microsoft.Maui-net6.sln");
StartVisualStudio("Microsoft.Maui-net6.sln");
DotNetCoreBuild("./src/DotNet/Dotnet.csproj");
var ext = IsRunningOnWindows() ? ".exe" : "";
DotNetCoreBuild("./Microsoft.Maui.BuildTasks-net6.sln", new DotNetCoreBuildSettings { ToolPath = $"./bin/dotnet/dotnet{ext}" });
StartVisualStudioForDotNet6();
});

Task("VS")
Expand Down Expand Up @@ -1206,6 +1206,22 @@ void StartVisualStudio(string sln = "./Microsoft.Maui.sln")
StartProcess("open", new ProcessSettings{ Arguments = sln });
}

void StartVisualStudioForDotNet6(string sln = "./Microsoft.Maui-net6.sln")
{
if (isCIBuild)
return;
if (!IsRunningOnWindows())
{
Information("This target is only supported on Windows.");
return;
}
var vsLatest = VSWhereLatest();
if (vsLatest == null)
throw new Exception("Unable to find Visual Studio!");
var devenv = vsLatest.CombineWithFilePath("./Common7/IDE/devenv.exe");
StartProcess("powershell", $"./eng/dogfood.ps1 -vs '{devenv}' -sln '{sln}'");
}

MSBuildSettings GetMSBuildSettings(PlatformTarget? platformTarget = PlatformTarget.MSIL, string buildConfiguration = null)
{
var buildSettings = new MSBuildSettings {
Expand Down
9 changes: 9 additions & 0 deletions eng/Version.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project>
<!--Package versions-->
<PropertyGroup>
<MicrosoftNETSdkPackageVersion>6.0.100-preview.2.21155.3</MicrosoftNETSdkPackageVersion>
<MicrosoftAndroidSdkPackageVersion>11.0.200-ci.main.148</MicrosoftAndroidSdkPackageVersion>
<MicrosoftMacCatalystSdkPackageVersion>14.3.100-ci.main.337</MicrosoftMacCatalystSdkPackageVersion>
<MicrosoftiOSSdkPackageVersion>14.4.100-ci.main.1192</MicrosoftiOSSdkPackageVersion>
</PropertyGroup>
</Project>
102 changes: 102 additions & 0 deletions eng/dogfood.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<#
.SYNOPSIS
*Windows-only* Launches Visual Studio with environment variables to use the local ./bin/dotnet/dotnet.exe.
.DESCRIPTION
*Windows-only* Launches Visual Studio with environment variables to use the local ./bin/dotnet/dotnet.exe.
Script based on:
https://github.com/dotnet/runtime/blob/1be117d8e7c0cd29ebc55cbcff2a7fa70604ed39/eng/build.ps1#L186-L208
https://github.com/dotnet/runtime/blob/1be117d8e7c0cd29ebc55cbcff2a7fa70604ed39/eng/common/tools.ps1#L109
.PARAMETER vs
The path to Visual Studio, defaults to:
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe".
.PARAMETER sln
The path to a .sln or .project file, defaults to "Microsoft.Maui-net6.sln".
.PARAMETER modify
Modify the environment variables in the current session. This would
allow the "dotnet" command to work instead of ".\bin\dotnet\dotnet".
However, it would be good to do this in a new terminal session,
since you would have trouble running "dotnet build" if it needs to
provision .NET 6 and the iOS/Android workloads again.
.EXAMPLE
PS> .\scripts\dogfood.ps1
.EXAMPLE
PS> .\scripts\dogfood.ps1 -vs "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.exe"
.EXAMPLE
PS> .\scripts\dogfood.ps1 -sln .\path\to\MySolution.sln
#>

param(
[string]$vs = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe",
[string]$sln,
[switch]$modify
)

$dotnet=Join-Path $PSScriptRoot ../bin/dotnet/
$dotnet=(Get-Item $dotnet).FullName

if (-Not $sln) {
$sln=Join-Path $PSScriptRoot ../Microsoft.Maui-net6.sln
$sln=(Get-Item $sln).FullName
}

# Modify global.json, so the IDE can load
$globaljson = Join-Path $PSScriptRoot ../global.json
[xml] $xml = Get-Content (Join-Path $PSScriptRoot Version.props)
$json = Get-Content $globaljson | ConvertFrom-Json
$json | Add-Member sdk (New-Object -TypeName PSObject) -Force
$json.sdk | Add-Member version $xml.Project.PropertyGroup.MicrosoftNETSdkPackageVersion -Force
$json | ConvertTo-Json | Set-Content $globaljson

# NOTE: I've not found a better way to do this
# see: https://github.com/PowerShell/PowerShell/issues/3316
$oldDOTNET_INSTALL_DIR=$env:DOTNET_INSTALL_DIR
$oldDOTNET_ROOT=$env:DOTNET_ROOT
$oldDOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR=$env:DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR
$oldDOTNET_MULTILEVEL_LOOKUP=$env:DOTNET_MULTILEVEL_LOOKUP
$oldMSBuildEnableWorkloadResolver=$env:MSBuildEnableWorkloadResolver
$old_ExcludeMauiProjectCapability=$env:_ExcludeMauiProjectCapability
$oldPATH=$env:PATH

try {
$env:DOTNET_INSTALL_DIR=$dotnet

# This tells .NET to use the bootstrapped runtime
$env:DOTNET_ROOT=$env:DOTNET_INSTALL_DIR

# This tells MSBuild to load the SDK from the directory of the bootstrapped SDK
$env:DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR=$env:DOTNET_ROOT

# This tells .NET not to go looking for .NET in other places
$env:DOTNET_MULTILEVEL_LOOKUP=0

# This enables workload support inside the IDE
$env:MSBuildEnableWorkloadResolver=$true

# This disables the Maui @(ProjectCapability), a temporary workaround for 16.9
$env:_ExcludeMauiProjectCapability=$true

# Put our local dotnet.exe on PATH first so Visual Studio knows which one to use
$env:PATH=($env:DOTNET_ROOT + ";" + $env:PATH)

# Launch VS
& "$vs" "$sln"
} finally {
if (-Not $modify) {
$env:DOTNET_INSTALL_DIR = $oldDOTNET_INSTALL_DIR
$env:DOTNET_ROOT=$oldDOTNET_ROOT
$env:DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR=$oldDOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR
$env:DOTNET_MULTILEVEL_LOOKUP=$oldDOTNET_MULTILEVEL_LOOKUP
$env:MSBuildEnableWorkloadResolver=$oldMSBuildEnableWorkloadResolver
$env:_ExcludeMauiProjectCapability=$old_ExcludeMauiProjectCapability
$env:PATH=$oldPATH
}
}

exit 0
17 changes: 17 additions & 0 deletions eng/package.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
param ([string] $configuration = 'Debug')

$artifacts = Join-Path $PSScriptRoot ../artifacts

# Bootstrap .\bin\dotnet\
$csproj = Join-Path $PSScriptRoot ../src/DotNet/DotNet.csproj
& dotnet build $csproj -bl:$artifacts/dotnet-$configuration.binlog

$ext = if ($IsWindows) { ".exe" } else { "" }
$dotnet = Join-Path $PSScriptRoot ../bin/dotnet/dotnet$ext
$sln = Join-Path $PSScriptRoot ../Microsoft.Maui-net6.sln

# Build with .\bin\dotnet\dotnet.exe
& $dotnet pack $sln `
-c:$configuration `
-p:SymbolPackageFormat=snupkg `
-bl:$artifacts/maui-$configuration.binlog
6 changes: 4 additions & 2 deletions eng/pipelines/common/build-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ steps:
provisioning_script: $(provisionator.path)
provisioning_extra_args: $(provisionator.extraArguments)

- template: dotnet-install.yml
- powershell: |
& dotnet build src\DotNet\DotNet.csproj -bl:${{ parameters.artifactsTargetFolder }}\$(BuildConfiguration)-dotnet.binlog
displayName: install .NET
- powershell: |
$(System.DefaultWorkingDirectory)/build.ps1 --target provision --TeamProject="$(System.TeamProject)"
Expand Down Expand Up @@ -67,7 +69,7 @@ steps:
displayName: 'Copy Files dlls'
inputs:
Contents: |
**/bin/**/*.dll
src/**/bin/**/*.dll
TargetFolder: ${{ parameters.artifactsTargetFolder }}

- task: PublishBuildArtifacts@1
Expand Down
27 changes: 0 additions & 27 deletions eng/pipelines/common/dotnet-install.yml

This file was deleted.

15 changes: 0 additions & 15 deletions eng/pipelines/common/variables-net6.yml

This file was deleted.

Loading

0 comments on commit 64f93dc

Please sign in to comment.