Skip to content

[One .NET] temporary Windows & macOS installers for .NET 6 #5225

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Configuration.props
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
<!-- Version number from: https://github.com/dotnet/installer#installers-and-binaries -->
<DotNetPreviewVersionBand Condition=" '$(DotNetPreviewVersionBand)' == '' ">5.0.100</DotNetPreviewVersionBand>
<DotNetPreviewVersionFull Condition=" '$(DotNetPreviewVersionFull)' == '' ">$(DotNetPreviewVersionBand)-rtm.20509.5</DotNetPreviewVersionFull>
<WixToolPath Condition=" '$(WixToolPath)' == '' ">$(AndroidToolchainDirectory)\wix\</WixToolPath>
<AndroidCmakeVersion Condition=" '$(AndroidCmakeVersion)' == '' ">3.10.2</AndroidCmakeVersion>
<AndroidCmakeVersionPath Condition=" '$(AndroidCmakeVersionPath)' == '' ">$(AndroidCmakeVersion).4988404</AndroidCmakeVersionPath>
<AndroidSdkCmakeDirectory>$(AndroidSdkDirectory)\cmake\$(AndroidCmakeVersionPath)</AndroidSdkCmakeDirectory>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Xamarin.Android.Tools.BootstrapTasks
{
/// <summary>
/// Used for converting plain text license files to .rtf format.
/// Assumes the file is line wrapped with Environment.NewLine:
/// * Double new lines are preserved.
/// * Single new lines are replaced with spaces.
///
/// For a Unicode escape the control word \u is used, followed by
/// a 16-bit signed decimal integer giving the Unicode UTF-16 code
/// unit number. More information under 'Character encoding' here:
/// https://en.wikipedia.org/wiki/Rich_Text_Format
/// </summary>
public class ConvertToRichText : Task
{
[Required]
public string SourceFile { get; set; }

[Required]
public string DestinationFile { get; set; }

public override bool Execute ()
{
var text = File.ReadAllText (SourceFile);

text = text
.Replace (@"\", @"\\")
.Replace ("{", @"\{")
.Replace ("}", @"\}")
// Only want to keep "double" new lines
.Replace (Environment.NewLine + Environment.NewLine, $@"\par{Environment.NewLine} \par{Environment.NewLine} ")
.Replace (Environment.NewLine, " ");

Directory.CreateDirectory (Path.GetDirectoryName (DestinationFile));
using (var writer = File.CreateText (DestinationFile)) {
writer.Write (@"{\rtf1\ansi\ansicpg1250\deff0{\fonttbl\f0\fcharset0 Courier New;}\f0\pard ");
foreach (char letter in text) {
if (letter <= 0x7f) {
writer.Write (letter);
} else {
writer.Write ("\\u");
writer.Write (Convert.ToUInt32 (letter));
writer.Write ("?");
}
}
writer.Write (" } ");
}

return !Log.HasLoggedErrors;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Xamarin.Android.Tools.BootstrapTasks
{
/// <summary>
/// Generates a .wix file for the contents of ~/android-toolchain/dotnet/packs
/// The .wix file can be used to generate the .msi installer for Windows.
/// </summary>
public class GenerateWixFile : Task
{
[Required]
public string Template { get; set; }

[Required]
public string DestinationFile { get; set; }

[Required]
public string DotNetPath { get; set; }

[Required]
public string DotNetVersion { get; set; }

[Required]
public string MSIVersion { get; set; }

public override bool Execute ()
{
var settings = new XmlWriterSettings {
OmitXmlDeclaration = true,
Indent = true,
};

var directories = new StringBuilder ();
var components = new StringBuilder ();
using (var packWriter = XmlWriter.Create (directories, settings))
using (var componentWriter = XmlWriter.Create (components, settings)) {

// Components
componentWriter.WriteStartElement ("ComponentGroup");
componentWriter.WriteAttributeString ("Id", "ProductComponents");
componentWriter.WriteStartElement ("ComponentRef");
componentWriter.WriteAttributeString ("Id", "EnableWorkloadResolver");
componentWriter.WriteEndElement (); // </ComponentRef>

// dotnet
packWriter.WriteStartElement ("Directory");
packWriter.WriteAttributeString ("Id", "dotnet");
packWriter.WriteAttributeString ("Name", "dotnet");

// sdk
packWriter.WriteStartElement ("Directory");
packWriter.WriteAttributeString ("Id", "sdk");
packWriter.WriteAttributeString ("Name", "sdk");

// DOTNETVERSION
packWriter.WriteStartElement ("Directory");
packWriter.WriteAttributeString ("Id", "DOTNETVERSION");
packWriter.WriteAttributeString ("Name", DotNetVersion);
packWriter.WriteAttributeString ("FileSource", Path.Combine (DotNetPath, "sdk", DotNetVersion));

// EnableWorkloadResolver
packWriter.WriteStartElement ("Component");
packWriter.WriteAttributeString ("Id", "EnableWorkloadResolver");
packWriter.WriteStartElement ("File");
packWriter.WriteAttributeString ("Id", "EnableWorkloadResolver");
packWriter.WriteAttributeString ("Name", "EnableWorkloadResolver.sentinel");
packWriter.WriteAttributeString ("KeyPath", "yes");
packWriter.WriteEndElement (); // </File>
packWriter.WriteEndElement (); // </Component>
packWriter.WriteEndElement (); // </Directory> DOTNETVERSION
packWriter.WriteEndElement (); // </Directory> sdk

// sdk-manifests
var sdk_manifests_root = Path.Combine (DotNetPath, "sdk-manifests");
packWriter.WriteStartElement ("Directory");
packWriter.WriteAttributeString ("Id", "sdk_manifests");
packWriter.WriteAttributeString ("Name", "sdk-manifests");

// 5.0.100
var sdk_manifests = Directory.EnumerateDirectories (sdk_manifests_root).FirstOrDefault ();
if (string.IsNullOrEmpty (sdk_manifests)) {
Log.LogError ($"Cannot find child directory of: {sdk_manifests_root}");
return false;
}
var version_band = Path.GetFileName (sdk_manifests);
packWriter.WriteStartElement ("Directory");
packWriter.WriteAttributeString ("Id", "DOTNETVERSIONBAND");
packWriter.WriteAttributeString ("Name", version_band);
packWriter.WriteAttributeString ("FileSource", sdk_manifests);
var workload = Path.Combine (sdk_manifests, "Microsoft.NET.Workload.Android");
if (Directory.Exists (workload)) {
RecurseDirectory (sdk_manifests, packWriter, componentWriter, workload);
} else {
Log.LogError ($"Cannot find directory: {workload}");
return false;
}
packWriter.WriteEndElement (); // </Directory> version_band
packWriter.WriteEndElement (); // </Directory> sdk-manifests

// packs
var packs_dir = Path.Combine (DotNetPath, "packs");
packWriter.WriteStartElement ("Directory");
packWriter.WriteAttributeString ("Id", "packs");
packWriter.WriteAttributeString ("Name", "packs");
foreach (var directory in Directory.EnumerateDirectories (packs_dir, "Microsoft.Android.*")) {
RecurseDirectory (packs_dir, packWriter, componentWriter, directory);
}

packWriter.WriteEndDocument (); // </Directory>
componentWriter.WriteEndDocument (); // </ComponentGroup>
}

var template = File.ReadAllText (Template);
var contents = template
.Replace ("@MSIVERSION@", MSIVersion)
.Replace ("@DIRECTORIES@", directories.ToString ())
.Replace ("@COMPONENTS@", components.ToString ());

Log.LogMessage (MessageImportance.Low, "Writing XML to {0}: {1}", DestinationFile, contents);
File.WriteAllText (DestinationFile, contents);

return !Log.HasLoggedErrors;
}

static void RecurseDirectory (string top_dir, XmlWriter packWriter, XmlWriter componentWriter, string directory)
{
var directoryId = GetId (top_dir, directory);
packWriter.WriteStartElement ("Directory");
packWriter.WriteAttributeString ("Id", directoryId);
packWriter.WriteAttributeString ("Name", Path.GetFileName (directory));
packWriter.WriteAttributeString ("FileSource", directory);
foreach (var child in Directory.EnumerateDirectories (directory)) {
var directoryName = Path.GetFileName (child);
if (directoryName.StartsWith (".") || directoryName.StartsWith ("_"))
continue;
RecurseDirectory (top_dir, packWriter, componentWriter, child);
}
foreach (var file in Directory.EnumerateFiles (directory)) {
var fileName = Path.GetFileName (file);
if (fileName.StartsWith (".") || fileName.StartsWith ("_"))
continue;
var componentId = GetId (top_dir, file);
packWriter.WriteStartElement ("Component");
packWriter.WriteAttributeString ("Id", componentId);
packWriter.WriteStartElement ("File");
packWriter.WriteAttributeString ("Id", componentId);
packWriter.WriteAttributeString ("Name", Path.GetFileName (file));
packWriter.WriteAttributeString ("KeyPath", "yes");
packWriter.WriteEndElement (); // </File>
packWriter.WriteEndElement (); // </Component>
componentWriter.WriteStartElement ("ComponentRef");
componentWriter.WriteAttributeString ("Id", componentId);
componentWriter.WriteEndElement (); // </ComponentRef>
}
packWriter.WriteEndElement (); // </Directory>
}

static string GetId (string top_dir, string path)
{
if (string.IsNullOrEmpty (path))
return path;
if (path.Length > top_dir.Length + 1) {
path = path.Substring (top_dir.Length + 1);
}
return GetHashString (path);
}

static byte [] GetHash (string inputString)
{
using (var algorithm = SHA256.Create ())
return algorithm.ComputeHash (Encoding.UTF8.GetBytes (inputString));
}

static string GetHashString (string inputString)
{
var sb = new StringBuilder ("S", 65);
foreach (byte b in GetHash (inputString))
sb.Append (b.ToString ("X2"));
return sb.ToString ();
}
}
}
4 changes: 2 additions & 2 deletions build-tools/automation/azure-pipelines-oss.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ stages:
displayName: make jenkins

- script: >
echo "make create-installers V=1 CONFIGURATION=$(XA.Build.Configuration)" &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we want to continue calling make create-installers, so that the new make create-workload-installers target is executed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

…or do we not want to create a Workload installer for the OSS pipeline?

Copy link
Member Author

@jonathanpeppers jonathanpeppers Oct 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would have to add commands to create the .nupkg files for create-installers to work on the OSS pipeline. I would also have to make a Windows stage to create the .msi.

I thought it was simpler to not create these installers on the OSS pipeline for now. But if we have a need, we could?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also have to make a Windows stage to create the .msi.

We don't have a Windows stage OSS build (but perhaps we should?), so I don't think this would be needed.

I'm largely "just pondering" the community engagement angle. Is there a reason to not provide "OSS-blessed" packages, and/or ensure that the OSS tree can produce the .nupkg files?

That said, it might very well fail now, as the .nupkg files likely pulls in proprietary files, so this should be done as a separate PR, if ever.

make create-installers V=1 CONFIGURATION=$(XA.Build.Configuration)
echo "make create-pkg create-vsix V=1 CONFIGURATION=$(XA.Build.Configuration)" &&
make create-pkg create-vsix V=1 CONFIGURATION=$(XA.Build.Configuration)
workingDirectory: $(Build.SourcesDirectory)
displayName: create installers

Expand Down
71 changes: 64 additions & 7 deletions build-tools/automation/azure-pipelines.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,13 @@ stages:
artifactName: $(TestAssembliesArtifactName)
targetPath: xamarin-android/bin/Test$(XA.Build.Configuration)

- task: MSBuild@1
displayName: pack all nupkgs
inputs:
solution: $(System.DefaultWorkingDirectory)/xamarin-android/build-tools/create-packs/Microsoft.Android.Sdk.proj
configuration: $(XA.Build.Configuration)
msbuildArguments: /t:CreateAllPacks /restore /p:NuGetLicense=$(System.DefaultWorkingDirectory)/xamarin-android/external/monodroid/tools/scripts/License.txt /bl:$(System.DefaultWorkingDirectory)/xamarin-android/bin/Build$(XA.Build.Configuration)/create-all-packs.binlog

# Create installers
- script: make create-installers V=1 CONFIGURATION=$(XA.Build.Configuration)
workingDirectory: $(System.DefaultWorkingDirectory)/xamarin-android
Expand All @@ -227,13 +234,6 @@ stages:
artifactName: $(InstallerArtifactName)
targetPath: xamarin-android/bin/Build$(XA.Build.Configuration)/$(InstallerArtifactName)

- task: MSBuild@1
displayName: pack all nupkgs
inputs:
solution: $(System.DefaultWorkingDirectory)/xamarin-android/build-tools/create-packs/Microsoft.Android.Sdk.proj
configuration: $(XA.Build.Configuration)
msbuildArguments: /t:CreateAllPacks /restore /p:NuGetLicense=$(System.DefaultWorkingDirectory)/xamarin-android/external/monodroid/tools/scripts/License.txt /bl:$(System.DefaultWorkingDirectory)/xamarin-android/bin/Build$(XA.Build.Configuration)/create-all-packs.binlog

- task: NuGetCommand@2
displayName: push nupkgs
inputs:
Expand Down Expand Up @@ -1115,6 +1115,60 @@ stages:

- template: yaml-templates/fail-on-issue.yaml

- stage: dotnet_installers
displayName: .NET 6 Preview Installers
dependsOn: mac_build
jobs:
# Check - "Xamarin.Android (.NET 6 Preview Installers Create .msi and Upload)"
- job: dotnet_preview_installers
displayName: Create .msi and Upload
pool: $(HostedWinVS2019)
workspace:
clean: all
steps:
- checkout: self
submodules: recursive

- task: DownloadPipelineArtifact@2
inputs:
artifactName: $(NuGetArtifactName)
downloadPath: $(System.DefaultWorkingDirectory)\bin\Build$(XA.Build.Configuration)\nupkgs

- task: DownloadPipelineArtifact@2
inputs:
artifactName: $(InstallerArtifactName)
downloadPath: $(System.DefaultWorkingDirectory)\installer-artifacts
patterns: Microsoft.*.pkg

- task: MSBuild@1
displayName: msbuild Xamarin.Android.BootstrapTasks
inputs:
solution: Xamarin.Android.BootstrapTasks.sln
configuration: $(XA.Build.Configuration)
msbuildArguments: /restore /bl:$(System.DefaultWorkingDirectory)\bin\Build$(XA.Build.Configuration)\msbuild-bootstraptasks.binlog

- task: MSBuild@1
displayName: msbuild /t:CreateWorkloadInstallers
inputs:
solution: Xamarin.Android.sln
configuration: $(XA.Build.Configuration)
msbuildArguments: /t:CreateWorkloadInstallers /bl:$(System.DefaultWorkingDirectory)\bin\Build$(XA.Build.Configuration)\msbuild-workload.binlog

- script: copy /Y $(System.DefaultWorkingDirectory)\bin\Build$(XA.Build.Configuration)\*.msi $(System.DefaultWorkingDirectory)\installer-artifacts
displayName: copy .msi

- template: upload-to-storage\win\v1.yml@yaml
parameters:
ArtifactsDirectory: $(System.DefaultWorkingDirectory)\installer-artifacts
Azure.ContainerName: $(Azure.Container.Name)
Azure.BlobPrefix: $(Build.DefinitionName)/public/$(Build.BuildId)/$(Build.SourceBranchName)/$(Build.SourceVersion)
GitHub.Context: .NET 6 Preview Installers

- template: yaml-templates/upload-results.yaml
parameters:
solution: build-tools\Xamarin.Android.Tools.BootstrapTasks\Xamarin.Android.Tools.BootstrapTasks.csproj
artifactName: Build Results - .NET 6 Preview Installers

- stage: finalize_installers
displayName: Finalize Installers
dependsOn: mac_build
Expand Down Expand Up @@ -1148,6 +1202,9 @@ stages:
inputs:
artifactName: $(InstallerArtifactName)
downloadPath: $(System.DefaultWorkingDirectory)/storage-artifacts
patterns: |
xamarin.android*.pkg
Xamarin.Android*.vsix

- powershell: |
$pkg = Get-ChildItem -Path "$(System.DefaultWorkingDirectory)/storage-artifacts/*" -Include *.pkg -File
Expand Down
9 changes: 9 additions & 0 deletions build-tools/automation/yaml-templates/run-installer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ steps:
inputs:
artifactName: $(InstallerArtifactName)
downloadPath: $(System.DefaultWorkingDirectory)
patterns: xamarin.android*.pkg
condition: and(succeeded(), eq(variables['agent.os'], 'Darwin'))

- task: DownloadPipelineArtifact@2
inputs:
artifactName: $(InstallerArtifactName)
downloadPath: $(System.DefaultWorkingDirectory)
patterns: Xamarin.Android*.vsix
condition: and(succeeded(), eq(variables['agent.os'], 'Windows_NT'))

- powershell: |
$itemPattern = "*.vsix"
Expand Down
Loading