Add support for building Windows x86 version of dotnet CLI

- Changes to build scripts to produce Winx86 build artifacts like
  zip/installer.
- Change to run Nuget-xplat in the same process as dotnet.exe instead of
  spinning up a new 'corerun' process.
This commit is contained in:
Sridhar Periyasamy 2016-02-23 18:04:49 -08:00
parent 2aedd677c6
commit 834edfbc9c
11 changed files with 89 additions and 44 deletions

View file

@ -71,7 +71,7 @@ function RunCandle
-dBuildVersion="$env:DOTNET_MSI_VERSION" ` -dBuildVersion="$env:DOTNET_MSI_VERSION" `
-dDisplayVersion="$env:DOTNET_CLI_VERSION" ` -dDisplayVersion="$env:DOTNET_CLI_VERSION" `
-dReleaseSuffix="$env:ReleaseSuffix" ` -dReleaseSuffix="$env:ReleaseSuffix" `
-arch x64 ` -arch "$env:ARCHITECTURE" `
-ext WixDependencyExtension.dll ` -ext WixDependencyExtension.dll `
"$AuthWsxRoot\dotnet.wxs" ` "$AuthWsxRoot\dotnet.wxs" `
"$AuthWsxRoot\provider.wxs" ` "$AuthWsxRoot\provider.wxs" `
@ -136,7 +136,7 @@ function RunCandleForBundle
-dDisplayVersion="$env:DOTNET_CLI_VERSION" ` -dDisplayVersion="$env:DOTNET_CLI_VERSION" `
-dReleaseSuffix="$env:ReleaseSuffix" ` -dReleaseSuffix="$env:ReleaseSuffix" `
-dMsiSourcePath="$DotnetMSIOutput" ` -dMsiSourcePath="$DotnetMSIOutput" `
-arch x64 ` -arch "$env:ARCHITECTURE" `
-ext WixBalExtension.dll ` -ext WixBalExtension.dll `
-ext WixUtilExtension.dll ` -ext WixUtilExtension.dll `
-ext WixTagExtension.dll ` -ext WixTagExtension.dll `
@ -190,8 +190,8 @@ if(!(Test-Path $PackageDir))
mkdir $PackageDir | Out-Null mkdir $PackageDir | Out-Null
} }
$DotnetMSIOutput = Join-Path $PackageDir "dotnet-win-x64.$env:DOTNET_CLI_VERSION.msi" $DotnetMSIOutput = Join-Path $PackageDir "dotnet-win-$env:ARCHITECTURE.$env:DOTNET_CLI_VERSION.msi"
$DotnetBundleOutput = Join-Path $PackageDir "dotnet-win-x64.$env:DOTNET_CLI_VERSION.exe" $DotnetBundleOutput = Join-Path $PackageDir "dotnet-win-$env:ARCHITECTURE.$env:DOTNET_CLI_VERSION.exe"
Write-Host "Creating dotnet MSI at $DotnetMSIOutput" Write-Host "Creating dotnet MSI at $DotnetMSIOutput"
Write-Host "Creating dotnet Bundle at $DotnetBundleOutput" Write-Host "Creating dotnet Bundle at $DotnetBundleOutput"

View file

@ -26,7 +26,7 @@
<?if $(var.Platform)=x86?> <?if $(var.Platform)=x86?>
<?define Program_Files="ProgramFilesFolder"?> <?define Program_Files="ProgramFilesFolder"?>
<?define Win64AttributeValue=no?> <?define Win64AttributeValue=no?>
<?define UpgradeCode="70A1576F-63B6-4659-9E39-25C7B769DDE5"?> <?define UpgradeCode="25CAE344-22A6-422D-942E-942687C56A45"?>
<?elseif $(var.Platform)=x64?> <?elseif $(var.Platform)=x64?>
<?define Program_Files="ProgramFiles64Folder"?> <?define Program_Files="ProgramFiles64Folder"?>
<?define Win64AttributeValue=yes?> <?define Win64AttributeValue=yes?>

View file

