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!

~~ 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`

~~ TODO ~~

This obviously will change the Maui team's workflow, so:

* Need docs explaining how to do local dev, etc.

~~ 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 18, 2021
1 parent 2922521 commit b061357
Show file tree
Hide file tree
Showing 26 changed files with 343 additions and 120 deletions.
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
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
26 changes: 23 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,31 @@ 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 & targets
.\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 must continue 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
```

## Current News
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>
97 changes: 97 additions & 0 deletions eng/dogfood.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<#
.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
$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

# 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: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.

50 changes: 6 additions & 44 deletions eng/pipelines/handlers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ schedules:

variables:
- template: /eng/pipelines/common/variables.yml
- template: /eng/pipelines/common/variables-net6.yml
- name: LogDirectory
value: $(Build.ArtifactStagingDirectory)/logs
- name: provisionator.xcode
Expand All @@ -55,6 +54,8 @@ variables:
value: '$(System.DefaultWorkingDirectory)/eng/provisioning/provisioning.csx'
- name: provisionator.extraArguments
value: '--v'
- name: DotNet.Path
value: $(System.DefaultWorkingDirectory)/bin/dotnet/dotnet

parameters:
- name: BuildEverything
Expand Down Expand Up @@ -188,27 +189,7 @@ stages:
pool:
name: ${{ BuildPlatform.poolName }}
vmImage: ${{ BuildPlatform.vmImage }}
${{ if eq(BuildPlatform.name, 'macos') }}:
variables:
DotNet.Root: /usr/local/share/dotnet/
DotNet.Tools: ~/.dotnet/tools
steps:
- ${{ if eq(BuildPlatform.name, 'macos') }}:
- task: UseDotNet@2
displayName: install .NET Core 3.1
inputs:
version: 3.1.x
installationPath: $(DotNet.Root)
- template: common/dotnet-install.yml
- pwsh: |
dotnet tool install --global boots
boots ${{ BuildPlatform.bootsAndroid }}
boots ${{ BuildPlatform.bootsiOS }}
if ('${{ BuildPlatform.bootsMacCatalyst }}' -ne '') {
boots ${{ BuildPlatform.bootsMacCatalyst }}
}
displayName: install .NET workloads
errorActionPreference: stop
- ${{ if eq(BuildPlatform.name, 'macos') }}:
- bash: |
set -x
Expand All @@ -217,7 +198,7 @@ stages:
/usr/libexec/PlistBuddy -c "add :AppleSdkRoot string $(dirname $(dirname $(xcode-select -p)))" ~/Library/Preferences/Xamarin/Settings.plist || true
cat ~/Library/Preferences/Xamarin/Settings.plist || true
displayName: configure vsmac xcode
- pwsh: ./.nuspec/package.ps1 -configuration Release
- pwsh: ./eng/package.ps1 -configuration Release
displayName: pack nugets
errorActionPreference: stop
- task: CopyFiles@2
Expand Down Expand Up @@ -253,27 +234,7 @@ stages:
pool:
name: ${{ BuildPlatform.poolName }}
vmImage: ${{ BuildPlatform.vmImage }}
${{ if eq(BuildPlatform.name, 'macos') }}:
variables:
DotNet.Root: /usr/local/share/dotnet/
DotNet.Tools: ~/.dotnet/tools
steps:
- ${{ if eq(BuildPlatform.name, 'macos') }}:
- task: UseDotNet@2
displayName: install .NET Core 3.1
inputs:
version: 3.1.x
installationPath: $(DotNet.Root)
- template: common/dotnet-install.yml
- pwsh: |
dotnet tool install --global boots
boots ${{ BuildPlatform.bootsAndroid }}
boots ${{ BuildPlatform.bootsiOS }}
if ('${{ BuildPlatform.bootsMacCatalyst }}' -ne '') {
boots ${{ BuildPlatform.bootsMacCatalyst }}
}
displayName: install .NET workloads
errorActionPreference: stop
- ${{ if eq(BuildPlatform.name, 'macos') }}:
- bash: |
set -x
Expand All @@ -283,8 +244,9 @@ stages:
cat ~/Library/Preferences/Xamarin/Settings.plist || true
displayName: configure vsmac xcode
- pwsh: |
dotnet build Microsoft.Maui.BuildTasks-net6.sln -c $(BuildConfiguration) -bl:$(LogDirectory)/$(BuildConfiguration)-buildtasks.binlog
dotnet build Microsoft.Maui-net6.sln -c $(BuildConfiguration) -bl:$(LogDirectory)/$(BuildConfiguration).binlog
& dotnet build src\DotNet\DotNet.csproj -bl:$(LogDirectory)\$(BuildConfiguration)-dotnet.binlog
& $(DotNet.Path) build Microsoft.Maui.BuildTasks-net6.sln -c $(BuildConfiguration) -bl:$(LogDirectory)/$(BuildConfiguration)-buildtasks.binlog
& $(DotNet.Path) build Microsoft.Maui-net6.sln -c $(BuildConfiguration) -bl:$(LogDirectory)/$(BuildConfiguration).binlog
displayName: build samples
errorActionPreference: stop
- task: PublishBuildArtifacts@1
Expand Down
Loading

0 comments on commit b061357

Please sign in to comment.