refactor DependencyUtil, use for-libs and for-sources instead of by

This commit is contained in:
crazywhalecc 2024-02-16 18:56:33 +08:00
parent 1e898d271d
commit 939db75268
No known key found for this signature in database
GPG Key ID: 1F4BDD59391F2680
7 changed files with 145 additions and 169 deletions

View File

@ -107,7 +107,7 @@ abstract class UnixBuilderBase extends BuilderBase
// if no libs specified, compile all supported libs
if ($sorted_libraries === [] && $this->isLibsOnly()) {
$libraries = array_keys($support_lib_list);
$sorted_libraries = DependencyUtil::getLibsByDeps($libraries);
$sorted_libraries = DependencyUtil::getLibs($libraries);
}
// pkg-config must be compiled first, whether it is specified or not

View File

@ -192,7 +192,7 @@ class WindowsBuilder extends BuilderBase
// if no libs specified, compile all supported libs
if ($sorted_libraries === [] && $this->isLibsOnly()) {
$libraries = array_keys($support_lib_list);
$sorted_libraries = DependencyUtil::getLibsByDeps($libraries);
$sorted_libraries = DependencyUtil::getLibs($libraries);
}
// add lib object for builder

View File

@ -60,7 +60,7 @@ class BuildLibsCommand extends BuildCommand
// 只编译 library 的情况下,标记
$builder->setLibsOnly();
// 编译和检查库完整
$libraries = DependencyUtil::getLibsByDeps($libraries);
$libraries = DependencyUtil::getLibs($libraries);
$builder->buildLibs($libraries);
$time = round(microtime(true) - START_TIME, 3);

View File

