diff --git a/.pipelines/templates/nupkg.yml b/.pipelines/templates/nupkg.yml
index 427654e2516..9b666d4e578 100644
--- a/.pipelines/templates/nupkg.yml
+++ b/.pipelines/templates/nupkg.yml
@@ -258,7 +258,8 @@ jobs:
$linuxFxdPath = "$(Pipeline.Workspace)\CoOrdinatedBuildPipeline\drop_linux_sign_linux_fxd\Signed-fxdependent"
$alpineFxdPath = "$(Pipeline.Workspace)\CoOrdinatedBuildPipeline\drop_linux_sign_linux_fxd_x64_alpine\Signed-fxdependent-noopt-linux-musl-x64"
- $packageTypes = @('Unified', 'PowerShell.Linux.Alpine', 'PowerShell.Linux.x64', 'PowerShell.Linux.arm32', 'PowerShell.Linux.arm64', 'PowerShell.Windows.x64')
+ # Build global tools which do not have the shims exe generated in build.
+ $packageTypes = @('Unified', 'PowerShell.Linux.Alpine', 'PowerShell.Linux.x64', 'PowerShell.Linux.arm32', 'PowerShell.Linux.arm64')
$packageTypes | Foreach-Object {
$PackageType = $_
@@ -299,6 +300,12 @@ jobs:
$nupkgOutputPath = Join-Path -Path '$(Pipeline.Workspace)' -ChildPath 'nupkg'
Get-ChildItem -Path $nupkgOutputPath -Filter *.nupkg -Recurse | Copy-Item -Destination '$(ob_outputDirectory)' -Force -Verbose
+ # Copy Windows.x86 global tool from build to output directory
+ $winX64GlobalTool = "$(Pipeline.Workspace)\CoOrdinatedBuildPipeline\drop_windows_build_windows_fxdependent_release\globaltool\powershell*.nupkg"
+ Write-Verbose -Verbose "Finding Windows.x64 global tool at $winX64GlobalTool"
+ $globalToolPath = Get-Item $winX64GlobalTool
+ Copy-Item -Path $globalToolPath -Destination '$(ob_outputDirectory)' -Force -Verbose
+
Write-Verbose -Verbose "Copying global tools to output directory"
$gblToolOutputPath = Join-Path -Path '$(Pipeline.Workspace)' -ChildPath 'globaltools'
Get-ChildItem -Path $gblToolOutputPath -Filter *.nupkg -Recurse | Copy-Item -Destination '$(ob_outputDirectory)' -Force -Verbose
diff --git a/.pipelines/templates/obp-file-signing.yml b/.pipelines/templates/obp-file-signing.yml
index 06cd46dec29..ab750c2700f 100644
--- a/.pipelines/templates/obp-file-signing.yml
+++ b/.pipelines/templates/obp-file-signing.yml
@@ -1,5 +1,6 @@
parameters:
binPath: '$(ob_outputDirectory)'
+ globalTool: 'false'
steps:
- pwsh: |
@@ -138,10 +139,17 @@ steps:
- pwsh: |
Import-Module '$(PowerShellRoot)/build.psm1' -Force
Import-Module '$(PowerShellRoot)/tools/packaging' -Force
- $pathForUpload = New-Item -ItemType Directory -Path '$(ob_outputDirectory)/Signed-$(Runtime)' -Force
- Write-Verbose -Verbose -Message "pathForUpload: $pathForUpload"
- Copy-Item -Path '${{ parameters.binPath }}\*' -Destination $pathForUpload -Recurse -Force -Verbose
- Write-Verbose -Verbose -Message "Files copied to $pathForUpload"
+ $isGlobalTool = '${{ parameters.globalTool }}' -eq 'true'
+
+ if (-not $isGlobalTool) {
+ $pathForUpload = New-Item -ItemType Directory -Path '$(ob_outputDirectory)/Signed-$(Runtime)' -Force
+ Write-Verbose -Verbose -Message "pathForUpload: $pathForUpload"
+ Copy-Item -Path '${{ parameters.binPath }}\*' -Destination $pathForUpload -Recurse -Force -Verbose
+ Write-Verbose -Verbose -Message "Files copied to $pathForUpload"
+ }
+ else {
+ $pathForUpload = '${{ parameters.binPath }}'
+ }
Write-Verbose "Copying third party signed files to the build folder"
$thirdPartySignedFilesPath = (Get-Item '$(Pipeline.Workspace)/thirdPartyToBeSigned').FullName
diff --git a/.pipelines/templates/windows-hosted-build.yml b/.pipelines/templates/windows-hosted-build.yml
index 15ca7e9c587..d6be94368b6 100644
--- a/.pipelines/templates/windows-hosted-build.yml
+++ b/.pipelines/templates/windows-hosted-build.yml
@@ -89,6 +89,8 @@ jobs:
$null = New-Item -ItemType Directory -Path $buildWithSymbolsPath -Force -Verbose
Start-PSBuild -Runtime $runtime -Configuration Release -Output $buildWithSymbolsPath -Clean -PSModuleRestore @params
+ $refFolderPath = Join-Path $buildWithSymbolsPath 'ref'
+ Write-Verbose -Verbose "refFolderPath: $refFolderPath"
$outputPath = Join-Path '$(ob_outputDirectory)' 'psoptions'
$null = New-Item -ItemType Directory -Path $outputPath -Force
$psOptPath = "$outputPath/psoptions.json"
@@ -106,6 +108,39 @@ jobs:
}
}
+ if ($runtime -eq 'fxdependent')
+ {
+ ## Also build global tool
+ Write-Verbose -Message "Building PowerShell global tool for Windows.x64" -Verbose
+ $globalToolCsProjDir = Join-Path $(PowerShellRoot) 'src' 'GlobalTools' 'PowerShell.Windows.x64'
+ Push-Location -Path $globalToolCsProjDir -Verbose
+
+ $globalToolArtifactPath = Join-Path $(Build.SourcesDirectory) 'GlobalTool'
+ $vstsCommandString = "vso[task.setvariable variable=GlobalToolArtifactPath]${globalToolArtifactPath}"
+ Write-Host "sending " + $vstsCommandString
+ Write-Host "##$vstsCommandString"
+
+ dotnet publish --no-self-contained --artifacts-path $globalToolArtifactPath /property:PackageVersion=$(Version)
+ $globalToolBuildModulePath = Join-Path $globalToolArtifactPath 'publish' 'PowerShell.Windows.x64' 'release'
+ Pop-Location
+ # do this to ensure everything gets signed.
+ Restore-PSModuleToBuild -PublishPath $globalToolBuildModulePath
+
+ # Copy reference assemblies
+ Copy-Item -Path $refFolderPath -Destination $globalToolBuildModulePath -Recurse -Force
+
+ Write-Verbose -Verbose "clean unnecessary files in obj directory"
+ $objDir = Join-Path $globalToolArtifactPath 'obj' 'PowerShell.Windows.x64' 'release'
+
+ $filesToKeep = @("apphost.exe", "PowerShell.Windows.x64.pdb", "PowerShell.Windows.x64.dll", "project.assets.json")
+
+ # only four files are needed in obj folder for global tool packaging
+ Get-ChildItem -Path $objDir -File -Recurse |
+ Where-Object { -not $_.PSIsContainer } |
+ Where-Object { $_.name -notin $filesToKeep } |
+ Remove-Item -Verbose
+ }
+
Write-Verbose -Verbose "Completed building PowerShell for '$env:BuildConfiguration' configuration"
displayName: 'Build Windows Universal - $(Architecture)-$(BuildConfiguration) Symbols folder'
env:
@@ -128,4 +163,112 @@ jobs:
parameters:
binPath: '$(Pipeline.Workspace)/Symbols_$(Architecture)'
+ ## first we sign all the files in the bin folder
+ - ${{ if eq(variables['Architecture'], 'fxdependent') }}:
+ - template: /.pipelines/templates/obp-file-signing.yml@self
+ parameters:
+ binPath: '$(GlobalToolArtifactPath)/publish/PowerShell.Windows.x64/release'
+ globalTool: 'true'
+
+ - pwsh: |
+ Get-ChildItem '$(GlobalToolArtifactPath)/obj/PowerShell.Windows.x64/release'
+ displayName: Capture obj files
+ condition: and(succeeded(), eq(variables['Architecture'], 'fxdependent'))
+
+ ## Now we sign couple of file from the obj folder which are needed for the global tool packaging
+ - task: onebranch.pipeline.signing@1
+ displayName: Sign obj files
+ inputs:
+ command: 'sign'
+ signing_profile: external_distribution
+ files_to_sign: '**\*.dll;**\*.exe'
+ search_root: '$(GlobalToolArtifactPath)/obj/PowerShell.Windows.x64/release'
+ condition: and(succeeded(), eq(variables['Architecture'], 'fxdependent'))
+
+ - pwsh: |
+ <# The way the packaging works is a bit tricky as when it is built, we cannot add the modules that come from gallery.
+ We have to use dotnet pack to build the nupkg and then expand it as a zip.
+ After expanding we restore the signed files for the modules from the gallery.
+ We also delete pdbs, content and contentFiles folder which are not necessary.
+ After that, we repack using Compress-Archive and rename it back to a nupkg.
+ #>
+
+ Import-Module -Name $(PowerShellRoot)/build.psm1 -Force
+ Start-PSBootstrap
+ $packagingStrings = Import-PowerShellDataFile "$(PowerShellRoot)\tools\packaging\packaging.strings.psd1"
+
+ $outputPath = Join-Path '$(ob_outputDirectory)' 'globaltool'
+ $null = New-Item -ItemType Directory -Path $outputPath -Force
+ $globalToolCsProjDir = Join-Path $(PowerShellRoot) 'src' 'GlobalTools' 'PowerShell.Windows.x64'
+ Push-Location -Path $globalToolCsProjDir -Verbose
+
+ <#
+ $nuspecFilePath = "$globalToolCsProjDir\PowerShell.Windows.x64.nuspec"
+ $nuSpec = $packagingStrings.WindowsX64GlobalToolNuspec -f '$(Version)'
+ $nuSpec | Out-File -FilePath $nuspecFilePath -Encoding ascii
+ #>
+
+ dotnet pack --output $outputPath --no-build --artifacts-path '$(GlobalToolArtifactPath)' /property:PackageVersion=$(Version) /property:PackageIcon=Powershell_64.png
+
+ Write-Verbose -Verbose "Deleting content and contentFiles folders from the nupkg"
+
+ $nupkgs = Get-ChildItem -Path $outputPath -Filter powershell*.nupkg
+
+ $nupkgName = $nupkgs.Name
+ $newName = $nupkgName -replace '(\.nupkg)$', '.zip'
+ Rename-Item -Path $nupkgs.FullName -NewName $newName
+
+ $zipPath = Get-ChildItem -Path $outputPath -Filter powershell*.zip
+
+ # Expand zip and remove content and contentFiles folders
+ Expand-Archive -Path $zipPath -DestinationPath "$outputPath\temp" -Force
+
+ $modulesToCopy = @(
+ 'PowerShellGet'
+ 'PackageManagement'
+ 'Microsoft.PowerShell.PSResourceGet'
+ 'Microsoft.PowerShell.Archive'
+ 'PSReadLine'
+ 'ThreadJob'
+ )
+
+ $sourceModulePath = Join-Path '$(GlobalToolArtifactPath)' 'publish' 'PowerShell.Windows.x64' 'release' 'Modules'
+ $destModulesPath = Join-Path "$outputPath" 'temp' 'tools' 'net9.0' 'any' 'modules'
+
+ $modulesToCopy | ForEach-Object {
+ $modulePath = Join-Path $sourceModulePath $_
+ Copy-Item -Path $modulePath -Destination $destModulesPath -Recurse -Force
+ }
+
+ # Copy ref assemblies
+ Copy-Item '$(Pipeline.Workspace)/Symbols_$(Architecture)/ref' "$outputPath\temp\tools\net9.0\any\ref" -Recurse -Force
+
+ $contentPath = Join-Path "$outputPath\temp" 'content'
+ $contentFilesPath = Join-Path "$outputPath\temp" 'contentFiles'
+
+ Remove-Item -Path $contentPath,$contentFilesPath -Recurse -Force
+
+ # remove PDBs to reduce the size of the nupkg
+ Remove-Item -Path "$outputPath\temp\tools\net9.0\any\*.pdb" -Recurse -Force
+
+ Compress-Archive -Path "$outputPath\temp\*" -DestinationPath "$outputPath\$nupkgName" -Force
+
+ Remove-Item -Path "$outputPath\temp" -Recurse -Force
+ Remove-Item -Path $zipPath -Force
+
+ if (-not (Test-Path "$outputPath\powershell.windows.x64.*.nupkg")) {
+ throw "Global tool package not found at $outputPath"
+ }
+ displayName: 'Pack Windows.x64 global tool'
+ condition: and(succeeded(), eq(variables['Architecture'], 'fxdependent'))
+
+ - task: onebranch.pipeline.signing@1
+ displayName: Sign nupkg files
+ inputs:
+ command: 'sign'
+ cp_code: 'CP-401405'
+ files_to_sign: '**\*.nupkg'
+ search_root: '$(ob_outputDirectory)\globaltool'
+ condition: and(succeeded(), eq(variables['Architecture'], 'fxdependent'))
+
- template: /.pipelines/templates/step/finalize.yml@self
diff --git a/src/GlobalTools/PowerShell.Windows.x64/PowerShell.Windows.x64.csproj b/src/GlobalTools/PowerShell.Windows.x64/PowerShell.Windows.x64.csproj
new file mode 100644
index 00000000000..045faad6144
--- /dev/null
+++ b/src/GlobalTools/PowerShell.Windows.x64/PowerShell.Windows.x64.csproj
@@ -0,0 +1,31 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+ true
+ win-x64
+ pwsh
+ $(PackageVersion)
+
+
+
+
+
+ Modules\%(RecursiveDir)\%(FileName)%(Extension)
+ PreserveNewest
+ PreserveNewest
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/GlobalTools/PowerShell.Windows.x64/Powershell_64.png b/src/GlobalTools/PowerShell.Windows.x64/Powershell_64.png
new file mode 100644
index 00000000000..2a656ffc3c8
Binary files /dev/null and b/src/GlobalTools/PowerShell.Windows.x64/Powershell_64.png differ
diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1
index f7295bffcf1..8ba16f9e284 100644
--- a/tools/packaging/packaging.psm1
+++ b/tools/packaging/packaging.psm1
@@ -4314,20 +4314,22 @@ function New-GlobalToolNupkgSource
$toolSettings = $packagingStrings.GlobalToolSettingsFile -f "pwsh.dll"
}
- "PowerShell.Windows.x64"
- {
- $PackageName = "PowerShell.Windows.x64"
- $RootFolder = New-TempFolder
-
- Copy-Item -Path $iconPath -Destination "$RootFolder/$iconFileName" -Verbose
-
- $ridFolder = New-Item -Path (Join-Path $RootFolder "tools/$script:netCoreRuntime/any") -ItemType Directory
-
- Write-Log "New-GlobalToolNupkgSource: Copying runtime assemblies from $WindowsDesktopBinPath for $PackageType"
- Copy-Item "$WindowsDesktopBinPath/*" -Destination $ridFolder -Recurse
- Remove-Item -Path $ridFolder/runtimes/win-arm -Recurse -Force
- $toolSettings = $packagingStrings.GlobalToolSettingsFile -f "pwsh.dll"
- }
+ # Due to needing a signed shim for the global tool, we build the global tool in build instead of packaging.
+ # keeping the code for reference.
+ # "PowerShell.Windows.x64"
+ # {
+ # $PackageName = "PowerShell.Windows.x64"
+ # $RootFolder = New-TempFolder
+
+ # Copy-Item -Path $iconPath -Destination "$RootFolder/$iconFileName" -Verbose
+
+ # $ridFolder = New-Item -Path (Join-Path $RootFolder "tools/$script:netCoreRuntime/any") -ItemType Directory
+
+ # Write-Log "New-GlobalToolNupkgSource: Copying runtime assemblies from $WindowsDesktopBinPath for $PackageType"
+ # Copy-Item "$WindowsDesktopBinPath/*" -Destination $ridFolder -Recurse
+ # Remove-Item -Path $ridFolder/runtimes/win-arm -Recurse -Force
+ # $toolSettings = $packagingStrings.GlobalToolSettingsFile -f "pwsh.dll"
+ # }
"PowerShell.Windows.arm32"
{
diff --git a/tools/packaging/packaging.strings.psd1 b/tools/packaging/packaging.strings.psd1
index 39afb75a96b..adf39654d95 100644
--- a/tools/packaging/packaging.strings.psd1
+++ b/tools/packaging/packaging.strings.psd1
@@ -193,6 +193,29 @@ open {0}
+'@
+
+ WindowsX64GlobalToolNuspec = @'
+
+
+
+ PowerShelll.Windows.x64
+ {0}
+ Microsoft
+ Microsoft,PowerShell
+ https://github.com/PowerShell/PowerShell
+ Powershell_64.png
+ false
+ PowerShell global tool
+ MIT
+ PowerShell
+ en-US
+ © Microsoft Corporation. All rights reserved.
+
+
+
+
+
'@
GlobalToolSettingsFile = @'