openssh-portable/contrib/win32/openssh/OpenSSHBuildHelper.psm1

531 lines
16 KiB
PowerShell

Set-StrictMode -Version Latest
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -force -DisableNameChecking
[string] $script:platform = $env:PROCESSOR_ARCHITECTURE
[string] $script:vcPath = $null
[System.IO.DirectoryInfo] $script:OpenSSHRoot = $null
[System.IO.DirectoryInfo] $script:gitRoot = $null
[bool] $script:Verbose = $false
[string] $script:BuildLogFile = $null
<#
Called by Write-BuildMsg to write to the build log, if it exists.
#>
function Write-Log
{
param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Message
)
# write it to the log file, if present.
if (-not ([string]::IsNullOrEmpty($script:BuildLogFile)))
{
Add-Content -Path $script:BuildLogFile -Value $Message
}
}
<#
.Synopsis
Writes a build message.
.Parameter Message
The message to write.
.Parameter AsInfo
Writes a user message using Write-Information.
.Parameter AsVerbose
Writes a message using Write-Verbose and to the build log if -Verbose was specified to Start-DscBuild.
.Parameter AsWarning
Writes a message using Write-Warning and to the build log.
.Parameter AsError
Writes a message using Write-Error and to the build log.
.Parameter Silent
Writes the message only to the log.
.Parameter ErrorAction
Determines if the script is terminated when errors are written.
This parameter is ignored when -Silent is specified.
.Example
Write-BuildMsg -AsInfo 'Starting the build'
Writes an informational message to the log and to the user
.Example
Write-BuildMsg -AsError 'Terminating build' -Silent
Writes an error message only to the log
.Example
Write-BuildMsg -AsError 'Terminating build' -ErrorAction Stop
Writes an error message to the log and the user and terminates the build.
.Example
Write-BuildMsg -AsInfo 'Nuget is already installed' -Silent:(-not $script:Verbose)
Writes an informational message to the log. If -Verbose was specified, also
writes to message to the user.
#>
function Write-BuildMsg
{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Message,
[Parameter(ParameterSetName='Info')]
[switch] $AsInfo,
[Parameter(ParameterSetName='Verbose')]
[switch] $AsVerbose,
[Parameter(ParameterSetName='Warning')]
[switch] $AsWarning,
[Parameter(ParameterSetName='Error')]
[switch] $AsError,
[switch] $Silent
)
if ($AsVerbose)
{
if ($script:Verbose)
{
Write-Log -Message "VERBOSE: $message"
if (-not $Silent)
{
Write-Verbose -Message $message -Verbose
}
}
return
}
if ($AsInfo)
{
Write-Log -Message "INFO: $message"
if (-not $Silent)
{
Write-Information -MessageData $message -InformationAction Continue
}
return
}
if ($AsWarning)
{
Write-Log -Message "WARNING: $message"
if (-not $Silent)
{
Write-Warning -Message $message
}
return
}
if ($AsError)
{
Write-Log -Message "ERROR: $message"
if (-not $Silent)
{
Write-Error -Message $message
}
return
}
# if we reached here, no output type switch was specified.
Write-BuildMsg -AsError -ErrorAction Stop -Message 'Write-BuildMsg was called without selecting an output type.'
}
<#
.Synopsis
Verifies all tools and dependencies required for building Open SSH are installed on the machine.
#>
function Start-OpenSSHBootstrap
{
[bool] $silent = -not $script:Verbose
Set-StrictMode -Version Latest
Write-BuildMsg -AsInfo -Message "Checking tools and dependencies" -Silent:$silent
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
$newMachineEnvironmentPath = $machinePath
# Install chocolatey
$chocolateyPath = "$env:AllUsersProfile\chocolatey\bin"
if(Get-Command "choco" -ErrorAction SilentlyContinue)
{
Write-BuildMsg -AsVerbose -Message "Chocolatey is already installed. Skipping installation." -Silent:$silent
}
else
{
Write-BuildMsg -AsInfo -Message "Chocolatey not present. Installing chocolatey." -Silent:$silent
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:BuildLogFile
}
# Add git\cmd to the path
$gitCmdPath = "$env:ProgramFiles\git\cmd"
if (-not ($machinePath.ToLower().Contains($gitCmdPath.ToLower())))
{
Write-BuildMsg -AsVerbose -Message "Adding $gitCmdPath to Path environment variable" -Silent:$silent
$newMachineEnvironmentPath = "$gitCmdPath;$newMachineEnvironmentPath"
}
else
{
Write-BuildMsg -AsVerbose -Message "$gitCmdPath already present in Path environment variable" -Silent:$silent
}
$nativeMSBuildPath = "${env:ProgramFiles(x86)}\MSBuild\14.0\bin"
if($script:platform -ieq "AMD64")
{
$nativeMSBuildPath += "\amd64"
}
if (-not ($machinePath.ToLower().Contains($nativeMSBuildPath.ToLower())))
{
Write-BuildMsg -AsVerbose -Message "Adding $nativeMSBuildPath to Path environment variable" -Silent:$silent
$newMachineEnvironmentPath += ";$nativeMSBuildPath"
$env:Path += ";$nativeMSBuildPath"
}
else
{
Write-BuildMsg -AsVerbose -Message "$nativeMSBuildPath already present in Path environment variable" -Silent:$silent
}
# Update machine environment path
if ($newMachineEnvironmentPath -ne $machinePath)
{
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
}
# install nasm
$packageName = "nasm"
$nasmPath = "${env:ProgramFiles(x86)}\NASM"
if (-not (Test-Path -Path $nasmPath -PathType Container))
{
Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName." -Silent:$silent
choco install $packageName -y --force --limitoutput --execution-timeout 10000 2>&1 >> $script:BuildLogFile
}
else
{
Write-BuildMsg -AsVerbose -Message "$packageName present. Skipping installation." -Silent:$silent
}
# Install Visual Studio 2015 Community
$packageName = "VisualStudio2015Community"
$VSPackageInstalled = Get-ItemProperty "HKLM:\software\WOW6432Node\Microsoft\VisualStudio\14.0\setup\vs" -ErrorAction SilentlyContinue
if ($null -eq $VSPackageInstalled)
{
Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName."
$adminFilePath = "$script:OpenSSHRoot\contrib\win32\openssh\VSWithBuildTools.xml"
choco install $packageName -packageParameters "--AdminFile $adminFilePath" -y --force --limitoutput --execution-timeout 10000 2>&1 >> $script:BuildLogFile
}
else
{
Write-BuildMsg -AsVerbose -Message "$packageName present. Skipping installation." -Silent:$silent
}
# Install Windows 8.1 SDK
$packageName = "windows-sdk-8.1"
$sdkPath = "${env:ProgramFiles(x86)}\Windows Kits\8.1\bin\x86\register_app.vbs"
if (-not (Test-Path -Path $sdkPath))
{
Write-BuildMsg -AsInfo -Message "Windows 8.1 SDK not present. Installing $packageName."
choco install $packageName -y --limitoutput --force 2>&1 >> $script:BuildLogFile
}
else
{
Write-BuildMsg -AsInfo -Message "$packageName present. Skipping installation." -Silent:$silent
}
# Require restarting PowerShell session
if ($null -eq $VSPackageInstalled)
{
Write-Host "To apply changes, please close this PowerShell window, open a new one and call Start-SSHBuild or Start-DscBootstrap again." -ForegroundColor Black -BackgroundColor Yellow
Write-Host -NoNewLine 'Press any key to close this PowerShell window...' -ForegroundColor Black -BackgroundColor Yellow
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
exit
}
# Ensure the VS C toolset is installed
if ($null -eq $env:VS140COMNTOOLS)
{
Write-BuildMsg -AsError -ErrorAction Stop -Message "Cannot find Visual Studio 2015 Environment variable VS140COMNTOOlS"
}
$item = Get-Item(Join-Path -Path $env:VS140COMNTOOLS -ChildPath '../../vc')
$script:vcPath = $item.FullName
Write-BuildMsg -AsVerbose -Message "vcPath: $script:vcPath" -Silent:$silent
if ((Test-Path -Path "$script:vcPath\vcvarsall.bat") -eq $false)
{
Write-BuildMsg -AsError -ErrorAction Stop -Message "Could not find Visual Studio vcvarsall.bat at$script:vcPath, which means some required develop kits are missing on the machine."
}
}
function Clone-Win32OpenSSH
{
[bool] $silent = -not $script:Verbose
$win32OpenSSHPath = join-path $script:gitRoot "Win32-OpenSSH"
if (-not (Test-Path -Path $win32OpenSSHPath -PathType Container))
{
Write-BuildMsg -AsInfo -Message "clone repo Win32-OpenSSH" -Silent:$silent
Push-Location $gitRoot
git clone -q --recursive https://github.com/PowerShell/Win32-OpenSSH.git $win32OpenSSHPath
Pop-Location
}
Write-BuildMsg -AsInfo -Message "pull latest from repo Win32-OpenSSH" -Silent:$silent
Push-Location $win32OpenSSHPath
git fetch -q origin
git checkout -qf L1-Prod
Pop-Location
}
function Copy-OpenSSLSDK
{
[bool] $silent = -not $script:Verbose
$sourcePath = Join-Path $script:gitRoot "Win32-OpenSSH\contrib\win32\openssh\OpenSSLSDK"
Write-BuildMsg -AsInfo -Message "copying $sourcePath" -Silent:$silent
Copy-Item -Container -Path $sourcePath -Destination $PSScriptRoot -Recurse -Force -ErrorAction SilentlyContinue -ErrorVariable e
if($e -ne $null)
{
Write-BuildMsg -AsError -ErrorAction Stop -Message "Copy OpenSSL from $sourcePath failed "
}
}
function Build-OpenSSH
{
[CmdletBinding(SupportsShouldProcess=$false)]
param
(
[ValidateSet('x86', 'x64')]
[string]$NativeHostArch = "x64",
[ValidateSet('Debug', 'Release', '')]
[string]$Configuration = "Release"
)
Set-StrictMode -Version Latest
$script:BuildLogFile = $null
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
# Get openssh-portable root
$script:OpenSSHRoot = Get-Item -Path $repositoryRoot.FullName
$script:gitRoot = split-path $script:OpenSSHRoot
if($PSBoundParameters.ContainsKey("Verbose"))
{
$script:Verbose = ($PSBoundParameters['Verbose']).IsPresent
}
[bool] $silent = -not $script:Verbose
$script:BuildLogFile = Get-BuildLogFile -root $repositoryRoot.FullName -Configuration $Configuration -NativeHostArch $NativeHostArch
if (Test-Path -Path $script:BuildLogFile)
{
Remove-Item -Path $script:BuildLogFile -force
}
Write-BuildMsg -AsInfo -Message "Starting Open SSH build; Build Log: $($script:BuildLogFile)"
Start-OpenSSHBootstrap
Clone-Win32OpenSSH
Copy-OpenSSLSDK
$msbuildCmd = "msbuild.exe"
$solutionFile = Get-SolutionFile -root $repositoryRoot.FullName
$cmdMsg = @("${solutionFile}", "/p:Platform=${NativeHostArch}", "/p:Configuration=${Configuration}", "/m", "/noconlog", "/nologo", "/fl", "/flp:LogFile=${script:BuildLogFile}`;Append`;Verbosity=diagnostic")
& $msbuildCmd $cmdMsg
$errorCode = $LASTEXITCODE
if ($errorCode -ne 0)
{
Write-BuildMsg -AsError -ErrorAction Stop -Message "Build failed for OpenSSH.`nExitCode: $error."
}
Write-BuildMsg -AsInfo -Message "SSH build passed." -Silent:$silent
}
function Get-BuildLogFile
{
param
(
[Parameter(Mandatory=$true)]
[ValidateNotNull()]
[System.IO.DirectoryInfo] $root,
[ValidateSet('x86', 'x64')]
[string]$NativeHostArch = "x64",
[ValidateSet('Debug', 'Release', '')]
[string]$Configuration = "Release"
)
return Join-Path -Path $root -ChildPath "contrib\win32\openssh\OpenSSH$($Configuration)$($NativeHostArch).log"
}
function Get-SolutionFile
{
param
(
[Parameter(Mandatory=$true)]
[ValidateNotNull()]
[System.IO.DirectoryInfo] $root
)
return Join-Path -Path $root -ChildPath "contrib\win32\openssh\Win32-OpenSSH.sln"
}
<#
.Synopsis
Deploy all required files to build a package and create zip file.
#>
function Deploy-Win32OpenSSHBinaries
{
[CmdletBinding()]
param
(
[ValidateSet('Debug', 'Release', '')]
[string]$Configuration = "",
[ValidateSet('x86', 'x64', '')]
[string]$NativeHostArch = "",
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
if (-not (Test-Path -Path $OpenSSHDir -PathType Container))
{
$null = New-Item -Path $OpenSSHDir -ItemType Directory -Force -ErrorAction Stop
}
[string] $platform = $env:PROCESSOR_ARCHITECTURE
if(-not [String]::IsNullOrEmpty($NativeHostArch))
{
$folderName = $NativeHostArch
if($NativeHostArch -ieq 'x86')
{
$folderName = "Win32"
}
}
else
{
if($platform -ieq "AMD64")
{
$folderName = "x64"
}
else
{
$folderName = "Win32"
}
}
if([String]::IsNullOrEmpty($Configuration))
{
if( $folderName -ieq "Win32" )
{
$RealConfiguration = "Debug"
}
else
{
$RealConfiguration = "Release"
}
}
else
{
$RealConfiguration = $Configuration
}
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration"
if((Get-Service ssh-agent -ErrorAction Ignore) -ne $null) {
Stop-Service ssh-agent -Force
}
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHDir -Include *.exe,*.dll -Exclude *unittest*.* -Force -ErrorAction Stop
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "contrib\win32\openssh"
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHDir -Include *.ps1,sshd_config -Exclude AnalyzeCodeDiff.ps1 -Force -ErrorAction Stop
}
<#
.Synopsis
Deploy all required files to a location and install the binaries
#>
function Install-OpenSSH
{
[CmdletBinding()]
param
(
[ValidateSet('Debug', 'Release', '')]
[string]$Configuration = "",
[ValidateSet('x86', 'x64', '')]
[string]$NativeHostArch = "",
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
Deploy-Win32OpenSSHBinaries @PSBoundParameters
Push-Location $OpenSSHDir
& ( "$OpenSSHDir\install-sshd.ps1")
.\ssh-keygen.exe -A
& ( "$OpenSSHDir\install-sshlsa.ps1")
#machine will be reboot after Install-openssh anyway
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
$newMachineEnvironmentPath = $machinePath
if (-not ($machinePath.ToLower().Contains($OpenSSHDir.ToLower())))
{
$newMachineEnvironmentPath = "$OpenSSHDir;$newMachineEnvironmentPath"
$env:Path = "$OpenSSHDir;$env:Path"
}
# Update machine environment path
if ($newMachineEnvironmentPath -ne $machinePath)
{
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
}
Set-Service sshd -StartupType Automatic
Set-Service ssh-agent -StartupType Automatic
Start-Service sshd
Pop-Location
Write-Log -Message "OpenSSH installed!"
}
<#
.Synopsis
uninstalled sshd and sshla
#>
function UnInstall-OpenSSH
{
[CmdletBinding()]
param
(
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
Push-Location $OpenSSHDir
if((Get-Service ssh-agent -ErrorAction Ignore) -ne $null) {
Stop-Service ssh-agent -Force
}
&( "$OpenSSHDir\uninstall-sshd.ps1")
&( "$OpenSSHDir\uninstall-sshlsa.ps1")
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
$newMachineEnvironmentPath = $machinePath
if ($machinePath.ToLower().Contains($OpenSSHDir.ToLower()))
{
$newMachineEnvironmentPath.Replace("$OpenSSHDir;", '')
$env:Path = $env:Path.Replace("$OpenSSHDir;", '')
}
# Update machine environment path
# machine will be reboot after Uninstall-OpenSSH
if ($newMachineEnvironmentPath -ne $machinePath)
{
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
}
Pop-Location
}
Export-ModuleMember -Function Build-OpenSSH, Get-BuildLogFile, Install-OpenSSH, UnInstall-OpenSSH