mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-03-18 12:54:52 +08:00
Add Zig package support with downloader and installation checks
This commit is contained in:
parent
baddd60113
commit
dbc6dbee53
@ -82,7 +82,10 @@
|
|||||||
},
|
},
|
||||||
"zig": {
|
"zig": {
|
||||||
"type": "target",
|
"type": "target",
|
||||||
"artifact": "zig"
|
"artifact": "zig",
|
||||||
|
"static-bins": [
|
||||||
|
"{pkg_root_path}/zig/zig"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"nasm": {
|
"nasm": {
|
||||||
"type": "target",
|
"type": "target",
|
||||||
|
|||||||
98
src/Package/Artifact/zig.php
Normal file
98
src/Package/Artifact/zig.php
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Package\Artifact;
|
||||||
|
|
||||||
|
use StaticPHP\Artifact\ArtifactDownloader;
|
||||||
|
use StaticPHP\Artifact\Downloader\DownloadResult;
|
||||||
|
use StaticPHP\Attribute\Artifact\AfterBinaryExtract;
|
||||||
|
use StaticPHP\Attribute\Artifact\CustomBinary;
|
||||||
|
use StaticPHP\Exception\DownloaderException;
|
||||||
|
use StaticPHP\Runtime\SystemTarget;
|
||||||
|
|
||||||
|
class zig
|
||||||
|
{
|
||||||
|
#[CustomBinary('zig', [
|
||||||
|
'linux-x86_64',
|
||||||
|
'linux-aarch64',
|
||||||
|
'macos-x86_64',
|
||||||
|
'macos-aarch64',
|
||||||
|
])]
|
||||||
|
public function downBinary(ArtifactDownloader $downloader): DownloadResult
|
||||||
|
{
|
||||||
|
$index_json = default_shell()->executeCurl('https://ziglang.org/download/index.json', retries: $downloader->getRetry());
|
||||||
|
$index_json = json_decode($index_json ?: '', true);
|
||||||
|
$latest_version = null;
|
||||||
|
foreach ($index_json as $version => $data) {
|
||||||
|
$latest_version = $version;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$latest_version) {
|
||||||
|
throw new DownloaderException('Could not determine latest Zig version');
|
||||||
|
}
|
||||||
|
$zig_arch = SystemTarget::getTargetArch();
|
||||||
|
$zig_os = match (SystemTarget::getTargetOS()) {
|
||||||
|
'Windows' => 'win',
|
||||||
|
'Darwin' => 'macos',
|
||||||
|
'Linux' => 'linux',
|
||||||
|
default => throw new DownloaderException('Unsupported OS for Zig: ' . SystemTarget::getTargetOS()),
|
||||||
|
};
|
||||||
|
$platform_key = "{$zig_arch}-{$zig_os}";
|
||||||
|
if (!isset($index_json[$latest_version][$platform_key])) {
|
||||||
|
throw new DownloaderException("No download available for {$platform_key} in Zig version {$latest_version}");
|
||||||
|
}
|
||||||
|
$download_info = $index_json[$latest_version][$platform_key];
|
||||||
|
$url = $download_info['tarball'];
|
||||||
|
$sha256 = $download_info['shasum'];
|
||||||
|
$filename = basename($url);
|
||||||
|
$path = DOWNLOAD_PATH . DIRECTORY_SEPARATOR . $filename;
|
||||||
|
default_shell()->executeCurlDownload($url, $path, retries: $downloader->getRetry());
|
||||||
|
// verify hash
|
||||||
|
$file_hash = hash_file('sha256', $path);
|
||||||
|
if ($file_hash !== $sha256) {
|
||||||
|
throw new DownloaderException("Hash mismatch for downloaded Zig binary. Expected {$sha256}, got {$file_hash}");
|
||||||
|
}
|
||||||
|
return DownloadResult::archive(basename($path), ['url' => $url, 'version' => $latest_version], extract: PKG_ROOT_PATH . '/zig', verified: true, version: $latest_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[AfterBinaryExtract('zig', [
|
||||||
|
'linux-x86_64',
|
||||||
|
'linux-aarch64',
|
||||||
|
'macos-x86_64',
|
||||||
|
'macos-aarch64',
|
||||||
|
])]
|
||||||
|
public function postExtractZig(string $target_path): void
|
||||||
|
{
|
||||||
|
$files = ['zig', 'zig-cc', 'zig-c++', 'zig-ar', 'zig-ld.lld', 'zig-ranlib', 'zig-objcopy'];
|
||||||
|
$all_exist = true;
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if (!file_exists("{$target_path}/{$file}")) {
|
||||||
|
$all_exist = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($all_exist) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$script_path = ROOT_DIR . '/src/globals/scripts/zig-cc.sh';
|
||||||
|
$script_content = file_get_contents($script_path);
|
||||||
|
|
||||||
|
file_put_contents("{$target_path}/zig-cc", $script_content);
|
||||||
|
chmod("{$target_path}/zig-cc", 0755);
|
||||||
|
|
||||||
|
$script_content = str_replace('zig cc', 'zig c++', $script_content);
|
||||||
|
file_put_contents("{$target_path}/zig-c++", $script_content);
|
||||||
|
file_put_contents("{$target_path}/zig-ar", "#!/usr/bin/env bash\nexec zig ar $@");
|
||||||
|
file_put_contents("{$target_path}/zig-ld.lld", "#!/usr/bin/env bash\nexec zig ld.lld $@");
|
||||||
|
file_put_contents("{$target_path}/zig-ranlib", "#!/usr/bin/env bash\nexec zig ranlib $@");
|
||||||
|
file_put_contents("{$target_path}/zig-objcopy", "#!/usr/bin/env bash\nexec zig objcopy $@");
|
||||||
|
chmod("{$target_path}/zig-c++", 0755);
|
||||||
|
chmod("{$target_path}/zig-ar", 0755);
|
||||||
|
chmod("{$target_path}/zig-ld.lld", 0755);
|
||||||
|
chmod("{$target_path}/zig-ranlib", 0755);
|
||||||
|
chmod("{$target_path}/zig-objcopy", 0755);
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/StaticPHP/Doctor/Item/ZigCheck.php
Normal file
53
src/StaticPHP/Doctor/Item/ZigCheck.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace StaticPHP\Doctor\Item;
|
||||||
|
|
||||||
|
use StaticPHP\Attribute\Doctor\CheckItem;
|
||||||
|
use StaticPHP\Attribute\Doctor\FixItem;
|
||||||
|
use StaticPHP\Attribute\Doctor\OptionalCheck;
|
||||||
|
use StaticPHP\DI\ApplicationContext;
|
||||||
|
use StaticPHP\Doctor\CheckResult;
|
||||||
|
use StaticPHP\Package\PackageInstaller;
|
||||||
|
use StaticPHP\Toolchain\Interface\ToolchainInterface;
|
||||||
|
use StaticPHP\Toolchain\ZigToolchain;
|
||||||
|
|
||||||
|
#[OptionalCheck([self::class, 'optionalCheck'])]
|
||||||
|
class ZigCheck
|
||||||
|
{
|
||||||
|
public static function optionalCheck(): bool
|
||||||
|
{
|
||||||
|
return ApplicationContext::get(ToolchainInterface::class) instanceof ZigToolchain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @noinspection PhpUnused */
|
||||||
|
#[CheckItem('if zig is installed', level: 800)]
|
||||||
|
public function checkZig(): CheckResult
|
||||||
|
{
|
||||||
|
$installer = new PackageInstaller();
|
||||||
|
$package = 'zig';
|
||||||
|
$installer->addInstallPackage($package);
|
||||||
|
$installed = $installer->isPackageInstalled($package);
|
||||||
|
if ($installed) {
|
||||||
|
return CheckResult::ok();
|
||||||
|
}
|
||||||
|
return CheckResult::fail('zig is not installed', 'install-zig');
|
||||||
|
}
|
||||||
|
|
||||||
|
#[FixItem('install-zig')]
|
||||||
|
public function installZig(): bool
|
||||||
|
{
|
||||||
|
$arch = arch2gnu(php_uname('m'));
|
||||||
|
$os = match (PHP_OS_FAMILY) {
|
||||||
|
'Windows' => 'win',
|
||||||
|
'Darwin' => 'macos',
|
||||||
|
'BSD' => 'freebsd',
|
||||||
|
default => 'linux',
|
||||||
|
};
|
||||||
|
$installer = new PackageInstaller();
|
||||||
|
$installer->addInstallPackage('zig');
|
||||||
|
$installer->run(false);
|
||||||
|
return $installer->isPackageInstalled('zig');
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/globals/scripts/zig-cc.sh
Executable file
65
src/globals/scripts/zig-cc.sh
Executable file
@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [ "$BUILD_ROOT_PATH" = "" ]; then
|
||||||
|
echo "The script must be run in the SPC build environment."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
BUILDROOT_ABS=$BUILD_ROOT_PATH
|
||||||
|
PARSED_ARGS=()
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-isystem)
|
||||||
|
shift
|
||||||
|
ARG="$1"
|
||||||
|
shift
|
||||||
|
ARG_ABS="$(realpath "$ARG" 2>/dev/null || true)"
|
||||||
|
[[ "$ARG_ABS" == "$BUILDROOT_ABS" ]] && PARSED_ARGS+=("-I$ARG") || PARSED_ARGS+=("-isystem" "$ARG")
|
||||||
|
;;
|
||||||
|
-isystem*)
|
||||||
|
ARG="${1#-isystem}"
|
||||||
|
shift
|
||||||
|
ARG_ABS="$(realpath "$ARG" 2>/dev/null || true)"
|
||||||
|
[[ "$ARG_ABS" == "$BUILDROOT_ABS" ]] && PARSED_ARGS+=("-I$ARG") || PARSED_ARGS+=("-isystem$ARG")
|
||||||
|
;;
|
||||||
|
-march=*|-mcpu=*)
|
||||||
|
OPT_NAME="${1%%=*}"
|
||||||
|
OPT_VALUE="${1#*=}"
|
||||||
|
# Skip armv8- flags entirely as Zig doesn't support them
|
||||||
|
if [[ "$OPT_VALUE" == armv8-* ]]; then
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# replace -march=x86-64 with -march=x86_64
|
||||||
|
OPT_VALUE="${OPT_VALUE//-/_}"
|
||||||
|
PARSED_ARGS+=("${OPT_NAME}=${OPT_VALUE}")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
PARSED_ARGS+=("$1")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -n "$SPC_TARGET" ]] && TARGET="-target $SPC_TARGET" || TARGET=""
|
||||||
|
|
||||||
|
if [[ "$SPC_TARGET" =~ \.[0-9]+\.[0-9]+ ]]; then
|
||||||
|
output=$(zig cc $TARGET $SPC_COMPILER_EXTRA "${PARSED_ARGS[@]}" 2>&1)
|
||||||
|
status=$?
|
||||||
|
|
||||||
|
if [[ $status -eq 0 ]]; then
|
||||||
|
echo "$output"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "$output" | grep -qE "version '.*' in target triple"; then
|
||||||
|
filtered_output=$(echo "$output" | grep -vE "version '.*' in target triple")
|
||||||
|
echo "$filtered_output"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec zig cc $TARGET $SPC_COMPILER_EXTRA "${PARSED_ARGS[@]}"
|
||||||
Loading…
x
Reference in New Issue
Block a user