mirror of
https://github.com/php-win-ext/php-sdk-binary-tools.git
synced 2026-03-24 17:12:12 +01:00
457 lines
12 KiB
PHP
457 lines
12 KiB
PHP
<?php
|
|
|
|
namespace SDK;
|
|
|
|
use SDK\Build\Dependency\Fetcher;
|
|
|
|
class Config
|
|
{
|
|
/* Config variables. */
|
|
|
|
/** @var string */
|
|
protected static $depsHost = 'phpext.phptools.online';
|
|
|
|
/** @var int */
|
|
protected static $depsPort = 443;
|
|
|
|
/** @var string */
|
|
protected static $depsUriScheme = "https";
|
|
|
|
/** @var string */
|
|
protected static $depsBaseUri = "/api/downloadable/download";
|
|
|
|
/** @var string */
|
|
protected static $sdkNugetFeedUrl = "http://127.0.0.1/sdk/nuget"; // experimental?
|
|
|
|
/** @var array<mixed> */
|
|
protected static $knownBranches = array ();
|
|
|
|
/* Helper props and methods. */
|
|
|
|
/** @var ?string */
|
|
protected static $currentBranchName = NULL;
|
|
|
|
/** @var ?string */
|
|
protected static $currentArchName = NULL;
|
|
|
|
/** @var ?string */
|
|
protected static $currentCrtName = NULL;
|
|
|
|
/** @var ?string */
|
|
protected static $currentStabilityName = NULL;
|
|
|
|
/** @var ?string */
|
|
protected static $depsLocalPath = NULL;
|
|
|
|
public static function getDepsHost() : string
|
|
{/*{{{*/
|
|
return self::$depsHost;
|
|
}/*}}}*/
|
|
|
|
public static function getDepsPort() : int
|
|
{/*{{{*/
|
|
return self::$depsPort;
|
|
}/*}}}*/
|
|
|
|
public static function getDepsUriScheme() : string
|
|
{/*{{{*/
|
|
return self::$depsUriScheme;
|
|
}/*}}}*/
|
|
|
|
public static function getDepsBaseUri() : string
|
|
{/*{{{*/
|
|
return self::$depsBaseUri;
|
|
}/*}}}*/
|
|
|
|
public static function setCurrentArchName(string $arch) : void
|
|
{/*{{{*/
|
|
$arch = strtolower($arch);
|
|
|
|
if ("x64" != $arch && "x86" != $arch && "arm64" != $arch) {
|
|
throw new Exception("Unknown arch keyword, x86 or x64 or arm64 is accepted");
|
|
}
|
|
|
|
self::$currentArchName = $arch;
|
|
} /*}}}*/
|
|
|
|
public static function getCurrentArchName() : string
|
|
{/*{{{*/
|
|
if (NULL === self::$currentArchName) {
|
|
if (FALSE !== ($env = getenv('PHP_SDK_ARCH'))) {
|
|
self::setCurrentArchName($env);
|
|
} else {
|
|
/* XXX this might be not true for other compilers! */
|
|
passthru("where cl.exe >nul", $status);
|
|
if ($status) {
|
|
throw new Exception("Couldn't execute cl.exe.");
|
|
}
|
|
|
|
exec("cl.exe /? 2>&1", $out);
|
|
|
|
if (preg_match(",x64,", $out[0])) {
|
|
self::setCurrentArchName("x64");
|
|
} elseif (preg_match(",x86,", $out[0])) {
|
|
self::setCurrentArchName("x86");
|
|
} elseif (preg_match(",arm64,", $out[0])) {
|
|
self::setCurrentArchName("arm64");
|
|
} else {
|
|
throw new Exception("Couldn't determine Arch.");
|
|
}
|
|
}
|
|
}
|
|
|
|
return self::$currentArchName;
|
|
} /*}}}*/
|
|
|
|
public static function setCurrentCrtName(string $crt) : void
|
|
{/*{{{*/
|
|
self::$currentCrtName = $crt;
|
|
} /*}}}*/
|
|
|
|
public static function getCurrentCrtName() : ?string
|
|
{/*{{{*/
|
|
if (NULL === self::$currentCrtName) {
|
|
if (FALSE !== ($env = getenv('PHP_SDK_VS'))) {
|
|
self::setCurrentCrtName($env);
|
|
} else {
|
|
$all_branches = Config::getKnownBranches();
|
|
|
|
if (!isset($all_branches[Config::getCurrentBranchName()])) {
|
|
throw new Exception("Couldn't find any configuration for branch '" . Config::getCurrentBranchName() . "'");
|
|
}
|
|
|
|
$branch = $all_branches[Config::getCurrentBranchName()];
|
|
if (count($branch) > 1) {
|
|
throw new Exception("Multiple CRTs are available for this branch, please choose one from " . implode(",", array_keys($branch)));
|
|
}
|
|
|
|
self::setCurrentCrtName(array_keys($branch)[0]);
|
|
}
|
|
}
|
|
|
|
return self::$currentCrtName;
|
|
} /*}}}*/
|
|
|
|
public static function setCurrentStabilityName(string $stability) : void
|
|
{/*{{{*/
|
|
if ("stable" != $stability && "staging" != $stability) {
|
|
throw new Exception("Unknown stability keyword, either stable or staging is accepted");
|
|
}
|
|
|
|
self::$currentStabilityName = $stability;
|
|
} /*}}}*/
|
|
|
|
public static function getCurrentStabilityName() : ?string
|
|
{/*{{{*/
|
|
if (NULL === self::$currentStabilityName) {
|
|
if ("master" == Config::getCurrentBranchName()) {
|
|
Config::setCurrentStabilityName("staging");
|
|
} else {
|
|
Config::setCurrentStabilityName("stable");
|
|
}
|
|
}
|
|
|
|
return self::$currentStabilityName;
|
|
} /*}}}*/
|
|
|
|
/** @return array<mixed> */
|
|
public static function getKnownBranches() : array
|
|
{/*{{{*/
|
|
if (empty(self::$knownBranches)) {
|
|
$cache_file = "known_branches.txt";
|
|
$deps_path = self::getDepsLocalPath();
|
|
if (!$deps_path) {
|
|
throw new Exception("Couldn't determine dependencies path. Please either switch to the PHP source root or use -d option.");
|
|
}
|
|
$cache = new Cache($deps_path);
|
|
$fetcher = new Fetcher(self::$depsHost, self::$depsPort, self::$depsUriScheme);
|
|
|
|
$tmp = $fetcher->getByUri(self::$depsBaseUri . "/series/");
|
|
if ("" !== $tmp) {
|
|
$data = array();
|
|
if (preg_match_all(",packages-(.+)-(v[cs]\d+)-(x86|x64|arm64)-(stable|staging)\.txt,Us", $tmp, $m, PREG_SET_ORDER)) {
|
|
foreach ($m as $b) {
|
|
if (!isset($data[$b[1]])) {
|
|
$data[$b[1]] = array();
|
|
}
|
|
|
|
$data[$b[1]][$b[2]][] = array("arch" => $b[3], "stability" => $b[4]);
|
|
}
|
|
|
|
$cache->cachecontent($cache_file, json_encode($data, JSON_PRETTY_PRINT), true);
|
|
}
|
|
} else {
|
|
/* It might be ok to use cached branches list, if a fetch failed. */
|
|
$tmp = $cache->getCachedContent($cache_file, true);
|
|
if (NULL == $tmp) {
|
|
throw new Exception("No cached branches list found");
|
|
}
|
|
$data = json_decode($tmp, true);
|
|
}
|
|
|
|
if (!is_array($data) || empty($data)) {
|
|
throw new Exception("Failed to fetch supported branches");
|
|
}
|
|
self::$knownBranches = $data;
|
|
}
|
|
|
|
return self::$knownBranches;
|
|
}/*}}}*/
|
|
|
|
public static function setCurrentBranchName(string $name) : void
|
|
{/*{{{*/
|
|
if (!array_key_exists($name, self::getKnownBranches())) {
|
|
throw new Exception("Unsupported branch '$name'");
|
|
}
|
|
|
|
self::$currentBranchName = $name;
|
|
}/*}}}*/
|
|
|
|
public static function guessCurrentBranchName() : ?string
|
|
{/*{{{*/
|
|
$branch = NULL;
|
|
$found = false;
|
|
|
|
$rmtools_branch = getenv("PHP_RMTOOLS_PHP_BUILD_BRANCH");
|
|
if ("master" == $rmtools_branch) {
|
|
return "master";
|
|
}
|
|
|
|
/* Try to figure out the branch. The worky scenarios are
|
|
- CWD is in php-src
|
|
- phpize is on the path
|
|
FIXME for the dev package, there should be a php-config utility
|
|
*/
|
|
$fl = "main/php_version.h";
|
|
$found = file_exists($fl);
|
|
|
|
if (!$found) {
|
|
exec("where phpize", $out, $status);
|
|
if (!$status) {
|
|
$fl = dirname($out[0]) . DIRECTORY_SEPARATOR . "include" . DIRECTORY_SEPARATOR . $fl;
|
|
$found = file_exists($fl);
|
|
}
|
|
}
|
|
|
|
if ($found) {
|
|
$s = file_get_contents($fl);
|
|
$major = $minor = NULL;
|
|
|
|
if (preg_match(",PHP_MAJOR_VERSION (\d+),", $s, $m)) {
|
|
$major = $m[1];
|
|
}
|
|
if (preg_match(",PHP_MINOR_VERSION (\d+),", $s, $m)) {
|
|
$minor = $m[1];
|
|
}
|
|
|
|
if (is_numeric($major) && is_numeric($minor)) {
|
|
$branch = "$major.$minor";
|
|
}
|
|
|
|
/* Verify that we use an available branch name. Master has some
|
|
version, but no dedicated series. For master, it rather
|
|
makes sense to use master as branch name. */
|
|
$git = trim(shell_exec("where git.exe"));
|
|
if ($git && is_dir(".git")) {
|
|
$cmd = "\"$git\" branch";
|
|
|
|
$ret = trim(shell_exec($cmd));
|
|
if (preg_match_all(",\*\s+master,", $ret) > 0) {
|
|
$branch = "master";
|
|
}
|
|
}
|
|
}
|
|
|
|
return $branch;
|
|
}/*}}}*/
|
|
|
|
public static function getCurrentBranchName() : string
|
|
{/*{{{*/
|
|
if (NULL == self::$currentBranchName) {
|
|
$branch = self::guessCurrentBranchName();
|
|
self::setCurrentBranchName($branch);
|
|
}
|
|
|
|
return self::$currentBranchName;
|
|
}/*}}}*/
|
|
|
|
/** @return array<mixed> */
|
|
public static function getCurrentBranchData() : array
|
|
{/*{{{*/
|
|
$ret = array();
|
|
$branches = self::getKnownBranches();
|
|
|
|
$current_branch_name = self::getCurrentBranchName();
|
|
if (!array_key_exists($current_branch_name, $branches)) {
|
|
throw new Exception("Unknown branch '$current_branch_name'");
|
|
}
|
|
|
|
$crt = null;
|
|
$cur_crt = Config::getCurrentCrtName();
|
|
if (count($branches[$current_branch_name]) > 1) {
|
|
if (NULL === $cur_crt) {
|
|
throw new Exception("More than one CRT is available for branch '$current_branch_name', pass one explicitly.");
|
|
}
|
|
|
|
$cur_crt_usable = false;
|
|
foreach (array_keys($branches[$current_branch_name]) as $crt) {
|
|
if ($cur_crt == $crt) {
|
|
$cur_crt_usable = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!$cur_crt_usable) {
|
|
throw new Exception("The passed CRT '$cur_crt' doesn't match any available for branch '$current_branch_name'");
|
|
}
|
|
$data = $branches[$current_branch_name][$cur_crt];
|
|
} else {
|
|
/* Evaluate CRTs, to avoid ambiquity. */
|
|
$crt = key($branches[$current_branch_name]);
|
|
$data = $branches[$current_branch_name][$crt];
|
|
if ($crt != $cur_crt) {
|
|
throw new Exception("The passed CRT '$cur_crt' doesn't match any available for branch '$current_branch_name'");
|
|
}
|
|
}
|
|
|
|
$ret["name"] = $current_branch_name;
|
|
$ret["crt"] = $crt;
|
|
|
|
/* Last step, filter by arch and stability. */
|
|
foreach ($data as $d) {
|
|
if (self::getCurrentArchName() == $d["arch"]) {
|
|
if (self::getCurrentStabilityName() == $d["stability"]) {
|
|
$ret["arch"] = $d["arch"];
|
|
$ret["stability"] = $d["stability"];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!isset($ret["arch"]) || !$ret["arch"]) {
|
|
throw new Exception("Failed to find config with arch '" . self::getCurrentArchName() . "'");
|
|
}
|
|
if (!isset($ret["stability"]) || !$ret["stability"]) {
|
|
throw new Exception("Failed to find config with stability '" . self::getCurrentStabilityName() . "'");
|
|
}
|
|
if (!isset($ret["crt"]) || !$ret["crt"]) {
|
|
throw new Exception("Failed to find config with arch '" . self::getCurrentArchName() . "'");
|
|
}
|
|
|
|
return $ret;
|
|
}/*}}}*/
|
|
|
|
public static function getSdkNugetFeedUrl() : string
|
|
{/*{{{*/
|
|
return self::$sdkNugetFeedUrl;
|
|
}/*}}}*/
|
|
|
|
public static function getSdkPath() : string
|
|
{/*{{{*/
|
|
$path = getenv("PHP_SDK_ROOT_PATH");
|
|
|
|
if (!$path) {
|
|
throw new Exception("PHP_SDK_ROOT_PATH isn't set!");
|
|
}
|
|
|
|
$path = realpath($path);
|
|
if (!file_exists($path)) {
|
|
throw new Exception("The path '$path' is non existent.");
|
|
}
|
|
|
|
return $path;
|
|
}/*}}}*/
|
|
|
|
public static function getSdkVersion() : string
|
|
{/*{{{*/
|
|
$path = self::getSdkPath() . DIRECTORY_SEPARATOR . "VERSION";
|
|
|
|
if (!file_exists($path)) {
|
|
throw new Exception("Couldn't find the SDK version file.");
|
|
}
|
|
|
|
return file_get_contents($path);
|
|
}/*}}}*/
|
|
|
|
public static function getDepsLocalPath() : ?string
|
|
{/*{{{*/
|
|
if (NULL == self::$depsLocalPath) {
|
|
if (file_exists("Makefile")) {
|
|
$s = file_get_contents("Makefile");
|
|
|
|
if (preg_match(",PHP_BUILD=(.+),", $s, $m)) {
|
|
if (isset($m[1])) {
|
|
self::setDepsLocalPath(trim($m[1]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NULL == self::$depsLocalPath) {
|
|
$tmp = dirname(getcwd()) . DIRECTORY_SEPARATOR . "deps";
|
|
if (is_dir($tmp)) {
|
|
self::setDepsLocalPath($tmp);
|
|
}
|
|
}
|
|
|
|
if (NULL == self::$depsLocalPath) {
|
|
$tmp = realpath("../deps");
|
|
if (is_dir($tmp)) {
|
|
self::setDepsLocalPath($tmp);
|
|
}
|
|
}
|
|
|
|
if (NULL == self::$depsLocalPath) {
|
|
if (file_exists("main/php_version.h")) {
|
|
/* Deps dir might not exist. */
|
|
self::setDepsLocalPath(realpath("..") . DIRECTORY_SEPARATOR . "deps");
|
|
}
|
|
}
|
|
|
|
return self::$depsLocalPath;
|
|
}/*}}}*/
|
|
|
|
public static function setDepsLocalPath(string $path) : void
|
|
{/*{{{*/
|
|
self::$depsLocalPath = $path;
|
|
}/*}}}*/
|
|
|
|
public static function getCacheDir() : string
|
|
{/*{{{*/
|
|
$path = self::getSdkPath() . DIRECTORY_SEPARATOR . ".cache";
|
|
|
|
if (!file_exists($path)) {
|
|
if (!mkdir($path)) {
|
|
throw new Exception("Failed to create '$path'");
|
|
}
|
|
}
|
|
|
|
return $path;
|
|
}/*}}}*/
|
|
|
|
public static function getTmpDir() : string
|
|
{/*{{{*/
|
|
$path = self::getSdkPath() . DIRECTORY_SEPARATOR . ".tmp";
|
|
|
|
if (!file_exists($path)) {
|
|
if (!mkdir($path)) {
|
|
throw new Exception("Failed to create '$path'");
|
|
}
|
|
}
|
|
|
|
return $path;
|
|
}/*}}}*/
|
|
|
|
public static function getSdkUserAgentName() : string
|
|
{/*{{{*/
|
|
return "PHP-SDK-BINARY-TOOLS/" . self::getSdkVersion();
|
|
}/*}}}*/
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* tab-width: 4
|
|
* c-basic-offset: 4
|
|
* End:
|
|
* vim600: sw=4 ts=4 fdm=marker
|
|
* vim<600: sw=4 ts=4
|
|
*/
|