diff --git a/build.psm1 b/build.psm1 index a5f4a1c540..ae3e4dfc6f 100644 --- a/build.psm1 +++ b/build.psm1 @@ -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'" diff --git a/src/powershell-native/CMakeLists.txt b/src/powershell-native/CMakeLists.txt index 4889c163f4..051d880ca5 100644 --- a/src/powershell-native/CMakeLists.txt +++ b/src/powershell-native/CMakeLists.txt @@ -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 () diff --git a/src/powershell-native/Install-PowerShellRemoting.ps1 b/src/powershell-native/Install-PowerShellRemoting.ps1 index dbada625e8..5bfbf0e6b9 100644 --- a/src/powershell-native/Install-PowerShellRemoting.ps1 +++ b/src/powershell-native/Install-PowerShellRemoting.ps1 @@ -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 = '' + $regKeyValueFormatString = @" + + + + + + + + + + + + +"@ $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 diff --git a/src/powershell-native/coreclr_defs.cmake b/src/powershell-native/coreclr_defs.cmake index b0d26adc1e..1b6ea3eeb5 100644 --- a/src/powershell-native/coreclr_defs.cmake +++ b/src/powershell-native/coreclr_defs.cmake @@ -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) diff --git a/src/powershell-native/nativemsh/pwrshcommon/ConfigFileReader.cpp b/src/powershell-native/nativemsh/pwrshcommon/ConfigFileReader.cpp index b3b65874f3..33b79046a4 100644 --- a/src/powershell-native/nativemsh/pwrshcommon/ConfigFileReader.cpp +++ b/src/powershell-native/nativemsh/pwrshcommon/ConfigFileReader.cpp @@ -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'\\')