diff --git a/windows-release/azure-pipelines.yml b/windows-release/azure-pipelines.yml index f06dbc01..ee5f8adf 100644 --- a/windows-release/azure-pipelines.yml +++ b/windows-release/azure-pipelines.yml @@ -39,6 +39,10 @@ parameters: displayName: "Signature description" type: string default: 'Built: $(Build.BuildNumber)' +- name: DoFreethreaded + displayName: "Include free-threaded builds (3.13 and later)" + type: boolean + default: true - name: DoARM64 displayName: "Publish ARM64 build (3.11 and later)" type: boolean @@ -106,6 +110,7 @@ variables: ${{ else }}: IsRealSigned: false DoCHM: ${{ parameters.DoCHM }} + DoFreethreaded: ${{ parameters.DoFreethreaded }} DoLayout: ${{ parameters.DoLayout }} DoMSIX: ${{ parameters.DoMSIX }} DoNuget: ${{ parameters.DoNuget }} @@ -128,6 +133,7 @@ stages: - template: stage-build.yml parameters: ARM64TclTk: ${{ parameters.ARM64TclTk }} + DoFreethreaded: ${{ parameters.DoFreethreaded }} DoPGO: ${{ parameters.DoPGO }} DoPGOARM64: ${{ parameters.DoPGOARM64 }} @@ -147,8 +153,11 @@ stages: - template: stage-layout-full.yml parameters: ARM64TclTk: ${{ parameters.ARM64TclTk }} + DoFreethreaded: ${{ parameters.DoFreethreaded }} - template: stage-layout-embed.yml - template: stage-layout-nuget.yml + parameters: + DoFreethreaded: ${{ parameters.DoFreethreaded }} - stage: Pack dependsOn: Layout @@ -157,12 +166,15 @@ stages: parameters: ${{ if and(parameters.SigningCertificate, ne(parameters.SigningCertificate, 'Unsigned')) }}: SigningCertificate: ${{ parameters.SigningCertificate }} + DoFreethreaded: ${{ parameters.DoFreethreaded }} - stage: Test dependsOn: Pack jobs: - template: stage-test-embed.yml - template: stage-test-nuget.yml + parameters: + DoFreethreaded: ${{ parameters.DoFreethreaded }} - ${{ if eq(parameters.DoMSIX, 'true') }}: - stage: Layout_MSIX @@ -192,12 +204,15 @@ stages: ARM64TclTk: ${{ parameters.ARM64TclTk }} ${{ if and(parameters.SigningCertificate, ne(parameters.SigningCertificate, 'Unsigned')) }}: SigningCertificate: ${{ parameters.SigningCertificate }} + DoFreethreaded: ${{ parameters.DoFreethreaded }} - stage: Test_MSI displayName: Test MSI installer dependsOn: Build_MSI jobs: - template: stage-test-msi.yml + parameters: + DoFreethreaded: ${{ parameters.DoFreethreaded }} - ${{ if eq(parameters.DoPublish, 'true') }}: - ${{ if eq(parameters.DoMSI, 'true') }}: diff --git a/windows-release/build-steps-pgo.yml b/windows-release/build-steps-pgo.yml index 32c8a670..fa18a047 100644 --- a/windows-release/build-steps-pgo.yml +++ b/windows-release/build-steps-pgo.yml @@ -2,6 +2,7 @@ parameters: PGInstrument: false PGRun: false PGUpdate: false + DoFreethreaded: false steps: - template: ./checkout.yml @@ -28,6 +29,15 @@ steps: IncludeUwp: true Py_OutDir: '$(Build.BinariesDirectory)\bin' + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - powershell: | + $env:SigningCertificate = $null + .\PCbuild\build.bat -v -p $(Platform) -c PGInstrument --disable-gil + displayName: 'Run free-threaded build' + env: + IncludeUwp: true + Py_OutDir: '$(Build.BinariesDirectory)\bin' + - ${{ if ne(parameters.PGRun, 'true') }}: # Not running in this job, so we publish our entire build and object files @@ -66,6 +76,16 @@ steps: env: PYTHONHOME: '$(Build.SourcesDirectory)' + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - powershell: | + $exe = (gci "$(Build.BinariesDirectory)\bin\$(Arch)\instrumented\python3*t.exe" | select -First 1) + & $exe -m test --pgo + ignoreLASTEXITCODE: true + displayName: 'Collect free-threaded profile' + env: + PYTHONHOME: '$(Build.SourcesDirectory)' + + - ${{ if ne(parameters.PGUpdate, 'true') }}: # Not finishing in this job, so publish the binaries - task: PublishPipelineArtifact@0 @@ -107,6 +127,15 @@ steps: IncludeUwp: true Py_OutDir: '$(Build.BinariesDirectory)\bin' + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - powershell: | + $env:SigningCertificate = $null + .\PCbuild\build.bat -v -p $(Platform) -c PGUpdate --disable-gil + displayName: 'Run free-threaded build with PGO' + env: + IncludeUwp: true + Py_OutDir: '$(Build.BinariesDirectory)\bin' + - powershell: | $kitroot = (gp 'HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots\').KitsRoot10 $tool = (gci -r "$kitroot\Bin\*\x64\signtool.exe" | sort FullName -Desc | select -First 1) diff --git a/windows-release/build-steps.yml b/windows-release/build-steps.yml index 228b93a4..0bee73b8 100644 --- a/windows-release/build-steps.yml +++ b/windows-release/build-steps.yml @@ -1,5 +1,6 @@ parameters: ShouldPGO: false + DoFreethreaded: false steps: - template: ./checkout.yml @@ -15,6 +16,12 @@ steps: Write-Host "##vso[build.addbuildtag]$($d.PythonVersion)-$(Name)" displayName: 'Extract version numbers' +- ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - powershell: | + Write-Host "##vso[build.addbuildtag]freethreaded" + Write-Host "##vso[build.addbuildtag]$(VersionText)-freethreaded" + displayName: 'Add freethreaded tags' + - ${{ if eq(parameters.ShouldPGO, 'false') }}: - powershell: | $env:SigningCertificate = $null @@ -24,6 +31,15 @@ steps: IncludeUwp: true Py_OutDir: '$(Build.BinariesDirectory)\bin' + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - powershell: | + $env:SigningCertificate = $null + .\PCbuild\build.bat -v -p $(Platform) -c $(Configuration) --disable-gil + displayName: 'Run free-threaded build' + env: + IncludeUwp: true + Py_OutDir: '$(Build.BinariesDirectory)\bin' + - ${{ if eq(parameters.ShouldPGO, 'true') }}: - powershell: | $env:SigningCertificate = $null @@ -33,6 +49,15 @@ steps: IncludeUwp: true Py_OutDir: '$(Build.BinariesDirectory)\bin' + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - powershell: | + $env:SigningCertificate = $null + .\PCbuild\build.bat -v -p $(Platform) --pgo --disable-gil + displayName: 'Run free-threaded build' + env: + IncludeUwp: true + Py_OutDir: '$(Build.BinariesDirectory)\bin' + - powershell: | $kitroot = (gp 'HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots\').KitsRoot10 $tool = (gci -r "$kitroot\Bin\*\x64\signtool.exe" | sort FullName -Desc | select -First 1) diff --git a/windows-release/msi-steps.yml b/windows-release/msi-steps.yml index 89f3150a..d9e14ccd 100644 --- a/windows-release/msi-steps.yml +++ b/windows-release/msi-steps.yml @@ -1,5 +1,6 @@ parameters: ARM64TclTk: true + DoFreethreaded: false SigningCertificate: '' steps: @@ -90,7 +91,7 @@ steps: call Tools\msi\get_externals.bat call PCbuild\find_python.bat echo ##vso[task.setvariable variable=PYTHON]%PYTHON% - call PCbuild/find_msbuild.bat + call PCbuild\find_msbuild.bat echo ##vso[task.setvariable variable=MSBUILD]%MSBUILD% displayName: 'Get external dependencies' @@ -106,6 +107,12 @@ steps: gc msbuild.rsp displayName: 'Generate response file' + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - powershell: | + "/p:IncludeFreethreaded=true" | Out-File "$(ResponseFile)" -Append -Encoding UTF8 + gc "$(ResponseFile)" + displayName: 'Add Include_freethreaded to response file' + - ${{ if parameters.SigningCertificate }}: - task: DotNetCoreCLI@2 inputs: diff --git a/windows-release/purge.py b/windows-release/purge.py index de9fdc95..c5f2c10c 100644 --- a/windows-release/purge.py +++ b/windows-release/purge.py @@ -37,6 +37,9 @@ "exe.msi", "exe_d.msi", "exe_pdb.msi", + "freethreaded.msi", + "freethreaded_d.msi", + "freethreaded_pdb.msi", "launcher.msi", "lib.msi", "lib_d.msi", diff --git a/windows-release/stage-build.yml b/windows-release/stage-build.yml index ce9e30d9..7a98b376 100644 --- a/windows-release/stage-build.yml +++ b/windows-release/stage-build.yml @@ -3,6 +3,7 @@ parameters: DoPGO: false # DoPGOARM64 only applies if DoPGO is also true DoPGOARM64: true + DoFreethreaded: false jobs: - job: Build_Docs @@ -95,6 +96,8 @@ jobs: steps: - template: ./build-steps.yml + parameters: + DoFreethreaded: ${{ parameters.DoFreethreaded }} - ${{ if eq(parameters.DoPGO, 'true') }}: @@ -118,6 +121,7 @@ jobs: steps: - template: ./build-steps-pgo.yml parameters: + DoFreethreaded: ${{ parameters.DoFreethreaded }} PGInstrument: true PGRun: true PGUpdate: true @@ -143,6 +147,7 @@ jobs: steps: - template: ./build-steps-pgo.yml parameters: + DoFreethreaded: ${{ parameters.DoFreethreaded }} PGInstrument: true - job: Build_Python_PGO_2 @@ -168,6 +173,7 @@ jobs: steps: - template: ./build-steps-pgo.yml parameters: + DoFreethreaded: ${{ parameters.DoFreethreaded }} PGRun: true - job: Build_Python_PGO_3 @@ -191,6 +197,7 @@ jobs: steps: - template: ./build-steps-pgo.yml parameters: + DoFreethreaded: ${{ parameters.DoFreethreaded }} PGUpdate: true diff --git a/windows-release/stage-layout-full.yml b/windows-release/stage-layout-full.yml index 343ee1f7..3eb45ca3 100644 --- a/windows-release/stage-layout-full.yml +++ b/windows-release/stage-layout-full.yml @@ -1,5 +1,6 @@ parameters: ARM64TclTk: true + DoFreethreaded: false jobs: - job: Make_Layouts @@ -73,8 +74,22 @@ jobs: env: TCL_LIBRARY: $(TclLibrary) + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - powershell: | + $(LayoutCmd) --copy "$(Build.ArtifactStagingDirectory)\layout_freethreaded" --preset-default --include-freethreaded + displayName: 'Generate full freethreaded layout' + env: + TCL_LIBRARY: $(TclLibrary) + - task: PublishPipelineArtifact@0 displayName: 'Publish Artifact: layout_full_$(Name)' inputs: targetPath: '$(Build.ArtifactStagingDirectory)\layout' artifactName: layout_full_$(Name) + + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - task: PublishPipelineArtifact@0 + displayName: 'Publish Artifact: layout_full_freethreaded_$(Name)' + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)\layout_freethreaded' + artifactName: layout_full_freethreaded_$(Name) diff --git a/windows-release/stage-layout-nuget.yml b/windows-release/stage-layout-nuget.yml index b60a324d..215c0fb6 100644 --- a/windows-release/stage-layout-nuget.yml +++ b/windows-release/stage-layout-nuget.yml @@ -1,3 +1,6 @@ +parameters: + DoFreethreaded: false + jobs: - job: Make_Nuget_Layout displayName: Make Nuget layout @@ -45,8 +48,20 @@ jobs: $(LayoutCmd) --copy "$(Build.ArtifactStagingDirectory)\nuget" --preset-nuget displayName: 'Generate nuget layout' + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - powershell: | + $(LayoutCmd) --copy "$(Build.ArtifactStagingDirectory)\nuget_freethreaded" --preset-nuget --include-freethreaded + displayName: 'Generate freethreaded nuget layout' + - task: PublishPipelineArtifact@0 displayName: 'Publish Artifact: layout_nuget_$(Name)' inputs: targetPath: '$(Build.ArtifactStagingDirectory)\nuget' artifactName: layout_nuget_$(Name) + + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - task: PublishPipelineArtifact@0 + displayName: 'Publish Artifact: layout_nuget_freethreaded_$(Name)' + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)\nuget_freethreaded' + artifactName: layout_nuget_freethreaded_$(Name) diff --git a/windows-release/stage-msi.yml b/windows-release/stage-msi.yml index d4cf4c9b..0b6fa76c 100644 --- a/windows-release/stage-msi.yml +++ b/windows-release/stage-msi.yml @@ -1,15 +1,16 @@ parameters: ARM64TclTk: true + DoFreethreaded: false SigningCertificate: '' jobs: - ${{ if parameters.SigningCertificate }}: - job: Make_Signed_MSI displayName: Make signed MSI - + pool: vmImage: windows-2022 - + variables: - group: CPythonSign - name: ReleaseUri @@ -18,10 +19,10 @@ jobs: value: https://www.python.org/ftp/python/{version}/{arch}{releasename}/{msi} - name: Py_OutDir value: $(Build.BinariesDirectory) - + workspace: clean: all - + steps: - template: msi-steps.yml parameters: @@ -32,19 +33,20 @@ jobs: - ${{ else }}: - job: Make_MSI displayName: Make MSI - + pool: vmImage: windows-2022 - + variables: ReleaseUri: http://www.python.org/{arch} DownloadUrl: https://www.python.org/ftp/python/{version}/{arch}{releasename}/{msi} Py_OutDir: $(Build.BinariesDirectory) - + workspace: clean: all - + steps: - template: msi-steps.yml parameters: ARM64TclTk: ${{ parameters.ARM64TclTk }} + DoFreethreaded: ${{ parameters.DoFreethreaded }} diff --git a/windows-release/stage-pack-nuget.yml b/windows-release/stage-pack-nuget.yml index 2b4721da..ded8ce6c 100644 --- a/windows-release/stage-pack-nuget.yml +++ b/windows-release/stage-pack-nuget.yml @@ -1,4 +1,5 @@ parameters: + DoFreethreaded: false SigningCertificate: '' jobs: @@ -34,6 +35,13 @@ jobs: artifactName: layout_nuget_$(Name) targetPath: $(Build.BinariesDirectory)\layout + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - task: DownloadPipelineArtifact@1 + displayName: 'Download artifact: layout_nuget_freethreaded_$(Name)' + inputs: + artifactName: layout_nuget_freethreaded_$(Name) + targetPath: $(Build.BinariesDirectory)\layout_freethreaded + - task: NugetToolInstaller@0 displayName: 'Install Nuget' inputs: @@ -58,6 +66,26 @@ jobs: condition: and(succeeded(), variables['OverrideNugetVersion']) displayName: 'Create nuget package' + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - powershell: > + nuget pack + "$(Build.BinariesDirectory)\layout_freethreaded\python.nuspec" + -OutputDirectory $(Build.ArtifactStagingDirectory) + -NoPackageAnalysis + -NonInteractive + condition: and(succeeded(), not(variables['OverrideNugetVersion'])) + displayName: 'Create freethreaded nuget package' + + - powershell: > + nuget pack + "$(Build.BinariesDirectory)\layout_freethreaded\python.nuspec" + -OutputDirectory $(Build.ArtifactStagingDirectory) + -NoPackageAnalysis + -NonInteractive + -Version "$(OverrideNugetVersion)" + condition: and(succeeded(), variables['OverrideNugetVersion']) + displayName: 'Create freethreaded nuget package' + - template: sign-nuget-files.yml parameters: Include: '*.nupkg' diff --git a/windows-release/stage-test-msi.yml b/windows-release/stage-test-msi.yml index 9aef742f..4f9f1009 100644 --- a/windows-release/stage-test-msi.yml +++ b/windows-release/stage-test-msi.yml @@ -1,3 +1,6 @@ +parameters: + DoFreethreaded: false + jobs: - job: Test_MSI displayName: Test MSI @@ -8,6 +11,12 @@ jobs: workspace: clean: all + variables: + ${{ if eq(parameters.DoFreethreaded, 'true') }}: + IncludeFreethreadedOpt: Include_freethreaded=1 + ${{ else }}: + IncludeFreethreadedOpt: '' + strategy: matrix: win32_User: @@ -51,8 +60,13 @@ jobs: Include_debug=1 Include_symbols=1 InstallAllUsers=$(InstallAllUsers) + $(IncludeFreethreadedOpt) displayName: 'Install Python' + - powershell: | + gci "$(Build.BinariesDirectory)\python" + displayName: 'List installed files' + - powershell: | $p = gi "$(Build.BinariesDirectory)\Python\python.exe" Write-Host "##vso[task.prependpath]$(Split-Path -Parent $p)" @@ -68,6 +82,14 @@ jobs: displayName: 'Collect site' condition: and(succeeded(), not(variables['SkipTests'])) + - ${{ if eq(parameters.DoFreethreaded, 'true') }}: + - powershell: | + $p = (gci "$(Build.BinariesDirectory)\Python\python3*t.exe" | select -First 1) + Write-Host "Found $p" + & $p -c "import sys; print(sys.version)" + displayName: 'Collect free-threaded version number' + condition: and(succeeded(), not(variables['SkipTests'])) + - powershell: | gci -r "${env:PROGRAMDATA}\Microsoft\Windows\Start Menu\Programs\Python*" displayName: 'Capture per-machine Start Menu items'