build: Enable building for win-arm and win-arm64 (#5524)

* enable win-arm and win-arm64 builds

* fix using arm64 tools for build
fix finding vs2017 dynamically

* change install-powershellremoting.ps1 script to use reg provider rather than reg.exe so that error doesn't show on success
fix formatting issue in cmake.defs

* add check that path being read from config file is valid
address PR feedback

* fix copying of PowerShell.Core.Instrumentation as VS2017 puts it in $HOME/source
address PR feedback
This commit is contained in:
Steve Lee
2017-12-10 10:29:53 -08:00
committed by Travis Plunk
parent bfa017d998
commit e2dc0eafbc
5 changed files with 124 additions and 64 deletions
+69 -22
View File
@@ -172,8 +172,12 @@ function Start-BuildNativeWindowsBinaries {
[ValidateSet('Debug', 'Release')]
[string]$Configuration = 'Release',
[ValidateSet('x64', 'x86')]
[string]$Arch = 'x64'
# The `x64_arm` syntax is the build environment for VS2017, `x64` means the host is an x64 machine and will use
# the x64 built tool. The `arm` refers to the target architecture when doing cross compilation.
[ValidateSet('x64', 'x86', 'x64_arm64', 'x64_arm')]
[string]$Arch = 'x64',
[switch]$Clean
)
if (-not $Environment.IsWindows) {
@@ -193,8 +197,16 @@ function Start-BuildNativeWindowsBinaries {
throw 'Win 10 SDK not found. Run "Start-PSBootstrap -BuildWindowsNative" or install Microsoft Windows 10 SDK from https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk'
}
$vcPath = (Get-Item(Join-Path -Path "$env:VS140COMNTOOLS" -ChildPath '../../vc')).FullName
if ($env:VS140COMNTOOLS -ne $null) {
$vcPath = (Get-Item(Join-Path -Path "$env:VS140COMNTOOLS" -ChildPath '../../vc')).FullName
} else {
$vcPath = (Get-ChildItem "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017" -Filter "VC" -Directory -Recurse | Select-Object -First 1).FullName
}
$atlMfcIncludePath = Join-Path -Path $vcPath -ChildPath 'atlmfc/include'
if (!(Test-Path $atlMfcIncludePath)) { # for VS2017, need to search for it
$atlMfcIncludePath = (Get-ChildItem $vcPath -Filter AtlBase.h -Recurse -File | Select-Object -First 1).DirectoryName
}
# atlbase.h is included in the pwrshplugin project
if ((Test-Path -Path $atlMfcIncludePath\atlbase.h) -eq $false) {
@@ -202,42 +214,62 @@ function Start-BuildNativeWindowsBinaries {
}
# vcvarsall.bat is used to setup environment variables
if ((Test-Path -Path $vcPath\vcvarsall.bat) -eq $false) {
throw "Could not find Visual Studio vcvarsall.bat at $vcPath. Please ensure the optional feature 'Common Tools for Visual C++' is installed."
$vcvarsallbatPath = "$vcPath\vcvarsall.bat"
if (!(Test-Path -Path $vcvarsallbatPath)) { # for VS2017, need to search for it
$vcvarsallbatPath = (Get-ChildItem $vcPath -Filter vcvarsall.bat -Recurse -File | Select-Object -First 1).FullName
}
if ((Test-Path -Path $vcvarsallbatPath) -eq $false) {
throw "Could not find Visual Studio vcvarsall.bat at $vcvarsallbatPath. Please ensure the optional feature 'Common Tools for Visual C++' is installed."
}
log "Start building native Windows binaries"
if ($Clean) {
git clean -fdx
Remove-Item $HOME\source\cmakecache.txt -ErrorAction SilentlyContinue
}
try {
Push-Location "$PSScriptRoot\src\powershell-native"
# setup cmakeGenerator
$cmakeGeneratorPlatform = ""
if ($Arch -eq 'x86') {
$cmakeGenerator = 'Visual Studio 14 2015'
$cmakeGenerator = 'Visual Studio 15 2017'
$cmakeArch = 'x86'
} elseif ($Arch -eq 'x64_arm') {
$cmakeGenerator = 'Visual Studio 15 2017 ARM'
$cmakeArch = 'arm'
} elseif ($Arch -eq 'x64_arm64') {
$cmakeGenerator = 'Visual Studio 15 2017'
$cmakeArch = 'arm64'
$cmakeGeneratorPlatform = "-A ARM64"
} else {
$cmakeGenerator = 'Visual Studio 14 2015 Win64'
$cmakeGenerator = 'Visual Studio 15 2017 Win64'
$cmakeArch = 'x64'
}
# Compile native resources
$currentLocation = Get-Location
@("nativemsh/pwrshplugin") | ForEach-Object {
@("nativemsh\pwrshplugin") | ForEach-Object {
$nativeResourcesFolder = $_
Get-ChildItem $nativeResourcesFolder -Filter "*.mc" | ForEach-Object {
$command = @"
cmd.exe /C cd /d "$currentLocation" "&" "$($vcPath)\vcvarsall.bat" "$Arch" "&" mc.exe -o -d -c -U "$($_.FullName)" -h "$nativeResourcesFolder" -r "$nativeResourcesFolder"
cmd.exe /C cd /d "$currentLocation" "&" "$vcvarsallbatPath" "$Arch" "&" mc.exe -o -d -c -U "$($_.FullName)" -h "$currentLocation\$nativeResourcesFolder" -r "$currentLocation\$nativeResourcesFolder"
"@
log " Executing mc.exe Command: $command"
Start-NativeExecution { Invoke-Expression -Command:$command 2>&1 }
Start-NativeExecution { Invoke-Expression -Command:$command }
}
}
# make sure we use version we installed and not from VS
$cmakePath = (Get-Command cmake).Source
# Disabling until I figure out if it is necessary
# $overrideFlags = "-DCMAKE_USER_MAKE_RULES_OVERRIDE=$PSScriptRoot\src\powershell-native\windows-compiler-override.txt"
$overrideFlags = ""
$location = Get-Location
$command = @"
cmd.exe /C cd /d "$location" "&" "$($vcPath)\vcvarsall.bat" "$Arch" "&" cmake "$overrideFlags" -DBUILD_ONECORE=ON -DBUILD_TARGET_ARCH=$Arch -G "$cmakeGenerator" . "&" msbuild ALL_BUILD.vcxproj "/p:Configuration=$Configuration"
cmd.exe /C cd /d "$currentLocation" "&" "$vcvarsallbatPath" "$Arch" "&" "$cmakePath" "$overrideFlags" -DBUILD_ONECORE=ON -DBUILD_TARGET_ARCH=$cmakeArch -G "$cmakeGenerator" $cmakeGeneratorPlatform "$currentLocation" "&" msbuild ALL_BUILD.vcxproj "/p:Configuration=$Configuration"
"@
log " Executing Build Command: $command"
Start-NativeExecution { Invoke-Expression -Command:$command }
@@ -258,15 +290,18 @@ cmd.exe /C cd /d "$location" "&" "$($vcPath)\vcvarsall.bat" "$Arch" "&" cmake "$
$location = "$PSScriptRoot\src\PowerShell.Core.Instrumentation"
Set-Location -Path $location
Remove-Item $HOME\source\cmakecache.txt -ErrorAction SilentlyContinue
$command = @"
cmd.exe /C cd /d "$location" "&" "$($vcPath)\vcvarsall.bat" "$Arch" "&" cmake "$overrideFlags" -DBUILD_ONECORE=ON -DBUILD_TARGET_ARCH=$Arch -G "$cmakeGenerator" . "&" msbuild ALL_BUILD.vcxproj "/p:Configuration=$Configuration"
cmd.exe /C cd /d "$location" "&" "$vcvarsallbatPath" "$Arch" "&" "$cmakePath" "$overrideFlags" -DBUILD_ONECORE=ON -DBUILD_TARGET_ARCH=$cmakeArch -G "$cmakeGenerator" $cmakeGeneratorPlatform "$location" "&" msbuild ALL_BUILD.vcxproj "/p:Configuration=$Configuration"
"@
log " Executing Build Command for PowerShell.Core.Instrumentation: $command"
Start-NativeExecution { Invoke-Expression -Command:$command }
# Copy the binary to the packaging directory
# NOTE: No PDB file; it's a resource-only DLL.
$srcPath = [IO.Path]::Combine($location, $Configuration, 'PowerShell.Core.Instrumentation.dll')
# VS2017 puts this in $HOME\source
$srcPath = [IO.Path]::Combine($HOME, "source", $Configuration, 'PowerShell.Core.Instrumentation.dll')
Copy-Item -Path $srcPath -Destination $dstPath
} finally {
@@ -364,7 +399,9 @@ function Start-PSBuild {
"win7-x86",
"osx.10.12-x64",
"linux-x64",
"linux-arm")]
"linux-arm",
"win-arm",
"win-arm64")]
[string]$Runtime,
[ValidateSet('Linux', 'Debug', 'Release', 'CodeCoverage', '')] # We might need "Checked" as well
@@ -381,6 +418,10 @@ function Start-PSBuild {
throw "Cross compiling for linux-arm is only supported on Ubuntu environment"
}
if ("win-arm","win-arm64" -contains $Runtime -and -not $Environment.IsWindows) {
throw "Cross compiling for win-arm or win-arm64 is only supported on Windows environment"
}
function Stop-DevPowerShell {
Get-Process pwsh* |
Where-Object {
@@ -652,7 +693,9 @@ function New-PSOptions {
"win7-x64",
"osx.10.12-x64",
"linux-x64",
"linux-arm")]
"linux-arm",
"win-arm",
"win-arm64")]
[string]$Runtime,
[switch]$CrossGen,
@@ -1631,11 +1674,11 @@ function Start-PSBootstrap {
# Install cmake
$cmakePath = "${env:ProgramFiles}\CMake\bin"
if($cmakePresent) {
if($cmakePresent -and !($force.IsPresent)) {
log "Cmake is already installed. Skipping installation."
} else {
log "Cmake not present. Installing cmake."
Start-NativeExecution { choco install cmake -y --version 3.6.0 }
log "Cmake not present or -Force used. Installing cmake."
Start-NativeExecution { choco install cmake -y --version 3.10.0 }
if (-not ($machinePath.ToLower().Contains($cmakePath.ToLower()))) {
log "Adding $cmakePath to Path environment variable"
$env:Path += ";$cmakePath"
@@ -2132,7 +2175,9 @@ function Start-CrossGen {
"win7-x64",
"osx.10.12-x64",
"linux-x64",
"linux-arm")]
"linux-arm",
"win-arm",
"win-arm64")]
[string]
$Runtime
)
@@ -2186,8 +2231,10 @@ function Start-CrossGen {
$crossGenRuntime = if ($Environment.IsWindows) {
if ($Runtime -match "-x86") {
"win-x86"
} else {
} elseif ($Runtime -match "-x64") {
"win-x64"
} elseif (!($env:PROCESSOR_ARCHITECTURE -match "arm")) {
throw "crossgen for 'win-arm' and 'win-arm64' must be run on that platform"
}
} elseif ($Runtime -eq "linux-arm") {
throw "crossgen is not available for 'linux-arm'"
+9 -5
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.4)
cmake_minimum_required(VERSION 3.10.0)
project(PowerShellNative)
@@ -11,9 +11,6 @@ endif ()
#
# Normalize the platform name
#
# TODO: Only x64 and x86 are supported right now. This needs to be expanded to arm and arm64 to match CoreCLR
#
SET(BUILD_ARCH_ARM 0)
SET(BUILD_ARCH_ARM64 0)
SET(BUILD_ARCH_X86 0)
@@ -21,8 +18,9 @@ SET(BUILD_ARCH_AMD64 0)
if (BUILD_TARGET_ARCH)
SET(WindowsSDKPlatform ${BUILD_TARGET_ARCH})
message(STATUS "Building for " ${BUILD_TARGET_ARCH})
else ()
message(FATAL_ERROR "Target architecture value should be specified through BUILD_TARGET_ARCH. Supported values are x64 or x86.")
message(FATAL_ERROR "Target architecture value should be specified through BUILD_TARGET_ARCH. Supported values are x64, x86, arm, or arm64")
endif (BUILD_TARGET_ARCH)
if (WindowsSDKPlatform STREQUAL "x64" OR WindowsSDKPlatform STREQUAL "X64" OR WindowsSDKPlatform STREQUAL "amd64" OR WindowsSDKPlatform STREQUAL "AMD64")
@@ -31,6 +29,12 @@ if (WindowsSDKPlatform STREQUAL "x64" OR WindowsSDKPlatform STREQUAL "X64" OR Wi
elseif (WindowsSDKPlatform STREQUAL "x86" OR WindowsSDKPlatform STREQUAL "X86")
SET(WindowsSDKPlatform "x86")
SET(BUILD_ARCH_X86 1)
elseif (WindowsSDKPlatform STREQUAL "arm" OR WindowsSDKPlatform STREQUAL "ARM")
SET(WindowsSDKPlatform "arm")
SET(BUILD_ARCH_ARM 1)
elseif (WindowsSDKPlatform STREQUAL "arm64" OR WindowsSDKPlatform STREQUAL "ARM64")
SET(WindowsSDKPlatform "arm64")
SET(BUILD_ARCH_ARM64 1)
else()
message(FATAL_ERROR "Unsupported WindowsSDKPlatform: " ${WindowsSDKPlatform})
endif ()
@@ -44,38 +44,37 @@ function Register-WinRmPlugin
$pluginEndpointName
)
$header = "Windows Registry Editor Version 5.00`n`n"
$regKeyFormatString = "[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WSMAN\Plugin\{0}]`n"
$regKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WSMAN\Plugin\$pluginEndpointName"
$regKeyName = '"ConfigXML"="{0}"'
#
# Example Values:
#
# Filename = %windir%\\system32\\PowerShell\\6.0.0\\pwrshplugin.dll
# Name = PowerShell.6.0.0
#
$pluginArchitecture = "64"
if ($env:PROCESSOR_ARCHITECTURE -match "x86")
if ($env:PROCESSOR_ARCHITECTURE -match "x86" -or $env:PROCESSOR_ARCHITECTURE -eq "ARM")
{
$pluginArchitecture = "32"
}
$regKeyValueFormatString = '<PlugInConfiguration xmlns=\"http://schemas.microsoft.com/wbem/wsman/1/config/PluginConfiguration\" Name=\"{0}\" Filename=\"{1}\" SDKVersion=\"2\" XmlRenderingType=\"text\" Enabled=\"True\" OutputBufferingMode=\"Block\" ProcessIdleTimeoutSec=\"0\" Architecture=\"{2}\" UseSharedProcess=\"false\" RunAsUser=\"\" RunAsPassword=\"\" AutoRestart=\"false\"><InitializationParameters><Param Name=\"PSVersion\" Value=\"5.0\"/></InitializationParameters><Resources><Resource ResourceUri=\"http://schemas.microsoft.com/powershell/{0}\" SupportsOptions=\"true\" ExactMatch=\"true\"><Security Uri=\"http://schemas.microsoft.com/powershell/{0}\" ExactMatch=\"true\" Sddl=\"O:NSG:BAD:P(A;;GA;;;BA)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)\"/><Capability Type=\"Shell\"/></Resource></Resources><Quotas IdleTimeoutms=\"7200000\" MaxConcurrentUsers=\"5\" MaxProcessesPerShell=\"15\" MaxMemoryPerShellMB=\"1024\" MaxShellsPerUser=\"25\" MaxConcurrentCommandsPerShell=\"1000\" MaxShells=\"25\" MaxIdleTimeoutms=\"43200000\"/></PlugInConfiguration>'
$regKeyValueFormatString = @"
<PlugInConfiguration xmlns="http://schemas.microsoft.com/wbem/wsman/1/config/PluginConfiguration" Name="{0}" Filename="{1}"
SDKVersion="2" XmlRenderingType="text" Enabled="True" OutputBufferingMode="Block" ProcessIdleTimeoutSec="0" Architecture="{2}"
UseSharedProcess="false" RunAsUser="" RunAsPassword="" AutoRestart="false">
<InitializationParameters>
<Param Name="PSVersion" Value="6.0"/>
</InitializationParameters>
<Resources>
<Resource ResourceUri="http://schemas.microsoft.com/powershell/{0}" SupportsOptions="true" ExactMatch="true">
<Security Uri="http://schemas.microsoft.com/powershell/{0}" ExactMatch="true"
Sddl="O:NSG:BAD:P(A;;GA;;;BA)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)"/>
<Capability Type="Shell"/>
</Resource>
</Resources>
<Quotas IdleTimeoutms="7200000" MaxConcurrentUsers="5" MaxProcessesPerShell="15" MaxMemoryPerShellMB="1024" MaxShellsPerUser="25"
MaxConcurrentCommandsPerShell="1000" MaxShells="25" MaxIdleTimeoutms="43200000"/>
</PlugInConfiguration>
"@
$valueString = $regKeyValueFormatString -f $pluginEndpointName, $pluginAbsolutePath, $pluginArchitecture
$keyValuePair = $regKeyName -f $valueString
$regKey = $regKeyFormatString -f $pluginEndpointName
$fileName = "$pluginEndpointName.reg"
Set-Content -path .\$fileName "$header$regKey$keyValuePair`n"
Write-Verbose "Performing WinRM registration with: $fileName"
reg.exe import .\$fileName
# Clean up
Remove-Item .\$fileName
New-Item $regKey -Force > $null
New-ItemProperty -Path $regKey -Name ConfigXML -Value $valueString > $null
}
function Generate-PluginConfigFile
@@ -98,7 +97,7 @@ function Generate-PluginConfigFile
Set-Content -Path $pluginFile -Value "PSHOMEDIR=$targetPsHomeDir"
Add-Content -Path $pluginFile -Value "CORECLRDIR=$targetPsHomeDir"
Write-Verbose "Created Plugin Config File: $pluginFile"
Write-Verbose "Created Plugin Config File: $pluginFile" -Verbose
}
######################
@@ -140,20 +139,18 @@ else
$resolvedPluginAbsolutePath = Resolve-Path $pluginBasePath
}
# The registration reg file requires "\\" instead of "\" in its path so it is properly escaped in the XML
$pluginRawPath = Join-Path $resolvedPluginAbsolutePath "pwrshplugin.dll"
$fixedPluginPath = $pluginRawPath -replace '\\','\\'
$pluginPath = Join-Path $resolvedPluginAbsolutePath "pwrshplugin.dll"
# This is forced to ensure the the file is placed correctly
Copy-Item $targetPsHome\pwrshplugin.dll $resolvedPluginAbsolutePath -Force -Verbose
$pluginFile = Join-Path $resolvedPluginAbsolutePath "RemotePowerShellConfig.txt"
Generate-PluginConfigFile $pluginFile $targetPsHome
Generate-PluginConfigFile $pluginFile (Resolve-Path $targetPsHome)
$pluginEndpointName = "powershell.$targetPsVersion"
# Register the plugin
Register-WinRmPlugin $fixedPluginPath $pluginEndpointName
Register-WinRmPlugin $pluginPath $pluginEndpointName
####################################################################
# #
@@ -174,13 +171,13 @@ if (! (Test-Path $resolvedPluginAbsolutePath\pwrshplugin.dll))
try
{
Write-Host "`nGet-PSSessionConfiguration $pluginEndpointName" -foregroundcolor "green"
Get-PSSessionConfiguration $pluginEndpointName
Get-PSSessionConfiguration $pluginEndpointName -ErrorAction Stop
}
catch [Microsoft.PowerShell.Commands.WriteErrorException]
{
Write-Error "No remoting session configuration matches the name $pluginEndpointName."
throw "No remoting session configuration matches the name $pluginEndpointName."
}
Write-Host "Restarting WinRM to ensure that the plugin configuration change takes effect.`nThis is required for WinRM running on Windows SKUs prior to Windows 10." -foregroundcolor "green"
Write-Host "Restarting WinRM to ensure that the plugin configuration change takes effect.`nThis is required for WinRM running on Windows SKUs prior to Windows 10." -foregroundcolor Magenta
Restart-Service winrm
+7 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.4)
cmake_minimum_required(VERSION 3.10.0)
set(CMAKE_CXX_STANDARD_LIBRARIES "") # do not link against standard win32 libs i.e. kernel32, uuid, user32, etc.
@@ -61,16 +61,20 @@ if (BUILD_ARCH_AMD64)
add_definitions(-D_WIN64)
add_definitions(-DAMD64)
add_definitions(-DBIT64=1)
add_definitions(-D_M_AMD64)
elseif (BUILD_ARCH_X86)
add_definitions(-D_X86_)
elseif (BUILD_ARCH_ARM)
add_definitions(-D_ARM_)
add_definitions(-D_WIN32)
add_definitions(-D_M_ARM)
add_definitions(-DARM)
elseif (BUILD_ARCH_ARM64)
add_definitions(-D_ARM64_)
add_definitions(-DARM64)
add_definitions(-D_WIN64)
add_definitions(-DBIT64=1)
add_definitions(-D_M_ARM64)
endif ()
# Define the CRT lib references that link into Desktop imports
@@ -146,6 +150,8 @@ if (BUILD_ARCH_AMD64)
add_definitions(-D_TARGET_AMD64_=1)
elseif (BUILD_ARCH_ARM)
add_definitions(-D_TARGET_ARM_=1)
elseif (BUILD_ARCH_ARM64)
add_definitions(-D_TARGET_ARM64_=1)
elseif (BUILD_ARCH_X86)
add_definitions(-D_TARGET_X86_=1)
endif (BUILD_ARCH_AMD64)
@@ -44,9 +44,12 @@ namespace NativeMsh
}
else if (*iter == L'p' || *iter == L'P')
{
this->pathToPowerShellAssemblies = this->getValueFromLine(line, psHomeDirTag);
if (this->pathToPowerShellAssemblies.size() > 0) // Found a match
std::wstring psHomeDir = this->getValueFromLine(line, psHomeDirTag);
HANDLE dirHandle = CreateFileW(psHomeDir.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (INVALID_HANDLE_VALUE != dirHandle)
{
CloseHandle(dirHandle);
this->pathToPowerShellAssemblies = psHomeDir;
std::wstring::const_iterator slashIter = this->pathToPowerShellAssemblies.end();
slashIter--;
if (*slashIter != L'\\')
@@ -59,9 +62,12 @@ namespace NativeMsh
}
else if (*iter == L'c' || *iter == L'C')
{
this->coreClrDirectory = this->getValueFromLine(line, coreClrDirTag);
if (this->coreClrDirectory.size() > 0) // Found a match
std::wstring coreClrDir = this->getValueFromLine(line, coreClrDirTag);
HANDLE dirHandle = CreateFileW(coreClrDir.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (INVALID_HANDLE_VALUE != dirHandle)
{
CloseHandle(dirHandle);
this->coreClrDirectory = coreClrDir;
std::wstring::const_iterator slashIter = this->coreClrDirectory.end();
slashIter--;
if (*slashIter != L'\\')