mirror of
https://github.com/actions/python-versions.git
synced 2025-04-04 14:29:38 +00:00
* Support building free-threaded CPython Add support for Python's free threading build mode where the global interpreter lock is disabled. The packages are marked using a suffix on the architecture, like 'x64-freethreaded' or 'arm64-freethreaded'. * Match '-freethreaded' in arch * Use type 'string' instead of 'str' * On Linux, only delete Python installations with the same architecture. This matches the macOS behavior and allows users to install both the free-threading and default builds at the same time.
230 lines
8.8 KiB
PowerShell
230 lines
8.8 KiB
PowerShell
using module "./nix-python-builder.psm1"
|
|
|
|
class macOSPythonBuilder : NixPythonBuilder {
|
|
<#
|
|
.SYNOPSIS
|
|
MacOS Python builder class.
|
|
|
|
.DESCRIPTION
|
|
Contains methods that required to build macOS Python artifact from sources. Inherited from base NixPythonBuilder.
|
|
|
|
While python.org provides precompiled binaries for macOS, switching to them risks breaking existing customers.
|
|
If we wanted to start using the official binaries instead of building from source, we should avoid changing previous versions
|
|
so we remain backwards compatible.
|
|
|
|
.PARAMETER platform
|
|
The full name of platform for which Python should be built.
|
|
|
|
.PARAMETER version
|
|
The version of Python that should be built.
|
|
|
|
#>
|
|
|
|
macOSPythonBuilder(
|
|
[semver] $version,
|
|
[string] $architecture,
|
|
[string] $platform
|
|
) : Base($version, $architecture, $platform) { }
|
|
|
|
[void] PrepareEnvironment() {
|
|
<#
|
|
.SYNOPSIS
|
|
Prepare system environment by installing dependencies and required packages.
|
|
#>
|
|
|
|
if ($this.Version -eq "3.7.17") {
|
|
# We have preinstalled ncurses and readLine on the hoster runners. But we need to install bzip2 for
|
|
# setting up an environemnt
|
|
# If we get any issues realted to ncurses or readline we can try to run this command
|
|
# brew install ncurses readline
|
|
Execute-Command -Command "brew install bzip2"
|
|
}
|
|
}
|
|
|
|
[void] Configure() {
|
|
<#
|
|
.SYNOPSIS
|
|
Execute configure script with required parameters.
|
|
#>
|
|
|
|
$pythonBinariesLocation = $this.GetFullPythonToolcacheLocation()
|
|
$configureString = "./configure"
|
|
$configureString += " --prefix=$pythonBinariesLocation"
|
|
$configureString += " --enable-optimizations"
|
|
$configureString += " --enable-shared"
|
|
$configureString += " --with-lto"
|
|
|
|
### For Python versions which support it, compile a universal2 (arm64 + x86_64 hybrid) build. The arm64 slice
|
|
### will never be used itself by a Github Actions runner but using a universal2 Python is the only way to build
|
|
### universal2 C extensions and wheels. This is supported by Python >= 3.10 and was backported to Python >=
|
|
### 3.9.1 and >= 3.8.10.
|
|
### Disabled, discussion: https://github.com/actions/python-versions/pull/114
|
|
# if ($this.Version -ge "3.8.10" -and $this.Version -ne "3.8.13" -and $this.Version -ne "3.9.0" ) {
|
|
# $configureString += " --enable-universalsdk --with-universal-archs=universal2"
|
|
# }
|
|
|
|
### OS X 10.11, Apple no longer provides header files for the deprecated system version of OpenSSL.
|
|
### Solution is to install these libraries from a third-party package manager,
|
|
### and then add the appropriate paths for the header and library files to configure command.
|
|
### Link to documentation (https://cpython-devguide.readthedocs.io/setup/#build-dependencies)
|
|
if ($this.Version -lt "3.7.0") {
|
|
$env:LDFLAGS = "-L/usr/local/opt/openssl@3/lib -L/usr/local/opt/zlib/lib"
|
|
$env:CFLAGS = "-I/usr/local/opt/openssl@3/include -I/usr/local/opt/zlib/include"
|
|
} else {
|
|
$configureString += " --with-openssl=/usr/local/opt/openssl@3"
|
|
|
|
# For Python 3.7.2 and 3.7.3 we need to provide PATH for zlib to pack it properly. Otherwise the build will fail
|
|
# with the error: zipimport.ZipImportError: can't decompress data; zlib not available
|
|
if ($this.Version -eq "3.7.2" -or $this.Version -eq "3.7.3" -or $this.Version -eq "3.7.17") {
|
|
$env:LDFLAGS = "-L/usr/local/opt/zlib/lib"
|
|
$env:CFLAGS = "-I/usr/local/opt/zlib/include"
|
|
}
|
|
|
|
# if ($this.Version -gt "3.7.12") {
|
|
$configureString += " --with-tcltk-includes='-I /usr/local/opt/tcl-tk/include/tcl-tk' --with-tcltk-libs='-L/usr/local/opt/tcl-tk/lib -ltcl8.6 -ltk8.6'"
|
|
# }
|
|
|
|
if ($this.Version -eq "3.7.17") {
|
|
$env:LDFLAGS += " -L$(brew --prefix bzip2)/lib -L$(brew --prefix readline)/lib -L$(brew --prefix ncurses)/lib"
|
|
$env:CFLAGS += " -I$(brew --prefix bzip2)/include -I$(brew --prefix readline)/include -I$(brew --prefix ncurses)/include"
|
|
}
|
|
}
|
|
|
|
### Compile with support of loadable sqlite extensions. Unavailable for Python 2.*
|
|
### Link to documentation (https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.enable_load_extension)
|
|
if ($this.Version -ge "3.2.0") {
|
|
$configureString += " --enable-loadable-sqlite-extensions"
|
|
$env:LDFLAGS += " -L$(brew --prefix sqlite3)/lib"
|
|
$env:CFLAGS += " -I$(brew --prefix sqlite3)/include"
|
|
$env:CPPFLAGS += "-I$(brew --prefix sqlite3)/include"
|
|
}
|
|
|
|
Write-Host "The passed configure options are: "
|
|
Write-Host $configureString
|
|
|
|
Execute-Command -Command $configureString
|
|
}
|
|
|
|
[string] GetPkgName() {
|
|
<#
|
|
.SYNOPSIS
|
|
Return Python installation Package.
|
|
#>
|
|
|
|
$nativeVersion = Convert-Version -version $this.Version
|
|
$architecture = "-macos11"
|
|
$extension = ".pkg"
|
|
|
|
$pkg = "python-${nativeVersion}${architecture}${extension}"
|
|
|
|
return $pkg
|
|
}
|
|
|
|
[uri] GetPkgUri() {
|
|
<#
|
|
.SYNOPSIS
|
|
Get base Python URI and return complete URI for Python installation package.
|
|
#>
|
|
|
|
$base = $this.GetBaseUri()
|
|
$versionName = $this.GetBaseVersion()
|
|
$pkg = $this.GetPkgName()
|
|
|
|
$uri = "${base}/${versionName}/${pkg}"
|
|
|
|
return $uri
|
|
}
|
|
|
|
[string] DownloadPkg() {
|
|
<#
|
|
.SYNOPSIS
|
|
Download Python installation executable into artifact location.
|
|
#>
|
|
|
|
$pkgUri = $this.GetPkgUri()
|
|
|
|
Write-Host "Sources URI: $pkgUri"
|
|
$pkgLocation = Download-File -Uri $pkgUri -OutputFolder $this.WorkFolderLocation
|
|
Write-Debug "Done; Package location: $pkgLocation"
|
|
|
|
New-Item -Path $this.WorkFolderLocation -Name "build_output.txt" -ItemType File
|
|
return $pkgLocation
|
|
}
|
|
|
|
[string] GetFrameworkName() {
|
|
<#
|
|
.SYNOPSIS
|
|
Get the Python installation Package name.
|
|
#>
|
|
|
|
if ($this.IsFreeThreaded()) {
|
|
return "PythonT.framework"
|
|
} else {
|
|
return "Python.framework"
|
|
}
|
|
}
|
|
|
|
[string] GetPkgChoices() {
|
|
<#
|
|
.SYNOPSIS
|
|
Reads the configuration XML file for the Python installer
|
|
#>
|
|
|
|
$config = if ($this.IsFreeThreaded()) { "freethreaded" } else { "default" }
|
|
$choicesFile = Join-Path $PSScriptRoot "../config/macos-pkg-choices-$($config).xml"
|
|
$choicesTemplate = Get-Content -Path $choicesFile -Raw
|
|
|
|
$variablesToReplace = @{
|
|
"{{__VERSION_MAJOR_MINOR__}}" = "$($this.Version.Major).$($this.Version.Minor)";
|
|
}
|
|
|
|
$variablesToReplace.keys | ForEach-Object { $choicesTemplate = $choicesTemplate.Replace($_, $variablesToReplace[$_]) }
|
|
return $choicesTemplate
|
|
}
|
|
|
|
[void] CreateInstallationScriptPkg() {
|
|
<#
|
|
.SYNOPSIS
|
|
Create Python artifact installation script based on specified template.
|
|
#>
|
|
|
|
$installationTemplateLocation = Join-Path -Path $this.InstallationTemplatesLocation -ChildPath "macos-pkg-setup-template.sh"
|
|
$installationTemplateContent = Get-Content -Path $installationTemplateLocation -Raw
|
|
$installationScriptLocation = New-Item -Path $this.WorkFolderLocation -Name $this.InstallationScriptName -ItemType File
|
|
|
|
$variablesToReplace = @{
|
|
"{{__VERSION_FULL__}}" = $this.Version;
|
|
"{{__PKG_NAME__}}" = $this.GetPkgName();
|
|
"{{__ARCH__}}" = $this.Architecture;
|
|
"{{__FRAMEWORK_NAME__}}" = $this.GetFrameworkName();
|
|
"{{__PKG_CHOICES__}}" = $this.GetPkgChoices();
|
|
}
|
|
|
|
$variablesToReplace.keys | ForEach-Object { $installationTemplateContent = $installationTemplateContent.Replace($_, $variablesToReplace[$_]) }
|
|
$installationTemplateContent | Out-File -FilePath $installationScriptLocation
|
|
Write-Debug "Done; Installation script location: $installationScriptLocation)"
|
|
}
|
|
|
|
[void] Build() {
|
|
<#
|
|
.SYNOPSIS
|
|
Generates Python artifact from downloaded Python installation executable.
|
|
#>
|
|
|
|
$PkgVersion = [semver]"3.11.0-beta.1"
|
|
|
|
if (($this.Version -ge $PkgVersion) -or ($this.Architecture -eq "arm64")) {
|
|
Write-Host "Download Python $($this.Version) [$($this.Architecture)] package..."
|
|
$this.DownloadPkg()
|
|
|
|
Write-Host "Create installation script..."
|
|
$this.CreateInstallationScriptPkg()
|
|
} else {
|
|
([NixPythonBuilder]$this).Build()
|
|
}
|
|
|
|
Write-Host "Archive artifact"
|
|
$this.ArchiveArtifact()
|
|
}
|
|
}
|