@ -214,7 +214,7 @@ class DownloadCommand extends BaseCommand
*/
private function calculateSourcesByExt(array $extensions, bool $include_suggests = true): array
{
[$extensions, $libraries] = $include_suggests ? DependencyUtil::getAllExtLibsByDeps($extensions) : DependencyUtil::getExtLibsByDeps($extensions);
[$extensions, $libraries] = $include_suggests ? DependencyUtil::getExtsAndLibs($extensions, [], true, true) : DependencyUtil::getExtsAndLibs($extensions);
$sources = [];
foreach ($extensions as $extension) {
if (Config::getExt($extension, 'type') === 'external') {

View File

@ -22,8 +22,8 @@ class DumpLicenseCommand extends BaseCommand
{
$this->addOption('for-extensions', null, InputOption::VALUE_REQUIRED, 'Dump by extensions and related libraries', null);
$this->addOption('without-php', null, InputOption::VALUE_NONE, 'Dump without php-src');
$this->addOption('by-libs', null, InputOption::VALUE_REQUIRED, 'Dump by libraries', null);
$this->addOption('by-sources', null, InputOption::VALUE_REQUIRED, 'Dump by original sources (source.json)', null);
$this->addOption('for-libs', null, InputOption::VALUE_REQUIRED, 'Dump by libraries', null);
$this->addOption('for-sources', null, InputOption::VALUE_REQUIRED, 'Dump by original sources (source.json)', null);
$this->addOption('dump-dir', null, InputOption::VALUE_REQUIRED, 'Change dump directory', BUILD_ROOT_PATH . '/license');
}
@ -39,7 +39,7 @@ class DumpLicenseCommand extends BaseCommand
// 从参数中获取要编译的 extensions并转换为数组
$extensions = array_map('trim', array_filter(explode(',', $this->getOption('for-extensions'))));
// 根据提供的扩展列表获取依赖库列表并编译
[$extensions, $libraries] = DependencyUtil::getExtLibsByDeps($extensions);
[$extensions, $libraries] = DependencyUtil::getExtsAndLibs($extensions);
$dumper->addExts($extensions);
$dumper->addLibs($libraries);
if (!$this->getOption('without-php')) {
@ -52,22 +52,22 @@ class DumpLicenseCommand extends BaseCommand
$this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir'));
return static::SUCCESS;
}
if ($this->getOption('by-libs') !== null) {
$libraries = array_map('trim', array_filter(explode(',', $this->getOption('by-libs'))));
$libraries = DependencyUtil::getLibsByDeps($libraries);
if ($this->getOption('for-libs') !== null) {
$libraries = array_map('trim', array_filter(explode(',', $this->getOption('for-libs'))));
$libraries = DependencyUtil::getLibs($libraries);
$dumper->addLibs($libraries);
$dumper->dump($this->getOption('dump-dir'));
$this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir'));
return static::SUCCESS;
}
if ($this->getOption('by-sources') !== null) {
$sources = array_map('trim', array_filter(explode(',', $this->getOption('by-sources'))));
if ($this->getOption('for-sources') !== null) {
$sources = array_map('trim', array_filter(explode(',', $this->getOption('for-sources'))));
$dumper->addSources($sources);
$dumper->dump($this->getOption('dump-dir'));
$this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir'));
return static::SUCCESS;
}
$this->output->writeln('You must use one of "--for-extensions=", "--by-libs=", "--by-sources=" to dump');
$this->output->writeln('You must use one of "--for-extensions=", "--for-libs=", "--for-sources=" to dump');
return static::FAILURE;
}
}

View File

@ -59,7 +59,7 @@ class AllExtCommand extends BaseCommand
}
try {
[, $libraries, $not_included] = DependencyUtil::getExtLibsByDeps([$extension]);
[, $libraries, $not_included] = DependencyUtil::getExtsAndLibs([$extension]);
} catch (WrongUsageException) {
$libraries = $not_included = [];
}

View File

@ -5,104 +5,164 @@ declare(strict_types=1);
namespace SPC\util;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\Config;
/**
* 依赖处理工具类,包含处理扩展、库的依赖列表顺序等
* Dependency processing tool class, including processing extensions, library dependency list order, etc.
*/
class DependencyUtil
{
public static function getExtsAndLibs(array $exts, array $additional_libs = [], bool $include_suggested_exts = false, bool $include_suggested_libs = false): array
/**
* Convert platform extensions to library dependencies and suggestions.
*
* @throws WrongUsageException
* @throws FileSystemException
*/
public static function platExtToLibs(): array
{
if (!$include_suggested_exts && !$include_suggested_libs) {
return self::getExtLibsByDeps($exts, $additional_libs);
$exts = Config::getExts();
$libs = Config::getLibs();
$dep_list = [];
foreach ($exts as $ext_name => $ext) {
// convert ext-depends value to ext@xxx
$ext_depends = Config::getExt($ext_name, 'ext-depends', []);
$ext_depends = array_map(fn ($x) => "ext@{$x}", $ext_depends);
// convert ext-suggests value to ext@xxx
$ext_suggests = Config::getExt($ext_name, 'ext-suggests', []);
$ext_suggests = array_map(fn ($x) => "ext@{$x}", $ext_suggests);
// merge ext-depends with lib-depends
$lib_depends = Config::getExt($ext_name, 'lib-depends', []);
$depends = array_merge($ext_depends, $lib_depends);
// merge ext-suggests with lib-suggests
$lib_suggests = Config::getExt($ext_name, 'lib-suggests', []);
$suggests = array_merge($ext_suggests, $lib_suggests);
$dep_list["ext@{$ext_name}"] = [
'depends' => $depends,
'suggests' => $suggests,
];
}
if ($include_suggested_exts && $include_suggested_libs) {
return self::getAllExtLibsByDeps($exts, $additional_libs);
foreach ($libs as $lib_name => $lib) {
$dep_list[$lib_name] = [
'depends' => Config::getLib($lib_name, 'lib-depends', []),
'suggests' => Config::getLib($lib_name, 'lib-suggests', []),
];
}
if (!$include_suggested_exts) {
return self::getExtLibsByDeps($exts, $additional_libs);
}
return self::getAllExtLibsByDeps($exts, $additional_libs, false);
// here is an array that only contains dependency map
return $dep_list;
}
/**
* Obtain the dependent lib list according to the required ext list, and sort according to the dependency
*
* @param array $exts extensions list
* @param array $additional_libs List of additional libraries to add to activate the extra library features triggered by lib-suggests
* @return array Returns an array containing three arrays, [extensions, libraries, not included extensions]
* @throws WrongUsageException
* @throws RuntimeException
* @throws FileSystemException
*/
public static function getExtLibsByDeps(array $exts, array $additional_libs = [], bool $include_suggested_exts = false): array
public static function getLibs(array $libs, bool $include_suggested_libs = false): array
{
$sorted = [];
$visited = [];
$not_included_exts = [];
foreach ($exts as $ext) {
if (!isset($visited[$ext])) {
self::visitExtDeps($ext, $visited, $sorted);
}
}
$sorted_suggests = [];
$visited_suggests = [];
$final = [];
foreach ($exts as $ext) {
if (!isset($visited_suggests[$ext])) {
self::visitExtAllDeps($ext, $visited_suggests, $sorted_suggests);
}
}
foreach ($sorted_suggests as $suggest) {
if (in_array($suggest, $sorted)) {
$final[] = $suggest;
}
}
$libs = $additional_libs;
$dep_list = self::platExtToLibs();
foreach ($final as $ext) {
if (!in_array($ext, $exts)) {
$not_included_exts[] = $ext;
}
foreach (Config::getExt($ext, 'lib-depends', []) as $lib) {
if (!in_array($lib, $libs)) {
$libs[] = $lib;
if ($include_suggested_libs) {
foreach ($dep_list as $name => $obj) {
foreach ($obj['suggests'] as $id => $suggest) {
if (!str_starts_with($suggest, 'ext@')) {
$dep_list[$name]['depends'][] = $suggest;
array_splice($dep_list[$name]['suggests'], $id, 1);
}
}
}
}
return [$final, self::getLibsByDeps($libs), $not_included_exts];
$final = self::doVisitPlat($libs, $dep_list);
$libs_final = [];
foreach ($final as $item) {
if (!str_starts_with($item, 'ext@')) {
$libs_final[] = $item;
}
}
return $libs_final;
}
/**
* 根据 lib 库的依赖关系进行一个排序,同时返回多出来的依赖列表
*
* @param array $libs 要排序的 libs 列表
* @return array 排序后的列表
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
* @throws FileSystemException|WrongUsageException
*/
public static function getLibsByDeps(array $libs): array
public static function getExtsAndLibs(array $exts, array $additional_libs = [], bool $include_suggested_exts = false, bool $include_suggested_libs = false): array
{
$sorted = [];
$visited = [];
$dep_list = self::platExtToLibs();
// 遍历所有
foreach ($libs as $lib) {
if (!isset($visited[$lib])) {
self::visitLibDeps($lib, $visited, $sorted);
// include suggested extensions
if ($include_suggested_exts) {
// check every deps suggests contains ext@
foreach ($dep_list as $name => $obj) {
foreach ($obj['suggests'] as $id => $suggest) {
if (str_starts_with($suggest, 'ext@')) {
$dep_list[$name]['depends'][] = $suggest;
array_splice($dep_list[$name]['suggests'], $id, 1);
}
}
}
}
// include suggested libraries
if ($include_suggested_libs) {
// check every deps suggests
foreach ($dep_list as $name => $obj) {
foreach ($obj['suggests'] as $id => $suggest) {
if (!str_starts_with($suggest, 'ext@')) {
$dep_list[$name]['depends'][] = $suggest;
array_splice($dep_list[$name]['suggests'], $id, 1);
}
}
}
}
// convert ext_name to ext@ext_name
$origin_exts = $exts;
$exts = array_map(fn ($x) => "ext@{$x}", $exts);
$exts = array_merge($exts, $additional_libs);
$final = self::doVisitPlat($exts, $dep_list);
// revert array
$exts_final = [];
$libs_final = [];
$not_included_final = [];
foreach ($final as $item) {
if (str_starts_with($item, 'ext@')) {
$tmp = substr($item, 4);
if (!in_array($tmp, $origin_exts)) {
$not_included_final[] = $tmp;
}
$exts_final[] = $tmp;
} else {
$libs_final[] = $item;
}
}
return [$exts_final, $libs_final, $not_included_final];
}
/**
* @throws WrongUsageException
*/
private static function doVisitPlat(array $deps, array $dep_list): array
{
// default: get extension exts and libs sorted by dep_list
$sorted = [];
$visited = [];
foreach ($deps as $ext_name) {
if (!isset($dep_list[$ext_name])) {
$ext_name = str_starts_with($ext_name, 'ext@') ? ('Extension [' . substr($ext_name, 4) . ']') : ('Library [' . $ext_name . ']');
throw new WrongUsageException("{$ext_name} not exist !");
}
if (!isset($visited[$ext_name])) {
self::visitPlatDeps($ext_name, $dep_list, $visited, $sorted);
}
}
$sorted_suggests = [];
$visited_suggests = [];
$final = [];
foreach ($libs as $lib) {
if (!isset($visited_suggests[$lib])) {
self::visitLibAllDeps($lib, $visited_suggests, $sorted_suggests);
foreach ($deps as $ext_name) {
if (!isset($visited_suggests[$ext_name])) {
self::visitPlatAllDeps($ext_name, $dep_list, $visited_suggests, $sorted_suggests);
}
}
foreach ($sorted_suggests as $suggest) {
@ -113,50 +173,7 @@ class DependencyUtil
return $final;
}
public static function getAllExtLibsByDeps(array $exts, array $additional_libs = [], bool $include_suggested_libs = true): array
{
$sorted = [];
$visited = [];
$not_included_exts = [];
foreach ($exts as $ext) {
if (!isset($visited[$ext])) {
self::visitExtAllDeps($ext, $visited, $sorted);
}
}
$libs = $additional_libs;
foreach ($sorted as $ext) {
if (!in_array($ext, $exts)) {
$not_included_exts[] = $ext;
}
$total = $include_suggested_libs ? array_merge(Config::getExt($ext, 'lib-depends', []), Config::getExt($ext, 'lib-suggests', [])) : Config::getExt($ext, 'lib-depends', []);
foreach ($total as $dep) {
if (!in_array($dep, $libs)) {
$libs[] = $dep;
}
}
}
return [$sorted, self::getAllLibsByDeps($libs), $not_included_exts];
}
public static function getAllLibsByDeps(array $libs): array
{
$sorted = [];
$visited = [];
foreach ($libs as $lib) {
if (!isset($visited[$lib])) {
self::visitLibAllDeps($lib, $visited, $sorted);
}
}
return $sorted;
}
/**
* @throws FileSystemException
* @throws RuntimeException
* @throws WrongUsageException
*/
private static function visitLibAllDeps(string $lib_name, array &$visited, array &$sorted): void
private static function visitPlatAllDeps(string $lib_name, array $dep_list, array &$visited, array &$sorted): void
{
// 如果已经识别到了,那就不管
if (isset($visited[$lib_name])) {
@ -164,37 +181,13 @@ class DependencyUtil
}
$visited[$lib_name] = true;
// 遍历该依赖的所有依赖(此处的 getLib 如果检测到当前库不存在的话,会抛出异常)
foreach (array_merge(Config::getLib($lib_name, 'lib-depends', []), Config::getLib($lib_name, 'lib-suggests', [])) as $dep) {
self::visitLibDeps($dep, $visited, $sorted);
foreach (array_merge($dep_list[$lib_name]['depends'], $dep_list[$lib_name]['suggests']) as $dep) {
self::visitPlatAllDeps($dep, $dep_list, $visited, $sorted);
}
$sorted[] = $lib_name;
}
/**
* @throws RuntimeException
* @throws FileSystemException
* @throws WrongUsageException
*/
private static function visitExtAllDeps(string $ext_name, array &$visited, array &$sorted): void
{
// 如果已经识别到了,那就不管
if (isset($visited[$ext_name])) {
return;
}
$visited[$ext_name] = true;
// 遍历该依赖的所有依赖(此处的 getLib 如果检测到当前库不存在的话,会抛出异常)
foreach (array_merge(Config::getExt($ext_name, 'ext-depends', []), Config::getExt($ext_name, 'ext-suggests', [])) as $dep) {
self::visitExtDeps($dep, $visited, $sorted);
}
$sorted[] = $ext_name;
}
/**
* @throws RuntimeException
* @throws FileSystemException
* @throws WrongUsageException
*/
private static function visitLibDeps(string $lib_name, array &$visited, array &$sorted): void
private static function visitPlatDeps(string $lib_name, array $dep_list, array &$visited, array &$sorted): void
{
// 如果已经识别到了,那就不管
if (isset($visited[$lib_name])) {
@ -202,26 +195,9 @@ class DependencyUtil
}
$visited[$lib_name] = true;
// 遍历该依赖的所有依赖(此处的 getLib 如果检测到当前库不存在的话,会抛出异常)
foreach (Config::getLib($lib_name, 'lib-depends', []) as $dep) {
self::visitLibDeps($dep, $visited, $sorted);
foreach ($dep_list[$lib_name]['depends'] as $dep) {
self::visitPlatDeps($dep, $dep_list, $visited, $sorted);
}
$sorted[] = $lib_name;
}
/**
* @throws RuntimeException
* @throws FileSystemException
* @throws WrongUsageException
*/
private static function visitExtDeps(string $ext_name, array &$visited, array &$sorted): void
{
if (isset($visited[$ext_name])) {
return;
}
$visited[$ext_name] = true;
foreach (Config::getExt($ext_name, 'ext-depends', []) as $dep) {
self::visitExtDeps($dep, $visited, $sorted);
}
$sorted[] = $ext_name;
}
}