2016-02-23 16:21:00 -08: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-21 17:23:43 -08:00
try {
$Runtime = [ System.Runtime.InteropServices.RuntimeInformation ]
$OSPlatform = [ System.Runtime.InteropServices.OSPlatform ]
2016-03-04 12:11:01 -08:00
2016-07-21 16:52:22 -07:00
$IsCoreCLR = $true
2016-03-04 12:11:01 -08:00
$IsLinux = $Runtime :: IsOSPlatform ( $OSPlatform :: Linux )
$IsOSX = $Runtime :: IsOSPlatform ( $OSPlatform :: OSX )
$IsWindows = $Runtime :: IsOSPlatform ( $OSPlatform :: Windows )
2016-04-08 15:13:50 -07:00
} catch {
# If these are already set, then they're read-only and we're done
try {
2016-07-21 16:52:22 -07:00
$IsCoreCLR = $false
2016-04-08 15:13:50 -07:00
$IsLinux = $false
$IsOSX = $false
$IsWindows = $true
}
catch { }
2016-02-21 17:23:43 -08:00
}
2016-02-21 16:21:04 -08:00
2016-06-20 11:39:39 -07:00
if ( $IsLinux ) {
$LinuxInfo = Get-Content / etc / os-release | ConvertFrom-StringData
2016-06-30 13:41:43 -07:00
$IsUbuntu = $LinuxInfo . ID -match 'ubuntu' -and $LinuxInfo . VERSION_ID -match '14.04'
$IsCentOS = $LinuxInfo . ID -match 'centos' -and $LinuxInfo . VERSION_ID -match '7'
2016-06-20 11:39:39 -07:00
}
2016-04-01 22:01:05 -07:00
2016-04-01 14:41:13 -07:00
function Start-PSBuild {
2016-03-11 16:19:05 -08:00
[ CmdletBinding ( DefaultParameterSetName = 'CoreCLR' )]
2016-02-21 15:06:39 -08:00
param (
2016-07-19 19:09:06 -07: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 16:41:50 -07:00
[ switch ] $NoPath ,
2016-02-23 16:21:00 -08:00
[ switch ] $Restore ,
2016-05-06 10:28:45 -07:00
[ string ] $Output ,
2016-06-15 03:42:54 -07:00
[ switch ] $ResGen ,
2016-06-17 11:23:29 -07:00
[ switch ] $TypeGen ,
2016-06-22 19:46:16 -07:00
[ switch ] $Clean ,
2016-03-11 16:19:05 -08:00
2016-07-19 12:51:11 -07:00
# this switch will re-build only System.Mangement.Automation.dll
# it's useful for development, to do a quick changes in the engine
[ switch ] $SMAOnly ,
2016-04-08 16:05:39 -07:00
[ Parameter ( ParameterSetName = 'CoreCLR' )]
[ switch ] $Publish ,
2016-03-03 15:54:52 -08: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-06-02 20:13:30 -07:00
"debian.8-x64" ,
2016-06-16 18:39:29 -07:00
"centos.7-x64" ,
2016-03-03 15:54:52 -08:00
"win7-x64" ,
2016-04-01 17:01:18 -07:00
"win81-x64" ,
2016-03-03 15:54:52 -08:00
"win10-x64" ,
"osx.10.11-x64" )]
2016-03-11 16:19:05 -08:00
[ Parameter ( ParameterSetName = 'CoreCLR' )]
[ string ] $Runtime ,
2016-06-22 19:46:16 -07:00
[ Parameter ( ParameterSetName = 'FullCLR' , Mandatory = $true )]
2016-03-11 16:19:05 -08:00
[ switch ] $FullCLR ,
2016-06-21 14:30:26 -07:00
[ Parameter ( ParameterSetName = 'FullCLR' )]
2016-06-22 19:46:16 -07:00
[ switch ] $XamlGen ,
2016-06-21 14:30:26 -07:00
2016-03-11 16:19:05 -08:00
[ Parameter ( ParameterSetName = 'FullCLR' )]
2016-07-15 16:52:00 -07:00
[ ValidateSet ( 'x86' , 'x64' )] # TODO: At some point, we need to add ARM support to match CoreCLR
2016-07-01 12:09:50 -07:00
[ string ] $NativeHostArch = "x64" ,
2016-03-11 16:19:05 -08:00
2016-07-07 11:34:10 -07:00
[ ValidateSet ( 'Linux' , 'Debug' , 'Release' , '' )] # We might need "Checked" as well
2016-07-01 12:09:50 -07:00
[ string ] $Configuration
2016-02-23 16:21:00 -08:00
)
2016-02-21 15:06:39 -08:00
2016-07-19 19:09:06 -07:00
function Stop-DevPowerShell
{
Get-Process powershell * |
Where-Object {
$_ . Modules |
Where-Object {
$_ . FileName -eq ( Resolve-Path $script:Options . Output ). Path
}
} |
Stop-Process -Verbose
}
2016-06-22 19:46:16 -07:00
if ( $Clean )
{
log "Cleaning your working directory. You can also do it with 'git clean -fdX'"
2016-07-25 19:53:21 -07:00
Push-Location $PSScriptRoot
try
{
git clean -fdX
}
finally
{
Pop-Location
}
2016-06-22 19:46:16 -07:00
}
2016-06-01 11:13:49 -07: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 15:35:09 -07:00
2016-04-01 12:14:09 -07:00
# simplify ParameterSetNames
2016-04-01 14:41:13 -07:00
if ( $PSCmdlet . ParameterSetName -eq 'FullCLR' ) {
2016-03-11 16:19:05 -08:00
$FullCLR = $true
}
2016-06-20 11:59:14 -07:00
# Add .NET CLI tools to PATH
Find-Dotnet
2016-04-13 16:41:50 -07:00
2016-05-04 13:33:59 -07: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 09:39:59 -07:00
2016-03-11 16:19:05 -08:00
# verify we have all tools in place to do the build
2016-06-20 11:39:39 -07:00
$precheck = precheck 'dotnet' "Build dependency 'dotnet' not found in PATH. Run Start-PSBootstrap. Also see: https://dotnet.github.io/getting-started/"
2016-04-01 14:41:13 -07:00
if ( $FullCLR ) {
2016-03-11 16:19:05 -08:00
# cmake is needed to build powershell.exe
2016-07-21 15:47:28 -07:00
$precheck = $precheck -and ( precheck 'cmake' 'cmake not found. Run Start-PSBootstrap. You can also install it from https://chocolatey.org/packages/cmake.portable' )
2016-04-01 14:41:13 -07:00
2016-06-22 19:46:16 -07:00
Use-MSBuild
2016-07-05 13:03:25 -07:00
2016-06-16 16:43:51 -07:00
#mc.exe is Message Compiler for native resources
2016-07-21 11:07:45 -07:00
$mcexe = Get-ChildItem "${env:ProgramFiles(x86)}\Windows Kits\10\" -Recurse -Filter 'mc.exe' | ? { $_ . FullName -match 'x64' } | select -First 1 | % { $_ . FullName }
2016-06-16 16:43:51 -07:00
if ( -not $mcexe ) {
2016-07-21 15:47:28 -07:00
throw 'mc.exe 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 16:43:51 -07:00
}
2016-07-15 16:52:00 -07:00
$vcVarsPath = ( Get-Item ( Join-Path -Path " $env:VS140COMNTOOLS " -ChildPath '../../vc' )). FullName
if (( Test-Path -Path $vcVarsPath \ vcvarsall . bat ) -eq $false )
{
throw "Could not find Visual Studio vcvarsall.bat at" + $vcVarsPath
}
2016-07-01 12:09:50 -07:00
# setup msbuild configuration
if ( $Configuration -eq 'Debug' -or $Configuration -eq 'Release' )
{
$msbuildConfiguration = $Configuration
}
else
{
$msbuildConfiguration = 'Release'
}
# setup cmakeGenerator
if ( $NativeHostArch -eq 'x86' )
{
$cmakeGenerator = 'Visual Studio 14 2015'
}
else
{
$cmakeGenerator = 'Visual Studio 14 2015 Win64'
}
2016-04-09 17:59:13 -07:00
} elseif ( $IsLinux -or $IsOSX ) {
2016-04-01 14:42:40 -07:00
foreach ( $Dependency in 'cmake' , 'make' , 'g++' ) {
2016-06-20 11:39:39 -07:00
$precheck = $precheck -and ( precheck $Dependency "Build dependency ' $Dependency ' not found. Run Start-PSBootstrap." )
2016-04-01 14:42:40 -07:00
}
}
2016-04-01 14:43:18 -07:00
2016-04-01 14:41:13 -07:00
# Abort if any precheck failed
if ( -not $precheck ) {
return
}
2016-03-11 16:19:05 -08:00
2016-04-14 15:06:14 -07:00
# set output options
2016-07-19 12:51:11 -07:00
$OptionsArguments = @ {
Publish = $Publish
Output = $Output
FullCLR = $FullCLR
Runtime = $Runtime
Configuration = $Configuration
Verbose = $true
SMAOnly =[ bool ] $SMAOnly
}
2016-04-14 15:06:14 -07:00
$script:Options = New-PSOptions @OptionsArguments
2016-04-01 17:51:38 -07:00
2016-07-19 19:09:06 -07:00
if ( $StopDevPowerShell )
{
Stop-DevPowerShell
}
2016-04-14 15:06:14 -07:00
# setup arguments
2016-04-01 17:51:38 -07:00
$Arguments = @ ()
2016-07-26 16:43:32 -07:00
if ( $Publish -or $FullCLR ) {
2016-04-08 16:05:39 -07:00
$Arguments += "publish"
} else {
$Arguments += "build"
}
2016-05-06 10:28:45 -07:00
if ( $Output ) {
$Arguments += "--output" , ( Join-Path $PSScriptRoot $Output )
}
2016-07-19 12:51:11 -07:00
elseif ( $SMAOnly ) {
$Arguments += "--output" , ( Split-Path $script:Options . Output )
}
2016-04-14 15:06:14 -07:00
$Arguments += "--configuration" , $Options . Configuration
$Arguments += "--framework" , $Options . Framework
$Arguments += "--runtime" , $Options . Runtime
2016-04-01 17:51:38 -07:00
2016-03-11 18:24:43 -08:00
# handle Restore
2016-07-15 16:52:00 -07:00
if ( $Restore -or -not ( Test-Path " $( $Options . Top ) /project.lock.json" )) {
log "Run dotnet restore"
2016-03-25 14:58:09 -07:00
2016-07-15 16:52:00 -07:00
$RestoreArguments = @ ( "--verbosity" )
if ( $PSCmdlet . MyInvocation . BoundParameters [ "Verbose" ]. IsPresent ) {
$RestoreArguments += "Info"
} else {
$RestoreArguments += "Warning"
}
$RestoreArguments += " $PSScriptRoot "
Start-NativeExecution { dotnet restore $RestoreArguments }
}
2016-02-21 15:06:39 -08:00
2016-06-15 03:42:54 -07:00
# handle ResGen
2016-06-17 07:51:32 -07:00
# Heuristic to run ResGen on the fresh machine
2016-07-15 16:52:00 -07:00
if ( $ResGen -or -not ( Test-Path " $PSScriptRoot /src/Microsoft.PowerShell.ConsoleHost/gen" ))
{
log "Run ResGen (generating C# bindings for resx files)"
Start-ResGen
}
2016-06-15 03:42:54 -07:00
2016-06-21 14:30:26 -07:00
# handle xaml files
# Heuristic to resolve xaml on the fresh machine
2016-07-15 16:52:00 -07:00
if ( $FullCLR -and ( $XamlGen -or -not ( Test-Path " $PSScriptRoot /src/Microsoft.PowerShell.Activities/gen/*.g.cs" )))
{
log "Run XamlGen (generating .g.cs and .resources for .xaml files)"
Start-XamlGen -MSBuildConfiguration $msbuildConfiguration
}
2016-06-21 14:30:26 -07:00
2016-03-11 16:19:05 -08:00
# Build native components
2016-07-27 09:02:36 -07:00
if (( $IsLinux -or $IsOSX ) -and -not $SMAOnly ) {
2016-04-01 14:42:40 -07:00
$Ext = if ( $IsLinux ) {
"so"
} elseif ( $IsOSX ) {
"dylib"
2016-03-11 16:19:05 -08:00
}
2016-04-01 14:42:40 -07:00
$Native = " $PSScriptRoot /src/libpsl-native"
2016-04-14 15:06:14 -07:00
$Lib = " $( $Options . Top ) /libpsl-native. $Ext "
2016-04-01 14:42:40 -07:00
log "Start building $Lib "
try {
Push-Location $Native
2016-07-13 00:08:06 -07:00
Start-NativeExecution { cmake -DCMAKE_BUILD_TYPE = Debug . }
Start-NativeExecution { make -j }
Start-NativeExecution { ctest - -verbose }
2016-04-01 14:42:40 -07:00
} finally {
Pop-Location
}
2016-04-09 17:59:13 -07:00
if ( -not ( Test-Path $Lib )) {
2016-04-01 14:42:40 -07:00
throw "Compilation of $Lib failed"
}
2016-07-19 12:51:11 -07:00
} elseif ( $FullCLR -and ( -not $SMAOnly )) {
2016-03-11 18:24:43 -08:00
log "Start building native powershell.exe"
2016-02-21 15:06:39 -08:00
2016-04-01 14:41:13 -07:00
try {
2016-04-14 15:06:14 -07:00
Push-Location " $PSScriptRoot \src\powershell-native"
2016-02-24 11:50:56 -08:00
2016-06-16 16:43:51 -07:00
# Compile native resources
@ ( "nativemsh/pwrshplugin" ) | % {
$nativeResourcesFolder = $_
Get-ChildItem $nativeResourcesFolder -Filter "*.mc" | % {
2016-07-22 14:19:21 -07:00
$command = @"
cmd.exe /C cd /d "(Get-Location)" "&" " $( $vcVarsPath ) \vcvarsall.bat" " $NativeHostArch " "&" " $mcexe " -o -d -c -U $( $_ . FullName ) -h " $nativeResourcesFolder " -r " $nativeResourcesFolder "
"@
log " Executing mc.exe Command: $command "
Start-NativeExecution { Invoke-Expression -Command: $command }
2016-06-16 16:43:51 -07:00
}
}
2016-07-13 15:17:16 -07:00
# Disabling until I figure out if it is necessary
# $overrideFlags = "-DCMAKE_USER_MAKE_RULES_OVERRIDE=$PSScriptRoot\src\powershell-native\windows-compiler-override.txt"
$overrideFlags = ""
2016-07-07 11:34:10 -07:00
$location = Get-Location
#
2016-07-15 16:52:00 -07:00
# BUILD_ONECORE
2016-07-07 11:34:10 -07:00
#
2016-07-15 16:52:00 -07:00
$BuildOneCoreValues = @ ( "ON" , "OFF" )
foreach ( $oneCoreValue in $BuildOneCoreValues )
{
$command = @"
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 11:34:10 -07:00
"@
2016-07-19 16:38:40 -07:00
log " Executing Build Command: $command "
2016-07-15 16:52:00 -07:00
Start-NativeExecution { Invoke-Expression -Command: $command }
}
2016-07-18 15:04:45 -07:00
# Copy the executable binary from the local build directory to the expected destination to enable Start-DevPowerShell to work
#
# TODO: This should be updated to handle per-architecture builds gracefully.
2016-07-22 13:39:45 -07:00
2016-07-18 15:04:45 -07:00
$dstPath = ( $script:Options ). Top
2016-07-22 13:39:45 -07:00
@ (
'powershell.exe' ,
'powershell.pdb' ,
'pwrshplugin.dll' ,
'pwrshplugin.pdb'
) | % {
$srcPath = Join-Path ( Join-Path ( Join-Path ( Get-Location ) "bin" ) $msbuildConfiguration ) "FullCLR/ $_ "
log " Copying $srcPath to $dstPath "
Copy-Item $srcPath $dstPath
}
2016-04-01 14:41:13 -07:00
} finally {
Pop-Location
2016-02-24 11:50:56 -08:00
}
2016-02-21 15:06:39 -08:00
}
2016-06-17 11:23:29 -07:00
# handle TypeGen
if ( $TypeGen -or -not ( Test-Path " $PSScriptRoot /src/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext/CorePsTypeCatalog.cs" ))
{
log "Run TypeGen (generating CorePsTypeCatalog.cs)"
Start-TypeGen
}
2016-04-01 14:41:13 -07:00
try {
2016-04-01 12:14:09 -07:00
# Relative paths do not work well if cwd is not changed to project
2016-04-14 15:06:14 -07:00
Push-Location $Options . Top
2016-04-19 16:39:06 -07:00
log "Run dotnet $Arguments from $pwd "
2016-04-19 16:59:03 -07:00
Start-NativeExecution { dotnet $Arguments }
2016-04-14 15:06:14 -07:00
log "PowerShell output: $( $Options . Output ) "
2016-04-01 14:41:13 -07:00
} finally {
2016-04-01 12:14:09 -07:00
Pop-Location
2016-03-11 16:19:05 -08:00
}
2016-04-01 17:51:38 -07:00
}
2016-04-14 15:06:14 -07:00
function New-PSOptions {
[ CmdletBinding ()]
param (
2016-07-01 12:09:50 -07:00
[ ValidateSet ( "Linux" , "Debug" , "Release" , "" )]
2016-04-14 15:06:14 -07:00
[ string ] $Configuration ,
2016-04-18 20:22:20 -07:00
[ ValidateSet ( "netcoreapp1.0" , "net451" )]
2016-04-14 15:06:14 -07: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-06-02 20:13:30 -07:00
"debian.8-x64" ,
2016-06-16 18:39:29 -07:00
"centos.7-x64" ,
2016-04-14 15:06:14 -07:00
"win7-x64" ,
"win81-x64" ,
"win10-x64" ,
"osx.10.11-x64" )]
[ string ] $Runtime ,
[ switch ] $Publish ,
2016-05-06 10:28:45 -07:00
[ string ] $Output ,
2016-04-14 15:06:14 -07:00
2016-07-19 12:51:11 -07:00
[ switch ] $FullCLR ,
[ switch ] $SMAOnly
2016-04-14 15:06:14 -07:00
)
2016-06-20 11:59:14 -07:00
# Add .NET CLI tools to PATH
Find-Dotnet
2016-04-14 15:06:14 -07:00
if ( -not $Configuration ) {
$Configuration = if ( $IsLinux -or $IsOSX ) {
"Linux"
} elseif ( $IsWindows ) {
"Debug"
}
2016-07-01 12:09:50 -07:00
Write-Verbose "Using configuration ' $Configuration '"
2016-04-01 22:01:37 -07:00
}
2016-07-21 18:47:46 -07:00
if ( $FullCLR ) {
2016-07-26 16:43:32 -07:00
$Top = " $PSScriptRoot /src/powershell-win-full"
2016-07-21 18:47:46 -07:00
} else {
if ( $Configuration -eq 'Linux' )
{
$Top = " $PSScriptRoot /src/powershell-unix"
}
else
{
2016-07-26 16:47:57 -07:00
$Top = " $PSScriptRoot /src/powershell-win-core"
2016-07-21 18:47:46 -07:00
}
}
Write-Verbose "Top project directory is $Top "
2016-04-14 15:06:14 -07:00
if ( -not $Framework ) {
$Framework = if ( $FullCLR ) {
"net451"
} else {
2016-04-18 20:22:20 -07:00
"netcoreapp1.0"
2016-04-14 15:06:14 -07:00
}
2016-07-01 12:09:50 -07:00
Write-Verbose "Using framework ' $Framework '"
2016-04-14 15:06:14 -07: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 12:09:50 -07:00
Write-Verbose "Using runtime ' $Runtime '"
2016-04-14 15:06:14 -07:00
}
}
$Executable = if ( $IsLinux -or $IsOSX ) {
"powershell"
} elseif ( $IsWindows ) {
"powershell.exe"
}
2016-05-06 10:28:45 -07:00
# Build the Output path
if ( $Output ) {
$Output = Join-Path $PSScriptRoot $Output
} else {
2016-07-26 16:43:32 -07:00
$Output = [ IO.Path ]:: Combine ( $Top , "bin" , $Configuration , $Framework , $Runtime )
2016-05-06 10:28:45 -07:00
# Publish injects the publish directory
2016-07-26 16:43:32 -07:00
if ( $Publish -or $FullCLR ) {
2016-05-06 10:28:45 -07:00
$Output = [ IO.Path ]:: Combine ( $Output , "publish" )
}
$Output = [ IO.Path ]:: Combine ( $Output , $Executable )
2016-04-14 15:06:14 -07:00
}
2016-07-19 12:51:11 -07:00
$RealFramework = $Framework
if ( $SMAOnly )
{
$Top = " $PSScriptRoot /src/System.Management.Automation"
if ( $Framework -match 'netcoreapp' )
{
$RealFramework = 'netstandard1.6'
}
}
2016-04-14 15:06:14 -07:00
return @ { Top = $Top ;
Configuration = $Configuration ;
2016-07-19 12:51:11 -07:00
Framework = $RealFramework ;
2016-04-14 15:06:14 -07:00
Runtime = $Runtime ;
Output = $Output }
}
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 15:06:39 -08:00
}
2016-04-01 22:01:05 -07:00
2016-07-26 17:41:03 -07: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
$foundTag = $false
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
$values | %{
if ( $_ -notmatch "CI|FEATURE|SCENARIO|SLOW" ) {
$warnings += " ${fullname} includes improper tag ' $_ ', line ' $lineno '"
}
$alltags [ $_ ]++
}
$foundTag = $true
}
}
if ( ! $foundTag ) {
$warnings += " ${fullname} does not include -Tag in Describe, line ' $lineno '"
}
}
}
if ( $Warnings . Count -gt 0 ) {
$alltags [ 'Result' ] = "Fail"
}
else {
$alltags [ 'Result' ] = "Pass"
}
$alltags [ 'Warnings' ] = $warnings
$o = [ pscustomobject ] $alltags
$o . psobject . TypeNames . Add ( "DescribeTagsInUse" )
$o
}
2016-04-01 22:01:45 -07:00
function Start-PSPester {
[ CmdletBinding ()] param (
2016-07-25 17:43:28 -07:00
[ string ] $OutputFormat = "NUnitXml" ,
[ string ] $OutputFile = "pester-tests.xml" ,
[ switch ] $DisableExit ,
[ string[] ] $ExcludeTag = "Slow" ,
[ string[] ] $Tag = "CI" ,
2016-07-22 17:46:12 -07:00
[ string ] $Path = " $PSScriptRoot /test/powershell"
2016-04-01 22:01:45 -07:00
)
2016-07-25 17:43:28 -07:00
$tagString = "-outputFormat ${OutputFormat} -outputFile ${outputFile} "
if ( ! $DisableExit ) { $tagString += " -EnableExit" }
2016-07-26 14:37:15 -07:00
if ( $ExcludeTag -and ( $ExcludeTag -ne "" )) { $tagString += " -ExcludeTag @('" + (${ ExcludeTag } -join "','" ) + "')" }
2016-07-25 17:43:28 -07:00
if ( $Tag ) { $tagString += " -Tag @('" + (${ Tag } -join "','" ) + "')" }
2016-04-01 22:01:45 -07:00
2016-07-25 17:43:28 -07:00
$powershell = get-psoutput
$psdir = [ io.path ]:: GetDirectoryName ( $powershell )
$moduleDir = [ io.path ]:: Combine ( $psdir , "Modules" , "Pester" )
Write-Verbose "Import-Module ' $moduleDir '; Invoke-Pester $tagString $Path "
2016-07-26 14:37:15 -07:00
$powershellexe = get-psoutput
& $powershell -noprofile -c "Import-Module ' $moduleDir '; Invoke-Pester $tagString $Path "
2016-04-01 22:01:45 -07:00
if ( $LASTEXITCODE -ne 0 ) {
throw " $LASTEXITCODE Pester tests failed"
}
}
2016-04-01 20:45:32 -07:00
function Start-PSxUnit {
2016-04-01 22:01:05 -07:00
[ CmdletBinding ()] param ()
2016-06-20 11:59:14 -07:00
2016-06-28 19:56:47 -07:00
log "xUnit tests are currently disabled pending fixes due to API and AssemblyLoadContext changes - @andschwa"
return
2016-04-01 20:45:32 -07:00
if ( $IsWindows ) {
throw "xUnit tests are only currently supported on Linux / OS X"
}
2016-04-01 22:01:37 -07:00
2016-04-14 15:09:35 -07:00
if ( $IsOSX ) {
log "Not yet supported on OS X, pretending they passed..."
return
}
2016-06-20 11:59:14 -07:00
# Add .NET CLI tools to PATH
Find-Dotnet
2016-06-01 11:10:29 -07:00
$Arguments = "--configuration" , "Linux" , "-parallel" , "none"
2016-05-31 16:06:19 -07:00
if ( $PSCmdlet . MyInvocation . BoundParameters [ "Verbose" ]. IsPresent ) {
2016-06-01 11:10:29 -07:00
$Arguments += "-verbose"
2016-05-31 16:06:19 -07:00
}
2016-04-01 22:01:37 -07:00
$Content = Split-Path -Parent ( Get-PSOutput )
2016-06-01 11:10:29 -07:00
if ( -not ( Test-Path $Content )) {
throw "PowerShell must be built before running tests!"
}
2016-04-01 20:45:32 -07:00
try {
Push-Location $PSScriptRoot / test / csharp
2016-04-25 14:11:13 -07: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 11:10:29 -07:00
Write-Verbose "Output is $Output "
2016-04-18 20:22:20 -07:00
2016-04-25 14:11:13 -07:00
Copy-Item -ErrorAction SilentlyContinue -Recurse -Path $Content /* -Include Modules , libpsl-native * -Destination $Output
2016-06-01 11:10:29 -07:00
Start-NativeExecution { dotnet test $Arguments }
2016-04-18 20:22:20 -07:00
2016-04-01 20:45:32 -07:00
if ( $LASTEXITCODE -ne 0 ) {
throw " $LASTEXITCODE xUnit tests failed"
}
} finally {
Pop-Location
}
}
2016-04-13 15:11:38 -07:00
function Start-PSBootstrap {
2016-07-22 14:31:32 -07:00
[ CmdletBinding (
SupportsShouldProcess = $true ,
ConfirmImpact = "High" )]
param (
2016-06-14 13:33:19 -07:00
[ ValidateSet ( "dev" , "beta" , "preview" )]
2016-06-23 13:23:03 -07:00
[ string ] $Channel = "rel-1.0.0" ,
2016-07-05 11:03:08 -07:00
[ string ] $Version = "latest" ,
2016-07-22 14:31:32 -07:00
[ switch ] $Package ,
[ switch ] $Force
2016-06-14 13:33:19 -07:00
)
2016-04-13 15:11:38 -07:00
2016-06-22 19:46:16 -07:00
log "Installing Open PowerShell build dependencies"
2016-04-13 15:11:38 -07:00
2016-06-10 14:02:25 -07:00
Push-Location $PSScriptRoot / tools
2016-04-13 15:11:38 -07:00
2016-06-10 14:02:25 -07:00
try {
2016-06-30 13:41:43 -07:00
# Install ours and .NET's dependencies
2016-07-05 10:36:38 -07:00
$Deps = @ ()
2016-06-30 13:41:43 -07:00
if ( $IsUbuntu ) {
2016-07-05 10:36:38 -07:00
# Build tools
$Deps += "curl" , "g++" , "cmake" , "make"
# .NET Core required runtime libraries
$Deps += "libicu52" , "libunwind8"
2016-07-05 11:03:08 -07:00
# Packaging tools
if ( $Package ) { $Deps += "ruby-dev" }
2016-07-05 10:36:38 -07:00
# Install dependencies
sudo apt-get install -y -qq $Deps
2016-06-30 13:41:43 -07:00
} elseif ( $IsCentos ) {
2016-07-05 10:36:38 -07:00
# Build tools
$Deps += "curl" , "gcc-c++" , "cmake" , "make"
# .NET Core required runtime libraries
$Deps += "libicu" , "libunwind"
2016-07-05 11:03:08 -07:00
# Packaging tools
if ( $Package ) { $Deps += "ruby-devel" , "rpmbuild" }
2016-07-05 10:36:38 -07:00
# Install dependencies
sudo yum install -y -q $Deps
2016-06-10 14:02:25 -07:00
} elseif ( $IsOSX ) {
precheck 'brew' "Bootstrap dependency 'brew' not found, must install Homebrew! See http://brew.sh/"
2016-07-05 10:36:38 -07:00
# Build tools
$Deps += "curl" , "cmake"
# .NET Core required runtime libraries
$Deps += "openssl"
2016-07-05 11:03:08 -07:00
# Packaging tools
if ( $Package ) { $Deps += "ruby" }
2016-07-05 10:36:38 -07:00
# Install dependencies
brew install $Deps
# OpenSSL libraries must be updated
2016-06-10 14:24:20 -07:00
brew link - -force openssl
2016-06-10 14:02:25 -07:00
}
2016-04-13 15:11:38 -07:00
2016-07-05 11:03:08 -07:00
# Install [fpm](https://github.com/jordansissel/fpm)
if ( $Package ) {
gem install fpm
}
2016-06-10 14:02:25 -07:00
$obtainUrl = "https://raw.githubusercontent.com/dotnet/cli/rel/1.0.0/scripts/obtain"
2016-04-13 15:11:38 -07:00
2016-06-10 14:02:25 -07:00
# 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"
}
2016-04-13 15:11:38 -07:00
2016-06-10 14:02:25 -07:00
if ( $uninstallScript ) {
curl -s $obtainUrl / uninstall / $uninstallScript -o $uninstallScript
chmod + x $uninstallScript
sudo ./ $uninstallScript
} else {
Write-Warning "This script only removes prior versions of dotnet for Ubuntu 14.04 and OS X"
}
2016-04-13 15:11:38 -07:00
2016-06-10 14:02:25 -07:00
# Install new dotnet 1.0.0 preview packages
$installScript = "dotnet-install.sh"
curl -s $obtainUrl / $installScript -o $installScript
chmod + x $installScript
2016-06-14 13:33:19 -07:00
bash ./ $installScript -c $Channel -v $Version
2016-06-10 14:02:25 -07:00
}
2016-04-13 15:11:38 -07:00
2016-06-10 14:02:25 -07:00
# Install for Windows
2016-07-21 16:52:22 -07:00
if ( $IsWindows -and -not $IsCoreCLR ) {
2016-06-10 14:02:25 -07:00
Remove-Item -ErrorAction SilentlyContinue -Recurse -Force ~\ AppData \ Local \ Microsoft \ dotnet
$installScript = "dotnet-install.ps1"
Invoke-WebRequest -Uri $obtainUrl / $installScript -OutFile $installScript
2016-06-14 13:33:19 -07:00
& ./ $installScript -c $Channel -v $Version
2016-07-21 15:33:16 -07:00
$machinePath = [ Environment ]:: GetEnvironmentVariable ( 'Path' , 'MACHINE' )
2016-07-21 15:47:28 -07:00
$newMachineEnvironmentPath = $machinePath
2016-07-22 14:31:32 -07:00
$cmakePresent = precheck 'cmake' $null
$sdkPath = "${env:ProgramFiles(x86)}\Microsoft SDKs\Windows\v10.0A"
$sdkPresent = Test-Path -Path $sdkPath -PathType Container
2016-07-21 15:47:28 -07:00
# Install chocolatey
2016-07-21 15:33:16 -07:00
$chocolateyPath = " $env:AllUsersProfile \chocolatey\bin"
2016-07-21 15:53:36 -07:00
2016-07-22 16:42:19 -07:00
if ( precheck 'choco' $null )
2016-07-21 15:33:16 -07:00
{
log "Chocolatey is already installed. Skipping installation."
}
2016-07-22 14:31:32 -07:00
elseif (( $cmakePresent -eq $false ) -or ( $sdkPresent -eq $false ))
2016-07-21 15:33:16 -07:00
{
log "Chocolatey not present. Installing chocolatey."
2016-07-22 16:42:19 -07:00
if ( $Force -or $PSCmdlet . ShouldProcess ( "Install chocolatey via https://chocolatey.org/install.ps1" ))
2016-07-21 15:33:16 -07:00
{
2016-07-22 16:42:19 -07:00
Invoke-Expression (( new-object net . webclient ). DownloadString ( 'https://chocolatey.org/install.ps1' ))
if ( -not ( $machinePath . ToLower (). Contains ( $chocolateyPath . ToLower ())))
{
log "Adding $chocolateyPath to Path environment variable"
$env:Path += "; $chocolateyPath "
$newMachineEnvironmentPath += "; $chocolateyPath "
}
else
{
log " $chocolateyPath already present in Path environment variable"
}
2016-07-21 15:33:16 -07:00
}
else
{
2016-07-22 16:42:19 -07: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 15:33:16 -07:00
}
}
2016-07-22 14:31:32 -07:00
else
{
log "Skipping installation of chocolatey, cause both cmake and Win 10 SDK are present."
}
2016-07-21 15:47:28 -07:00
# Install cmake
$cmakePath = "${env:ProgramFiles(x86)}\CMake\bin"
2016-07-22 14:31:32 -07:00
if ( $cmakePresent )
2016-07-21 15:47:28 -07:00
{
log "Cmake is already installed. Skipping installation."
}
else
{
log "Cmake not present. Installing cmake."
choco install cmake . portable -y - -version 3.6 . 0
if ( -not ( $machinePath . ToLower (). Contains ( $cmakePath . ToLower ())))
{
log "Adding $cmakePath to Path environment variable"
$env:Path += "; $cmakePath "
$newMachineEnvironmentPath = " $cmakePath ; $newMachineEnvironmentPath "
}
else
{
log " $cmakePath already present in Path environment variable"
}
}
2016-07-21 16:10:57 -07:00
# Install Windows 10 SDK
$packageName = "windows-sdk-10.0"
2016-07-22 14:31:32 -07:00
if ( -not $sdkPresent )
2016-07-21 16:10:57 -07:00
{
log "Windows 10 SDK not present. Installing $packageName ."
choco install windows-sdk - 10.0 -y
}
else
{
log "Windows 10 SDK present. Skipping installation."
}
2016-07-22 14:31:32 -07:00
# Update path machine environment variable
2016-07-21 15:47:28 -07:00
if ( $newMachineEnvironmentPath -ne $machinePath )
{
2016-07-22 14:31:32 -07:00
log "Updating Path machine environment variable"
2016-07-22 16:42:19 -07:00
if ( $Force -or $PSCmdlet . ShouldProcess ( "Update Path machine environment variable to $newMachineEnvironmentPath " ))
2016-07-22 14:31:32 -07:00
{
[ Environment ]:: SetEnvironmentVariable ( 'Path' , $newMachineEnvironmentPath , 'MACHINE' )
}
2016-07-21 15:47:28 -07:00
}
2016-06-10 14:02:25 -07:00
} elseif ( $IsWindows ) {
Write-Warning "Start-PSBootstrap cannot be run in Core PowerShell on Windows (need Invoke-WebRequest!)"
}
} finally {
Pop-Location
2016-04-13 15:11:38 -07:00
}
}
2016-04-01 14:41:13 -07:00
function Start-PSPackage {
2016-04-01 22:01:05 -07:00
[ CmdletBinding ()] param (
2016-04-09 18:02:37 -07:00
# PowerShell packages use Semantic Versioning http://semver.org/
2016-02-23 16:21:00 -08:00
[ string ] $Version ,
2016-04-09 18:02:37 -07:00
# Package iteration version (rarely changed)
2016-02-26 18:51:13 -08:00
[ int ] $Iteration = 1 ,
2016-04-09 18:02:37 -07:00
# Ubuntu, CentOS, and OS X packages are supported
2016-02-26 18:51:13 -08:00
[ ValidateSet ( "deb" , "osxpkg" , "rpm" )]
[ string ] $Type
2016-02-23 16:21:00 -08:00
)
2016-02-21 16:21:04 -08:00
2016-04-09 18:02:37 -07:00
$Description = @"
Open PowerShell on .NET Core
PowerShell is an open-source, cross-platform, scripting language and rich object shell.
Built upon .NET Core, it is also a C# REPL.
"@
2016-05-24 14:29:19 -07:00
# Use Git tag if not given a version
if ( -not $Version ) {
$Version = ( git - -git-dir = " $PSScriptRoot /.git" describe ) -Replace '^v'
}
$Source = Split-Path -Parent ( Get-PSOutput -Options ( New-PSOptions -Publish ))
Write-Verbose "Packaging $Source "
if ( $IsWindows ) {
2016-07-12 15:37:40 -07:00
# Product Guid needs to be unique for every PowerShell version to allow SxS install
$productGuid = [ guid ]:: NewGuid ()
$msiPackagePath = New-MSIPackage -ProductSourcePath $Source -ProductVersion $Version -AssetsPath " $PSScriptRoot \Assets" -ProductGuid $productGuid
2016-07-05 09:26:16 -07:00
$appxPackagePath = New-AppxPackage -PackageVersion $Version -SourcePath $Source -AssetsPath " $PSScriptRoot \Assets"
2016-06-02 10:31:02 -07:00
$packages = @ ( $msiPackagePath , $appxPackagePath )
2016-06-20 13:03:54 -07:00
2016-06-02 10:31:02 -07:00
return $packages
2016-05-24 14:29:19 -07:00
}
2016-02-21 16:21:04 -08:00
2016-04-09 17:59:13 -07:00
if ( -not ( Get-Command "fpm" -ErrorAction SilentlyContinue )) {
2016-02-21 16:21:04 -08:00
throw "Build dependency 'fpm' not found in PATH! See: https://github.com/jordansissel/fpm"
}
2016-02-23 16:21:00 -08:00
# Decide package output type
2016-04-09 18:02:37 -07:00
if ( -not $Type ) {
2016-06-20 13:03:54 -07:00
$Type = if ( $IsLinux ) {
if ( $LinuxInfo . ID -match 'ubuntu' ) {
"deb"
} elseif ( $LinuxInfo . ID -match 'centos' ) {
"rpm"
} else {
throw "Building packages for $( $LinuxInfo . PRETTY_NAME ) is unsupported!"
}
} elseif ( $IsOSX ) {
'osxpkg'
}
2016-02-26 18:51:13 -08:00
Write-Warning "-Type was not specified, continuing with $Type "
}
2016-02-21 16:21:04 -08:00
2016-04-09 18:02:37 -07:00
# Follow the Filesystem Hierarchy Standard for Linux and OS X
$Destination = if ( $IsLinux ) {
"/opt/microsoft/powershell"
} elseif ( $IsOSX ) {
"/usr/local/microsoft/powershell"
}
# Destination for symlink to powershell executable
$Link = if ( $IsLinux ) {
"/usr/bin"
} elseif ( $IsOSX ) {
"/usr/local/bin"
}
New-Item -Force -ItemType SymbolicLink -Path / tmp / powershell -Target $Destination / powershell > $null
2016-05-24 14:29:19 -07:00
2016-05-16 14:53:40 -07:00
# there is a weired bug in fpm
# 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
$symlink_dest = " $Destination /powershell"
$hack_dest = "./_fpm_symlink_hack_powershell"
if ( $IsOSX )
{
if ( Test-Path $symlink_dest )
{
Write-Warning "Move $symlink_dest to $hack_dest (fpm utime bug)"
Move-Item $symlink_dest $hack_dest
}
}
2016-04-09 18:02:37 -07:00
# Change permissions for packaging
chmod -R go = u $Source / tmp / powershell
2016-02-26 18:51:13 -08:00
$libunwind = switch ( $Type ) {
"deb" { "libunwind8" }
"rpm" { "libunwind" }
}
$libicu = switch ( $Type ) {
"deb" { "libicu52" }
"rpm" { "libicu" }
}
2016-04-09 18:02:37 -07:00
$Arguments = @ (
"--force" , "--verbose" ,
"--name" , "powershell" ,
"--version" , $Version ,
"--iteration" , $Iteration ,
"--maintainer" , "Andrew Schwartzmeyer <andschwa@microsoft.com>" ,
"--vendor" , "Microsoft <mageng@microsoft.com>" ,
"--url" , "https://github.com/PowerShell/PowerShell" ,
"--license" , "Unlicensed" ,
"--description" , $Description ,
"--category" , "shells" ,
"--rpm-os" , "linux" ,
"--depends" , $libunwind ,
"--depends" , $libicu ,
"--deb-build-depends" , "dotnet" ,
"--deb-build-depends" , "cmake" ,
"--deb-build-depends" , "g++" ,
"-t" , $Type ,
"-s" , "dir" ,
" $Source /= $Destination /" ,
"/tmp/powershell= $Link "
)
2016-02-23 16:21:00 -08:00
# Build package
2016-04-09 18:02:37 -07:00
fpm $Arguments
2016-05-16 14:53:40 -07:00
if ( $IsOSX )
{
# this is continuation of a fpm hack for a weired bug
if ( Test-Path $hack_dest )
{
Write-Warning "Move $hack_dest to $symlink_dest (fpm utime bug)"
Move-Item $hack_dest $symlink_dest
}
}
2016-02-21 16:21:04 -08:00
}
2016-05-19 19:03:43 -07:00
function Publish-NuGetFeed
{
param (
[ string ] $OutputPath = " $PSScriptRoot /nuget-artifacts" ,
[ Parameter ( Mandatory = $true )]
[ string ] $VersionSuffix
)
2016-06-20 11:59:14 -07:00
# Add .NET CLI tools to PATH
Find-Dotnet
2016-05-19 19:03:43 -07:00
@ (
'Microsoft.PowerShell.Commands.Management' ,
'Microsoft.PowerShell.Commands.Utility' ,
'Microsoft.PowerShell.ConsoleHost' ,
'Microsoft.PowerShell.Security' ,
2016-06-24 17:25:56 -07:00
'System.Management.Automation' ,
'Microsoft.PowerShell.CoreCLR.AssemblyLoadContext' ,
2016-07-26 16:43:32 -07:00
'Microsoft.PowerShell.CoreCLR.Eventing' ,
'Microsoft.PowerShell.SDK'
2016-05-19 19:03:43 -07:00
) | % {
if ( $VersionSuffix )
{
dotnet pack "src/ $_ " - -output $OutputPath - -version-suffix $VersionSuffix
}
else
{
dotnet pack "src/ $_ " - -output $OutputPath
}
}
}
2016-07-01 12:09:50 -07:00
function Start-DevPowerShell {
2016-02-03 10:53:43 -08:00
param (
2016-07-27 10:48:36 -07:00
[ switch ] $FullCLR ,
2016-02-03 10:53:43 -08:00
[ switch ] $ZapDisable ,
[ string[] ] $ArgumentList = '' ,
[ switch ] $LoadProfile ,
2016-07-27 10:48:36 -07:00
[ string ] $binDir = ( Split-Path ( New-PSOptions -FullCLR: $FullCLR ). Output ),
2016-07-01 12:09:50 -07:00
[ switch ] $NoNewWindow ,
[ string ] $Command ,
[ switch ] $KeepPSModulePath
2016-02-03 10:53:43 -08:00
)
2016-04-01 22:01:05 -07:00
try {
2016-07-27 12:27:41 -07:00
if (( -not $NoNewWindow ) -and ( $IsCoreCLR ))
2016-07-27 10:55:42 -07:00
{
2016-07-27 12:27:41 -07:00
Write-Warning "Start-DevPowerShell -NoNewWindow is currently implied in PowerShellCore edition https://github.com/PowerShell/PowerShell/issues/1543"
2016-07-27 10:55:42 -07:00
$NoNewWindow = $true
}
2016-07-01 12:09:50 -07:00
if ( -not $LoadProfile ) {
2016-02-03 17:25:51 -08:00
$ArgumentList = @ ( '-noprofile' ) + $ArgumentList
2016-02-03 10:53:43 -08:00
}
2016-07-01 12:09:50 -07:00
if ( -not $KeepPSModulePath )
{
if ( -not $Command )
{
$ArgumentList = @ ( '-NoExit' ) + $ArgumentList
}
2016-07-28 11:47:36 -07:00
$Command = '$env:PSMODULEPATH = Join-Path $env:DEVPATH Modules; ' + $Command
2016-07-01 12:09:50 -07:00
}
if ( $Command )
{
$ArgumentList = $ArgumentList + @ ( "-command $Command " )
}
2016-02-03 10:53:43 -08:00
$env:DEVPATH = $binDir
2016-04-01 22:01:05 -07:00
if ( $ZapDisable ) {
2016-02-21 15:06:39 -08:00
$env:COMPLUS_ZapDisable = 1
2016-02-03 10:53:43 -08:00
}
2016-07-27 10:48:36 -07:00
if ( $FullCLR -and ( -not ( Test-Path $binDir \ powershell . exe . config ))) {
2016-02-03 10:53:43 -08:00
$configContents = @"
2016-02-21 15:06:39 -08:00
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
2016-04-01 22:01:05 -07:00
<runtime>
<developmentMode developerInstallation="true"/>
</runtime>
2016-02-03 10:53:43 -08:00
</configuration>
"@
$configContents | Out-File -Encoding Ascii $binDir \ powershell . exe . config
}
2016-02-21 15:06:39 -08:00
# splatting for the win
2016-02-03 17:25:51 -08:00
$startProcessArgs = @ {
2016-07-27 10:48:36 -07:00
FilePath = " $binDir \powershell"
2016-02-03 17:25:51 -08:00
ArgumentList = " $ArgumentList "
2016-02-21 15:06:39 -08:00
}
2016-02-04 13:19:24 -08:00
if ( $NoNewWindow ) {
$startProcessArgs . NoNewWindow = $true
$startProcessArgs . Wait = $true
}
2016-02-21 15:06:39 -08:00
2016-02-03 17:25:51 -08:00
Start-Process @startProcessArgs
2016-04-01 22:01:05 -07:00
} finally {
2016-02-03 10:53:43 -08:00
ri env : DEVPATH
2016-04-01 22:01:05 -07:00
if ( $ZapDisable ) {
2016-02-03 10:53:43 -08:00
ri env : COMPLUS_ZapDisable
}
}
2016-02-20 14:35:46 -08:00
}
2016-03-22 16:00:20 -07:00
<#
2016-06-13 17:37:24 -07:00
. EXAMPLE
PS C:> Copy-MappedFiles -PslMonadRoot .\src\monad
copy files FROM .\src\monad (old location of submodule) TO src/<project> folders
2016-03-22 16:00:20 -07:00
#>
2016-06-13 17:37:24 -07:00
function Copy-MappedFiles {
2016-04-01 14:41:13 -07:00
2016-03-22 16:00:20 -07:00
[ CmdletBinding ()]
param (
2016-06-13 17:37:24 -07:00
[ Parameter ( ValueFromPipeline = $true )]
[ string[] ] $Path = " $PSScriptRoot " ,
[ Parameter ( Mandatory = $true )]
2016-06-13 18:46:15 -07:00
[ string ] $PslMonadRoot ,
2016-06-15 19:07:49 -07:00
[ switch ] $Force ,
[ switch ] $WhatIf
2016-03-22 16:00:20 -07:00
)
2016-06-13 17:37:24 -07:00
begin
{
2016-06-13 18:46:15 -07:00
function MaybeTerminatingWarning
{
param ([ string ] $Message )
if ( $Force )
{
Write-Warning " $Message : ignoring (-Force)"
}
2016-06-15 19:07:49 -07:00
elseif ( $WhatIf )
{
Write-Warning " $Message : ignoring (-WhatIf)"
}
2016-06-13 18:46:15 -07:00
else
{
throw " $Message : use -Force to ignore"
}
}
2016-06-13 17:37:24 -07:00
if ( -not ( Test-Path -PathType Container $PslMonadRoot ))
{
throw " $pslMonadRoot is not a valid folder"
}
2016-04-01 14:41:13 -07:00
2016-06-13 18:46:15 -07:00
# Do some intelligens to prevent shouting us in the foot with CL management
# finding base-line CL
2016-06-15 13:27:32 -07:00
$cl = git - -git-dir = " $PSScriptRoot /.git" tag | % { if ( $_ -match 'SD.(\d+)$' ) {[ int ] $Matches [ 1 ]} } | Sort-Object -Descending | Select-Object -First 1
2016-06-13 18:46:15 -07:00
if ( $cl )
{
2016-06-22 19:46:16 -07:00
log "Current base-line CL is SD: $cl (based on tags)"
2016-06-13 18:46:15 -07:00
}
else
{
MaybeTerminatingWarning "Could not determine base-line CL based on tags"
}
try
{
Push-Location $PslMonadRoot
2016-06-17 06:14:12 -07:00
if ( git status - -porcelain -uno )
2016-06-13 18:46:15 -07:00
{
MaybeTerminatingWarning " $pslMonadRoot has changes"
}
if ( git log - -grep = "SD: $cl " HEAD ^.. HEAD )
{
2016-06-28 15:52:38 -07:00
log " $pslMonadRoot HEAD matches [SD: $cl ]"
2016-06-13 18:46:15 -07:00
}
else
{
2016-06-22 19:46:16 -07:00
Write-Warning "Try to checkout this commit in $pslMonadRoot :"
git log - -grep = "SD: $cl " | Write-Warning
2016-06-13 18:46:15 -07:00
MaybeTerminatingWarning " $pslMonadRoot HEAD doesn't match [SD: $cl ]"
}
}
finally
{
Pop-Location
}
$map = @ {}
2016-03-22 16:00:20 -07:00
}
2016-06-13 17:37:24 -07:00
process
{
$map += Get-Mappings $Path -Root $PslMonadRoot
}
2016-03-22 16:00:20 -07:00
2016-06-13 17:37:24 -07:00
end
{
$map . GetEnumerator () | % {
2016-06-15 13:27:32 -07:00
New-Item -ItemType Directory ( Split-Path $_ . Value ) -ErrorAction SilentlyContinue > $null
2016-03-22 16:00:20 -07:00
2016-06-15 19:07:49 -07:00
Copy-Item $_ . Key $_ . Value -Verbose: ([ bool ] $PSBoundParameters [ 'Verbose' ]) -WhatIf: $WhatIf
2016-03-22 16:00:20 -07:00
}
}
}
2016-06-13 17:37:24 -07:00
function Get-Mappings
{
[ CmdletBinding ()]
2016-03-22 16:00:20 -07:00
param (
2016-06-13 17:37:24 -07:00
[ Parameter ( ValueFromPipeline = $true )]
[ string[] ] $Path = " $PSScriptRoot " ,
[ string ] $Root ,
[ switch ] $KeepRelativePaths
2016-03-22 16:00:20 -07:00
)
2016-06-13 17:37:24 -07:00
begin
{
$mapFiles = @ ()
2016-03-22 16:00:20 -07:00
}
2016-06-13 17:37:24 -07:00
process
{
Write-Verbose "Discovering map files in $Path "
$count = $mapFiles . Count
2016-03-22 16:00:20 -07:00
2016-06-13 17:37:24 -07:00
if ( -not ( Test-Path $Path ))
{
throw "Mapping file not found in $mappingFilePath "
2016-03-22 16:00:20 -07:00
}
2016-06-13 17:37:24 -07:00
if ( Test-Path -PathType Container $Path )
{
$mapFiles += Get-ChildItem -Recurse $Path -Filter 'map.json' -File
}
else
{
# it exists and it's a file, don't check the name pattern
$mapFiles += Get-ChildItem $Path
}
Write-Verbose "Found $( $mapFiles . Count - $count ) map files in $Path "
2016-03-22 16:00:20 -07:00
}
2016-06-13 17:37:24 -07:00
end
{
$map = @ {}
$mapFiles | % {
2016-06-30 16:42:58 -07:00
$file = $_
try
{
$rawHashtable = $_ | Get-Content -Raw | ConvertFrom-Json | Convert-PSObjectToHashtable
}
catch
{
Write-Error "Exception, when processing $( $file . FullName ) : $_ "
}
2016-06-13 17:37:24 -07:00
$mapRoot = Split-Path $_ . FullName
if ( $KeepRelativePaths )
{
# 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 ( '\' , '/' )
}
$rawHashtable . GetEnumerator () | % {
$newKey = if ( $Root ) { Join-Path $Root $_ . Key } else { $_ . Key }
$newValue = if ( $KeepRelativePaths ) { ( $mapRoot + '/' + $_ . Value ) } else { Join-Path $mapRoot $_ . Value }
$map [ $newKey ] = $newValue
}
}
return $map
}
2016-03-22 16:00:20 -07:00
}
2016-03-23 16:57:59 -07:00
<#
2016-06-13 17:37:24 -07:00
.EXAMPLE Send-GitDiffToSd -diffArg1 32b90c048aa0c5bc8e67f96a98ea01c728c4a5be~1 -diffArg2 32b90c048aa0c5bc8e67f96a98ea01c728c4a5be -AdminRoot d:\e\ps_dev\admin
2016-03-23 16:57:59 -07:00
Apply a signle commit to admin folder
#>
2016-04-01 22:01:05 -07:00
function Send-GitDiffToSd {
2016-03-23 16:57:59 -07:00
param (
[ Parameter ( Mandatory )]
[ string ] $diffArg1 ,
[ Parameter ( Mandatory )]
[ string ] $diffArg2 ,
[ Parameter ( Mandatory )]
2016-06-13 17:37:24 -07:00
[ string ] $AdminRoot ,
2016-03-23 16:57:59 -07:00
[ switch ] $WhatIf
)
2016-06-13 17:37:24 -07: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 16:57:59 -07:00
$affectedFiles = git diff - -name-only $diffArg1 $diffArg2
2016-06-13 17:37:24 -07:00
$affectedFiles | % {
2016-06-22 19:46:16 -07:00
log "Changes in file $_ "
2016-06-13 17:37:24 -07:00
}
2016-03-23 16:57:59 -07:00
$rev = Get-InvertedOrderedMap $m
foreach ( $file in $affectedFiles ) {
2016-04-01 22:01:05 -07:00
if ( $rev . Contains ) {
2016-06-13 17:37:24 -07:00
$sdFilePath = $rev [ $file ]
if ( -not $sdFilePath )
{
Write-Warning "Cannot find mapped file for $file , skipping"
continue
}
2016-03-23 16:57:59 -07:00
$diff = git diff $diffArg1 $diffArg2 -- $file
2016-04-01 22:01:05 -07:00
if ( $diff ) {
2016-06-22 19:46:16 -07:00
log "Apply patch to $sdFilePath "
2016-03-23 16:57:59 -07:00
Set-Content -Value $diff -Path $env:TEMP \ diff -Encoding Ascii
2016-04-01 22:01:05 -07:00
if ( $WhatIf ) {
2016-06-22 19:46:16 -07:00
log "Patch content"
2016-06-15 13:27:32 -07:00
Get-Content $env:TEMP \ diff
2016-04-01 22:01:05 -07:00
} else {
2016-04-01 14:41:13 -07:00
& $patchPath - -binary -p1 $sdFilePath $env:TEMP \ diff
2016-03-23 16:57:59 -07:00
}
2016-04-01 22:01:05 -07:00
} else {
2016-06-22 19:46:16 -07:00
log "No changes in $file "
2016-03-23 16:57:59 -07:00
}
2016-04-01 22:01:05 -07:00
} else {
2016-06-22 19:46:16 -07:00
log "Ignore changes in $file , because there is no mapping for it"
2016-03-23 16:57:59 -07:00
}
2016-04-01 14:41:13 -07:00
}
2016-03-23 16:57:59 -07:00
}
2016-04-01 22:01:05 -07:00
2016-06-17 11:23:29 -07:00
function Start-TypeGen
{
[ CmdletBinding ()]
param ()
2016-06-20 11:59:14 -07:00
# Add .NET CLI tools to PATH
Find-Dotnet
2016-06-17 11:23:29 -07:00
Push-Location " $PSScriptRoot /src/TypeCatalogParser"
try
{
2016-07-26 16:59:45 -07:00
dotnet run
2016-06-17 11:23:29 -07:00
}
finally
{
Pop-Location
}
Push-Location " $PSScriptRoot /src/TypeCatalogGen"
try
{
dotnet run ../ Microsoft . PowerShell . CoreCLR . AssemblyLoadContext / CorePsTypeCatalog . cs powershell . inc
}
finally
{
Pop-Location
}
}
2016-04-04 14:20:34 -07:00
function Start-ResGen
{
2016-06-15 03:42:54 -07:00
[ CmdletBinding ()]
param ()
2016-08-02 11:47:53 -07:00
# Add .NET CLI tools to PATH
Find-Dotnet
2016-06-14 16:48:20 -07:00
2016-08-02 11:47:53 -07:00
Push-Location " $PSScriptRoot /src/ResGen"
try
{
Start-NativeExecution { dotnet run } | Write-Verbose
}
finally
{
Pop-Location
2016-04-04 14:20:34 -07:00
}
}
2016-04-01 22:01:05 -07:00
2016-06-20 11:59:14 -07: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 16:02:07 -07:00
<#
2016-07-01 13:51:14 -07:00
This is one-time conversion. We use it for to turn GetEventResources.txt into GetEventResources.resx
2016-06-30 16:02:07 -07:00
.EXAMPLE Convert-TxtResourceToXml -Path Microsoft.PowerShell.Commands.Diagnostics\resources
#>
function Convert-TxtResourceToXml
{
param (
[ string[] ] $Path
)
process
{
$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-22 19:46:16 -07:00
function Start-XamlGen
2016-06-21 14:30:26 -07:00
{
[ CmdletBinding ()]
param (
[ Parameter ()]
[ ValidateSet ( "Debug" , "Release" )]
[ string ]
$MSBuildConfiguration = "Release"
)
2016-06-21 16:54:57 -07:00
Use-MSBuild
2016-06-21 14:30:26 -07:00
Get-ChildItem -Path " $PSScriptRoot /src" -Directory | % {
$XamlDir = Join-Path -Path $_ . FullName -ChildPath Xamls
if (( Test-Path -Path $XamlDir -PathType Container ) -and
( @ ( Get-ChildItem -Path " $XamlDir \*.xaml" ). Count -gt 0 ))
{
$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 15:12:15 -07: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 14:30:26 -07:00
$DestinationDir = Join-Path -Path $_ . FullName -ChildPath gen
2016-06-22 19:46:16 -07:00
New-Item -ItemType Directory $DestinationDir -ErrorAction SilentlyContinue > $null
2016-06-24 15:12:15 -07:00
$filesToCopy = Get-Item " $SourceDir \*.cs" , " $SourceDir \*.g.resources"
if ( -not $filesToCopy )
{
throw "No .cs or .g.resources files are generated for $XamlDir , something went wrong. Run 'Start-XamlGen -Verbose' for details."
}
$filesToCopy | % {
2016-06-22 19:46:16 -07:00
$sourcePath = $_ . FullName
Write-Verbose "Copy generated xaml artifact: $sourcePath -> $DestinationDir "
Copy-Item -Path $sourcePath -Destination $DestinationDir
2016-06-21 14:30:26 -07: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 15:02:46 -07:00
<Reference Include="WindowsBase.dll">
2016-06-21 14:30:26 -07:00
<Private>False</Private>
</Reference>
2016-06-24 15:02:46 -07:00
<Reference Include="PresentationCore.dll">
2016-06-21 14:30:26 -07:00
<Private>False</Private>
</Reference>
2016-06-24 15:02:46 -07:00
<Reference Include="PresentationFramework.dll">
2016-06-21 14:30:26 -07: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-21 18:24:24 -07:00
[ string ] $XamlDir ,
[ switch ] $IgnoreMsbuildFailure
2016-06-21 14:30:26 -07:00
)
2016-06-22 19:46:16 -07:00
log "ConvertFrom-Xaml for $XamlDir "
2016-06-21 18:24:24 -07:00
2016-06-21 14:30:26 -07: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 15:03:38 -07:00
msbuild $XamlProjPath | Write-Verbose
2016-06-21 14:30:26 -07:00
if ( $LASTEXITCODE -ne 0 )
{
2016-06-21 18:24:24 -07:00
$message = "When processing $XamlDir 'msbuild $XamlProjPath > `$ null' failed with exit code $LASTEXITCODE "
if ( $IgnoreMsbuildFailure )
{
2016-06-24 15:12:15 -07:00
Write-Verbose $message
2016-06-21 18:24:24 -07:00
}
else
{
throw $message
}
2016-06-21 14:30:26 -07:00
}
return ( Join-Path -Path $OutputDir -ChildPath "obj\Any CPU\ $Configuration " )
}
2016-06-20 11:59:14 -07:00
2016-06-21 16:54:57 -07:00
function script: Use-MSBuild {
2016-06-24 14:52:04 -07: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-22 19:46:16 -07:00
2016-06-24 14:52:04 -07:00
$msbuild = get-command msbuild -ErrorAction SilentlyContinue
2016-06-22 19:46:16 -07:00
if ( $msbuild )
{
2016-06-24 14:52:04 -07:00
# all good, nothing to do
return
2016-06-21 16:54:57 -07:00
}
2016-06-22 19:46:16 -07:00
2016-06-24 14:52:04 -07:00
if ( -not ( Test-Path $frameworkMsBuildLocation ))
2016-06-22 19:46:16 -07:00
{
2016-06-24 14:52:04 -07:00
throw "msbuild not found in ' $frameworkMsBuildLocation '. Install Visual Studio 2015."
2016-06-22 19:46:16 -07:00
}
2016-06-24 14:52:04 -07:00
Set-Alias msbuild $frameworkMsBuildLocation -Scope Script
2016-06-21 16:54:57 -07:00
}
2016-04-01 22:01:05 -07:00
function script: log([string]$message ) {
Write-Host -Foreground Green $message
2016-07-28 06:36:50 -07:00
#reset colors for older package to at return to default after error message on a compiliation error
[ console ]:: ResetColor ()
2016-04-01 22:01:05 -07:00
}
function script: precheck([string]$command , [ string ] $missedMessage ) {
$c = Get-Command $command -ErrorAction SilentlyContinue
if ( -not $c ) {
2016-07-21 15:53:36 -07:00
if ( $missedMessage -ne $null )
{
Write-Warning $missedMessage
}
2016-04-01 22:01:05 -07: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 = @ {}
foreach ( $property in $InputObject . PSObject . Properties )
{
$hash [ $property . Name ] = Convert-PSObjectToHashtable $property . Value
}
$hash
} else {
$InputObject
}
}
}
2016-04-04 14:20:34 -07:00
2016-04-19 16:59:03 -07: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"
try
{
& $sb
2016-07-07 11:34:10 -07:00
# note, if $sb doens't have a native invocation, $LASTEXITCODE will
2016-04-19 16:59:03 -07:00
# point to the obsolete value
if ( $LASTEXITCODE -ne 0 )
{
2016-05-18 14:30:24 -07:00
throw "Execution of { $sb } failed with exit code $LASTEXITCODE "
2016-04-19 16:59:03 -07:00
}
}
finally
{
$script:ErrorActionPreference = $backupEAP
}
}
2016-04-04 14:20:34 -07:00
2016-06-27 16:04:57 -07: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
if ( 1 -eq $packageVersionTokens . Count )
{
# In case the input is of the form a.b.c, add a '0' at the end for revision field
2016-07-26 21:22:37 -07:00
$packageVersion = $packageVersion + '.0'
2016-06-27 16:04:57 -07:00
}
elseif ( 1 -lt $packageVersionTokens . Count )
{
# We have all the four fields
2016-07-26 21:22:37 -07:00
$packageBuildTokens = ([ regex ]:: Matches ( $packageVersionTokens [ 1 ], "\d+" ))[ 0 ]. value
$packageVersion = $packageVersion + '.' + $packageBuildTokens [ 0 ]
2016-06-27 16:04:57 -07:00
}
return $packageVersion
}
2016-06-06 13:20:00 -07:00
function New-MSIPackage
2016-05-24 14:23:38 -07:00
{
[ CmdletBinding ()]
param (
# Name of the Product
[ ValidateNotNullOrEmpty ()]
2016-06-27 11:39:49 -07:00
[ string ] $ProductName = 'PowerShell' ,
2016-05-24 14:23:38 -07: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-06-27 11:39:49 -07:00
[ string ] $ProductWxsPath = ( Join-Path $pwd '\assets\Product.wxs' ),
# Path to Assets folder containing artifacts such as icons, images
[ Parameter ( Mandatory = $true )]
[ ValidateNotNullOrEmpty ()]
[ string ] $AssetsPath
2016-05-24 14:23:38 -07:00
)
$wixToolsetBinPath = "${env:ProgramFiles(x86)}\WiX Toolset v3.10\bin"
Write-Verbose "Ensure Wix Toolset is present on the machine @ $wixToolsetBinPath "
if ( -not ( Test-Path $wixToolsetBinPath ))
{
throw "Install Wix Toolset prior to running this script - https://wix.codeplex.com/downloads/get/1540240"
}
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 11:39:49 -07:00
2016-06-27 16:04:57 -07:00
$ProductVersion = Get-PackageVersionAsMajorMinorBuildRevision -Version $ProductVersion -Verbose
2016-05-24 14:23:38 -07:00
2016-06-27 11:39:49 -07:00
$assetsInSourcePath = " $ProductSourcePath " + '\assets'
New-Item $assetsInSourcePath -type directory -Force | Write-Verbose
$assetsInSourcePath = Join-Path $ProductSourcePath 'assets'
Write-Verbose "Place dependencies such as icons to $assetsInSourcePath "
Copy-Item " $AssetsPath \*.ico" $assetsInSourcePath -Force
2016-05-24 14:23:38 -07: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" )
$msiLocationPath = Join-Path $pwd " $productVersionWithName .msi"
2016-05-24 14:41:23 -07:00
Remove-Item -ErrorAction SilentlyContinue $msiLocationPath -Force
2016-05-24 14:23:38 -07:00
2016-05-24 15:02:24 -07: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
& $wixLightExePath -out " $productVersionWithName .msi" $wixObjProductPath $wixObjFragmentPath -ext WixUIExtension -v | Write-Verbose
2016-05-24 14:23:38 -07:00
2016-05-24 14:41:23 -07:00
Remove-Item -ErrorAction SilentlyContinue *. wixpdb -Force
2016-05-24 14:23:38 -07:00
2016-05-24 14:41:05 -07:00
Write-Verbose "You can find the MSI @ $msiLocationPath "
return $msiLocationPath
2016-05-24 14:23:38 -07:00
}
2016-06-02 10:31:02 -07:00
# Function to create an Appx package compatible with Windows 8.1 and above
function New-AppxPackage
{
[ CmdletBinding ()]
param (
# Name of the Package
[ ValidateNotNullOrEmpty ()]
2016-06-27 11:39:49 -07:00
[ string ] $PackageName = 'PowerShell' ,
2016-06-02 10:31:02 -07:00
# Version of the Package
[ Parameter ( Mandatory = $true )]
[ ValidateNotNullOrEmpty ()]
[ string ] $PackageVersion ,
# Source Path to the Binplaced Files
[ Parameter ( Mandatory = $true )]
[ ValidateNotNullOrEmpty ()]
[ string ] $SourcePath ,
# Path to Assets folder containing Appx specific artifacts
[ Parameter ( Mandatory = $true )]
[ ValidateNotNullOrEmpty ()]
[ string ] $AssetsPath
)
2016-06-27 16:04:57 -07:00
$PackageVersion = Get-PackageVersionAsMajorMinorBuildRevision -Version $PackageVersion -Verbose
2016-06-02 10:31:02 -07:00
Write-Verbose "Package Version is $PackageVersion "
$win10sdkBinPath = "${env:ProgramFiles(x86)}\Windows Kits\10\bin\x64"
Write-Verbose "Ensure Win10 SDK is present on the machine @ $win10sdkBinPath "
if ( -not ( Test-Path $win10sdkBinPath ))
{
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 "
if ( -not ( Test-Path $SourcePath ))
{
throw "Invalid SourcePath - $SourcePath "
}
Write-Verbose "Ensure Assets Path is valid - $AssetsPath "
if ( -not ( Test-Path $AssetsPath ))
{
throw "Invalid AssetsPath - $AssetsPath "
}
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 11:39:49 -07: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 10:31:02 -07:00
<Properties>
2016-06-27 11:39:49 -07:00
<DisplayName>PowerShell</DisplayName>
2016-06-02 10:31:02 -07: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 11:39:49 -07: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 10:31:02 -07: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
$assetsInSourcePath = " $SourcePath " + '\Assets'
New-Item $assetsInSourcePath -type directory -Force | Out-Null
$assetsInSourcePath = Join-Path $SourcePath 'Assets'
Write-Verbose "Place AppxManifest dependencies such as images to $assetsInSourcePath "
Copy-Item " $AssetsPath \*.png" $assetsInSourcePath -Force
2016-06-02 11:23:28 -07:00
$appxPackageName = $PackageName + "_" + $PackageVersion
$appxPackagePath = " $pwd \ $appxPackageName .appx"
2016-06-02 10:31:02 -07:00
Write-Verbose "Calling MakeAppx from $makeappxExePath to create the package @ $appxPackagePath "
& $makeappxExePath pack / o / v / d $SourcePath / p $appxPackagePath | Write-Verbose
Write-Verbose "Clean-up Appx artifacts and Assets from $SourcePath "
Remove-Item $assetsInSourcePath -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item " $SourcePath \AppxManifest.xml" -Force -ErrorAction SilentlyContinue
return $appxPackagePath
}
2016-06-30 16:02:07 -07:00
$script:RESX_TEMPLATE = @'
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
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
associated with the data types.
Example:
... 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>
There are any number of "resheader" rows that contain simple
name/value pairs.
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
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: 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 10:36:38 -07:00
'@