@ -14,6 +14,8 @@ namespace Microsoft.DotNet.Cli.Build
{ {
public static readonly string CoreCLRVersion = "1.0.1-rc2-23811"; public static readonly string CoreCLRVersion = "1.0.1-rc2-23811";
public static readonly string AppDepSdkVersion = "1.0.6-prerelease-00003"; public static readonly string AppDepSdkVersion = "1.0.6-prerelease-00003";
public static readonly bool IsWinx86 = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
RuntimeInformation.ProcessArchitecture == Architecture.X86;
public static readonly List<string> AssembliesToCrossGen = GetAssembliesToCrossGen(); public static readonly List<string> AssembliesToCrossGen = GetAssembliesToCrossGen();
@ -60,16 +62,18 @@ namespace Microsoft.DotNet.Cli.Build
Mkdirp(cmakeOut); Mkdirp(cmakeOut);
var configuration = c.BuildContext.Get<string>("Configuration"); var configuration = c.BuildContext.Get<string>("Configuration");
var architecture = PlatformServices.Default.Runtime.RuntimeArchitecture;
// Run the build // Run the build
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
// Why does Windows directly call cmake but Linux/Mac calls "build.sh" in the corehost dir? // Why does Windows directly call cmake but Linux/Mac calls "build.sh" in the corehost dir?
// See the comment in "src/corehost/build.sh" for details. It doesn't work for some reason. // See the comment in "src/corehost/build.sh" for details. It doesn't work for some reason.
var visualStudio = IsWinx86 ? "Visual Studio 14 2015" : "Visual Studio 14 2015 Win64";
ExecIn(cmakeOut, "cmake", ExecIn(cmakeOut, "cmake",
Path.Combine(c.BuildContext.BuildDirectory, "src", "corehost"), Path.Combine(c.BuildContext.BuildDirectory, "src", "corehost"),
"-G", "-G",
"Visual Studio 14 2015 Win64"); visualStudio);
var pf32 = RuntimeInformation.OSArchitecture == Architecture.X64 ? var pf32 = RuntimeInformation.OSArchitecture == Architecture.X64 ?
Environment.GetEnvironmentVariable("ProgramFiles(x86)") : Environment.GetEnvironmentVariable("ProgramFiles(x86)") :
@ -203,6 +207,25 @@ namespace Microsoft.DotNet.Cli.Build
File.Delete(Path.Combine(binDir, $"dotnet{Constants.ExeSuffix}")); File.Delete(Path.Combine(binDir, $"dotnet{Constants.ExeSuffix}"));
File.Copy(Path.Combine(binDir, $"corehost{Constants.ExeSuffix}"), Path.Combine(binDir, $"dotnet{Constants.ExeSuffix}")); File.Copy(Path.Combine(binDir, $"corehost{Constants.ExeSuffix}"), Path.Combine(binDir, $"dotnet{Constants.ExeSuffix}"));
// HACK
// bootstrapping for Windows x86. Copy csc/vbc from stage0.
// This is a temporary hack for https://github.com/dotnet/roslyn/issues/8951
if (IsWinx86)
{
List<string> x86compilerBins = new List<string> {
"csc.dll",
"Microsoft.CodeAnalysis.CSharp.dll",
"Microsoft.CodeAnalysis.dll",
"Microsoft.CodeAnalysis.VisualBasic.dll",
"vbc.dll"
};
foreach (var binary in x86compilerBins)
{
File.Copy(Path.Combine(DotNetCli.Stage0.BinPath, binary), Path.Combine(binDir, binary), true);
}
}
// Crossgen Roslyn // Crossgen Roslyn
var result = Crossgen(c, binDir); var result = Crossgen(c, binDir);
if (!result.Success) if (!result.Success)
@ -233,8 +256,16 @@ namespace Microsoft.DotNet.Cli.Build
// Find toolchain package // Find toolchain package
string packageId; string packageId;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
if (IsWinx86)
{
// https://github.com/dotnet/cli/issues/1550
c.Warn("Native compilation is not yet working on Windows x86");
return c.Success();
}
packageId = "toolchain.win7-x64.Microsoft.DotNet.AppDep"; packageId = "toolchain.win7-x64.Microsoft.DotNet.AppDep";
} }
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
@ -282,10 +313,11 @@ namespace Microsoft.DotNet.Cli.Build
} }
// Find crossgen // Find crossgen
string arch = PlatformServices.Default.Runtime.RuntimeArchitecture;
string packageId; string packageId;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
packageId = "runtime.win7-x64.Microsoft.NETCore.Runtime.CoreCLR"; packageId = $"runtime.win7-{arch}.Microsoft.NETCore.Runtime.CoreCLR";
} }
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{ {

View file

@ -27,6 +27,7 @@ namespace Microsoft.DotNet.Cli.Build
// This is overkill, but I want to cover all the variables used in all OSes (including where some have the same names) // This is overkill, but I want to cover all the variables used in all OSes (including where some have the same names)
var buildVersion = c.BuildContext.Get<BuildVersion>("BuildVersion"); var buildVersion = c.BuildContext.Get<BuildVersion>("BuildVersion");
var configuration = c.BuildContext.Get<string>("Configuration"); var configuration = c.BuildContext.Get<string>("Configuration");
var architecture = PlatformServices.Default.Runtime.RuntimeArchitecture;
var env = new Dictionary<string, string>() var env = new Dictionary<string, string>()
{ {
{ "RID", PlatformServices.Default.Runtime.GetRuntimeIdentifier() }, { "RID", PlatformServices.Default.Runtime.GetRuntimeIdentifier() },
@ -50,7 +51,8 @@ namespace Microsoft.DotNet.Cli.Build
{ "DOTNET_CLI_VERSION", buildVersion.SimpleVersion }, { "DOTNET_CLI_VERSION", buildVersion.SimpleVersion },
{ "DOTNET_MSI_VERSION", buildVersion.GenerateMsiVersion() }, { "DOTNET_MSI_VERSION", buildVersion.GenerateMsiVersion() },
{ "VersionSuffix", buildVersion.VersionSuffix }, { "VersionSuffix", buildVersion.VersionSuffix },
{ "CONFIGURATION", configuration } { "CONFIGURATION", configuration },
{ "ARCHITECTURE", architecture }
}; };
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))

