# Use the .NET Core APIs to determine the current platform; if a runtime # exception is thrown, we are on FullCLR, not .NET Core. # # TODO: import Microsoft.PowerShell.Platform instead try { $Runtime = [System.Runtime.InteropServices.RuntimeInformation] $OSPlatform = [System.Runtime.InteropServices.OSPlatform] $IsCore = $true $IsLinux = $Runtime::IsOSPlatform($OSPlatform::Linux) $IsOSX = $Runtime::IsOSPlatform($OSPlatform::OSX) $IsWindows = $Runtime::IsOSPlatform($OSPlatform::Windows) } catch [System.Management.Automation.RuntimeException] { $IsCore = $false $IsLinux = $false $IsOSX = $false $IsWindows = $true } function Start-PSBuild { [CmdletBinding(DefaultParameterSetName='CoreCLR')] param( [switch]$Restore, [switch]$Clean, [string]$Output, # These runtimes must match those in project.json # We do not use ValidateScript since we want tab completion [ValidateSet("ubuntu.14.04-x64", "centos.7.1-x64", "win7-x64", "win10-x64", "osx.10.10-x64", "osx.10.11-x64")] [Parameter(ParameterSetName='CoreCLR')] [string]$Runtime, [Parameter(ParameterSetName='FullCLR')] [switch]$FullCLR, [Parameter(ParameterSetName='FullCLR')] [string]$cmakeGenerator = "Visual Studio 14 2015", [Parameter(ParameterSetName='FullCLR')] [ValidateSet("Debug", "Release")] [string]$msbuildConfiguration = "Release" ) function precheck([string]$command, [string]$missedMessage) { $c = Get-Command $command -ErrorAction SilentlyContinue if (-not $c) { Write-Warning $missedMessage return $false } else { return $true } } function log([string]$message) { Write-Host -Foreground Green $message } # simplify ParameterSetNames, set output if ($PSCmdlet.ParameterSetName -eq 'FullCLR') { $FullCLR = $true } if (-not $Output) { if ($FullCLR) { $Output = "$PSScriptRoot/binFull" } else { $Output = "$PSScriptRoot/bin" } } # verify we have all tools in place to do the build $precheck = precheck 'dotnet' "Build dependency 'dotnet' not found in PATH! See: https://dotnet.github.io/getting-started/" if ($FullCLR) { # cmake is needed to build powershell.exe $precheck = $precheck -and (precheck 'cmake' 'cmake not found. You can install it from https://chocolatey.org/packages/cmake.portable') # msbuild is needed to build powershell.exe # msbuild is part of .NET Framework, we can try to get it from well-known location. if (-not (Get-Command -Name msbuild -ErrorAction Ignore)) { $env:path += ";${env:SystemRoot}\Microsoft.Net\Framework\v4.0.30319" } $precheck = $precheck -and (precheck 'msbuild' 'msbuild not found. Install Visual Studio 2015.') } if (-not $precheck) { return } # handle clean if ($Clean) { Remove-Item -Force -Recurse $Output -ErrorAction SilentlyContinue } New-Item -Force -Type Directory $Output | Out-Null # define key build variables if ($FullCLR) { $Top = "$PSScriptRoot\src\Microsoft.PowerShell.ConsoleHost" $framework = 'net451' } else { $Top = "$PSScriptRoot/src/Microsoft.PowerShell.Linux.Host" $framework = 'netstandardapp1.5' } # handle Restore if ($Restore -Or -Not (Test-Path "$Top/project.lock.json")) { log "Run dotnet restore" # restore is genuinely verbose. # we don't show it by default to keep CI build log size small if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) { dotnet restore $PSScriptRoot } else { dotnet restore $PSScriptRoot > $null } } # Build native components if (-not $FullCLR) { if ($IsLinux -Or $IsOSX) { log "Start building native components" $InstallCommand = if ($IsLinux) { "apt-get" } elseif ($IsOSX) { "brew" } foreach ($Dependency in "cmake", "g++") { if (-Not (Get-Command $Dependency -ErrorAction SilentlyContinue)) { throw "Build dependency '$Dependency' not found in PATH! Run '$InstallCommand install $Dependency'" } } $Ext = if ($IsLinux) { "so" } elseif ($IsOSX) { "dylib" } $Native = "$PSScriptRoot/src/libpsl-native" $Lib = "$Native/src/libpsl-native.$Ext" Write-Verbose "Building $Lib" try { Push-Location $Native cmake -DCMAKE_BUILD_TYPE=Debug . make -j make test } finally { Pop-Location } if (-Not (Test-Path $Lib)) { throw "Compilation of $Lib failed" } Copy-Item $Lib $Output } } else { log "Start building native powershell.exe" $build = "$PSScriptRoot/build" if ($Clean) { Remove-Item -Force -Recurse $build -ErrorAction SilentlyContinue } mkdir $build -ErrorAction SilentlyContinue try { Push-Location $build if ($cmakeGenerator) { cmake -G $cmakeGenerator ..\src\powershell-native } else { cmake ..\src\powershell-native } msbuild powershell.vcxproj /p:Configuration=$msbuildConfiguration cp -rec $msbuildConfiguration\* $Output } finally { Pop-Location } } log "Building PowerShell" $Arguments = "--framework", $framework, "--output", $Output if ($IsLinux -Or $IsOSX) { $Arguments += "--configuration", "Linux" } if ($Runtime) { $Arguments += "--runtime", $Runtime } if ($FullCLR) { # there is a problem with code signing: # AssemblyKeyFileAttribute file path cannot be correctly located, if `dotnet publish $TOP` syntax is used # we workaround it with calling `dotnet publish` from $TOP directory instead. Push-Location $Top } else { $Arguments += $Top } Write-Verbose "Run dotnet publish $Arguments from $pwd" # this try-finally is part of workaround about AssemblyKeyFileAttribute issue try { dotnet publish $Arguments } finally { if ($FullCLR) { Pop-Location } } } function Start-PSPackage { # PowerShell packages use Semantic Versioning http://semver.org/ # # Ubuntu and OS X packages are supported. param( [string]$Version, [int]$Iteration = 1, [ValidateSet("deb", "osxpkg", "rpm")] [string]$Type ) if ($IsWindows) { throw "Building Windows packages is not yet supported!" } if (-Not (Get-Command "fpm" -ErrorAction SilentlyContinue)) { throw "Build dependency 'fpm' not found in PATH! See: https://github.com/jordansissel/fpm" } if (-Not(Test-Path "$PSScriptRoot/bin/powershell")) { throw "Please Start-PSBuild with the corresponding runtime for the package" } # Change permissions for packaging chmod -R go=u "$PSScriptRoot/bin" # Decide package output type if (-Not($Type)) { $Type = if ($IsLinux) { "deb" } elseif ($IsOSX) { "osxpkg" } Write-Warning "-Type was not specified, continuing with $Type" } # Use Git tag if not given a version if (-Not($Version)) { $Version = (git --git-dir="$PSScriptRoot/.git" describe) -Replace '^v' } $libunwind = switch ($Type) { "deb" { "libunwind8" } "rpm" { "libunwind" } } $libicu = switch ($Type) { "deb" { "libicu52" } "rpm" { "libicu" } } # Build package fpm --force --verbose ` --name "powershell" ` --version $Version ` --iteration $Iteration ` --maintainer "Andrew Schwartzmeyer " ` --vendor "Microsoft " ` --url "https://github.com/PowerShell/PowerShell" ` --license "Unlicensed" ` --description "Open PowerShell on .NET Core\nPowerShell is an open-source, cross-platform, scripting language and rich object shell. Built upon .NET Core, it is also a C# REPL.\n" ` --category "shells" ` --depends $libunwind ` --depends $libicu ` --deb-build-depends "dotnet" ` --deb-build-depends "cmake" ` --deb-build-depends "g++" ` -t $Type ` -s dir ` "$PSScriptRoot/bin/=/usr/local/share/powershell/" ` "$PSScriptRoot/package/powershell=/usr/local/bin" } function Start-DevPSGitHub { param( [switch]$ZapDisable, [string[]]$ArgumentList = '', [switch]$LoadProfile, [string]$binDir = "$PSScriptRoot\binFull", [switch]$NoNewWindow ) try { if ($LoadProfile -eq $false) { $ArgumentList = @('-noprofile') + $ArgumentList } $env:DEVPATH = $binDir if ($ZapDisable) { $env:COMPLUS_ZapDisable = 1 } if (-Not (Test-Path $binDir\powershell.exe.config)) { $configContents = @" "@ $configContents | Out-File -Encoding Ascii $binDir\powershell.exe.config } # splatting for the win $startProcessArgs = @{ FilePath = "$binDir\powershell.exe" ArgumentList = "$ArgumentList" } if ($NoNewWindow) { $startProcessArgs.NoNewWindow = $true $startProcessArgs.Wait = $true } Start-Process @startProcessArgs } finally { ri env:DEVPATH if ($ZapDisable) { ri env:COMPLUS_ZapDisable } } }