2016-02-24 00:21:00 +00:00
# Use the .NET Core APIs to determine the current platform; if a runtime
# exception is thrown, we are on FullCLR, not .NET Core.
2016-02-22 01:23:43 +00:00
try {
$Runtime = [ System.Runtime.InteropServices.RuntimeInformation ]
$OSPlatform = [ System.Runtime.InteropServices.OSPlatform ]
2016-03-04 20:11:01 +00:00
2016-07-21 23:52:22 +00:00
$IsCoreCLR = $true
2016-03-04 20:11:01 +00:00
$IsLinux = $Runtime :: IsOSPlatform ( $OSPlatform :: Linux )
$IsOSX = $Runtime :: IsOSPlatform ( $OSPlatform :: OSX )
$IsWindows = $Runtime :: IsOSPlatform ( $OSPlatform :: Windows )
2016-04-08 22:13:50 +00:00
} catch {
# If these are already set, then they're read-only and we're done
try {
2016-07-21 23:52:22 +00:00
$IsCoreCLR = $false
2016-04-08 22:13:50 +00:00
$IsLinux = $false
$IsOSX = $false
$IsWindows = $true
}
catch { }
2016-02-22 01:23:43 +00:00
}
2016-02-22 00:21:04 +00:00
2016-09-16 02:22:18 +00:00
if ( $IsWindows )
{
$IsAdmin = ( New-Object Security . Principal . WindowsPrincipal ( [ Security.Principal.WindowsIdentity ] :: GetCurrent ( ) ) ) . IsInRole ( [ Security.Principal.WindowsBuiltinRole ] :: Administrator )
}
2016-06-20 18:39:39 +00:00
if ( $IsLinux ) {
$LinuxInfo = Get-Content / etc / os-release | ConvertFrom-StringData
2016-06-30 20:41:43 +00:00
2016-08-11 20:38:35 +00:00
$IsUbuntu = $LinuxInfo . ID -match 'ubuntu'
$IsUbuntu14 = $IsUbuntu -and $LinuxInfo . VERSION_ID -match '14.04'
$IsUbuntu16 = $IsUbuntu -and $LinuxInfo . VERSION_ID -match '16.04'
2016-06-30 20:41:43 +00:00
$IsCentOS = $LinuxInfo . ID -match 'centos' -and $LinuxInfo . VERSION_ID -match '7'
2016-06-20 18:39:39 +00:00
}
2016-10-31 22:02:44 +00:00
#
# At the moment, we just support x64 builds. When we support x86 builds, this
# check may need to verify the SDK for the specified architecture.
#
function Get-Win10SDKBinDir {
return " $ {env:ProgramFiles(x86)}\Windows Kits\10\bin\x64 "
}
function Test-Win10SDK {
# The Windows 10 SDK is installed to "${env:ProgramFiles(x86)}\Windows Kits\10\bin\x64",
# but the directory may exist even if the SDK has not been installed.
#
# A slightly more robust check is for the mc.exe binary within that directory.
# It is only present if the SDK is installed.
return ( Test-Path " $ {env:ProgramFiles(x86)}\Windows Kits\10\bin\x64\mc.exe " )
}
2016-04-02 05:01:05 +00:00
2016-04-01 21:41:13 +00:00
function Start-PSBuild {
2016-03-12 00:19:05 +00:00
[ CmdletBinding ( DefaultParameterSetName = 'CoreCLR' ) ]
2016-02-21 23:06:39 +00:00
param (
2016-07-20 02:09:06 +00:00
# When specified this switch will stops running dev powershell
# to help avoid compilation error, because file are in use.
[ switch ] $StopDevPowerShell ,
2016-04-13 23:41:50 +00:00
[ switch ] $NoPath ,
2016-02-24 00:21:00 +00:00
[ switch ] $Restore ,
2016-05-06 17:28:45 +00:00
[ string ] $Output ,
2016-06-15 10:42:54 +00:00
[ switch ] $ResGen ,
2016-06-17 18:23:29 +00:00
[ switch ] $TypeGen ,
2016-06-23 02:46:16 +00:00
[ switch ] $Clean ,
2016-03-12 00:19:05 +00:00
2016-08-26 20:46:03 +00:00
# this switch will re-build only System.Management.Automation.dll
2016-07-19 19:51:11 +00:00
# it's useful for development, to do a quick changes in the engine
[ switch ] $SMAOnly ,
2016-03-03 23:54:52 +00:00
# These runtimes must match those in project.json
# We do not use ValidateScript since we want tab completion
[ ValidateSet ( " ubuntu.14.04-x64 " ,
2016-08-01 22:18:42 +00:00
" ubuntu.16.04-x64 " ,
2016-06-03 03:13:30 +00:00
" debian.8-x64 " ,
2016-06-17 01:39:29 +00:00
" centos.7-x64 " ,
2016-03-03 23:54:52 +00:00
" win7-x64 " ,
2016-04-02 00:01:18 +00:00
" win81-x64 " ,
2016-03-03 23:54:52 +00:00
" win10-x64 " ,
" osx.10.11-x64 " ) ]
2016-03-12 00:19:05 +00:00
[ Parameter ( ParameterSetName = 'CoreCLR' ) ]
[ string ] $Runtime ,
2016-06-23 02:46:16 +00:00
[ Parameter ( ParameterSetName = 'FullCLR' , Mandatory = $true ) ]
2016-03-12 00:19:05 +00:00
[ switch ] $FullCLR ,
2016-06-21 21:30:26 +00:00
[ Parameter ( ParameterSetName = 'FullCLR' ) ]
2016-06-23 02:46:16 +00:00
[ switch ] $XamlGen ,
2016-06-21 21:30:26 +00:00
2016-03-12 00:19:05 +00:00
[ Parameter ( ParameterSetName = 'FullCLR' ) ]
2016-07-15 23:52:00 +00:00
[ ValidateSet ( 'x86' , 'x64' ) ] # TODO: At some point, we need to add ARM support to match CoreCLR
2016-07-01 19:09:50 +00:00
[ string ] $NativeHostArch = " x64 " ,
2016-03-12 00:19:05 +00:00
2016-07-07 18:34:10 +00:00
[ ValidateSet ( 'Linux' , 'Debug' , 'Release' , '' ) ] # We might need "Checked" as well
2016-07-29 17:00:46 +00:00
[ string ] $Configuration ,
2016-08-03 07:19:39 +00:00
[ Parameter ( ParameterSetName = 'CoreCLR' ) ]
2016-07-29 17:00:46 +00:00
[ switch ] $Publish ,
2016-08-03 07:19:39 +00:00
[ Parameter ( ParameterSetName = 'CoreCLR' ) ]
2016-08-02 17:38:12 +00:00
[ switch ] $CrossGen
2016-02-24 00:21:00 +00:00
)
2016-02-21 23:06:39 +00:00
2016-08-03 20:23:21 +00:00
function Stop-DevPowerShell {
2016-07-20 02:09:06 +00:00
Get-Process powershell * |
2016-08-03 20:23:21 +00:00
Where-Object {
$_ . Modules |
Where-Object {
2016-07-20 02:09:06 +00:00
$_ . FileName -eq ( Resolve-Path $script:Options . Output ) . Path
2016-08-03 20:23:21 +00:00
}
} |
2016-07-20 02:09:06 +00:00
Stop-Process -Verbose
}
2016-08-03 20:23:21 +00:00
if ( $CrossGen -and ! $Publish ) {
# By specifying -CrossGen, we implicitly set -Publish to $true, if not already specified.
2016-08-03 07:19:39 +00:00
$Publish = $true
}
2016-08-03 20:23:21 +00:00
if ( $Clean ) {
2016-06-23 02:46:16 +00:00
log " Cleaning your working directory. You can also do it with 'git clean -fdX' "
2016-07-26 02:53:21 +00:00
Push-Location $PSScriptRoot
2016-08-03 20:23:21 +00:00
try {
2016-07-26 02:53:21 +00:00
git clean -fdX
2016-08-03 20:23:21 +00:00
} finally {
2016-07-26 02:53:21 +00:00
Pop-Location
}
2016-06-23 02:46:16 +00:00
}
2016-06-01 18:13:49 +00:00
# save Git description to file for PowerShell to include in PSVersionTable
git - -git -dir = " $PSScriptRoot /.git " describe - -dirty - -abbrev = 60 > " $psscriptroot /powershell.version "
2016-05-18 22:35:09 +00:00
2016-04-01 19:14:09 +00:00
# simplify ParameterSetNames
2016-04-01 21:41:13 +00:00
if ( $PSCmdlet . ParameterSetName -eq 'FullCLR' ) {
2016-03-12 00:19:05 +00:00
$FullCLR = $true
}
2016-06-20 18:59:14 +00:00
# Add .NET CLI tools to PATH
Find-Dotnet
2016-04-13 23:41:50 +00:00
2016-08-04 23:15:49 +00:00
# verify we have all tools in place to do the build
$precheck = precheck 'dotnet' " Build dependency 'dotnet' not found in PATH. Run Start-PSBootstrap. Also see: https://dotnet.github.io/getting-started/ "
2016-05-04 20:33:59 +00:00
if ( $IsWindows ) {
# use custom package store - this value is also defined in nuget.config under config/repositoryPath
# dotnet restore uses this value as the target for installing the assemblies for referenced nuget packages.
# dotnet build does not currently consume the config value but will consume env:NUGET_PACKAGES to resolve these dependencies
$env:NUGET_PACKAGES = " $PSScriptRoot \Packages "
2016-04-22 16:39:59 +00:00
2016-03-12 00:19:05 +00:00
# cmake is needed to build powershell.exe
2016-08-18 04:13:52 +00:00
$precheck = $precheck -and ( precheck 'cmake' 'cmake not found. Run Start-PSBootstrap. You can also install it from https://chocolatey.org/packages/cmake' )
2016-04-01 21:41:13 +00:00
2016-06-23 02:46:16 +00:00
Use-MSBuild
2016-07-05 20:03:25 +00:00
2016-06-16 23:43:51 +00:00
#mc.exe is Message Compiler for native resources
2016-10-31 22:02:44 +00:00
if ( -Not ( Test-Win10SDK ) ) {
throw 'Win 10 SDK not found. Run Start-PSBootstrap or install Microsoft Windows 10 SDK from https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk'
2016-06-16 23:43:51 +00:00
}
2016-07-15 23:52:00 +00:00
$vcVarsPath = ( Get-Item ( Join-Path -Path " $env:VS140COMNTOOLS " -ChildPath '../../vc' ) ) . FullName
2016-08-03 20:23:21 +00:00
if ( ( Test-Path -Path $vcVarsPath \ vcvarsall . bat ) -eq $false ) {
2016-08-14 18:30:54 +00:00
throw " Could not find Visual Studio vcvarsall.bat at $vcVarsPath . Please ensure the optional feature 'Common Tools for Visual C++' is installed. "
2016-07-15 23:52:00 +00:00
}
2016-07-01 19:09:50 +00:00
# setup msbuild configuration
2016-08-03 20:23:21 +00:00
if ( $Configuration -eq 'Debug' -or $Configuration -eq 'Release' ) {
2016-07-01 19:09:50 +00:00
$msbuildConfiguration = $Configuration
2016-08-03 20:23:21 +00:00
} else {
2016-07-01 19:09:50 +00:00
$msbuildConfiguration = 'Release'
}
# setup cmakeGenerator
2016-08-03 20:23:21 +00:00
if ( $NativeHostArch -eq 'x86' ) {
$cmakeGenerator = 'Visual Studio 14 2015'
} else {
$cmakeGenerator = 'Visual Studio 14 2015 Win64'
2016-07-01 19:09:50 +00:00
}
2016-04-10 00:59:13 +00:00
} elseif ( $IsLinux -or $IsOSX ) {
2016-04-01 21:42:40 +00:00
foreach ( $Dependency in 'cmake' , 'make' , 'g++' ) {
2016-06-20 18:39:39 +00:00
$precheck = $precheck -and ( precheck $Dependency " Build dependency ' $Dependency ' not found. Run Start-PSBootstrap. " )
2016-04-01 21:42:40 +00:00
}
}
2016-04-01 21:43:18 +00:00
2016-04-01 21:41:13 +00:00
# Abort if any precheck failed
if ( -not $precheck ) {
return
}
2016-02-21 23:06:39 +00:00
2016-04-14 22:06:14 +00:00
# set output options
2016-07-19 19:51:11 +00:00
$OptionsArguments = @ {
Publish = $Publish
2016-09-28 17:47:16 +00:00
CrossGen = $CrossGen
2016-07-19 19:51:11 +00:00
Output = $Output
FullCLR = $FullCLR
Runtime = $Runtime
Configuration = $Configuration
Verbose = $true
SMAOnly = [ bool ] $SMAOnly
}
2016-04-14 22:06:14 +00:00
$script:Options = New-PSOptions @OptionsArguments
2016-04-02 00:51:38 +00:00
2016-08-03 20:23:21 +00:00
if ( $StopDevPowerShell ) {
2016-07-20 02:09:06 +00:00
Stop-DevPowerShell
}
2016-04-14 22:06:14 +00:00
# setup arguments
2016-04-02 00:51:38 +00:00
$Arguments = @ ( )
2016-07-26 23:43:32 +00:00
if ( $Publish -or $FullCLR ) {
2016-04-08 23:05:39 +00:00
$Arguments + = " publish "
} else {
$Arguments + = " build "
}
2016-05-06 17:28:45 +00:00
if ( $Output ) {
2016-10-03 18:04:40 +00:00
$Arguments + = " --output " , $Output
2016-05-06 17:28:45 +00:00
}
2016-07-19 19:51:11 +00:00
elseif ( $SMAOnly ) {
$Arguments + = " --output " , ( Split-Path $script:Options . Output )
}
2016-04-14 22:06:14 +00:00
$Arguments + = " --configuration " , $Options . Configuration
$Arguments + = " --framework " , $Options . Framework
$Arguments + = " --runtime " , $Options . Runtime
2016-04-02 00:51:38 +00:00
2016-03-12 02:24:43 +00:00
# handle Restore
2016-07-15 23:52:00 +00:00
if ( $Restore -or -not ( Test-Path " $( $Options . Top ) /project.lock.json " ) ) {
log " Run dotnet restore "
$RestoreArguments = @ ( " --verbosity " )
if ( $PSCmdlet . MyInvocation . BoundParameters [ " Verbose " ] . IsPresent ) {
$RestoreArguments + = " Info "
} else {
$RestoreArguments + = " Warning "
}
$RestoreArguments + = " $PSScriptRoot "
Start-NativeExecution { dotnet restore $RestoreArguments }
2016-08-04 17:16:41 +00:00
# .NET Core's crypto library needs brew's OpenSSL libraries added to its rpath
if ( $IsOSX ) {
# This is the restored library used to build
# This is allowed to fail since the user may have already restored
2016-08-11 20:38:35 +00:00
Write-Warning " .NET Core links the incorrect OpenSSL, correcting NuGet package libraries... "
2016-08-04 17:16:41 +00:00
find $env:HOME / . nuget -name System . Security . Cryptography . Native . dylib | xargs sudo install_name_tool -add_rpath / usr / local / opt / openssl / lib
2016-09-20 21:26:07 +00:00
find $env:HOME / . nuget -name System . Net . Http . Native . dylib | xargs sudo install_name_tool -change / usr / lib / libcurl . 4 . dylib / usr / local / opt / curl / lib / libcurl . 4 . dylib
2016-08-04 17:16:41 +00:00
}
2016-07-15 23:52:00 +00:00
}
2016-02-21 23:06:39 +00:00
2016-06-15 10:42:54 +00:00
# handle ResGen
2016-06-17 14:51:32 +00:00
# Heuristic to run ResGen on the fresh machine
2016-08-03 20:23:21 +00:00
if ( $ResGen -or -not ( Test-Path " $PSScriptRoot /src/Microsoft.PowerShell.ConsoleHost/gen " ) ) {
2016-07-15 23:52:00 +00:00
log " Run ResGen (generating C# bindings for resx files) "
Start-ResGen
}
2016-06-15 10:42:54 +00:00
2016-06-21 21:30:26 +00:00
# handle xaml files
# Heuristic to resolve xaml on the fresh machine
2016-08-03 20:23:21 +00:00
if ( $FullCLR -and ( $XamlGen -or -not ( Test-Path " $PSScriptRoot /src/Microsoft.PowerShell.Activities/gen/*.g.cs " ) ) ) {
2016-07-15 23:52:00 +00:00
log " Run XamlGen (generating .g.cs and .resources for .xaml files) "
Start-XamlGen -MSBuildConfiguration $msbuildConfiguration
}
2016-06-21 21:30:26 +00:00
2016-03-12 00:19:05 +00:00
# Build native components
2016-07-27 16:02:36 +00:00
if ( ( $IsLinux -or $IsOSX ) -and -not $SMAOnly ) {
2016-04-01 21:42:40 +00:00
$Ext = if ( $IsLinux ) {
" so "
} elseif ( $IsOSX ) {
" dylib "
}
2016-02-21 23:06:39 +00:00
2016-04-01 21:42:40 +00:00
$Native = " $PSScriptRoot /src/libpsl-native "
2016-04-14 22:06:14 +00:00
$Lib = " $( $Options . Top ) /libpsl-native. $Ext "
2016-04-01 21:42:40 +00:00
log " Start building $Lib "
2016-02-24 19:50:56 +00:00
2016-04-01 21:42:40 +00:00
try {
Push-Location $Native
2016-07-13 07:08:06 +00:00
Start-NativeExecution { cmake -DCMAKE_BUILD_TYPE = Debug . }
Start-NativeExecution { make -j }
Start-NativeExecution { ctest - -verbose }
2016-04-01 21:42:40 +00:00
} finally {
Pop-Location
2016-03-12 00:19:05 +00:00
}
2016-04-01 21:42:40 +00:00
2016-04-10 00:59:13 +00:00
if ( -not ( Test-Path $Lib ) ) {
2016-04-01 21:42:40 +00:00
throw " Compilation of $Lib failed "
}
2016-08-04 23:15:49 +00:00
} elseif ( $IsWindows -and ( -not $SMAOnly ) ) {
log " Start building native Windows binaries "
2016-02-21 23:06:39 +00:00
2016-04-01 21:41:13 +00:00
try {
2016-04-14 22:06:14 +00:00
Push-Location " $PSScriptRoot \src\powershell-native "
2016-02-21 23:06:39 +00:00
2016-06-16 23:43:51 +00:00
# Compile native resources
2016-07-29 21:01:08 +00:00
$currentLocation = Get-Location
2016-06-16 23:43:51 +00:00
@ ( " nativemsh/pwrshplugin " ) | % {
$nativeResourcesFolder = $_
Get-ChildItem $nativeResourcesFolder -Filter " *.mc " | % {
2016-07-22 21:19:21 +00:00
$command = @"
2016-08-19 17:53:49 +00:00
cmd . exe / C cd / d " $currentLocation " " & " " $( $vcVarsPath ) \vcvarsall.bat " " $NativeHostArch " " & " mc . exe -o -d -c -U " $( $_ . FullName ) " -h " $nativeResourcesFolder " -r " $nativeResourcesFolder "
2016-07-22 21:19:21 +00:00
" @
log " Executing mc.exe Command: $command "
2016-08-30 01:53:06 +00:00
Start-NativeExecution { Invoke-Expression -Command: $command 2 > & 1 }
2016-06-16 23:43:51 +00:00
}
}
2016-08-03 20:23:21 +00:00
2016-08-04 23:15:49 +00:00
function Build-NativeWindowsBinaries {
param (
# Describes wither it should build the CoreCLR or FullCLR version
[ ValidateSet ( " ON " , " OFF " ) ]
[ string ] $OneCoreValue ,
# Array of file names to copy from the local build directory to the packaging directory
[ string[] ] $FilesToCopy
)
2016-08-03 20:23:21 +00:00
# Disabling until I figure out if it is necessary
2016-08-04 23:15:49 +00:00
# $overrideFlags = "-DCMAKE_USER_MAKE_RULES_OVERRIDE=$PSScriptRoot\src\powershell-native\windows-compiler-override.txt"
$overrideFlags = " "
$location = Get-Location
2016-07-15 23:52:00 +00:00
$command = @"
2016-08-04 23:15:49 +00:00
cmd . exe / C cd / d " $location " " & " " $( $vcVarsPath ) \vcvarsall.bat " " $NativeHostArch " " & " cmake " $overrideFlags " -DBUILD_ONECORE = $OneCoreValue -G " $cmakeGenerator " . " & " msbuild ALL_BUILD . vcxproj " /p:Configuration= $msbuildConfiguration "
2016-07-07 18:34:10 +00:00
" @
2016-07-19 23:38:40 +00:00
log " Executing Build Command: $command "
2016-07-15 23:52:00 +00:00
Start-NativeExecution { Invoke-Expression -Command: $command }
2016-07-18 22:04:45 +00:00
2016-08-04 23:15:49 +00:00
$clrTarget = " FullClr "
if ( $OneCoreValue -eq " ON " )
{
$clrTarget = " CoreClr "
}
# Copy the binaries from the local build directory to the packaging directory
$dstPath = ( $script:Options ) . Top
$FilesToCopy | % {
$srcPath = Join-Path ( Join-Path ( Join-Path ( Get-Location ) " bin " ) $msbuildConfiguration ) " $clrTarget / $_ "
log " Copying $srcPath to $dstPath "
Copy-Item $srcPath $dstPath
}
}
if ( $FullCLR ) {
$fullBinaries = @ (
'powershell.exe' ,
'powershell.pdb' ,
'pwrshplugin.dll' ,
'pwrshplugin.pdb'
)
Build-NativeWindowsBinaries " OFF " $fullBinaries
}
else
{
$coreClrBinaries = @ (
'pwrshplugin.dll' ,
'pwrshplugin.pdb'
)
Build-NativeWindowsBinaries " ON " $coreClrBinaries
2016-08-07 02:45:41 +00:00
# Place the remoting configuration script in the same directory
# as the binary so it will get published.
Copy-Item . \ Install-PowerShellRemoting . ps1 ( $script:Options ) . Top
2016-07-22 20:39:45 +00:00
}
2016-04-01 21:41:13 +00:00
} finally {
Pop-Location
2016-03-12 00:19:05 +00:00
}
}
2016-02-21 23:06:39 +00:00
2016-06-17 18:23:29 +00:00
# handle TypeGen
2016-08-03 20:23:21 +00:00
if ( $TypeGen -or -not ( Test-Path " $PSScriptRoot /src/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext/CorePsTypeCatalog.cs " ) ) {
2016-06-17 18:23:29 +00:00
log " Run TypeGen (generating CorePsTypeCatalog.cs) "
Start-TypeGen
}
2016-04-01 21:41:13 +00:00
try {
2016-04-01 19:14:09 +00:00
# Relative paths do not work well if cwd is not changed to project
2016-04-14 22:06:14 +00:00
Push-Location $Options . Top
2016-04-19 23:39:06 +00:00
log " Run dotnet $Arguments from $pwd "
2016-04-19 23:59:03 +00:00
Start-NativeExecution { dotnet $Arguments }
2016-07-29 17:00:46 +00:00
2016-08-03 20:23:21 +00:00
if ( $CrossGen ) {
2016-07-29 17:00:46 +00:00
$publishPath = Split-Path $Options . Output
2016-08-02 20:33:51 +00:00
Start-CrossGen -PublishPath $publishPath
2016-08-02 17:38:12 +00:00
log " PowerShell.exe with ngen binaries is available at: $( $Options . Output ) "
2016-08-03 20:23:21 +00:00
} else {
2016-07-29 17:00:46 +00:00
log " PowerShell output: $( $Options . Output ) "
}
2016-04-01 21:41:13 +00:00
} finally {
2016-04-01 19:14:09 +00:00
Pop-Location
2016-03-12 00:19:05 +00:00
}
2016-04-02 00:51:38 +00:00
}
2016-09-28 23:20:29 +00:00
function Compress-TestContent {
[ CmdletBinding ( ) ]
param (
$Destination
)
$powerShellTestRoot = Join-Path $PSScriptRoot 'test\powershell'
Add-Type -AssemblyName System . IO . Compression . FileSystem
$resolvedPath = $ExecutionContext . SessionState . Path . GetUnresolvedProviderPathFromPSPath ( $Destination )
[ System.IO.Compression.ZipFile ] :: CreateFromDirectory ( $powerShellTestRoot , $resolvedPath )
}
2016-04-14 22:06:14 +00:00
function New-PSOptions {
[ CmdletBinding ( ) ]
param (
2016-07-01 19:09:50 +00:00
[ ValidateSet ( " Linux " , " Debug " , " Release " , " " ) ]
2016-04-14 22:06:14 +00:00
[ string ] $Configuration ,
2016-04-19 03:22:20 +00:00
[ ValidateSet ( " netcoreapp1.0 " , " net451 " ) ]
2016-04-14 22:06:14 +00:00
[ string ] $Framework ,
# These are duplicated from Start-PSBuild
# We do not use ValidateScript since we want tab completion
[ ValidateSet ( " " ,
" ubuntu.14.04-x64 " ,
2016-08-01 22:18:42 +00:00
" ubuntu.16.04-x64 " ,
2016-06-03 03:13:30 +00:00
" debian.8-x64 " ,
2016-06-17 01:39:29 +00:00
" centos.7-x64 " ,
2016-04-14 22:06:14 +00:00
" win7-x64 " ,
" win81-x64 " ,
" win10-x64 " ,
" osx.10.11-x64 " ) ]
[ string ] $Runtime ,
[ switch ] $Publish ,
2016-09-28 17:47:16 +00:00
[ switch ] $CrossGen ,
2016-05-06 17:28:45 +00:00
[ string ] $Output ,
2016-04-14 22:06:14 +00:00
2016-07-19 19:51:11 +00:00
[ switch ] $FullCLR ,
[ switch ] $SMAOnly
2016-04-14 22:06:14 +00:00
)
2016-06-20 18:59:14 +00:00
# Add .NET CLI tools to PATH
Find-Dotnet
2016-09-28 17:47:16 +00:00
$ConfigWarningMsg = " The passed-in Configuration value '{0}' is not supported on '{1}'. Use '{2}' instead. "
2016-04-14 22:06:14 +00:00
if ( -not $Configuration ) {
$Configuration = if ( $IsLinux -or $IsOSX ) {
" Linux "
} elseif ( $IsWindows ) {
" Debug "
}
2016-09-28 17:47:16 +00:00
} else {
switch ( $Configuration ) {
" Linux " {
if ( $IsWindows ) {
$Configuration = " Debug "
Write-Warning ( $ConfigWarningMsg -f $switch . Current , " Windows " , $Configuration )
}
}
Default {
if ( $IsLinux -or $IsOSX ) {
$Configuration = " Linux "
Write-Warning ( $ConfigWarningMsg -f $switch . Current , $LinuxInfo . PRETTY_NAME , $Configuration )
}
}
}
2016-04-14 22:06:14 +00:00
}
2016-09-28 17:47:16 +00:00
Write-Verbose " Using configuration ' $Configuration ' "
2016-04-14 22:06:14 +00:00
2016-09-28 17:47:16 +00:00
$PowerShellDir = if ( $FullCLR ) {
" powershell-win-full "
} elseif ( $Configuration -eq 'Linux' ) {
" powershell-unix "
2016-07-22 01:47:46 +00:00
} else {
2016-09-28 17:47:16 +00:00
" powershell-win-core "
2016-07-22 01:47:46 +00:00
}
2016-09-28 17:47:16 +00:00
$Top = [ IO.Path ] :: Combine ( $PSScriptRoot , " src " , $PowerShellDir )
2016-07-22 01:47:46 +00:00
Write-Verbose " Top project directory is $Top "
2016-04-14 22:06:14 +00:00
if ( -not $Framework ) {
$Framework = if ( $FullCLR ) {
" net451 "
} else {
2016-04-19 03:22:20 +00:00
" netcoreapp1.0 "
2016-04-14 22:06:14 +00:00
}
2016-07-01 19:09:50 +00:00
Write-Verbose " Using framework ' $Framework ' "
2016-04-14 22:06:14 +00:00
}
if ( -not $Runtime ) {
$Runtime = dotnet - -info | % {
if ( $_ -match " RID " ) {
$_ -split " \s+ " | Select-Object -Last 1
}
}
if ( -not $Runtime ) {
Throw " Could not determine Runtime Identifier, please update dotnet "
} else {
2016-07-01 19:09:50 +00:00
Write-Verbose " Using runtime ' $Runtime ' "
2016-04-14 22:06:14 +00:00
}
2016-04-02 05:01:37 +00:00
}
2016-04-14 22:06:14 +00:00
$Executable = if ( $IsLinux -or $IsOSX ) {
" powershell "
} elseif ( $IsWindows ) {
" powershell.exe "
}
2016-05-06 17:28:45 +00:00
# Build the Output path
2016-10-03 18:04:40 +00:00
if ( ! $Output ) {
2016-07-26 23:43:32 +00:00
$Output = [ IO.Path ] :: Combine ( $Top , " bin " , $Configuration , $Framework , $Runtime )
2016-04-14 22:06:14 +00:00
2016-05-06 17:28:45 +00:00
# Publish injects the publish directory
2016-07-26 23:43:32 +00:00
if ( $Publish -or $FullCLR ) {
2016-05-06 17:28:45 +00:00
$Output = [ IO.Path ] :: Combine ( $Output , " publish " )
}
2016-04-14 22:06:14 +00:00
2016-05-06 17:28:45 +00:00
$Output = [ IO.Path ] :: Combine ( $Output , $Executable )
}
2016-04-14 22:06:14 +00:00
2016-07-19 19:51:11 +00:00
$RealFramework = $Framework
if ( $SMAOnly )
{
2016-09-28 17:47:16 +00:00
$Top = [ IO.Path ] :: Combine ( $PSScriptRoot , " src " , " System.Management.Automation " )
2016-07-19 19:51:11 +00:00
if ( $Framework -match 'netcoreapp' )
{
$RealFramework = 'netstandard1.6'
}
}
2016-04-14 22:06:14 +00:00
return @ { Top = $Top ;
Configuration = $Configuration ;
2016-07-19 19:51:11 +00:00
Framework = $RealFramework ;
2016-04-14 22:06:14 +00:00
Runtime = $Runtime ;
2016-09-28 17:47:16 +00:00
Output = $Output ;
Publish = $Publish ;
CrossGen = $CrossGen }
2016-04-14 22:06:14 +00:00
}
function Get-PSOutput {
[ CmdletBinding ( ) ] param (
[ hashtable ] $Options
)
if ( $Options ) {
return $Options . Output
} elseif ( $script:Options ) {
return $script:Options . Output
} else {
return ( New-PSOptions ) . Output
}
2016-02-21 23:06:39 +00:00
}
2016-04-02 05:01:05 +00:00
2016-07-27 00:41:03 +00:00
function Get-PesterTag {
param ( [ Parameter ( Position = 0 ) ] [ string ] $testbase = " $PSScriptRoot /test/powershell " )
$alltags = @ { }
$warnings = @ ( )
get-childitem -Recurse $testbase -File | ? { $_ . name -match " tests.ps1 " } | % {
$fullname = $_ . fullname
$tok = $err = $null
$ast = [ System.Management.Automation.Language.Parser ] :: ParseFile ( $FullName , [ ref ] $tok , [ ref ] $err )
$des = $ast . FindAll ( { $args [ 0 ] -is " System.Management.Automation.Language.CommandAst " -and $args [ 0 ] . CommandElements [ 0 ] . Value -eq " Describe " } , $true )
foreach ( $describe in $des ) {
$elements = $describe . CommandElements
$lineno = $elements [ 0 ] . Extent . StartLineNumber
2016-09-27 01:12:11 +00:00
$foundPriorityTags = @ ( )
2016-07-27 00:41:03 +00:00
for ( $i = 0 ; $i -lt $elements . Count ; $i + + ) {
if ( $elements [ $i ] . extent . text -match " ^-t " ) {
$vAst = $elements [ $i + 1 ]
if ( $vAst . FindAll ( { $args [ 0 ] -is " System.Management.Automation.Language.VariableExpressionAst " } , $true ) ) {
$warnings + = " TAGS must be static strings, error in ${fullname} , line $lineno "
}
$values = $vAst . FindAll ( { $args [ 0 ] -is " System.Management.Automation.Language.StringConstantExpressionAst " } , $true ) . Value
2016-09-16 02:33:54 +00:00
$values | % {
if ( @ ( 'REQUIREADMINONWINDOWS' , 'SLOW' ) -contains $_ ) {
# These are valid tags also, but they are not the priority tags
}
elseif ( @ ( 'CI' , 'FEATURE' , 'SCENARIO' ) -contains $_ ) {
2016-09-27 01:12:11 +00:00
$foundPriorityTags + = $_
2016-09-16 02:33:54 +00:00
}
else {
2016-07-27 00:41:03 +00:00
$warnings + = " ${fullname} includes improper tag ' $_ ', line ' $lineno ' "
}
2016-09-16 02:33:54 +00:00
2016-08-03 20:23:21 +00:00
$alltags [ $_ ] + +
2016-09-16 02:33:54 +00:00
}
2016-07-27 00:41:03 +00:00
}
}
2016-09-27 01:12:11 +00:00
if ( $foundPriorityTags . Count -eq 0 ) {
$warnings + = " ${fullname} : $lineno does not include -Tag in Describe "
}
elseif ( $foundPriorityTags . Count -gt 1 ) {
$warnings + = " ${fullname} : $lineno includes more then one scope -Tag: $foundPriorityTags "
2016-07-27 00:41:03 +00:00
}
}
}
if ( $Warnings . Count -gt 0 ) {
$alltags [ 'Result' ] = " Fail "
}
else {
$alltags [ 'Result' ] = " Pass "
}
$alltags [ 'Warnings' ] = $warnings
2016-08-03 20:23:21 +00:00
$o = [ pscustomobject ] $alltags
2016-07-27 00:41:03 +00:00
$o . psobject . TypeNames . Add ( " DescribeTagsInUse " )
$o
}
2016-09-12 17:39:42 +00:00
function Publish-PSTestTools {
2016-09-12 06:14:30 +00:00
[ CmdletBinding ( ) ]
param ( )
Find-Dotnet
2016-10-31 16:41:13 +00:00
$tools = " $PSScriptRoot /test/tools/EchoArgs " , " $PSScriptRoot /test/tools/CreateChildProcess "
2016-09-12 17:39:42 +00:00
# Publish EchoArgs so it can be run by tests
2016-10-31 16:41:13 +00:00
foreach ( $tool in $tools )
{
Push-Location $tool
try {
dotnet publish - -output bin
} finally {
Pop-Location
}
2016-09-12 06:14:30 +00:00
}
2016-10-31 16:41:13 +00:00
2016-09-12 06:14:30 +00:00
}
2016-04-02 05:01:45 +00:00
function Start-PSPester {
2016-08-31 19:13:05 +00:00
[ CmdletBinding ( ) ]
param (
2016-07-26 00:43:28 +00:00
[ string ] $OutputFormat = " NUnitXml " ,
[ string ] $OutputFile = " pester-tests.xml " ,
2016-09-16 02:22:18 +00:00
[ string[] ] $ExcludeTag = 'Slow' ,
2016-07-26 00:43:28 +00:00
[ string[] ] $Tag = " CI " ,
2016-08-30 18:47:27 +00:00
[ string ] $Path = " $PSScriptRoot /test/powershell " ,
[ switch ] $ThrowOnFailure ,
[ switch ] $FullCLR ,
2016-09-09 21:39:41 +00:00
[ string ] $binDir = ( Split-Path ( New-PSOptions -FullCLR: $FullCLR ) . Output ) ,
[ string ] $powershell = ( Join-Path $binDir 'powershell' ) ,
2016-09-16 02:33:54 +00:00
[ string ] $Pester = ( [ IO.Path ] :: Combine ( $binDir , " Modules " , " Pester " ) ) ,
2016-09-16 02:22:18 +00:00
[ switch ] $Unelevate
2016-04-02 05:01:45 +00:00
)
2016-07-26 23:01:31 +00:00
2016-09-16 02:22:18 +00:00
# we need to do few checks and if user didn't provide $ExcludeTag explicitly, we should alternate the default
if ( $Unelevate )
{
if ( -not $IsWindows )
{
throw '-Unelevate is currently not supported on non-Windows platforms'
}
if ( -not $IsAdmin )
{
throw '-Unelevate cannot be applied because the current user is not Administrator'
}
2016-09-26 20:15:58 +00:00
if ( -not $PSBoundParameters . ContainsKey ( 'ExcludeTag' ) )
2016-09-16 02:22:18 +00:00
{
$ExcludeTag + = 'RequireAdminOnWindows'
}
}
elseif ( $IsWindows -and ( -not $IsAdmin ) )
{
2016-09-26 20:15:58 +00:00
if ( -not $PSBoundParameters . ContainsKey ( 'ExcludeTag' ) )
2016-09-16 02:22:18 +00:00
{
$ExcludeTag + = 'RequireAdminOnWindows'
}
}
2016-08-31 19:13:05 +00:00
Write-Verbose " Running pester tests at ' $path ' with tag ' $( $Tag -join ''', ''' ) ' and ExcludeTag ' $( $ExcludeTag -join ''', ''' ) ' " -Verbose
2016-09-12 17:39:42 +00:00
Publish-PSTestTools
2016-08-09 19:03:30 +00:00
# All concatenated commands/arguments are suffixed with the delimiter (space)
$Command = " "
# Windows needs the execution policy adjusted
if ( $IsWindows ) {
$Command + = " Set-ExecutionPolicy -Scope Process Unrestricted; "
}
2016-08-30 18:47:27 +00:00
$startParams = @ { binDir = $binDir }
2016-08-09 19:03:30 +00:00
2016-08-30 18:47:27 +00:00
if ( ! $FullCLR )
{
2016-09-09 21:39:41 +00:00
$Command + = " Import-Module ' $Pester '; "
2016-08-30 18:47:27 +00:00
}
2016-09-16 02:22:18 +00:00
if ( $Unelevate )
{
$outputBufferFilePath = [ System.IO.Path ] :: GetTempFileName ( )
}
2016-09-21 21:41:20 +00:00
2016-08-09 19:03:30 +00:00
$Command + = " Invoke-Pester "
$Command + = " -OutputFormat ${OutputFormat} -OutputFile ${OutputFile} "
if ( $ExcludeTag -and ( $ExcludeTag -ne " " ) ) {
$Command + = " -ExcludeTag @(' " + ( $ { ExcludeTag } -join " ',' " ) + " ') "
2016-08-04 23:46:44 +00:00
}
2016-08-09 19:03:30 +00:00
if ( $Tag ) {
$Command + = " -Tag @(' " + ( $ { Tag } -join " ',' " ) + " ') "
}
2016-08-22 13:57:30 +00:00
$Command + = " ' " + $Path + " ' "
2016-09-16 02:22:18 +00:00
if ( $Unelevate )
{
2016-09-21 21:41:20 +00:00
$Command + = " *> $outputBufferFilePath ; '__UNELEVATED_TESTS_THE_END__' >> $outputBufferFilePath "
2016-09-16 02:22:18 +00:00
}
2016-08-09 19:03:30 +00:00
Write-Verbose $Command
2016-08-30 18:47:27 +00:00
2016-08-09 19:03:30 +00:00
# To ensure proper testing, the module path must not be inherited by the spawned process
2016-08-30 18:47:27 +00:00
if ( $FullCLR )
{
Start-DevPowerShell -binDir $binDir -FullCLR -NoNewWindow -ArgumentList '-noprofile' , '-noninteractive' -Command $command
}
else {
try {
$originalModulePath = $env:PSMODULEPATH
2016-09-16 02:22:18 +00:00
if ( $Unelevate )
{
Start-UnelevatedProcess -process $powershell -arguments @ ( '-noprofile' , '-c' , $Command )
$currentLines = 0
while ( $true )
{
$lines = Get-Content $outputBufferFilePath | Select-Object -Skip $currentLines
2016-09-16 02:33:54 +00:00
$lines | Write-Host
if ( $lines | ? { $_ -eq '__UNELEVATED_TESTS_THE_END__' } )
2016-09-16 02:22:18 +00:00
{
break
}
2016-09-16 02:33:54 +00:00
$count = ( $lines | measure-object ) . Count
2016-09-16 02:22:18 +00:00
if ( $count -eq 0 )
{
sleep 1
}
else
{
$currentLines + = $count
}
}
}
else
{
& $powershell -noprofile -c $Command
}
2016-08-30 18:47:27 +00:00
} finally {
$env:PSMODULEPATH = $originalModulePath
2016-09-16 02:22:18 +00:00
if ( $Unelevate )
{
Remove-Item $outputBufferFilePath
}
2016-08-30 18:47:27 +00:00
}
2016-08-09 19:03:30 +00:00
}
2016-08-30 18:47:27 +00:00
if ( $ThrowOnFailure )
{
Test-PSPesterResults -TestResultsFile $OutputFile
}
}
2016-09-16 02:22:18 +00:00
function script: Start-UnelevatedProcess
{
param (
[ string ] $process ,
[ string[] ] $arguments
)
if ( -not $IsWindows )
{
throw " Start-UnelevatedProcess is currently not supported on non-Windows platforms "
}
runas . exe / trustlevel : 0x20000 " $process $arguments "
}
2016-08-30 18:47:27 +00:00
#
# Read the test result file and
# Throw if a test failed
function Test-PSPesterResults
{
param (
[ string ] $TestResultsFile = " pester-tests.xml " ,
[ string ] $TestArea = 'test/powershell'
)
2016-08-09 19:03:30 +00:00
2016-08-30 18:47:27 +00:00
if ( ! ( Test-Path $TestResultsFile ) )
{
throw " Test result file ' $testResultsFile ' not found for $TestArea . "
}
$x = [ xml ] ( Get-Content -raw $testResultsFile )
if ( [ int ] $x . 'test-results' . failures -gt 0 )
{
throw " $( $x . 'test-results' . failures ) tests in $TestArea failed "
2016-04-02 05:01:45 +00:00
}
}
2016-04-02 03:45:32 +00:00
function Start-PSxUnit {
2016-04-02 05:01:05 +00:00
[ CmdletBinding ( ) ] param ( )
2016-06-20 18:59:14 +00:00
2016-06-29 02:56:47 +00:00
log " xUnit tests are currently disabled pending fixes due to API and AssemblyLoadContext changes - @andschwa "
return
2016-04-02 03:45:32 +00:00
if ( $IsWindows ) {
throw " xUnit tests are only currently supported on Linux / OS X "
}
2016-04-02 05:01:37 +00:00
2016-04-14 22:09:35 +00:00
if ( $IsOSX ) {
log " Not yet supported on OS X, pretending they passed... "
return
}
2016-06-20 18:59:14 +00:00
# Add .NET CLI tools to PATH
Find-Dotnet
2016-06-01 18:10:29 +00:00
$Arguments = " --configuration " , " Linux " , " -parallel " , " none "
2016-05-31 23:06:19 +00:00
if ( $PSCmdlet . MyInvocation . BoundParameters [ " Verbose " ] . IsPresent ) {
2016-06-01 18:10:29 +00:00
$Arguments + = " -verbose "
2016-05-31 23:06:19 +00:00
}
2016-04-02 05:01:37 +00:00
$Content = Split-Path -Parent ( Get-PSOutput )
2016-06-01 18:10:29 +00:00
if ( -not ( Test-Path $Content ) ) {
throw " PowerShell must be built before running tests! "
}
2016-04-02 03:45:32 +00:00
try {
Push-Location $PSScriptRoot / test / csharp
2016-04-25 21:11:13 +00:00
# Path manipulation to obtain test project output directory
$Output = Join-Path $pwd ( ( Split-Path -Parent ( Get-PSOutput ) ) -replace ( New-PSOptions ) . Top )
2016-06-01 18:10:29 +00:00
Write-Verbose " Output is $Output "
2016-04-19 03:22:20 +00:00
2016-04-25 21:11:13 +00:00
Copy-Item -ErrorAction SilentlyContinue -Recurse -Path $Content / * -Include Modules , libpsl-native * -Destination $Output
2016-06-01 18:10:29 +00:00
Start-NativeExecution { dotnet test $Arguments }
2016-04-19 03:22:20 +00:00
2016-04-02 03:45:32 +00:00
if ( $LASTEXITCODE -ne 0 ) {
throw " $LASTEXITCODE xUnit tests failed "
}
} finally {
Pop-Location
}
}
2016-04-13 22:11:38 +00:00
2016-09-09 21:35:54 +00:00
function Install-Dotnet {
[ CmdletBinding ( ) ]
param (
[ string ] $Channel = " rel-1.0.0 " ,
[ string ] $Version = " latest " ,
[ switch ] $NoSudo
)
# This allows sudo install to be optional; needed when running in containers / as root
# Note that when it is null, Invoke-Expression (but not &) must be used to interpolate properly
$sudo = if ( ! $NoSudo ) { " sudo " }
$obtainUrl = " https://raw.githubusercontent.com/dotnet/cli/rel/1.0.0/scripts/obtain "
# Install for Linux and OS X
if ( $IsLinux -or $IsOSX ) {
# Uninstall all previous dotnet packages
$uninstallScript = if ( $IsUbuntu ) {
" dotnet-uninstall-debian-packages.sh "
} elseif ( $IsOSX ) {
" dotnet-uninstall-pkgs.sh "
}
if ( $uninstallScript ) {
Start-NativeExecution {
curl -sO $obtainUrl / uninstall / $uninstallScript
Invoke-Expression " $sudo bash ./ $uninstallScript "
}
} else {
Write-Warning " This script only removes prior versions of dotnet for Ubuntu 14.04 and OS X "
}
# Install new dotnet 1.0.0 preview packages
$installScript = " dotnet-install.sh "
Start-NativeExecution {
curl -sO $obtainUrl / $installScript
bash . / $installScript -c $Channel -v $Version
}
# .NET Core's crypto library needs brew's OpenSSL libraries added to its rpath
if ( $IsOSX ) {
# This is the library shipped with .NET Core
# This is allowed to fail as the user may have installed other versions of dotnet
Write-Warning " .NET Core links the incorrect OpenSSL, correcting .NET CLI libraries... "
find $env:HOME / . dotnet -name System . Security . Cryptography . Native . dylib | xargs sudo install_name_tool -add_rpath / usr / local / opt / openssl / lib
}
} elseif ( $IsWindows ) {
Remove-Item -ErrorAction SilentlyContinue -Recurse -Force ~ \ AppData \ Local \ Microsoft \ dotnet
$installScript = " dotnet-install.ps1 "
Invoke-WebRequest -Uri $obtainUrl / $installScript -OutFile $installScript
& . / $installScript -c $Channel -v $Version
}
}
2016-04-13 22:11:38 +00:00
function Start-PSBootstrap {
2016-07-22 21:31:32 +00:00
[ CmdletBinding (
SupportsShouldProcess = $true ,
ConfirmImpact = " High " ) ]
param (
2016-06-23 20:23:03 +00:00
[ string ] $Channel = " rel-1.0.0 " ,
2016-07-05 18:03:08 +00:00
[ string ] $Version = " latest " ,
2016-07-22 21:31:32 +00:00
[ switch ] $Package ,
2016-09-08 23:21:20 +00:00
[ switch ] $NoSudo ,
2016-07-22 21:31:32 +00:00
[ switch ] $Force
2016-06-14 20:33:19 +00:00
)
2016-04-13 22:11:38 +00:00
2016-08-17 00:03:34 +00:00
log " Installing PowerShell build dependencies "
2016-04-13 22:11:38 +00:00
2016-06-10 21:02:25 +00:00
Push-Location $PSScriptRoot / tools
2016-04-13 22:11:38 +00:00
2016-09-08 23:21:20 +00:00
# This allows sudo install to be optional; needed when running in containers / as root
# Note that when it is null, Invoke-Expression (but not &) must be used to interpolate properly
$sudo = if ( ! $NoSudo ) { " sudo " }
2016-06-10 21:02:25 +00:00
try {
2016-08-18 15:44:37 +00:00
# Update googletest submodule for linux native cmake
if ( $IsLinux -or $IsOSX ) {
2016-09-01 02:42:27 +00:00
try {
Push-Location $PSScriptRoot
$Submodule = " $PSScriptRoot /src/libpsl-native/test/googletest "
Remove-Item -Path $Submodule -Recurse -Force -ErrorAction SilentlyContinue
git submodule update - -init - - $submodule
} finally {
Pop-Location
}
2016-08-18 15:44:37 +00:00
}
2016-06-30 20:41:43 +00:00
# Install ours and .NET's dependencies
2016-07-05 17:36:38 +00:00
$Deps = @ ( )
2016-06-30 20:41:43 +00:00
if ( $IsUbuntu ) {
2016-07-05 17:36:38 +00:00
# Build tools
$Deps + = " curl " , " g++ " , " cmake " , " make "
2016-08-11 20:38:35 +00:00
2016-07-05 17:36:38 +00:00
# .NET Core required runtime libraries
2016-08-11 20:38:35 +00:00
$Deps + = " libunwind8 "
if ( $IsUbuntu14 ) { $Deps + = " libicu52 " }
elseif ( $IsUbuntu16 ) { $Deps + = " libicu55 " }
2016-07-05 18:03:08 +00:00
# Packaging tools
2016-09-08 19:53:40 +00:00
if ( $Package ) { $Deps + = " ruby-dev " , " groff " }
2016-08-11 20:38:35 +00:00
2016-07-05 17:36:38 +00:00
# Install dependencies
2016-09-08 23:31:36 +00:00
Start-NativeExecution {
Invoke-Expression " $sudo apt-get update "
Invoke-Expression " $sudo apt-get install -y -qq $Deps "
}
2016-08-11 20:38:35 +00:00
} elseif ( $IsCentOS ) {
2016-07-05 17:36:38 +00:00
# Build tools
2016-08-19 06:23:27 +00:00
$Deps + = " which " , " curl " , " gcc-c++ " , " cmake " , " make "
2016-08-11 20:38:35 +00:00
2016-07-05 17:36:38 +00:00
# .NET Core required runtime libraries
$Deps + = " libicu " , " libunwind "
2016-08-11 20:38:35 +00:00
2016-07-05 18:03:08 +00:00
# Packaging tools
2016-09-08 19:53:40 +00:00
if ( $Package ) { $Deps + = " ruby-devel " , " rpm-build " , " groff " }
2016-08-11 20:38:35 +00:00
2016-07-05 17:36:38 +00:00
# Install dependencies
2016-09-08 23:21:20 +00:00
Start-NativeExecution {
Invoke-Expression " $sudo yum install -y -q $Deps "
}
2016-06-10 21:02:25 +00:00
} elseif ( $IsOSX ) {
precheck 'brew' " Bootstrap dependency 'brew' not found, must install Homebrew! See http://brew.sh/ "
2016-08-11 20:38:35 +00:00
2016-07-05 17:36:38 +00:00
# Build tools
2016-09-20 21:26:07 +00:00
$Deps + = " cmake "
2016-08-11 20:38:35 +00:00
2016-07-05 17:36:38 +00:00
# .NET Core required runtime libraries
$Deps + = " openssl "
2016-08-11 20:38:35 +00:00
2016-07-05 17:36:38 +00:00
# Install dependencies
2016-09-08 23:21:43 +00:00
Start-NativeExecution { brew install $Deps }
2016-09-20 21:26:07 +00:00
# Install patched version of curl
Start-NativeExecution { brew install curl - -with -openssl }
2016-06-10 21:02:25 +00:00
}
2016-04-13 22:11:38 +00:00
2016-08-10 19:49:16 +00:00
# Install [fpm](https://github.com/jordansissel/fpm) and [ronn](https://github.com/rtomayko/ronn)
2016-07-05 18:03:08 +00:00
if ( $Package ) {
2016-09-08 23:21:43 +00:00
try {
# We cannot guess if the user wants to run gem install as root
Start-NativeExecution { gem install fpm ronn }
} catch {
Write-Warning " Installation of fpm and ronn gems failed! Must resolve manually. "
}
2016-07-05 18:03:08 +00:00
}
2016-09-09 21:35:54 +00:00
$DotnetArguments = @ { Channel = $Channel ; Version = $Version ; NoSudo = $NoSudo }
Install-Dotnet @DotnetArguments
2016-04-13 23:41:50 +00:00
2016-06-10 21:02:25 +00:00
# Install for Windows
2016-09-09 21:35:54 +00:00
if ( $IsWindows ) {
2016-07-21 22:33:16 +00:00
$machinePath = [ Environment ] :: GetEnvironmentVariable ( 'Path' , 'MACHINE' )
2016-07-21 22:47:28 +00:00
$newMachineEnvironmentPath = $machinePath
2016-07-22 21:31:32 +00:00
$cmakePresent = precheck 'cmake' $null
2016-10-31 22:02:44 +00:00
$sdkPresent = Test-Win10SDK
2016-07-22 21:31:32 +00:00
2016-07-21 22:47:28 +00:00
# Install chocolatey
2016-07-21 22:33:16 +00:00
$chocolateyPath = " $env:AllUsersProfile \chocolatey\bin "
2016-08-03 20:23:21 +00:00
if ( precheck 'choco' $null ) {
2016-07-21 22:33:16 +00:00
log " Chocolatey is already installed. Skipping installation. "
}
2016-08-03 20:23:21 +00:00
elseif ( ( $cmakePresent -eq $false ) -or ( $sdkPresent -eq $false ) ) {
2016-07-21 22:33:16 +00:00
log " Chocolatey not present. Installing chocolatey. "
2016-08-03 20:23:21 +00:00
if ( $Force -or $PSCmdlet . ShouldProcess ( " Install chocolatey via https://chocolatey.org/install.ps1 " ) ) {
2016-07-22 23:42:19 +00:00
Invoke-Expression ( ( new-object net . webclient ) . DownloadString ( 'https://chocolatey.org/install.ps1' ) )
2016-08-03 20:23:21 +00:00
if ( -not ( $machinePath . ToLower ( ) . Contains ( $chocolateyPath . ToLower ( ) ) ) ) {
2016-07-22 23:42:19 +00:00
log " Adding $chocolateyPath to Path environment variable "
$env:Path + = " ; $chocolateyPath "
2016-08-03 20:23:21 +00:00
$newMachineEnvironmentPath + = " ; $chocolateyPath "
} else {
2016-07-22 23:42:19 +00:00
log " $chocolateyPath already present in Path environment variable "
}
2016-08-03 20:23:21 +00:00
} else {
2016-07-22 23:42:19 +00:00
Write-Error " Chocolatey is required to install missing dependencies. Please install it from https://chocolatey.org/ manually. Alternatively, install cmake and Windows 10 SDK. "
return $null
2016-07-21 22:33:16 +00:00
}
2016-08-03 20:23:21 +00:00
} else {
2016-07-22 21:31:32 +00:00
log " Skipping installation of chocolatey, cause both cmake and Win 10 SDK are present. "
}
2016-07-21 22:47:28 +00:00
# Install cmake
2016-08-25 15:47:52 +00:00
$cmakePath = " ${env:ProgramFiles} \CMake\bin "
2016-08-03 20:23:21 +00:00
if ( $cmakePresent ) {
2016-07-21 22:47:28 +00:00
log " Cmake is already installed. Skipping installation. "
2016-08-03 20:23:21 +00:00
} else {
2016-07-21 22:47:28 +00:00
log " Cmake not present. Installing cmake. "
2016-10-27 20:06:17 +00:00
Start-NativeExecution { choco install cmake -y - -version 3.6 . 0 }
2016-08-03 20:23:21 +00:00
if ( -not ( $machinePath . ToLower ( ) . Contains ( $cmakePath . ToLower ( ) ) ) ) {
2016-07-21 22:47:28 +00:00
log " Adding $cmakePath to Path environment variable "
$env:Path + = " ; $cmakePath "
$newMachineEnvironmentPath = " $cmakePath ; $newMachineEnvironmentPath "
2016-08-03 20:23:21 +00:00
} else {
2016-07-21 22:47:28 +00:00
log " $cmakePath already present in Path environment variable "
}
}
2016-08-03 20:23:21 +00:00
# Install Windows 10 SDK
2016-07-21 23:10:57 +00:00
$packageName = " windows-sdk-10.0 "
2016-08-03 20:23:21 +00:00
if ( -not $sdkPresent ) {
2016-07-21 23:10:57 +00:00
log " Windows 10 SDK not present. Installing $packageName . "
2016-10-27 20:06:17 +00:00
Start-NativeExecution { choco install windows-sdk - 10.0 -y }
2016-08-03 20:23:21 +00:00
} else {
2016-07-21 23:10:57 +00:00
log " Windows 10 SDK present. Skipping installation. "
}
2016-08-03 20:23:21 +00:00
2016-07-22 21:31:32 +00:00
# Update path machine environment variable
2016-08-03 20:23:21 +00:00
if ( $newMachineEnvironmentPath -ne $machinePath ) {
2016-07-22 21:31:32 +00:00
log " Updating Path machine environment variable "
2016-08-03 20:23:21 +00:00
if ( $Force -or $PSCmdlet . ShouldProcess ( " Update Path machine environment variable to $newMachineEnvironmentPath " ) ) {
2016-07-22 21:31:32 +00:00
[ Environment ] :: SetEnvironmentVariable ( 'Path' , $newMachineEnvironmentPath , 'MACHINE' )
}
2016-07-21 22:47:28 +00:00
}
2016-06-10 21:02:25 +00:00
}
} finally {
Pop-Location
2016-04-13 22:11:38 +00:00
}
}
2016-04-01 21:41:13 +00:00
function Start-PSPackage {
2016-04-02 05:01:05 +00:00
[ CmdletBinding ( ) ] param (
2016-04-10 01:02:37 +00:00
# PowerShell packages use Semantic Versioning http://semver.org/
2016-02-24 00:21:00 +00:00
[ string ] $Version ,
2016-02-22 00:21:04 +00:00
2016-08-10 19:49:16 +00:00
# Package name
2016-08-10 23:21:25 +00:00
[ ValidatePattern ( " ^powershell " ) ]
2016-08-10 19:49:16 +00:00
[ string ] $Name = " powershell " ,
2016-04-10 01:02:37 +00:00
2016-08-10 19:49:16 +00:00
# Ubuntu, CentOS, and OS X, and Windows packages are supported
2016-09-28 17:47:16 +00:00
[ ValidateSet ( " deb " , " osxpkg " , " rpm " , " msi " , " appx " , " zip " ) ]
[ string[] ] $Type ,
# Generate windows downlevel package
[ ValidateSet ( " win81-x64 " , " win7-x64 " ) ]
[ ValidateScript ( { $IsWindows } ) ]
[ string ] $WindowsDownLevel
2016-08-10 19:49:16 +00:00
)
2016-08-10 21:10:43 +00:00
2016-09-28 17:47:16 +00:00
# Runtime and Configuration settings required by the package
( $Runtime , $Configuration ) = if ( $WindowsDownLevel ) {
$WindowsDownLevel , " Release "
} else {
New-PSOptions -Configuration " Release " -WarningAction SilentlyContinue | ForEach-Object { $_ . Runtime , $_ . Configuration }
}
Write-Verbose " Packaging RID: ' $Runtime '; Packaging Configuration: ' $Configuration ' " -Verbose
# Make sure the most recent build satisfies the package requirement
if ( -not $Script:Options -or ## Start-PSBuild hasn't been executed yet
-not $Script:Options . CrossGen -or ## Last build didn't specify -CrossGen
$Script:Options . Runtime -ne $Runtime -or ## Last build wasn't for the required RID
$Script:Options . Configuration -eq " Debug " -or ## Last build was with 'Debug' configuration
$Script:Options . Framework -ne " netcoreapp1.0 " ) ## Last build wasn't for CoreCLR
{
# It's possible that the most recent build doesn't satisfy the package requirement but
# an earlier build does. e.g., run the following in order on win10-x64:
# Start-PSBuild -Clean -CrossGen -Runtime win10-x64 -Configuration Release
# Start-PSBuild -FullCLR
# Start-PSPackage -Type msi
# It's also possible that the last build actually satisfies the package requirement but
# then `Start-PSPackage` runs from a new PS session or `build.psm1` was reloaded.
#
# In these cases, the user will be asked to build again even though it's technically not
# necessary. However, we want it that way -- being very explict when generating packages.
# This check serves as a simple gate to ensure that the user knows what he is doing, and
# also ensure `Start-PSPackage` does what the user asks/expects, because once packages
# are generated, it'll be hard to verify if they were built from the correct content.
throw " Please ensure you have run 'Start-PSBuild -Clean -CrossGen -Runtime $Runtime -Configuration $Configuration '! "
}
2016-05-24 21:29:19 +00:00
# Use Git tag if not given a version
if ( -not $Version ) {
$Version = ( git - -git -dir = " $PSScriptRoot /.git " describe ) -Replace '^v'
}
2016-02-22 00:21:04 +00:00
2016-09-28 17:47:16 +00:00
$Source = Split-Path -Path $Script:Options . Output -Parent
Write-Verbose " Packaging Source: ' $Source ' " -Verbose
2016-05-24 21:29:19 +00:00
2016-02-24 00:21:00 +00:00
# Decide package output type
2016-09-28 17:47:16 +00:00
if ( -not $Type ) {
$Type = if ( $IsLinux ) {
2016-08-10 19:49:16 +00:00
if ( $LinuxInfo . ID -match " ubuntu " ) {
2016-06-20 20:03:54 +00:00
" deb "
2016-08-10 19:49:16 +00:00
} elseif ( $LinuxInfo . ID -match " centos " ) {
2016-06-20 20:03:54 +00:00
" rpm "
} else {
throw " Building packages for $( $LinuxInfo . PRETTY_NAME ) is unsupported! "
}
} elseif ( $IsOSX ) {
2016-08-10 19:49:16 +00:00
" osxpkg "
} elseif ( $IsWindows ) {
" msi " , " appx "
}
2016-09-28 17:47:16 +00:00
Write-Warning " -Type was not specified, continuing with $Type ! "
}
# Build the name suffix for win-plat packages
if ( $IsWindows ) {
$VersionTokens = $Version -split " - "
if ( $VersionTokens . Count -gt 1 ) {
# Get the suffix like 'alpha.10-win81-x64'
$NameSuffix = $VersionTokens [ 1 ] , $Runtime -join " - "
}
2016-08-10 19:49:16 +00:00
}
2016-09-28 17:47:16 +00:00
switch ( $Type ) {
" zip " {
$zipPackagePath = Join-Path $PWD " $Name - $Version - $Runtime .zip "
Compress-Archive -Path $Source \ * -DestinationPath $zipPackagePath
Write-Output $zipPackagePath
}
2016-08-10 19:49:16 +00:00
" msi " {
$Arguments = @ {
2016-09-28 17:47:16 +00:00
ProductNameSuffix = $NameSuffix
2016-08-10 19:49:16 +00:00
ProductSourcePath = $Source ;
ProductVersion = $Version ;
AssetsPath = " $PSScriptRoot \assets " ;
LicenseFilePath = " $PSScriptRoot \assets\license.rtf " ;
# Product Guid needs to be unique for every PowerShell version to allow SxS install
ProductGuid = [ Guid ] :: NewGuid ( )
}
New-MSIPackage @Arguments
}
" appx " {
$Arguments = @ {
2016-09-28 17:47:16 +00:00
PackageNameSuffix = $NameSuffix
2016-08-10 19:49:16 +00:00
PackageVersion = $Version ;
SourcePath = $Source ;
AssetsPath = " $PSScriptRoot \assets "
}
New-AppxPackage @Arguments
}
default {
$Arguments = @ {
Type = $_ ;
Source = $Source ;
Name = $Name ;
Version = $Version
}
New-UnixPackage @Arguments
}
}
}
function New-UnixPackage {
[ CmdletBinding ( ) ] param (
[ Parameter ( Mandatory ) ]
[ ValidateSet ( " deb " , " osxpkg " , " rpm " ) ]
[ string ] $Type ,
[ Parameter ( Mandatory ) ]
[ string ] $Source ,
2016-08-10 23:21:25 +00:00
# Must start with 'powershell' but may have any suffix
2016-08-10 19:49:16 +00:00
[ Parameter ( Mandatory ) ]
2016-08-10 23:21:25 +00:00
[ ValidatePattern ( " ^powershell " ) ]
2016-08-10 19:49:16 +00:00
[ string ] $Name ,
[ Parameter ( Mandatory ) ]
[ string ] $Version ,
# Package iteration version (rarely changed)
2016-08-16 21:15:05 +00:00
# This is a string because strings are appended to it
[ string ] $Iteration = " 1 "
2016-08-10 19:49:16 +00:00
)
2016-08-11 20:38:35 +00:00
# Validate platform
$ErrorMessage = " Must be on {0} to build ' $Type ' packages! "
switch ( $Type ) {
" deb " {
$WarningMessage = " Building for Ubuntu {0}.04! "
if ( ! $IsUbuntu ) {
throw ( $ErrorMessage -f " Ubuntu " )
} elseif ( $IsUbuntu14 ) {
Write-Warning ( $WarningMessage -f " 14 " )
} elseif ( $IsUbuntu16 ) {
Write-Warning ( $WarningMessage -f " 16 " )
}
}
" rpm " {
if ( ! $IsCentOS ) {
throw ( $ErrorMessage -f " CentOS " )
}
}
" osxpkg " {
if ( ! $IsOSX ) {
throw ( $ErrorMessage -f " OS X " )
}
}
}
2016-08-10 19:49:16 +00:00
foreach ( $Dependency in " fpm " , " ronn " ) {
if ( ! ( precheck $Dependency " Package dependency ' $Dependency ' not found. Run Start-PSBootstrap -Publish " ) ) {
throw " Dependency precheck failed! "
2016-06-20 20:03:54 +00:00
}
2016-02-27 02:51:13 +00:00
}
2016-02-22 00:21:04 +00:00
2016-08-10 19:49:16 +00:00
$Description = @"
PowerShell is an automation and configuration management platform .
It consists of a cross-platform command-line shell and associated scripting language .
" @
2016-08-10 23:21:25 +00:00
# Suffix is used for side-by-side package installation
$Suffix = $Name -replace " ^powershell "
if ( ! $Suffix ) {
Write-Warning " Suffix not given, building primary PowerShell package! "
$Suffix = $Version
}
# Setup staging directory so we don't change the original source directory
$Staging = " $PSScriptRoot /staging "
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $Staging
Copy-Item -Recurse $Source $Staging
# Rename files to given name if not "powershell"
if ( $Name -ne " powershell " ) {
$Files = @ ( " powershell " ,
" powershell.dll " ,
" powershell.deps.json " ,
" powershell.pdb " ,
" powershell.runtimeconfig.json " ,
" powershell.xml " )
foreach ( $File in $Files ) {
$NewName = $File -replace " ^powershell " , $Name
Move-Item " $Staging / $File " " $Staging / $NewName "
}
}
2016-04-10 01:02:37 +00:00
# Follow the Filesystem Hierarchy Standard for Linux and OS X
$Destination = if ( $IsLinux ) {
2016-08-10 23:21:25 +00:00
" /opt/microsoft/powershell/ $Suffix "
2016-04-10 01:02:37 +00:00
} elseif ( $IsOSX ) {
2016-08-10 23:21:25 +00:00
" /usr/local/microsoft/powershell/ $Suffix "
2016-04-10 01:02:37 +00:00
}
# Destination for symlink to powershell executable
$Link = if ( $IsLinux ) {
" /usr/bin "
} elseif ( $IsOSX ) {
" /usr/local/bin "
}
2016-08-10 23:21:25 +00:00
New-Item -Force -ItemType SymbolicLink -Path " /tmp/ $Name " -Target " $Destination / $Name " > $null
2016-05-24 21:29:19 +00:00
2016-08-31 20:16:11 +00:00
if ( $IsCentos ) {
$AfterInstallScript = [ io.path ] :: GetTempFileName ( )
$AfterRemoveScript = [ io.path ] :: GetTempFileName ( )
@ '
#!/bin/sh
if [ ! -f / etc / shells ] ; then
echo " {0} " > / etc / shells
else
grep -q " ^{0} $ " / etc / shells | | echo " {0} " > > / etc / shells
fi
' @ -f " $Link / $Name " | Out-File -FilePath $AfterInstallScript -Encoding ascii
@ '
if [ " $1 " = 0 ] ; then
if [ -f / etc / shells ] ; then
TmpFile = ` / bin / mktemp / tmp / . powershellmXXXXXX `
grep -v '^{0}$' / etc / shells > $TmpFile
cp -f $TmpFile / etc / shells
rm -f $TmpFile
fi
fi
' @ -f " $Link / $Name " | Out-File -FilePath $AfterRemoveScript -Encoding ascii
}
elseif ( $IsUbuntu ) {
$AfterInstallScript = [ io.path ] :: GetTempFileName ( )
$AfterRemoveScript = [ io.path ] :: GetTempFileName ( )
@ '
#!/bin/sh
set -e
case " $1 " in
( configure )
add-shell " {0} "
; ;
( abort-upgrade | abort-remove | abort-deconfigure )
exit 0
; ;
( * )
echo " postinst called with unknown argument ' $1 ' " > & 2
exit 0
; ;
esac
' @ -f " $Link / $Name " | Out-File -FilePath $AfterInstallScript -Encoding ascii
@ '
#!/bin/sh
set -e
case " $1 " in
( remove )
remove-shell " {0} "
; ;
esac
' @ -f " $Link / $Name " | Out-File -FilePath $AfterRemoveScript -Encoding ascii
}
2016-08-10 19:49:16 +00:00
# there is a weird bug in fpm
2016-05-16 21:53:40 +00:00
# if the target of the powershell symlink exists, `fpm` aborts
# with a `utime` error on OS X.
# so we move it to make symlink broken
2016-08-10 23:21:25 +00:00
$symlink_dest = " $Destination / $Name "
2016-05-16 21:53:40 +00:00
$hack_dest = " ./_fpm_symlink_hack_powershell "
2016-08-10 19:49:16 +00:00
if ( $IsOSX ) {
if ( Test-Path $symlink_dest ) {
2016-05-16 21:53:40 +00:00
Write-Warning " Move $symlink_dest to $hack_dest (fpm utime bug) "
Move-Item $symlink_dest $hack_dest
}
}
2016-08-10 19:49:16 +00:00
# run ronn to convert man page to roff
2016-08-10 23:21:25 +00:00
$RonnFile = Join-Path $PSScriptRoot " /assets/powershell.1.ronn "
$RoffFile = $RonnFile -replace " \.ronn $ "
2016-08-10 21:10:43 +00:00
2016-08-10 19:49:16 +00:00
# Run ronn on assets file
2016-08-10 23:21:25 +00:00
# Run does not play well with files named powershell6.0.1, so we generate and then rename
2016-08-10 19:49:16 +00:00
Start-NativeExecution { ronn - -roff $RonnFile }
2016-08-10 21:10:43 +00:00
2016-08-10 23:21:25 +00:00
# Setup for side-by-side man pages (noop if primary package)
$FixedRoffFile = $RoffFile -replace " powershell.1 $ " , " $Name .1 "
if ( $Name -ne " powershell " ) {
Move-Item $RoffFile $FixedRoffFile
}
2016-08-10 19:49:16 +00:00
# gzip in assets directory
2016-08-10 23:21:25 +00:00
$GzipFile = " $FixedRoffFile .gz "
Start-NativeExecution { gzip -f $FixedRoffFile }
$ManFile = Join-Path " /usr/local/share/man/man1 " ( Split-Path -Leaf $GzipFile )
2016-08-10 21:10:43 +00:00
2016-04-10 01:02:37 +00:00
# Change permissions for packaging
2016-08-11 18:34:58 +00:00
Start-NativeExecution {
find $Staging -type d | xargs chmod 755
find $Staging -type f | xargs chmod 644
chmod 644 $GzipFile
chmod 755 " $Staging / $Name " # only the executable should be executable
}
2016-04-10 01:02:37 +00:00
2016-09-19 23:23:40 +00:00
# Setup package dependencies
# These should match those in the Dockerfiles, but exclude tools like Git, which, and curl
$Dependencies = @ ( )
if ( $IsUbuntu ) {
$Dependencies = @ (
" libc6 " ,
" libcurl3 " ,
" libgcc1 " ,
" libssl1.0.0 " ,
" libstdc++6 " ,
" libtinfo5 " ,
" libunwind8 " ,
" libuuid1 " ,
" zlib1g "
)
# Please note the different libicu package dependency!
if ( $IsUbuntu14 ) {
$Dependencies + = " libicu52 "
} elseif ( $IsUbuntu16 ) {
$Dependencies + = " libicu55 "
2016-08-11 20:38:35 +00:00
}
2016-09-19 23:23:40 +00:00
} elseif ( $IsCentOS ) {
$Dependencies = @ (
" glibc " ,
" libcurl " ,
" libgcc " ,
" libicu " ,
" openssl " ,
" libstdc++ " ,
" ncurses-base " ,
" libunwind " ,
" uuid " ,
" zlib "
)
2016-02-27 02:51:13 +00:00
}
2016-08-16 21:15:05 +00:00
# iteration is "debian_revision"
# usage of this to differentiate distributions is allowed by non-standard
if ( $IsUbuntu14 ) {
$Iteration + = " ubuntu1.14.04.1 "
} elseif ( $IsUbuntu16 ) {
$Iteration + = " ubuntu1.16.04.1 "
}
# We currently only support CentOS 7
# https://fedoraproject.org/wiki/Packaging:DistTag
$rpm_dist = " el7.centos "
2016-04-10 01:02:37 +00:00
$Arguments = @ (
" --force " , " --verbose " ,
2016-08-10 19:49:16 +00:00
" --name " , $Name ,
2016-04-10 01:02:37 +00:00
" --version " , $Version ,
" --iteration " , $Iteration ,
2016-08-16 21:15:05 +00:00
" --rpm-dist " , $rpm_dist ,
2016-08-09 17:58:22 +00:00
" --maintainer " , " PowerShell Team <PowerShellTeam@hotmail.com> " ,
" --vendor " , " Microsoft Corporation " ,
" --url " , " https://microsoft.com/powershell " ,
" --license " , " MIT License " ,
2016-04-10 01:02:37 +00:00
" --description " , $Description ,
" --category " , " shells " ,
" --rpm-os " , " linux " ,
" -t " , $Type ,
2016-08-31 20:16:11 +00:00
" -s " , " dir "
)
2016-09-19 23:23:40 +00:00
foreach ( $Dependency in $Dependencies ) {
$Arguments + = @ ( " --depends " , $Dependency )
}
2016-08-31 20:16:11 +00:00
if ( $AfterInstallScript ) {
$Arguments + = @ ( " --after-install " , $AfterInstallScript )
}
if ( $AfterRemoveScript ) {
$Arguments + = @ ( " --after-remove " , $AfterRemoveScript )
}
$Arguments + = @ (
2016-08-10 23:21:25 +00:00
" $Staging /= $Destination / " ,
2016-08-10 19:49:16 +00:00
" $GzipFile = $ManFile " ,
2016-08-10 23:21:25 +00:00
" /tmp/ $Name = $Link "
2016-04-10 01:02:37 +00:00
)
2016-02-24 00:21:00 +00:00
# Build package
2016-08-10 19:49:16 +00:00
try {
2016-08-11 20:16:47 +00:00
$Output = Start-NativeExecution { fpm $Arguments }
2016-08-10 19:49:16 +00:00
} finally {
if ( $IsOSX ) {
# this is continuation of a fpm hack for a weird bug
if ( Test-Path $hack_dest ) {
Write-Warning " Move $hack_dest to $symlink_dest (fpm utime bug) "
Move-Item $hack_dest $symlink_dest
}
2016-05-16 21:53:40 +00:00
}
2016-08-31 20:16:11 +00:00
if ( $AfterInstallScript ) {
Remove-Item -erroraction 'silentlycontinue' $AfterInstallScript
}
if ( $AfterRemoveScript ) {
Remove-Item -erroraction 'silentlycontinue' $AfterRemoveScript
}
2016-05-16 21:53:40 +00:00
}
2016-08-11 20:16:47 +00:00
# Magic to get path output
2016-08-16 21:15:05 +00:00
return Get-Item ( Join-Path $PSScriptRoot ( ( $Output [ -1 ] -split " :path=> " ) [ -1 ] -replace '["{}]' ) )
2016-02-22 00:21:04 +00:00
}
2016-08-10 19:49:16 +00:00
2016-05-20 02:03:43 +00:00
function Publish-NuGetFeed
{
param (
[ string ] $OutputPath = " $PSScriptRoot /nuget-artifacts " ,
[ Parameter ( Mandatory = $true ) ]
[ string ] $VersionSuffix
)
2016-06-20 18:59:14 +00:00
# Add .NET CLI tools to PATH
Find-Dotnet
2016-05-20 02:03:43 +00:00
@ (
'Microsoft.PowerShell.Commands.Management' ,
'Microsoft.PowerShell.Commands.Utility' ,
'Microsoft.PowerShell.ConsoleHost' ,
'Microsoft.PowerShell.Security' ,
2016-06-25 00:25:56 +00:00
'System.Management.Automation' ,
'Microsoft.PowerShell.CoreCLR.AssemblyLoadContext' ,
2016-07-26 23:43:32 +00:00
'Microsoft.PowerShell.CoreCLR.Eventing' ,
2016-08-29 23:01:38 +00:00
'Microsoft.WSMan.Management' ,
'Microsoft.WSMan.Runtime' ,
2016-07-26 23:43:32 +00:00
'Microsoft.PowerShell.SDK'
2016-05-20 02:03:43 +00:00
) | % {
2016-08-03 20:23:21 +00:00
if ( $VersionSuffix ) {
2016-05-20 02:03:43 +00:00
dotnet pack " src/ $_ " - -output $OutputPath - -version -suffix $VersionSuffix
2016-08-03 20:23:21 +00:00
} else {
2016-05-20 02:03:43 +00:00
dotnet pack " src/ $_ " - -output $OutputPath
}
}
}
2016-07-01 19:09:50 +00:00
function Start-DevPowerShell {
2016-02-03 18:53:43 +00:00
param (
2016-07-27 17:48:36 +00:00
[ switch ] $FullCLR ,
2016-02-03 18:53:43 +00:00
[ switch ] $ZapDisable ,
[ string[] ] $ArgumentList = '' ,
[ switch ] $LoadProfile ,
2016-07-27 17:48:36 +00:00
[ string ] $binDir = ( Split-Path ( New-PSOptions -FullCLR: $FullCLR ) . Output ) ,
2016-07-01 19:09:50 +00:00
[ switch ] $NoNewWindow ,
[ string ] $Command ,
[ switch ] $KeepPSModulePath
2016-02-03 18:53:43 +00:00
)
2016-04-02 05:01:05 +00:00
try {
2016-08-03 20:23:21 +00:00
if ( ( -not $NoNewWindow ) -and ( $IsCoreCLR ) ) {
2016-07-27 19:27:41 +00:00
Write-Warning " Start-DevPowerShell -NoNewWindow is currently implied in PowerShellCore edition https://github.com/PowerShell/PowerShell/issues/1543 "
2016-07-27 17:55:42 +00:00
$NoNewWindow = $true
}
2016-07-01 19:09:50 +00:00
if ( -not $LoadProfile ) {
2016-02-04 01:25:51 +00:00
$ArgumentList = @ ( '-noprofile' ) + $ArgumentList
2016-02-03 18:53:43 +00:00
}
2016-08-03 20:23:21 +00:00
if ( -not $KeepPSModulePath ) {
if ( -not $Command ) {
2016-07-01 19:09:50 +00:00
$ArgumentList = @ ( '-NoExit' ) + $ArgumentList
}
2016-07-28 18:47:36 +00:00
$Command = '$env:PSMODULEPATH = Join-Path $env:DEVPATH Modules; ' + $Command
2016-08-03 20:23:21 +00:00
}
2016-07-01 19:09:50 +00:00
2016-08-03 20:23:21 +00:00
if ( $Command ) {
2016-07-01 19:09:50 +00:00
$ArgumentList = $ArgumentList + @ ( " -command $Command " )
}
2016-02-03 18:53:43 +00:00
$env:DEVPATH = $binDir
2016-04-02 05:01:05 +00:00
if ( $ZapDisable ) {
2016-02-21 23:06:39 +00:00
$env:COMPLUS_ZapDisable = 1
2016-02-03 18:53:43 +00:00
}
2016-07-27 17:48:36 +00:00
if ( $FullCLR -and ( -not ( Test-Path $binDir \ powershell . exe . config ) ) ) {
2016-02-03 18:53:43 +00:00
$configContents = @"
2016-02-21 23:06:39 +00:00
< ? xml version = " 1.0 " encoding = " utf-8 " ? >
< configuration >
2016-04-02 05:01:05 +00:00
< runtime >
< developmentMode developerInstallation = " true " / >
< / runtime >
2016-02-03 18:53:43 +00:00
< / configuration >
" @
$configContents | Out-File -Encoding Ascii $binDir \ powershell . exe . config
}
2016-02-21 23:06:39 +00:00
# splatting for the win
2016-02-04 01:25:51 +00:00
$startProcessArgs = @ {
2016-07-27 17:48:36 +00:00
FilePath = " $binDir \powershell "
2016-02-04 01:25:51 +00:00
ArgumentList = " $ArgumentList "
2016-02-21 23:06:39 +00:00
}
2016-02-04 21:19:24 +00:00
if ( $NoNewWindow ) {
$startProcessArgs . NoNewWindow = $true
$startProcessArgs . Wait = $true
}
2016-02-21 23:06:39 +00:00
2016-02-04 01:25:51 +00:00
Start-Process @startProcessArgs
2016-04-02 05:01:05 +00:00
} finally {
2016-08-30 18:47:27 +00:00
if ( $env:DevPath )
{
Remove-Item env : DEVPATH
}
2016-04-02 05:01:05 +00:00
if ( $ZapDisable ) {
2016-08-30 18:47:27 +00:00
Remove-Item env : COMPLUS_ZapDisable
2016-02-03 18:53:43 +00:00
}
}
2016-02-20 22:35:46 +00:00
}
2016-03-22 23:00:20 +00:00
<#
2016-08-03 20:23:21 +00:00
. EXAMPLE
2016-06-14 00:37:24 +00:00
PS C: > Copy-MappedFiles -PslMonadRoot . \ src \ monad
copy files FROM . \ src \ monad ( old location of submodule ) TO src / < project > folders
2016-03-22 23:00:20 +00:00
#>
2016-06-14 00:37:24 +00:00
function Copy-MappedFiles {
2016-04-01 21:41:13 +00:00
2016-03-22 23:00:20 +00:00
[ CmdletBinding ( ) ]
param (
2016-06-14 00:37:24 +00:00
[ Parameter ( ValueFromPipeline = $true ) ]
[ string[] ] $Path = " $PSScriptRoot " ,
[ Parameter ( Mandatory = $true ) ]
2016-06-14 01:46:15 +00:00
[ string ] $PslMonadRoot ,
2016-06-16 02:07:49 +00:00
[ switch ] $Force ,
[ switch ] $WhatIf
2016-03-22 23:00:20 +00:00
)
2016-08-03 20:23:21 +00:00
begin {
function MaybeTerminatingWarning {
2016-06-14 01:46:15 +00:00
param ( [ string ] $Message )
2016-08-03 20:23:21 +00:00
if ( $Force ) {
2016-06-14 01:46:15 +00:00
Write-Warning " $Message : ignoring (-Force) "
2016-08-03 20:23:21 +00:00
} elseif ( $WhatIf ) {
Write-Warning " $Message : ignoring (-WhatIf) "
} else {
2016-06-14 01:46:15 +00:00
throw " $Message : use -Force to ignore "
}
}
2016-08-03 20:23:21 +00:00
if ( -not ( Test-Path -PathType Container $PslMonadRoot ) ) {
2016-06-14 00:37:24 +00:00
throw " $pslMonadRoot is not a valid folder "
}
2016-04-01 21:41:13 +00:00
2016-08-26 20:46:03 +00:00
# Do some intelligence to prevent shooting us in the foot with CL management
2016-06-14 01:46:15 +00:00
# finding base-line CL
2016-06-15 20:27:32 +00:00
$cl = git - -git -dir = " $PSScriptRoot /.git " tag | % { if ( $_ -match 'SD.(\d+)$' ) { [ int ] $Matches [ 1 ] } } | Sort-Object -Descending | Select-Object -First 1
2016-08-03 20:23:21 +00:00
if ( $cl ) {
2016-06-23 02:46:16 +00:00
log " Current base-line CL is SD: $cl (based on tags) "
2016-08-03 20:23:21 +00:00
} else {
2016-06-14 01:46:15 +00:00
MaybeTerminatingWarning " Could not determine base-line CL based on tags "
}
2016-08-03 20:23:21 +00:00
try {
2016-06-14 01:46:15 +00:00
Push-Location $PslMonadRoot
2016-08-03 20:23:21 +00:00
if ( git status - -porcelain -uno ) {
2016-06-14 01:46:15 +00:00
MaybeTerminatingWarning " $pslMonadRoot has changes "
}
2016-08-03 20:23:21 +00:00
if ( git log - -grep = " SD: $cl " HEAD ^ . . HEAD ) {
2016-06-28 22:52:38 +00:00
log " $pslMonadRoot HEAD matches [SD: $cl ] "
2016-08-03 20:23:21 +00:00
} else {
Write-Warning " Try to checkout this commit in $pslMonadRoot : "
2016-06-23 02:46:16 +00:00
git log - -grep = " SD: $cl " | Write-Warning
2016-06-14 01:46:15 +00:00
MaybeTerminatingWarning " $pslMonadRoot HEAD doesn't match [SD: $cl ] "
}
2016-08-03 20:23:21 +00:00
} finally {
2016-06-14 01:46:15 +00:00
Pop-Location
}
$map = @ { }
2016-03-22 23:00:20 +00:00
}
2016-08-03 20:23:21 +00:00
process {
2016-06-14 00:37:24 +00:00
$map + = Get-Mappings $Path -Root $PslMonadRoot
}
2016-03-22 23:00:20 +00:00
2016-08-03 20:23:21 +00:00
end {
2016-06-14 00:37:24 +00:00
$map . GetEnumerator ( ) | % {
2016-06-15 20:27:32 +00:00
New-Item -ItemType Directory ( Split-Path $_ . Value ) -ErrorAction SilentlyContinue > $null
2016-06-16 02:07:49 +00:00
Copy-Item $_ . Key $_ . Value -Verbose: ( [ bool ] $PSBoundParameters [ 'Verbose' ] ) -WhatIf: $WhatIf
2016-03-22 23:00:20 +00:00
}
}
}
2016-06-14 00:37:24 +00:00
function Get-Mappings
{
[ CmdletBinding ( ) ]
2016-03-22 23:00:20 +00:00
param (
2016-06-14 00:37:24 +00:00
[ Parameter ( ValueFromPipeline = $true ) ]
[ string[] ] $Path = " $PSScriptRoot " ,
[ string ] $Root ,
[ switch ] $KeepRelativePaths
2016-03-22 23:00:20 +00:00
)
2016-08-03 20:23:21 +00:00
begin {
2016-06-14 00:37:24 +00:00
$mapFiles = @ ( )
}
2016-08-03 20:23:21 +00:00
process {
2016-06-14 00:37:24 +00:00
Write-Verbose " Discovering map files in $Path "
$count = $mapFiles . Count
2016-08-03 20:23:21 +00:00
if ( -not ( Test-Path $Path ) ) {
2016-06-14 00:37:24 +00:00
throw " Mapping file not found in $mappingFilePath "
2016-03-22 23:00:20 +00:00
}
2016-04-01 21:41:13 +00:00
2016-08-03 20:23:21 +00:00
if ( Test-Path -PathType Container $Path ) {
2016-06-14 00:37:24 +00:00
$mapFiles + = Get-ChildItem -Recurse $Path -Filter 'map.json' -File
2016-08-03 20:23:21 +00:00
} else {
2016-06-14 00:37:24 +00:00
# it exists and it's a file, don't check the name pattern
$mapFiles + = Get-ChildItem $Path
2016-03-22 23:00:20 +00:00
}
2016-06-14 00:37:24 +00:00
Write-Verbose " Found $( $mapFiles . Count - $count ) map files in $Path "
2016-03-22 23:00:20 +00:00
}
2016-08-03 20:23:21 +00:00
end {
2016-06-14 00:37:24 +00:00
$map = @ { }
$mapFiles | % {
2016-06-30 23:42:58 +00:00
$file = $_
2016-08-03 20:23:21 +00:00
try {
2016-06-30 23:42:58 +00:00
$rawHashtable = $_ | Get-Content -Raw | ConvertFrom-Json | Convert-PSObjectToHashtable
2016-08-03 20:23:21 +00:00
} catch {
2016-06-30 23:42:58 +00:00
Write-Error " Exception, when processing $( $file . FullName ) : $_ "
}
2016-06-14 00:37:24 +00:00
$mapRoot = Split-Path $_ . FullName
2016-08-03 20:23:21 +00:00
if ( $KeepRelativePaths ) {
2016-06-14 00:37:24 +00:00
# not very elegant way to find relative for the current directory path
$mapRoot = $mapRoot . Substring ( $PSScriptRoot . Length + 1 )
# keep original unix-style paths for git
$mapRoot = $mapRoot . Replace ( '\' , '/' )
2016-03-29 21:17:19 +00:00
}
2016-06-14 00:37:24 +00:00
$rawHashtable . GetEnumerator ( ) | % {
$newKey = if ( $Root ) { Join-Path $Root $_ . Key } else { $_ . Key }
2016-08-03 20:23:21 +00:00
$newValue = if ( $KeepRelativePaths ) { ( $mapRoot + '/' + $_ . Value ) } else { Join-Path $mapRoot $_ . Value }
2016-06-14 00:37:24 +00:00
$map [ $newKey ] = $newValue
2016-03-22 23:00:20 +00:00
}
}
2016-06-14 00:37:24 +00:00
return $map
}
2016-03-22 23:00:20 +00:00
}
2016-03-23 23:57:59 +00:00
<#
2016-06-14 00:37:24 +00:00
. EXAMPLE Send-GitDiffToSd -diffArg1 32b90c048aa0c5bc8e67f96a98ea01c728c4a5be ~ 1 -diffArg2 32b90c048aa0c5bc8e67f96a98ea01c728c4a5be -AdminRoot d: \ e \ ps_dev \ admin
2016-08-26 20:46:03 +00:00
Apply a single commit to admin folder
2016-03-23 23:57:59 +00:00
#>
2016-04-02 05:01:05 +00:00
function Send-GitDiffToSd {
2016-03-23 23:57:59 +00:00
param (
[ Parameter ( Mandatory ) ]
[ string ] $diffArg1 ,
[ Parameter ( Mandatory ) ]
[ string ] $diffArg2 ,
[ Parameter ( Mandatory ) ]
2016-06-14 00:37:24 +00:00
[ string ] $AdminRoot ,
2016-03-23 23:57:59 +00:00
[ switch ] $WhatIf
)
2016-06-14 00:37:24 +00:00
# this is only for windows, because you cannot have SD enlistment on Linux
$patchPath = ( ls ( Join-Path ( get-command git ) . Source '..\..' ) -Recurse -Filter 'patch.exe' ) . FullName
$m = Get-Mappings -KeepRelativePaths -Root $AdminRoot
2016-03-23 23:57:59 +00:00
$affectedFiles = git diff - -name -only $diffArg1 $diffArg2
2016-06-14 00:37:24 +00:00
$affectedFiles | % {
2016-06-23 02:46:16 +00:00
log " Changes in file $_ "
2016-06-14 00:37:24 +00:00
}
2016-03-23 23:57:59 +00:00
$rev = Get-InvertedOrderedMap $m
foreach ( $file in $affectedFiles ) {
2016-04-02 05:01:05 +00:00
if ( $rev . Contains ) {
2016-06-14 00:37:24 +00:00
$sdFilePath = $rev [ $file ]
if ( -not $sdFilePath )
{
Write-Warning " Cannot find mapped file for $file , skipping "
continue
}
2016-03-23 23:57:59 +00:00
$diff = git diff $diffArg1 $diffArg2 - - $file
2016-04-02 05:01:05 +00:00
if ( $diff ) {
2016-06-23 02:46:16 +00:00
log " Apply patch to $sdFilePath "
2016-03-23 23:57:59 +00:00
Set-Content -Value $diff -Path $env:TEMP \ diff -Encoding Ascii
2016-04-02 05:01:05 +00:00
if ( $WhatIf ) {
2016-06-23 02:46:16 +00:00
log " Patch content "
2016-06-15 20:27:32 +00:00
Get-Content $env:TEMP \ diff
2016-04-02 05:01:05 +00:00
} else {
2016-04-01 21:41:13 +00:00
& $patchPath - -binary -p1 $sdFilePath $env:TEMP \ diff
2016-03-23 23:57:59 +00:00
}
2016-04-02 05:01:05 +00:00
} else {
2016-06-23 02:46:16 +00:00
log " No changes in $file "
2016-03-23 23:57:59 +00:00
}
2016-04-02 05:01:05 +00:00
} else {
2016-06-23 02:46:16 +00:00
log " Ignore changes in $file , because there is no mapping for it "
2016-03-23 23:57:59 +00:00
}
2016-04-01 21:41:13 +00:00
}
2016-03-23 23:57:59 +00:00
}
2016-04-02 05:01:05 +00:00
2016-06-17 18:23:29 +00:00
function Start-TypeGen
{
[ CmdletBinding ( ) ]
param ( )
2016-06-20 18:59:14 +00:00
# Add .NET CLI tools to PATH
Find-Dotnet
2016-06-17 18:23:29 +00:00
Push-Location " $PSScriptRoot /src/TypeCatalogParser "
2016-08-03 20:23:21 +00:00
try {
2016-07-26 23:59:45 +00:00
dotnet run
2016-08-03 20:23:21 +00:00
} finally {
2016-06-17 18:23:29 +00:00
Pop-Location
}
Push-Location " $PSScriptRoot /src/TypeCatalogGen "
2016-08-03 20:23:21 +00:00
try {
2016-06-17 18:23:29 +00:00
dotnet run . . / Microsoft . PowerShell . CoreCLR . AssemblyLoadContext / CorePsTypeCatalog . cs powershell . inc
2016-08-03 20:23:21 +00:00
} finally {
2016-06-17 18:23:29 +00:00
Pop-Location
}
}
2016-04-04 21:20:34 +00:00
function Start-ResGen
{
2016-06-15 10:42:54 +00:00
[ CmdletBinding ( ) ]
param ( )
2016-08-02 18:47:53 +00:00
# Add .NET CLI tools to PATH
Find-Dotnet
Push-Location " $PSScriptRoot /src/ResGen "
2016-08-03 20:23:21 +00:00
try {
2016-08-02 18:47:53 +00:00
Start-NativeExecution { dotnet run } | Write-Verbose
2016-08-03 20:23:21 +00:00
} finally {
2016-08-02 18:47:53 +00:00
Pop-Location
2016-04-04 21:20:34 +00:00
}
}
2016-04-02 05:01:05 +00:00
2016-06-20 18:59:14 +00:00
function Find-Dotnet ( ) {
$originalPath = $env:PATH
$dotnetPath = if ( $IsWindows ) {
" $env:LocalAppData \Microsoft\dotnet "
} else {
" $env:HOME /.dotnet "
}
if ( -not ( precheck 'dotnet' " Could not find 'dotnet', appending $dotnetPath to PATH. " ) ) {
$env:PATH + = [ IO.Path ] :: PathSeparator + $dotnetPath
}
if ( -not ( precheck 'dotnet' " Still could not find 'dotnet', restoring PATH. " ) ) {
$env:PATH = $originalPath
}
}
2016-06-30 23:02:07 +00:00
<#
2016-07-01 20:51:14 +00:00
This is one-time conversion . We use it for to turn GetEventResources . txt into GetEventResources . resx
2016-06-30 23:02:07 +00:00
. EXAMPLE Convert-TxtResourceToXml -Path Microsoft . PowerShell . Commands . Diagnostics \ resources
#>
function Convert-TxtResourceToXml
{
param (
[ string[] ] $Path
)
2016-08-03 20:23:21 +00:00
process {
2016-06-30 23:02:07 +00:00
$Path | % {
Get-ChildItem $_ -Filter " *.txt " | % {
$txtFile = $_ . FullName
$resxFile = Join-Path ( Split-Path $txtFile ) " $( $_ . BaseName ) .resx "
$resourceHashtable = ConvertFrom-StringData ( Get-Content -Raw $txtFile )
$resxContent = $resourceHashtable . GetEnumerator ( ) | % {
@ '
< data name = " {0} " xml : space = " preserve " >
< value > { 1 } < / value >
< / data >
' @ -f $_ . Key , $_ . Value
} | Out-String
Set-Content -Path $resxFile -Value ( $script:RESX_TEMPLATE -f $resxContent )
}
}
}
}
2016-06-23 02:46:16 +00:00
function Start-XamlGen
2016-06-21 21:30:26 +00:00
{
[ CmdletBinding ( ) ]
param (
[ Parameter ( ) ]
[ ValidateSet ( " Debug " , " Release " ) ]
[ string ]
$MSBuildConfiguration = " Release "
)
2016-06-21 23:54:57 +00:00
Use-MSBuild
2016-06-21 21:30:26 +00:00
Get-ChildItem -Path " $PSScriptRoot /src " -Directory | % {
$XamlDir = Join-Path -Path $_ . FullName -ChildPath Xamls
if ( ( Test-Path -Path $XamlDir -PathType Container ) -and
2016-08-03 20:23:21 +00:00
( @ ( Get-ChildItem -Path " $XamlDir \*.xaml " ) . Count -gt 0 ) ) {
2016-06-21 21:30:26 +00:00
$OutputDir = Join-Path -Path $env:TEMP -ChildPath " _Resolve_Xaml_ "
Remove-Item -Path $OutputDir -Recurse -Force -ErrorAction SilentlyContinue
mkdir -Path $OutputDir -Force > $null
2016-06-24 22:12:15 +00:00
# we will get failures, but it's ok: we only need to copy *.g.cs files in the dotnet cli project.
$SourceDir = ConvertFrom-Xaml -Configuration $MSBuildConfiguration -OutputDir $OutputDir -XamlDir $XamlDir -IgnoreMsbuildFailure: $true
2016-06-21 21:30:26 +00:00
$DestinationDir = Join-Path -Path $_ . FullName -ChildPath gen
2016-08-03 20:23:21 +00:00
2016-06-23 02:46:16 +00:00
New-Item -ItemType Directory $DestinationDir -ErrorAction SilentlyContinue > $null
2016-06-24 22:12:15 +00:00
$filesToCopy = Get-Item " $SourceDir \*.cs " , " $SourceDir \*.g.resources "
2016-08-03 20:23:21 +00:00
if ( -not $filesToCopy ) {
2016-06-24 22:12:15 +00:00
throw " No .cs or .g.resources files are generated for $XamlDir , something went wrong. Run 'Start-XamlGen -Verbose' for details. "
}
$filesToCopy | % {
2016-06-23 02:46:16 +00:00
$sourcePath = $_ . FullName
Write-Verbose " Copy generated xaml artifact: $sourcePath -> $DestinationDir "
Copy-Item -Path $sourcePath -Destination $DestinationDir
2016-06-21 21:30:26 +00:00
}
}
}
}
$Script:XamlProj = @"
< Project DefaultTargets = " ResolveAssemblyReferences;MarkupCompilePass1;PrepareResources " xmlns = " http://schemas.microsoft.com/developer/msbuild/2003 " >
< PropertyGroup >
< Language > C #</Language>
< AssemblyName > Microsoft . PowerShell . Activities < / AssemblyName >
< OutputType > library < / OutputType >
< Configuration > { 0 } < / Configuration >
< Platform > Any CPU < / Platform >
< OutputPath > { 1 } < / OutputPath >
< Do_CodeGenFromXaml > true < / Do_CodeGenFromXaml >
< / PropertyGroup >
< Import Project = " `$ (MSBuildBinPath)\Microsoft.CSharp.targets " / >
< Import Project = " `$ (MSBuildBinPath)\Microsoft.WinFX.targets " Condition = " ' `$ (TargetFrameworkVersion)' == 'v2.0' OR ' `$ (TargetFrameworkVersion)' == 'v3.0' OR ' `$ (TargetFrameworkVersion)' == 'v3.5' " / >
< ItemGroup >
{ 2 }
2016-06-24 22:02:46 +00:00
< Reference Include = " WindowsBase.dll " >
2016-06-21 21:30:26 +00:00
< Private > False < / Private >
< / Reference >
2016-06-24 22:02:46 +00:00
< Reference Include = " PresentationCore.dll " >
2016-06-21 21:30:26 +00:00
< Private > False < / Private >
< / Reference >
2016-06-24 22:02:46 +00:00
< Reference Include = " PresentationFramework.dll " >
2016-06-21 21:30:26 +00:00
< Private > False < / Private >
< / Reference >
< / ItemGroup >
< / Project >
" @
$Script:XamlProjPage = @ '
< Page Include = " {0} " / >
' @
function script: ConvertFrom-Xaml {
[ CmdletBinding ( ) ]
param (
[ Parameter ( Mandatory = $true ) ]
[ string ] $Configuration ,
[ Parameter ( Mandatory = $true ) ]
[ string ] $OutputDir ,
[ Parameter ( Mandatory = $true ) ]
2016-06-22 01:24:24 +00:00
[ string ] $XamlDir ,
[ switch ] $IgnoreMsbuildFailure
2016-06-21 21:30:26 +00:00
)
2016-06-23 02:46:16 +00:00
log " ConvertFrom-Xaml for $XamlDir "
2016-06-22 01:24:24 +00:00
2016-06-21 21:30:26 +00:00
$Pages = " "
Get-ChildItem -Path " $XamlDir \*.xaml " | % {
$Page = $Script:XamlProjPage -f $_ . FullName
$Pages + = $Page
}
$XamlProjContent = $Script:XamlProj -f $Configuration , $OutputDir , $Pages
$XamlProjPath = Join-Path -Path $OutputDir -ChildPath xaml . proj
Set-Content -Path $XamlProjPath -Value $XamlProjContent -Encoding Ascii -NoNewline -Force
2016-06-24 22:03:38 +00:00
msbuild $XamlProjPath | Write-Verbose
2016-06-21 21:30:26 +00:00
2016-08-03 20:23:21 +00:00
if ( $LASTEXITCODE -ne 0 ) {
2016-06-22 01:24:24 +00:00
$message = " When processing $XamlDir 'msbuild $XamlProjPath > `$ null' failed with exit code $LASTEXITCODE "
2016-08-03 20:23:21 +00:00
if ( $IgnoreMsbuildFailure ) {
2016-06-24 22:12:15 +00:00
Write-Verbose $message
2016-08-03 20:23:21 +00:00
} else {
2016-06-22 01:24:24 +00:00
throw $message
}
2016-06-21 21:30:26 +00:00
}
return ( Join-Path -Path $OutputDir -ChildPath " obj\Any CPU\ $Configuration " )
}
2016-06-20 18:59:14 +00:00
2016-06-21 23:54:57 +00:00
function script: Use-MSBuild {
2016-06-24 21:52:04 +00:00
# TODO: we probably should require a particular version of msbuild, if we are taking this dependency
# msbuild v14 and msbuild v4 behaviors are different for XAML generation
$frameworkMsBuildLocation = " ${env:SystemRoot} \Microsoft.Net\Framework\v4.0.30319\msbuild "
2016-06-23 02:46:16 +00:00
2016-06-24 21:52:04 +00:00
$msbuild = get-command msbuild -ErrorAction SilentlyContinue
2016-08-03 20:23:21 +00:00
if ( $msbuild ) {
2016-06-24 21:52:04 +00:00
# all good, nothing to do
return
2016-06-21 23:54:57 +00:00
}
2016-06-23 02:46:16 +00:00
2016-08-03 20:23:21 +00:00
if ( -not ( Test-Path $frameworkMsBuildLocation ) ) {
2016-06-24 21:52:04 +00:00
throw " msbuild not found in ' $frameworkMsBuildLocation '. Install Visual Studio 2015. "
2016-06-23 02:46:16 +00:00
}
2016-06-24 21:52:04 +00:00
Set-Alias msbuild $frameworkMsBuildLocation -Scope Script
2016-06-21 23:54:57 +00:00
}
2016-04-02 05:01:05 +00:00
function script: log([string]$message ) {
Write-Host -Foreground Green $message
2016-08-26 20:46:03 +00:00
#reset colors for older package to at return to default after error message on a compilation error
2016-08-03 20:23:21 +00:00
[ console ] :: ResetColor ( )
2016-04-02 05:01:05 +00:00
}
function script: precheck([string]$command , [ string ] $missedMessage ) {
$c = Get-Command $command -ErrorAction SilentlyContinue
if ( -not $c ) {
2016-07-21 22:53:36 +00:00
if ( $missedMessage -ne $null )
{
Write-Warning $missedMessage
}
2016-04-02 05:01:05 +00:00
return $false
} else {
return $true
}
}
function script: Get-InvertedOrderedMap {
param (
$h
)
$res = [ ordered ] @ { }
foreach ( $q in $h . GetEnumerator ( ) ) {
if ( $res . Contains ( $q . Value ) ) {
throw " Cannot invert hashtable: duplicated key $( $q . Value ) "
}
$res [ $q . Value ] = $q . Key
}
return $res
}
## this function is from Dave Wyatt's answer on
## http://stackoverflow.com/questions/22002748/hashtables-from-convertfrom-json-have-different-type-from-powershells-built-in-h
function script: Convert-PSObjectToHashtable {
param (
[ Parameter ( ValueFromPipeline ) ]
$InputObject
)
process {
if ( $null -eq $InputObject ) { return $null }
if ( $InputObject -is [ System.Collections.IEnumerable ] -and $InputObject -isnot [ string ] ) {
$collection = @ (
foreach ( $object in $InputObject ) { Convert-PSObjectToHashtable $object }
)
Write-Output -NoEnumerate $collection
} elseif ( $InputObject -is [ psobject ] ) {
$hash = @ { }
2016-08-03 20:23:21 +00:00
foreach ( $property in $InputObject . PSObject . Properties ) {
2016-04-02 05:01:05 +00:00
$hash [ $property . Name ] = Convert-PSObjectToHashtable $property . Value
}
$hash
} else {
$InputObject
}
}
}
2016-04-04 21:20:34 +00:00
2016-04-19 23:59:03 +00:00
# this function wraps native command Execution
# for more information, read https://mnaoumov.wordpress.com/2015/01/11/execution-of-external-commands-in-powershell-done-right/
function script: Start-NativeExecution([scriptblock]$sb )
{
$backupEAP = $script:ErrorActionPreference
$script:ErrorActionPreference = " Continue "
2016-08-03 20:23:21 +00:00
try {
2016-04-19 23:59:03 +00:00
& $sb
2016-08-26 20:46:03 +00:00
# note, if $sb doesn't have a native invocation, $LASTEXITCODE will
2016-04-19 23:59:03 +00:00
# point to the obsolete value
2016-08-03 20:23:21 +00:00
if ( $LASTEXITCODE -ne 0 ) {
2016-05-18 21:30:24 +00:00
throw " Execution of { $sb } failed with exit code $LASTEXITCODE "
2016-04-19 23:59:03 +00:00
}
2016-08-03 20:23:21 +00:00
} finally {
2016-04-19 23:59:03 +00:00
$script:ErrorActionPreference = $backupEAP
}
}
2016-04-04 21:20:34 +00:00
2016-06-27 23:04:57 +00:00
# Builds coming out of this project can have version number as 'a.b.c' OR 'a.b.c-d-f'
# This function converts the above version into major.minor[.build[.revision]] format
function Get-PackageVersionAsMajorMinorBuildRevision
{
[ CmdletBinding ( ) ]
param (
# Version of the Package
[ Parameter ( Mandatory = $true ) ]
[ ValidateNotNullOrEmpty ( ) ]
[ string ] $Version
)
Write-Verbose " Extract the version in the form of major.minor[.build[.revision]] for $Version "
$packageVersionTokens = $Version . Split ( '-' )
$packageVersion = ( [ regex ] :: matches ( $Version , " \d+(\.\d+)+ " ) ) [ 0 ] . value
2016-08-03 20:23:21 +00:00
if ( 1 -eq $packageVersionTokens . Count ) {
2016-06-27 23:04:57 +00:00
# In case the input is of the form a.b.c, add a '0' at the end for revision field
2016-07-27 04:22:37 +00:00
$packageVersion = $packageVersion + '.0'
2016-08-03 20:23:21 +00:00
} elseif ( 1 -lt $packageVersionTokens . Count ) {
2016-06-27 23:04:57 +00:00
# We have all the four fields
2016-07-27 04:22:37 +00:00
$packageBuildTokens = ( [ regex ] :: Matches ( $packageVersionTokens [ 1 ] , " \d+ " ) ) [ 0 ] . value
2016-09-28 17:47:16 +00:00
$packageVersion = $packageVersion + '.' + $packageBuildTokens
2016-06-27 23:04:57 +00:00
}
return $packageVersion
}
2016-06-06 20:20:00 +00:00
function New-MSIPackage
2016-05-24 21:23:38 +00:00
{
[ CmdletBinding ( ) ]
param (
2016-08-04 20:30:00 +00:00
2016-05-24 21:23:38 +00:00
# Name of the Product
[ ValidateNotNullOrEmpty ( ) ]
2016-09-28 17:47:16 +00:00
[ string ] $ProductName = 'PowerShell' ,
# Suffix of the Name
[ string ] $ProductNameSuffix ,
2016-05-24 21:23:38 +00:00
# Version of the Product
[ Parameter ( Mandatory = $true ) ]
[ ValidateNotNullOrEmpty ( ) ]
[ string ] $ProductVersion ,
# Product Guid needs to change for every version to support SxS install
[ ValidateNotNullOrEmpty ( ) ]
[ string ] $ProductGuid = 'a5249933-73a1-4b10-8a4c-13c98bdc16fe' ,
# Source Path to the Product Files - required to package the contents into an MSI
[ Parameter ( Mandatory = $true ) ]
[ ValidateNotNullOrEmpty ( ) ]
[ string ] $ProductSourcePath ,
# File describing the MSI Package creation semantics
[ ValidateNotNullOrEmpty ( ) ]
2016-09-28 17:47:16 +00:00
[ string ] $ProductWxsPath = " $PSScriptRoot \assets\Product.wxs " ,
2016-06-27 18:39:49 +00:00
# Path to Assets folder containing artifacts such as icons, images
[ Parameter ( Mandatory = $true ) ]
[ ValidateNotNullOrEmpty ( ) ]
2016-08-04 20:30:00 +00:00
[ string ] $AssetsPath ,
2016-05-24 21:23:38 +00:00
2016-08-04 20:30:00 +00:00
# Path to license.rtf file - for the EULA
[ Parameter ( Mandatory = $true ) ]
[ ValidateNotNullOrEmpty ( ) ]
[ string ] $LicenseFilePath
2016-09-28 17:47:16 +00:00
)
2016-05-24 21:23:38 +00:00
$wixToolsetBinPath = " $ {env:ProgramFiles(x86)}\WiX Toolset v3.10\bin "
Write-Verbose " Ensure Wix Toolset is present on the machine @ $wixToolsetBinPath "
2016-08-04 20:30:00 +00:00
if ( -not ( Test-Path $wixToolsetBinPath ) )
{
2016-09-28 17:47:16 +00:00
throw " Wix Toolset is required to create MSI package. Please install Wix from https://wix.codeplex.com/downloads/get/1540240 "
2016-05-24 21:23:38 +00:00
}
Write-Verbose " Initialize Wix executables - Heat.exe, Candle.exe, Light.exe "
$wixHeatExePath = Join-Path $wixToolsetBinPath " Heat.exe "
$wixCandleExePath = Join-Path $wixToolsetBinPath " Candle.exe "
$wixLightExePath = Join-Path $wixToolsetBinPath " Light.exe "
2016-06-27 18:39:49 +00:00
2016-06-27 23:04:57 +00:00
$ProductVersion = Get-PackageVersionAsMajorMinorBuildRevision -Version $ProductVersion -Verbose
2016-08-04 20:30:00 +00:00
2016-06-27 18:39:49 +00:00
$assetsInSourcePath = Join-Path $ProductSourcePath 'assets'
2016-09-28 17:47:16 +00:00
New-Item $assetsInSourcePath -type directory -Force | Write-Verbose
2016-06-27 18:39:49 +00:00
2016-08-04 20:30:00 +00:00
Write-Verbose " Place dependencies such as icons to $assetsInSourcePath "
2016-06-27 18:39:49 +00:00
Copy-Item " $AssetsPath \*.ico " $assetsInSourcePath -Force
2016-08-04 20:30:00 +00:00
2016-05-24 21:23:38 +00:00
$productVersionWithName = $ProductName + " _ " + $ProductVersion
Write-Verbose " Create MSI for Product $productVersionWithName "
[ Environment ] :: SetEnvironmentVariable ( " ProductSourcePath " , $ProductSourcePath , " Process " )
[ Environment ] :: SetEnvironmentVariable ( " ProductName " , $ProductName , " Process " )
[ Environment ] :: SetEnvironmentVariable ( " ProductGuid " , $ProductGuid , " Process " )
[ Environment ] :: SetEnvironmentVariable ( " ProductVersion " , $ProductVersion , " Process " )
[ Environment ] :: SetEnvironmentVariable ( " ProductVersionWithName " , $productVersionWithName , " Process " )
$wixFragmentPath = ( Join-path $env:Temp " Fragment.wxs " )
$wixObjProductPath = ( Join-path $env:Temp " Product.wixobj " )
$wixObjFragmentPath = ( Join-path $env:Temp " Fragment.wixobj " )
2016-09-28 17:47:16 +00:00
$packageName = $productVersionWithName
if ( $ProductNameSuffix ) {
$packageName + = " - $ProductNameSuffix "
}
$msiLocationPath = Join-Path $pwd " $packageName .msi "
2016-05-24 21:41:23 +00:00
Remove-Item -ErrorAction SilentlyContinue $msiLocationPath -Force
2016-05-24 21:23:38 +00:00
2016-05-24 22:02:24 +00:00
& $wixHeatExePath dir $ProductSourcePath -dr $productVersionWithName -cg $productVersionWithName -gg -sfrag -srd -scom -sreg -out $wixFragmentPath -var env . ProductSourcePath -v | Write-Verbose
& $wixCandleExePath " $ProductWxsPath " " $wixFragmentPath " -out ( Join-Path " $env:Temp " " \\ " ) -arch x64 -v | Write-Verbose
2016-09-28 17:47:16 +00:00
& $wixLightExePath -out $msiLocationPath $wixObjProductPath $wixObjFragmentPath -ext WixUIExtension -dWixUILicenseRtf = " $LicenseFilePath " -v | Write-Verbose
2016-08-04 20:30:00 +00:00
2016-05-24 21:41:23 +00:00
Remove-Item -ErrorAction SilentlyContinue * . wixpdb -Force
2016-05-24 21:23:38 +00:00
2016-05-24 21:41:05 +00:00
Write-Verbose " You can find the MSI @ $msiLocationPath "
return $msiLocationPath
2016-05-24 21:23:38 +00:00
}
2016-06-02 17:31:02 +00:00
# Function to create an Appx package compatible with Windows 8.1 and above
function New-AppxPackage
{
[ CmdletBinding ( ) ]
param (
2016-08-03 20:23:21 +00:00
2016-06-02 17:31:02 +00:00
# Name of the Package
[ ValidateNotNullOrEmpty ( ) ]
2016-08-03 20:23:21 +00:00
[ string ] $PackageName = 'PowerShell' ,
2016-06-02 17:31:02 +00:00
2016-09-28 17:47:16 +00:00
# Suffix of the Name
[ string ] $PackageNameSuffix ,
2016-06-02 17:31:02 +00:00
# Version of the Package
[ Parameter ( Mandatory = $true ) ]
[ ValidateNotNullOrEmpty ( ) ]
2016-08-03 20:23:21 +00:00
[ string ] $PackageVersion ,
2016-06-02 17:31:02 +00:00
# Source Path to the Binplaced Files
[ Parameter ( Mandatory = $true ) ]
[ ValidateNotNullOrEmpty ( ) ]
[ string ] $SourcePath ,
# Path to Assets folder containing Appx specific artifacts
[ Parameter ( Mandatory = $true ) ]
[ ValidateNotNullOrEmpty ( ) ]
2016-08-03 20:23:21 +00:00
[ string ] $AssetsPath
2016-06-02 17:31:02 +00:00
)
2016-08-03 20:23:21 +00:00
2016-06-27 23:04:57 +00:00
$PackageVersion = Get-PackageVersionAsMajorMinorBuildRevision -Version $PackageVersion -Verbose
2016-06-02 17:31:02 +00:00
Write-Verbose " Package Version is $PackageVersion "
2016-10-31 22:02:44 +00:00
$win10sdkBinPath = Get-Win10SDKBinDir
2016-06-02 17:31:02 +00:00
Write-Verbose " Ensure Win10 SDK is present on the machine @ $win10sdkBinPath "
2016-10-31 22:02:44 +00:00
if ( -not ( Test-Win10SDK ) ) {
2016-06-02 17:31:02 +00:00
throw " Install Win10 SDK prior to running this script - https://go.microsoft.com/fwlink/p/?LinkID=698771 "
}
Write-Verbose " Ensure Source Path is valid - $SourcePath "
2016-08-03 20:23:21 +00:00
if ( -not ( Test-Path $SourcePath ) ) {
2016-06-02 17:31:02 +00:00
throw " Invalid SourcePath - $SourcePath "
}
Write-Verbose " Ensure Assets Path is valid - $AssetsPath "
2016-08-03 20:23:21 +00:00
if ( -not ( Test-Path $AssetsPath ) ) {
2016-06-02 17:31:02 +00:00
throw " Invalid AssetsPath - $AssetsPath "
}
2016-08-03 20:23:21 +00:00
2016-06-02 17:31:02 +00:00
Write-Verbose " Initialize MakeAppx executable path "
$makeappxExePath = Join-Path $win10sdkBinPath " MakeAppx.exe "
$appxManifest = @"
< Package xmlns = " http://schemas.microsoft.com/appx/manifest/foundation/windows10 " xmlns : uap = " http://schemas.microsoft.com/appx/manifest/uap/windows10 " xmlns : rescap = " http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities " >
2016-06-27 18:39:49 +00:00
< Identity Name = " Microsoft.PowerShell " ProcessorArchitecture = " x64 " Publisher = " CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US " Version = " #VERSION# " / >
2016-06-02 17:31:02 +00:00
< Properties >
2016-06-27 18:39:49 +00:00
< DisplayName > PowerShell < / DisplayName >
2016-06-02 17:31:02 +00:00
< PublisherDisplayName > Microsoft Corporation < / PublisherDisplayName >
< Logo > #LOGO#</Logo>
< / Properties >
< Resources >
< Resource Language = " en-us " / >
< / Resources >
< Dependencies >
< TargetDeviceFamily Name = " Windows.Desktop " MinVersion = " 10.0.14257.0 " MaxVersionTested = " 12.0.0.0 " / >
< TargetDeviceFamily Name = " Windows.Server " MinVersion = " 10.0.14257.0 " MaxVersionTested = " 12.0.0.0 " / >
< / Dependencies >
< Capabilities >
< rescap : Capability Name = " runFullTrust " / >
< / Capabilities >
< Applications >
2016-06-27 18:39:49 +00:00
< Application Id = " PowerShell " Executable = " powershell.exe " EntryPoint = " Windows.FullTrustApplication " >
< uap : VisualElements DisplayName = " PowerShell " Description = " PowerShell for every system " BackgroundColor = " transparent " Square150x150Logo = " #SQUARE150x150LOGO# " Square44x44Logo = " #SQUARE44x44LOGO# " >
2016-06-02 17:31:02 +00:00
< / uap : VisualElements >
< / Application >
< / Applications >
< / Package >
" @
$appxManifest = $appxManifest . Replace ( '#VERSION#' , $PackageVersion )
$appxManifest = $appxManifest . Replace ( '#LOGO#' , 'Assets\Powershell_256.png' )
$appxManifest = $appxManifest . Replace ( '#SQUARE150x150LOGO#' , 'Assets\Powershell_256.png' )
$appxManifest = $appxManifest . Replace ( '#SQUARE44x44LOGO#' , 'Assets\Powershell_48.png' )
Write-Verbose " Place Appx Manifest in $SourcePath "
$appxManifest | Out-File " $SourcePath \AppxManifest.xml " -Force
2016-08-03 20:23:21 +00:00
2016-06-02 17:31:02 +00:00
$assetsInSourcePath = Join-Path $SourcePath 'Assets'
2016-09-28 17:47:16 +00:00
New-Item $assetsInSourcePath -type directory -Force | Out-Null
2016-06-02 17:31:02 +00:00
2016-08-03 20:23:21 +00:00
Write-Verbose " Place AppxManifest dependencies such as images to $assetsInSourcePath "
2016-06-02 17:31:02 +00:00
Copy-Item " $AssetsPath \*.png " $assetsInSourcePath -Force
2016-08-03 20:23:21 +00:00
2016-06-02 18:23:28 +00:00
$appxPackageName = $PackageName + " _ " + $PackageVersion
2016-09-28 17:47:16 +00:00
if ( $PackageNameSuffix ) {
$appxPackageName = $appxPackageName , $PackageNameSuffix -join " - "
}
2016-06-02 18:23:28 +00:00
$appxPackagePath = " $pwd \ $appxPackageName .appx "
2016-06-02 17:31:02 +00:00
Write-Verbose " Calling MakeAppx from $makeappxExePath to create the package @ $appxPackagePath "
& $makeappxExePath pack / o / v / d $SourcePath / p $appxPackagePath | Write-Verbose
2016-08-03 20:23:21 +00:00
Write-Verbose " Clean-up Appx artifacts and Assets from $SourcePath "
2016-06-02 17:31:02 +00:00
Remove-Item $assetsInSourcePath -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item " $SourcePath \AppxManifest.xml " -Force -ErrorAction SilentlyContinue
return $appxPackagePath
}
2016-06-30 23:02:07 +00:00
2016-08-02 20:33:51 +00:00
function Start-CrossGen {
[ CmdletBinding ( ) ]
param (
[ Parameter ( Mandatory = $true ) ]
[ ValidateNotNullOrEmpty ( ) ]
[ String ]
$PublishPath
)
2016-08-03 19:35:58 +00:00
2016-08-02 20:33:51 +00:00
function Generate-CrossGenAssembly {
param (
[ Parameter ( Mandatory = $true ) ]
[ ValidateNotNullOrEmpty ( ) ]
[ String ]
$AssemblyPath ,
[ Parameter ( Mandatory = $true ) ]
[ ValidateNotNullOrEmpty ( ) ]
[ String ]
$CrossgenPath
)
$outputAssembly = $AssemblyPath . Replace ( " .dll " , " .ni.dll " )
$platformAssembliesPath = Split-Path $AssemblyPath -Parent
$crossgenFolder = Split-Path $CrossgenPath
$niAssemblyName = Split-Path $outputAssembly -Leaf
2016-08-03 19:35:58 +00:00
try {
2016-08-02 20:33:51 +00:00
Push-Location $crossgenFolder
# Generate the ngen assembly
2016-08-03 19:35:58 +00:00
Write-Verbose " Generating assembly $niAssemblyName "
2016-08-02 20:33:51 +00:00
Start-NativeExecution {
2016-08-03 07:19:39 +00:00
& $CrossgenPath / MissingDependenciesOK / in $AssemblyPath / out $outputAssembly / Platform_Assemblies_Paths $platformAssembliesPath
} | Write-Verbose
2016-08-03 19:35:58 +00:00
2016-08-02 20:33:51 +00:00
<#
# TODO: Generate the pdb for the ngen binary - currently, there is a hard dependency on diasymreader.dll, which is available at %windir%\Microsoft.NET\Framework\v4.0.30319.
# However, we still need to figure out the prerequisites on Linux.
Start-NativeExecution {
2016-08-03 07:19:39 +00:00
& $CrossgenPath / Platform_Assemblies_Paths $platformAssembliesPath / CreatePDB $platformAssembliesPath / lines $platformAssembliesPath $niAssemblyName
} | Write-Verbose
2016-08-02 20:33:51 +00:00
#>
2016-08-03 19:35:58 +00:00
} finally {
2016-08-02 20:33:51 +00:00
Pop-Location
}
}
2016-08-03 19:35:58 +00:00
if ( -not ( Test-Path $PublishPath ) ) {
2016-08-02 20:33:51 +00:00
throw " Path ' $PublishPath ' does not exist. "
}
2016-08-03 19:35:58 +00:00
# Get the path to crossgen
2016-08-03 19:05:26 +00:00
$crossGenSearchPath = if ( $IsWindows ) {
" $PSScriptRoot \Packages\*crossgen.exe "
2016-08-02 20:33:51 +00:00
} else {
2016-08-03 19:05:26 +00:00
" ~/.nuget/packages/*crossgen "
2016-08-02 20:33:51 +00:00
}
2016-08-03 19:05:26 +00:00
# The crossgen tool is only published for these particular runtimes
$crossGenRuntime = if ( $IsWindows ) {
" win7-x64 "
} elseif ( $IsLinux ) {
if ( $IsUbuntu ) {
" ubuntu.14.04-x64 "
} elseif ( $IsCentOS ) {
" rhel.7-x64 "
}
} elseif ( $IsOSX ) {
" osx.10.10-x64 "
}
if ( -not $crossGenRuntime ) {
throw " crossgen is not available for this platform "
}
2016-10-12 17:24:08 +00:00
# Get the CrossGen.exe for the correct runtime with the latest version
$crossGenPath = Get-ChildItem $crossGenSearchPath -Recurse | `
Where-Object { $_ . FullName -match $crossGenRuntime } | `
Sort-Object -Property FullName -Descending | `
Select-Object -First 1 | `
ForEach-Object { $_ . FullName }
2016-08-03 19:05:26 +00:00
if ( -not $crossGenPath ) {
2016-08-02 20:33:51 +00:00
throw " Unable to find latest version of crossgen.exe. 'Please run Start-PSBuild -Clean' first, and then try again. "
}
# Crossgen.exe requires the following assemblies:
# mscorlib.dll
# System.Private.CoreLib.dll
2016-08-03 19:35:58 +00:00
# clrjit.dll on Windows or libclrjit.so/dylib on Linux/OS X
2016-08-02 20:33:51 +00:00
$crossGenRequiredAssemblies = @ ( " mscorlib.dll " , " System.Private.CoreLib.dll " )
2016-08-03 19:35:58 +00:00
$crossGenRequiredAssemblies + = if ( $IsWindows ) {
" clrjit.dll "
} elseif ( $IsLinux ) {
" libclrjit.so "
} elseif ( $IsOSX ) {
" libclrjit.dylib "
2016-08-02 20:33:51 +00:00
}
2016-08-03 19:35:58 +00:00
# Make sure that all dependencies required by crossgen are at the directory.
2016-08-02 20:33:51 +00:00
$crossGenFolder = Split-Path $crossGenPath
2016-08-03 19:35:58 +00:00
foreach ( $assemblyName in $crossGenRequiredAssemblies ) {
if ( -not ( Test-Path " $crossGenFolder \ $assemblyName " ) ) {
2016-08-02 20:33:51 +00:00
Copy-Item -Path " $PublishPath \ $assemblyName " -Destination $crossGenFolder -Force -ErrorAction Stop
}
}
2016-08-03 19:35:58 +00:00
# Common PowerShell libraries to crossgen
2016-08-03 07:19:39 +00:00
$psCoreAssemblyList = @ (
" Microsoft.PowerShell.Commands.Utility.dll " ,
" Microsoft.PowerShell.Commands.Management.dll " ,
" Microsoft.PowerShell.Security.dll " ,
" Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll " ,
" Microsoft.PowerShell.CoreCLR.Eventing.dll " ,
" Microsoft.PowerShell.ConsoleHost.dll " ,
" Microsoft.PowerShell.PackageManagement.dll " ,
" Microsoft.PowerShell.PSReadLine.dll " ,
" System.Management.Automation.dll "
)
2016-08-02 20:33:51 +00:00
2016-08-03 19:35:58 +00:00
# Add Windows specific libraries
if ( $IsWindows ) {
2016-08-03 07:19:39 +00:00
$psCoreAssemblyList + = @ (
" Microsoft.WSMan.Management.dll " ,
" Microsoft.WSMan.Runtime.dll " ,
" Microsoft.PowerShell.LocalAccounts.dll " ,
" Microsoft.PowerShell.Commands.Diagnostics.dll " ,
" Microsoft.Management.Infrastructure.CimCmdlets.dll "
)
}
2016-08-03 19:35:58 +00:00
foreach ( $assemblyName in $psCoreAssemblyList ) {
2016-08-02 20:33:51 +00:00
$assemblyPath = Join-Path $PublishPath $assemblyName
2016-08-03 07:19:39 +00:00
Generate-CrossGenAssembly -CrossgenPath $crossGenPath -AssemblyPath $assemblyPath
}
2016-08-02 20:33:51 +00:00
2016-10-18 20:12:51 +00:00
#
# With the latest dotnet.exe, the default load context is only able to load TPAs, and TPA
# only contains IL assembly names. In order to make the default load context able to load
# the NI PS assemblies, we need to replace the IL PS assemblies with the corresponding NI
# PS assemblies, but with the same IL assembly names.
#
Write-Verbose " PowerShell Ngen assemblies have been generated. Deploying ... " -Verbose
2016-08-03 19:35:58 +00:00
foreach ( $assemblyName in $psCoreAssemblyList ) {
2016-08-03 07:19:39 +00:00
# Remove the IL assembly and its symbols.
2016-08-04 00:35:05 +00:00
$assemblyPath = Join-Path $PublishPath $assemblyName
2016-10-18 20:12:51 +00:00
$symbolsPath = [ System.IO.Path ] :: ChangeExtension ( $assemblyPath , " .pdb " )
Remove-Item $assemblyPath -Force -ErrorAction Stop
Remove-Item $symbolsPath -Force -ErrorAction Stop
# Rename the corresponding ni.dll assembly to be the same as the IL assembly
$niAssemblyPath = [ System.IO.Path ] :: ChangeExtension ( $assemblyPath , " ni.dll " )
Rename-Item $niAssemblyPath $assemblyPath -Force -ErrorAction Stop
2016-08-02 20:33:51 +00:00
}
}
2016-06-30 23:02:07 +00:00
2016-08-31 19:13:05 +00:00
# Cleans the PowerShell repo
# by default everything but the root folder and the Packages folder
# if you specify -IncludePackages it will clean the Packages folder
function Clear-PSRepo
{
[ CmdletBinding ( ) ]
param (
[ switch ] $IncludePackages
)
Get-ChildItem $PSScriptRoot \ * -Directory -Exclude 'Packages' | ForEach-Object {
Write-Verbose " Cleaning $_ ... "
git clean -fdX $_
}
if ( $IncludePackages )
{
remove-item $RepoRoot \ Packages \ -Recurse -Force -ErrorAction SilentlyContinue
}
}
2016-06-30 23:02:07 +00:00
$script:RESX_TEMPLATE = @ '
< ? xml version = " 1.0 " encoding = " utf-8 " ? >
< root >
2016-08-03 20:23:21 +00:00
< ! - -
Microsoft ResX Schema
2016-06-30 23:02:07 +00:00
Version 2.0
2016-08-03 20:23:21 +00:00
The primary goals of this format is to allow a simple XML format
that is mostly human readable . The generation and parsing of the
various data types are done through the TypeConverter classes
2016-06-30 23:02:07 +00:00
associated with the data types .
2016-08-03 20:23:21 +00:00
2016-06-30 23:02:07 +00:00
Example :
2016-08-03 20:23:21 +00:00
2016-06-30 23:02:07 +00:00
. . . ado . net / XML headers & schema . . .
< resheader name = " resmimetype " > text / microsoft-resx < / resheader >
< resheader name = " version " > 2.0 < / resheader >
< resheader name = " reader " > System . Resources . ResXResourceReader , System . Windows . Forms , . . . < / resheader >
< resheader name = " writer " > System . Resources . ResXResourceWriter , System . Windows . Forms , . . . < / resheader >
< data name = " Name1 " > < value > this is my long string < / value > < comment > this is a comment < / comment > < / data >
< data name = " Color1 " type = " System.Drawing.Color, System.Drawing " > Blue < / data >
< data name = " Bitmap1 " mimetype = " application/x-microsoft.net.object.binary.base64 " >
< value > [ base64 mime encoded serialized .NET Framework object ] < / value >
< / data >
< data name = " Icon1 " type = " System.Drawing.Icon, System.Drawing " mimetype = " application/x-microsoft.net.object.bytearray.base64 " >
< value > [ base64 mime encoded string representing a byte array form of the .NET Framework object ] < / value >
< comment > This is a comment < / comment >
< / data >
2016-08-03 20:23:21 +00:00
There are any number of " resheader " rows that contain simple
2016-06-30 23:02:07 +00:00
name / value pairs .
2016-08-03 20:23:21 +00:00
Each data row contains a name , and value . The row also contains a
type or mimetype . Type corresponds to a . NET class that support
text / value conversion through the TypeConverter architecture .
Classes that don ' t support this are serialized and stored with the
2016-06-30 23:02:07 +00:00
mimetype set .
2016-08-03 20:23:21 +00:00
The mimetype is used for serialized objects , and tells the
ResXResourceReader how to depersist the object . This is currently not
2016-06-30 23:02:07 +00:00
extensible . For a given mimetype the value must be set accordingly :
2016-08-03 20:23:21 +00:00
Note - application / x-microsoft . net . object . binary . base64 is the format
that the ResXResourceWriter will generate , however the reader can
2016-06-30 23:02:07 +00:00
read any of the formats listed below .
2016-08-03 20:23:21 +00:00
2016-06-30 23:02:07 +00:00
mimetype : application / x-microsoft . net . object . binary . base64
2016-08-03 20:23:21 +00:00
value : The object must be serialized with
2016-06-30 23:02:07 +00:00
: System . Runtime . Serialization . Formatters . Binary . BinaryFormatter
: and then encoded with base64 encoding .
2016-08-03 20:23:21 +00:00
2016-06-30 23:02:07 +00:00
mimetype : application / x-microsoft . net . object . soap . base64
2016-08-03 20:23:21 +00:00
value : The object must be serialized with
2016-06-30 23:02:07 +00:00
: System . Runtime . Serialization . Formatters . Soap . SoapFormatter
: and then encoded with base64 encoding .
mimetype : application / x-microsoft . net . object . bytearray . base64
2016-08-03 20:23:21 +00:00
value : The object must be serialized into a byte array
2016-06-30 23:02:07 +00:00
: using a System . ComponentModel . TypeConverter
: and then encoded with base64 encoding .
- - >
< xsd : schema id = " root " xmlns = " " xmlns : xsd = " http://www.w3.org/2001/XMLSchema " xmlns : msdata = " urn:schemas-microsoft-com:xml-msdata " >
< xsd : import namespace = " http://www.w3.org/XML/1998/namespace " / >
< xsd : element name = " root " msdata : IsDataSet = " true " >
< xsd : complexType >
< xsd : choice maxOccurs = " unbounded " >
< xsd : element name = " metadata " >
< xsd : complexType >
< xsd : sequence >
< xsd : element name = " value " type = " xsd:string " minOccurs = " 0 " / >
< / xsd : sequence >
< xsd : attribute name = " name " use = " required " type = " xsd:string " / >
< xsd : attribute name = " type " type = " xsd:string " / >
< xsd : attribute name = " mimetype " type = " xsd:string " / >
< xsd : attribute ref = " xml:space " / >
< / xsd : complexType >
< / xsd : element >
< xsd : element name = " assembly " >
< xsd : complexType >
< xsd : attribute name = " alias " type = " xsd:string " / >
< xsd : attribute name = " name " type = " xsd:string " / >
< / xsd : complexType >
< / xsd : element >
< xsd : element name = " data " >
< xsd : complexType >
< xsd : sequence >
< xsd : element name = " value " type = " xsd:string " minOccurs = " 0 " msdata : Ordinal = " 1 " / >
< xsd : element name = " comment " type = " xsd:string " minOccurs = " 0 " msdata : Ordinal = " 2 " / >
< / xsd : sequence >
< xsd : attribute name = " name " type = " xsd:string " use = " required " msdata : Ordinal = " 1 " / >
< xsd : attribute name = " type " type = " xsd:string " msdata : Ordinal = " 3 " / >
< xsd : attribute name = " mimetype " type = " xsd:string " msdata : Ordinal = " 4 " / >
< xsd : attribute ref = " xml:space " / >
< / xsd : complexType >
< / xsd : element >
< xsd : element name = " resheader " >
< xsd : complexType >
< xsd : sequence >
< xsd : element name = " value " type = " xsd:string " minOccurs = " 0 " msdata : Ordinal = " 1 " / >
< / xsd : sequence >
< xsd : attribute name = " name " type = " xsd:string " use = " required " / >
< / xsd : complexType >
< / xsd : element >
< / xsd : choice >
< / xsd : complexType >
< / xsd : element >
< / xsd : schema >
< resheader name = " resmimetype " >
< value > text / microsoft-resx < / value >
< / resheader >
< resheader name = " version " >
< value > 2.0 < / value >
< / resheader >
< resheader name = " reader " >
< value > System . Resources . ResXResourceReader , System . Windows . Forms , Version = 2.0 . 0 . 0 , Culture = neutral , PublicKeyToken = b77a5c561934e089 < / value >
< / resheader >
< resheader name = " writer " >
< value > System . Resources . ResXResourceWriter , System . Windows . Forms , Version = 2.0 . 0 . 0 , Culture = neutral , PublicKeyToken = b77a5c561934e089 < / value >
< / resheader >
{ 0 }
< / root >
2016-07-05 17:36:38 +00:00
' @