add license dumper

This commit is contained in:
crazywhalecc 2023-04-15 18:46:46 +08:00
parent 5b09e95e51
commit 960addc8f2
No known key found for this signature in database
GPG Key ID: 1F4BDD59391F2680
5 changed files with 173 additions and 6 deletions

View File

@ -98,3 +98,15 @@ jobs:
with:
name: micro-${{ inputs.version }}-${{ env.SPC_BUILD_OS }}
path: buildroot/bin/micro.sfx
# Upload extensions metadata
- uses: actions/upload-artifact@v3
with:
name: license-files.zip
path: buildroot/license/
- uses: actions/upload-artifact@v3
with:
name: build-meta
path: |
buildroot/build-extensions.json
buildroot/build-libraries.json

View File

@ -74,8 +74,8 @@
"url": "https://ftp.gnu.org/gnu/libiconv/",
"regex": "/href=\"(?<file>libiconv-(?<version>[^\"]+)\\.tar\\.gz)\"/",
"license": {
"type": "text",
"text": "TODO"
"type": "file",
"path": "COPYING"
}
},
"libmcrypt": {
@ -253,7 +253,7 @@
"url": "https://www.sqlite.org/2023/sqlite-autoconf-3410100.tar.gz",
"license": {
"type": "text",
"path": "The author disclaims copyright to this source code. In place of\na legal notice, here is a blessing:\n\n * May you do good and not evil.\n * May you find forgiveness for yourself and forgive others.\n * May you share freely, never taking more than you give."
"text": "The author disclaims copyright to this source code. In place of\na legal notice, here is a blessing:\n\n * May you do good and not evil.\n * May you find forgiveness for yourself and forgive others.\n * May you share freely, never taking more than you give."
}
},
"swoole": {

View File

@ -8,6 +8,7 @@ use SPC\builder\BuilderProvider;
use SPC\exception\ExceptionHandler;
use SPC\exception\WrongUsageException;
use SPC\util\DependencyUtil;
use SPC\util\LicenseDumper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@ -73,6 +74,13 @@ class BuildCliCommand extends BuildCommand
if ($rule !== BUILD_MICRO_NONE) {
logger()->info('phpmicro binary path: ' . BUILD_ROOT_PATH . '/bin/micro.sfx');
}
// 导出相关元数据
file_put_contents(BUILD_ROOT_PATH . '/build-extensions.json', json_encode($extensions, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
file_put_contents(BUILD_ROOT_PATH . '/build-libraries.json', json_encode($libraries, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
// 导出 LICENSE
$dumper = new LicenseDumper();
$dumper->addExts($extensions)->addLibs($libraries)->addSources(['php-src'])->dump(BUILD_ROOT_PATH . '/license');
logger()->info('License path: ' . BUILD_ROOT_PATH . '/license/');
return 0;
} catch (WrongUsageException $e) {
logger()->critical($e->getMessage());

View File

@ -4,8 +4,13 @@ declare(strict_types=1);
namespace SPC\command;
use Symfony\Component\Console\Input\InputArgument;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\util\DependencyUtil;
use SPC\util\LicenseDumper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
@ -18,12 +23,54 @@ class DumpLicenseCommand extends BaseCommand
public function configure()
{
$this->setDescription('Dump licenses for required libraries');
$this->addArgument('config-name', InputArgument::REQUIRED, 'Your config to be sorted, you can sort "lib", "source" and "ext".');
$this->addOption('by-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('dump-dir', null, InputOption::VALUE_REQUIRED, 'Change dump directory', BUILD_ROOT_PATH . '/license');
}
/**
* @throws WrongUsageException
* @throws FileSystemException
* @throws RuntimeException
*/
public function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln('<info>not implemented</info>');
$dumper = new LicenseDumper();
if ($input->getOption('by-extensions') !== null) {
// 从参数中获取要编译的 extensions并转换为数组
$extensions = array_map('trim', array_filter(explode(',', $input->getOption('by-extensions'))));
// 根据提供的扩展列表获取依赖库列表并编译
[$extensions, $libraries, $not_included] = DependencyUtil::getExtLibsByDeps($extensions);
$dumper->addExts($extensions);
$dumper->addLibs($libraries);
if (!$input->getOption('without-php')) {
$dumper->addSources(['php-src']);
}
$dumper->dump($input->getOption('dump-dir'));
$output->writeln('Dump license with extensions: ' . implode(', ', $extensions));
$output->writeln('Dump license with libraries: ' . implode(', ', $libraries));
$output->writeln('Dump license with' . ($input->getOption('without-php') ? 'out' : '') . ' php-src');
$output->writeln('Dump target dir: ' . $input->getOption('dump-dir'));
return 0;
}
if ($input->getOption('by-libs') !== null) {
$libraries = array_map('trim', array_filter(explode(',', $input->getOption('by-libs'))));
$libraries = DependencyUtil::getLibsByDeps($libraries);
$dumper->addLibs($libraries);
$dumper->dump($input->getOption('dump-dir'));
$output->writeln('Dump target dir: ' . $input->getOption('dump-dir'));
return 0;
}
if ($input->getOption('by-sources') !== null) {
$sources = array_map('trim', array_filter(explode(',', $input->getOption('by-sources'))));
$dumper->addSources($sources);
$dumper->dump($input->getOption('dump-dir'));
$output->writeln('Dump target dir: ' . $input->getOption('dump-dir'));
return 0;
}
$output->writeln('You must use one of "--by-extensions=", "--by-libs=", "--by-sources=" to dump');
return 1;
}
}

View File

@ -0,0 +1,100 @@
<?php
declare(strict_types=1);
namespace SPC\util;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
use SPC\store\Config;
use SPC\store\FileSystem;
class LicenseDumper
{
private array $exts = [];
private array $libs = [];
private array $sources = [];
public function addExts(array $exts): LicenseDumper
{
$this->exts = array_merge($exts, $this->exts);
return $this;
}
public function addLibs(array $libs): LicenseDumper
{
$this->libs = array_merge($libs, $this->libs);
return $this;
}
public function addSources(array $sources): LicenseDumper
{
$this->sources = array_merge($sources, $this->sources);
return $this;
}
/**
* @throws WrongUsageException
* @throws FileSystemException
* @throws RuntimeException
*/
public function dump(string $target_dir): bool
{
// mkdir first
if (is_dir($target_dir) && !FileSystem::removeDir($target_dir)) {
logger()->warning('Target dump directory is noe empty, be aware!');
}
FileSystem::createDir($target_dir);
foreach ($this->exts as $ext) {
if (Config::getExt($ext, 'type') !== 'external') {
continue;
}
$source_name = Config::getExt($ext, 'source');
$content = $this->getSourceLicense($source_name);
file_put_contents($target_dir . '/ext_' . $ext . '.txt', $content);
}
foreach ($this->libs as $lib) {
$source_name = Config::getLib($lib, 'source');
$content = $this->getSourceLicense($source_name);
file_put_contents($target_dir . '/lib_' . $lib . '.txt', $content);
}
foreach ($this->sources as $source) {
file_put_contents($target_dir . '/src_' . $source . '.txt', $this->getSourceLicense($source));
}
return true;
}
/**
* @throws FileSystemException
* @throws RuntimeException
*/
private function getSourceLicense(string $source_name): ?string
{
$src = Config::getSource($source_name)['license'] ?? null;
if ($src === null) {
throw new RuntimeException('source [' . $source_name . '] license meta is not exist');
}
return match ($src['type']) {
'text' => $src['text'],
'file' => $this->loadSourceFile($source_name, $src['path'], Config::getSource($source_name)['path'] ?? null),
default => throw new RuntimeException('source [' . $source_name . '] license type is not allowed'),
};
}
/**
* @throws RuntimeException
*/
private function loadSourceFile(string $source_name, string $in_path, ?string $custom_base_path = null): string
{
if (!file_exists(SOURCE_PATH . '/' . ($custom_base_path ?? $source_name) . '/' . $in_path)) {
throw new RuntimeException('source [' . $source_name . '] license file [' . $in_path . '] is not exist');
}
return file_get_contents(SOURCE_PATH . '/' . ($custom_base_path ?? $source_name) . '/' . $in_path);
}
}