View file

@ -35,7 +35,9 @@ namespace Microsoft.DotNet.Cli.Build
{ {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
return Path.Combine(Directory.GetCurrentDirectory(), ".dotnet_stage0", PlatformServices.Default.Runtime.OperatingSystemPlatform.ToString(), "cli", "bin"); return Path.Combine(Directory.GetCurrentDirectory(), ".dotnet_stage0",
PlatformServices.Default.Runtime.OperatingSystemPlatform.ToString(),
PlatformServices.Default.Runtime.RuntimeArchitecture, "cli", "bin");
} }
else else
{ {

View file

@ -5,7 +5,8 @@
param( param(
[string]$Channel="dev", [string]$Channel="dev",
[string]$version="Latest" [string]$version="Latest",
[string]$Architecture="x64"
) )
$ErrorActionPreference="Stop" $ErrorActionPreference="Stop"
@ -16,7 +17,7 @@ if ($fileVersion -eq "Latest") {
$fileVersion = "latest" $fileVersion = "latest"
} }
$Feed="https://dotnetcli.blob.core.windows.net/dotnet" $Feed="https://dotnetcli.blob.core.windows.net/dotnet"
$DotNetFileName="dotnet-win-x64.$fileVersion.zip" $DotNetFileName="dotnet-win-$Architecture.$fileVersion.zip"
$DotNetUrl="$Feed/$Channel/Binaries/$Version" $DotNetUrl="$Feed/$Channel/Binaries/$Version"
function say($str) function say($str)
@ -42,7 +43,7 @@ if (Test-Path $LocalFile)
{ {
if ($Version -eq "Latest") if ($Version -eq "Latest")
{ {
$RemoteResponse = Invoke-WebRequest -UseBasicParsing "$Feed/$Channel/dnvm/latest.win.version" $RemoteResponse = Invoke-WebRequest -UseBasicParsing "$Feed/$Channel/dnvm/latest.win.$Architecture.version"
$RemoteData = @([Text.Encoding]::UTF8.GetString($RemoteResponse.Content).Split([char[]]@(), [StringSplitOptions]::RemoveEmptyEntries)); $RemoteData = @([Text.Encoding]::UTF8.GetString($RemoteResponse.Content).Split([char[]]@(), [StringSplitOptions]::RemoveEmptyEntries));
$RemoteHash = $RemoteData[0].Trim() $RemoteHash = $RemoteData[0].Trim()
$RemoteVersion = $RemoteData[1].Trim() $RemoteVersion = $RemoteData[1].Trim()

View file

@ -26,7 +26,7 @@ $PackageVersion
$VersionContent | Out-File -Encoding UTF8 "$Stage2Dir\.version" $VersionContent | Out-File -Encoding UTF8 "$Stage2Dir\.version"
$PackageName = Join-Path $PackageDir "dotnet-win-x64.$PackageVersion.zip" $PackageName = Join-Path $PackageDir "dotnet-win-$env:ARCHITECTURE.$PackageVersion.zip"
if (Test-Path $PackageName) if (Test-Path $PackageName)
{ {

View file

@ -98,30 +98,16 @@ function UploadBinaries($zipFile)
} }
Write-Host "Updating the latest dotnet binaries for windows.." Write-Host "Updating the latest dotnet binaries for windows.."
$zipBlobLatest = "$env:CHANNEL/Binaries/Latest/dotnet-win-x64.latest.zip" $zipBlobLatest = "$env:CHANNEL/Binaries/Latest/dotnet-win-$env:ARCHITECTURE.latest.zip"
if(-Not (UploadFile $zipBlobLatest $zipFile $true)) if(-Not (UploadFile $zipBlobLatest $zipFile $true))
{ {
return -1 return -1
} }
# update the index file too
$indexContent = "Binaries/$env:DOTNET_CLI_VERSION/$fileName"
$indexFile = "$env:TEMP\latest.win.index"
$indexContent | Out-File -FilePath $indexFile
# upload the index file
$indexBlob = "$env:CHANNEL/dnvm/latest.win.index"
if(-Not (UploadFile $indexBlob $indexFile $true))
{
return -1
}
# update the version file # update the version file
$versionFile = Convert-Path $PSScriptRoot\..\..\artifacts\$env:RID\stage2\.version $versionFile = Convert-Path $PSScriptRoot\..\..\artifacts\$env:RID\stage2\.version
$versionBlob = "$env:CHANNEL/dnvm/latest.win.version" $versionBlob = "$env:CHANNEL/dnvm/latest.win.$env:ARCHITECTURE.version"
if(-Not (UploadFile $versionBlob $versionFile $true)) if(-Not (UploadFile $versionBlob $versionFile $true))
{ {
@ -142,7 +128,7 @@ function UploadInstallers($installerFile)
} }
Write-Host "Updating the latest dotnet installer for windows.." Write-Host "Updating the latest dotnet installer for windows.."
$installerBlobLatest = "$env:CHANNEL/Installers/Latest/dotnet-win-x64.latest.exe" $installerBlobLatest = "$env:CHANNEL/Installers/Latest/dotnet-win-$env:ARCHITECTURE.latest.exe"
if(-Not (UploadFile $installerBlobLatest $installerFile $true)) if(-Not (UploadFile $installerBlobLatest $installerFile $true))
{ {

View file

@ -5,6 +5,7 @@
param( param(
[string]$Configuration="Debug", [string]$Configuration="Debug",
[string]$Architecture="x64",
[switch]$NoPackage, [switch]$NoPackage,
[switch]$Help) [switch]$Help)
@ -14,6 +15,7 @@ if($Help)
Write-Host "" Write-Host ""
Write-Host "Options:" Write-Host "Options:"
Write-Host " -Configuration <CONFIGURATION> Build the specified Configuration (Debug or Release, default: Debug)" Write-Host " -Configuration <CONFIGURATION> Build the specified Configuration (Debug or Release, default: Debug)"
Write-Host " -Architecture <ARCHITECTURE> Build the specified architecture (x64 or x86 (supported only on Windows), default: x64)"
Write-Host " -NoPackage Skip packaging targets" Write-Host " -NoPackage Skip packaging targets"
Write-Host " -Help Display this help message" Write-Host " -Help Display this help message"
Write-Host " <TARGETS...> The build targets to run (Init, Compile, Publish, etc.; Default is a full build and publish)" Write-Host " <TARGETS...> The build targets to run (Init, Compile, Publish, etc.; Default is a full build and publish)"
@ -44,7 +46,7 @@ $env:CHANNEL=$env:RELEASE_SUFFIX
# Use a repo-local install directory (but not the artifacts directory because that gets cleaned a lot # Use a repo-local install directory (but not the artifacts directory because that gets cleaned a lot
if (!$env:DOTNET_INSTALL_DIR) if (!$env:DOTNET_INSTALL_DIR)
{ {
$env:DOTNET_INSTALL_DIR="$PSScriptRoot\..\.dotnet_stage0\Windows" $env:DOTNET_INSTALL_DIR="$PSScriptRoot\..\.dotnet_stage0\Windows\$Architecture"
} }
if (!(Test-Path $env:DOTNET_INSTALL_DIR)) if (!(Test-Path $env:DOTNET_INSTALL_DIR))
@ -54,7 +56,7 @@ if (!(Test-Path $env:DOTNET_INSTALL_DIR))
# Install a stage 0 # Install a stage 0
Write-Host "Installing .NET Core CLI Stage 0 from beta channel" Write-Host "Installing .NET Core CLI Stage 0 from beta channel"
& "$PSScriptRoot\obtain\install.ps1" -Channel $env:CHANNEL & "$PSScriptRoot\obtain\install.ps1" -Channel $env:CHANNEL -Architecture $Architecture
# Put the stage0 on the path # Put the stage0 on the path
$env:PATH = "$env:DOTNET_INSTALL_DIR\cli\bin;$env:PATH" $env:PATH = "$env:DOTNET_INSTALL_DIR\cli\bin;$env:PATH"

View file

@ -2,7 +2,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using NugetProgram = NuGet.CommandLine.XPlat.Program;
namespace Microsoft.DotNet.Tools.Restore namespace Microsoft.DotNet.Tools.Restore
{ {
@ -20,22 +22,16 @@ namespace Microsoft.DotNet.Tools.Restore
var result = Run(Enumerable.Concat( var result = Run(Enumerable.Concat(
prefixArgs, prefixArgs,
args)) args).ToArray());
.ForwardStdOut()
.ForwardStdErr()
.Execute();
return result.ExitCode; return result;
} }
private static Command Run(IEnumerable<string> nugetArgs) private static int Run(string[] nugetArgs)
{ {
var corerun = Path.Combine( var nugetAsm = typeof(NugetProgram).GetTypeInfo().Assembly;
AppContext.BaseDirectory, var mainMethod = nugetAsm.EntryPoint;
"corerun" + Constants.ExeSuffix); return (int)mainMethod.Invoke(null, new object[] { nugetArgs });
return Command.Create(corerun, Enumerable.Concat(
new[] { Path.Combine(AppContext.BaseDirectory, "NuGet.CommandLine.XPlat.dll") },
nugetArgs));
} }
} }
} }

View file

@ -89,6 +89,12 @@ namespace Microsoft.DotNet.Tests.EndToEnd
return; return;
} }
if (IsWinX86())
{
Console.WriteLine("Skipping native compilation tests on Windows x86 - https://github.com/dotnet/cli/issues/1550");
return;
}
var buildCommand = new BuildCommand(TestProject, output: OutputDirectory, native: true, framework: DefaultFramework); var buildCommand = new BuildCommand(TestProject, output: OutputDirectory, native: true, framework: DefaultFramework);
buildCommand.Execute().Should().Pass(); buildCommand.Execute().Should().Pass();
@ -105,6 +111,12 @@ namespace Microsoft.DotNet.Tests.EndToEnd
return; return;
} }
if (IsWinX86())
{
Console.WriteLine("Skipping native compilation tests on Windows x86 - https://github.com/dotnet/cli/issues/1550");
return;
}
var buildCommand = new BuildCommand(TestProject, output: OutputDirectory, native: true, nativeCppMode: true, framework: DefaultFramework); var buildCommand = new BuildCommand(TestProject, output: OutputDirectory, native: true, nativeCppMode: true, framework: DefaultFramework);
buildCommand.Execute().Should().Pass(); buildCommand.Execute().Should().Pass();
@ -121,6 +133,12 @@ namespace Microsoft.DotNet.Tests.EndToEnd
return; return;
} }
if (IsWinX86())
{
Console.WriteLine("Skipping native compilation tests on Windows x86 - https://github.com/dotnet/cli/issues/1550");
return;
}
// first build // first build
var buildCommand = new BuildCommand(TestProject, output: OutputDirectory, native: true, nativeCppMode: true, framework: DefaultFramework); var buildCommand = new BuildCommand(TestProject, output: OutputDirectory, native: true, nativeCppMode: true, framework: DefaultFramework);
var binariesOutputDirectory = GetCompilationOutputPath(OutputDirectory, false); var binariesOutputDirectory = GetCompilationOutputPath(OutputDirectory, false);
@ -233,6 +251,12 @@ namespace Microsoft.DotNet.Tests.EndToEnd
return false; return false;
} }
private bool IsWinX86()
{
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
RuntimeInformation.ProcessArchitecture == Architecture.X86;
}
private static DateTime GetLastWriteTimeUtcOfDirectoryFiles(string outputDirectory) private static DateTime GetLastWriteTimeUtcOfDirectoryFiles(string outputDirectory)
{ {
return Directory.EnumerateFiles(outputDirectory).Max(f => File.GetLastWriteTimeUtc(f)); return Directory.EnumerateFiles(outputDirectory).Max(f => File.GetLastWriteTimeUtc(f));