mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-09 18:05:36 +08:00
feat(tool): bundle python for the meson build
- add a python-win tool package that unzips the official python.org nuget package into the pkgroot (venv and ensurepip included) - meson uses it to build its venv and only falls back to a system python, so no manual environment setup is needed
This commit is contained in:
@@ -18,6 +18,7 @@ postgresql:
|
||||
- openssl
|
||||
- zlib
|
||||
tools@windows:
|
||||
- python-win
|
||||
- meson
|
||||
- ninja
|
||||
- winflexbison
|
||||
|
||||
8
config/pkg/tool/python-win.yml
Normal file
8
config/pkg/tool/python-win.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
python-win:
|
||||
type: tool
|
||||
artifact:
|
||||
binary: custom
|
||||
tool:
|
||||
provides:
|
||||
- python.exe
|
||||
binary-subdir: python-win/tools
|
||||
@@ -22,8 +22,11 @@ class meson_win
|
||||
$dir = dirname($target_path);
|
||||
$venv = "{$dir}\\venv";
|
||||
|
||||
// Prefer the python-win tool package (installed alongside via tools@windows),
|
||||
// fall back to whatever Python the machine already has.
|
||||
$candidates = ['"' . PKG_ROOT_PATH . '\python-win\tools\python.exe"', 'python', 'py -3'];
|
||||
$python = null;
|
||||
foreach (['python', 'py -3'] as $candidate) {
|
||||
foreach ($candidates as $candidate) {
|
||||
[$code] = cmd()->execWithResult("{$candidate} --version", false);
|
||||
if ($code === 0) {
|
||||
$python = $candidate;
|
||||
@@ -31,7 +34,7 @@ class meson_win
|
||||
}
|
||||
}
|
||||
if ($python === null) {
|
||||
throw new EnvironmentException('meson needs Python 3 on PATH. Install it from https://www.python.org or with `winget install Python.Python.3.13`.');
|
||||
throw new EnvironmentException('meson needs Python 3; the python-win tool package did not install and no system Python was found.');
|
||||
}
|
||||
|
||||
if (is_dir($venv)) {
|
||||
|
||||
66
src/Package/Artifact/python_win.php
Normal file
66
src/Package/Artifact/python_win.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Package\Artifact;
|
||||
|
||||
use StaticPHP\Artifact\ArtifactDownloader;
|
||||
use StaticPHP\Artifact\Downloader\DownloadResult;
|
||||
use StaticPHP\Artifact\Downloader\Type\CheckUpdateResult;
|
||||
use StaticPHP\Attribute\Artifact\AfterBinaryExtract;
|
||||
use StaticPHP\Attribute\Artifact\CustomBinary;
|
||||
use StaticPHP\Attribute\Artifact\CustomBinaryCheckUpdate;
|
||||
use StaticPHP\Exception\DownloaderException;
|
||||
|
||||
/**
|
||||
* Full CPython for Windows from the official python.org nuget package. It is a plain zip
|
||||
* (python.exe plus stdlib under tools/, venv and ensurepip included), so it installs into
|
||||
* the pkgroot without touching the system. Used by the meson tool package.
|
||||
*/
|
||||
class python_win
|
||||
{
|
||||
#[CustomBinary('python-win', [
|
||||
'windows-x86_64',
|
||||
])]
|
||||
public function downBinary(ArtifactDownloader $downloader): DownloadResult
|
||||
{
|
||||
$version = $this->getLatestVersion($downloader->getRetry());
|
||||
|
||||
$url = "https://api.nuget.org/v3-flatcontainer/python/{$version}/python.{$version}.nupkg";
|
||||
// .nupkg is a zip; name the cache file .zip so the extractor treats it as one
|
||||
$path = DOWNLOAD_PATH . DIRECTORY_SEPARATOR . "python-win-{$version}.zip";
|
||||
default_shell()->executeCurlDownload($url, $path, retries: $downloader->getRetry());
|
||||
|
||||
return DownloadResult::archive(basename($path), ['url' => $url, 'version' => $version], extract: '{pkg_root_path}/python-win', version: $version);
|
||||
}
|
||||
|
||||
#[CustomBinaryCheckUpdate('python-win', ['windows-x86_64'])]
|
||||
public function checkUpdateBinary(?string $old_version): CheckUpdateResult
|
||||
{
|
||||
$version = $this->getLatestVersion();
|
||||
return new CheckUpdateResult(
|
||||
old: $old_version,
|
||||
new: $version,
|
||||
needUpdate: $old_version === null || $version !== $old_version,
|
||||
);
|
||||
}
|
||||
|
||||
#[AfterBinaryExtract('python-win', ['windows-x86_64'])]
|
||||
public function afterExtract(string $target_path): void
|
||||
{
|
||||
if (!file_exists("{$target_path}\\tools\\python.exe")) {
|
||||
throw new DownloaderException("Python installation appears incomplete: python.exe not found at {$target_path}\\tools\\python.exe");
|
||||
}
|
||||
}
|
||||
|
||||
private function getLatestVersion(int $retries = 0): string
|
||||
{
|
||||
$index = default_shell()->executeCurl('https://api.nuget.org/v3-flatcontainer/python/index.json', retries: $retries);
|
||||
$versions = $index ? (json_decode($index, true)['versions'] ?? []) : [];
|
||||
$stable = array_filter($versions, fn ($v) => preg_match('/^\d+\.\d+\.\d+$/', $v));
|
||||
if ($stable === []) {
|
||||
throw new DownloaderException('Failed to get Python versions from the nuget index');
|
||||
}
|
||||
return end($stable);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user