mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-12 03:15:35 +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
|
- openssl
|
||||||
- zlib
|
- zlib
|
||||||
tools@windows:
|
tools@windows:
|
||||||
|
- python-win
|
||||||
- meson
|
- meson
|
||||||
- ninja
|
- ninja
|
||||||
- winflexbison
|
- 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);
|
$dir = dirname($target_path);
|
||||||
$venv = "{$dir}\\venv";
|
$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;
|
$python = null;
|
||||||
foreach (['python', 'py -3'] as $candidate) {
|
foreach ($candidates as $candidate) {
|
||||||
[$code] = cmd()->execWithResult("{$candidate} --version", false);
|
[$code] = cmd()->execWithResult("{$candidate} --version", false);
|
||||||
if ($code === 0) {
|
if ($code === 0) {
|
||||||
$python = $candidate;
|
$python = $candidate;
|
||||||
@@ -31,7 +34,7 @@ class meson_win
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($python === null) {
|
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)) {
|
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