-
Notifications
You must be signed in to change notification settings - Fork 123
/
Copy pathmacos-python-builder.psm1
195 lines (153 loc) · 6.9 KB
/
macos-python-builder.psm1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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.
#>
}
[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.
### 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)
$configureString += " --with-openssl=/usr/local/opt/openssl@3"
$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'"
### Compile with support of loadable sqlite extensions.
### Link to documentation (https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.enable_load_extension)
$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()
}
}