mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-03-18 12:54:52 +08:00
Add pack lib command
This commit is contained in:
parent
2a4959d973
commit
9f2132c001
33
src/StaticPHP/Command/Dev/PackLibCommand.php
Normal file
33
src/StaticPHP/Command/Dev/PackLibCommand.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace StaticPHP\Command\Dev;
|
||||||
|
|
||||||
|
use StaticPHP\Command\BaseCommand;
|
||||||
|
use StaticPHP\Package\PackageInstaller;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
|
||||||
|
#[AsCommand('dev:pack-lib', 'Packs a library package for distribution')]
|
||||||
|
class PackLibCommand extends BaseCommand
|
||||||
|
{
|
||||||
|
public function configure(): void
|
||||||
|
{
|
||||||
|
$this->addArgument('library', InputArgument::REQUIRED, 'The library will be compiled');
|
||||||
|
$this->addOption('show-libc-ver', null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
$library = $this->getArgument('library');
|
||||||
|
$show_libc_ver = $this->getOption('show-libc-ver');
|
||||||
|
|
||||||
|
$installer = new PackageInstaller(['pack-mode' => true]);
|
||||||
|
$installer->addBuildPackage($library);
|
||||||
|
|
||||||
|
$installer->run();
|
||||||
|
|
||||||
|
return static::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,6 +9,7 @@ use StaticPHP\Command\BuildTargetCommand;
|
|||||||
use StaticPHP\Command\Dev\EnvCommand;
|
use StaticPHP\Command\Dev\EnvCommand;
|
||||||
use StaticPHP\Command\Dev\IsInstalledCommand;
|
use StaticPHP\Command\Dev\IsInstalledCommand;
|
||||||
use StaticPHP\Command\Dev\LintConfigCommand;
|
use StaticPHP\Command\Dev\LintConfigCommand;
|
||||||
|
use StaticPHP\Command\Dev\PackLibCommand;
|
||||||
use StaticPHP\Command\Dev\ShellCommand;
|
use StaticPHP\Command\Dev\ShellCommand;
|
||||||
use StaticPHP\Command\DoctorCommand;
|
use StaticPHP\Command\DoctorCommand;
|
||||||
use StaticPHP\Command\DownloadCommand;
|
use StaticPHP\Command\DownloadCommand;
|
||||||
@ -63,6 +64,7 @@ class ConsoleApplication extends Application
|
|||||||
new IsInstalledCommand(),
|
new IsInstalledCommand(),
|
||||||
new EnvCommand(),
|
new EnvCommand(),
|
||||||
new LintConfigCommand(),
|
new LintConfigCommand(),
|
||||||
|
new PackLibCommand(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// add additional commands from registries
|
// add additional commands from registries
|
||||||
|
|||||||
@ -5,7 +5,13 @@ declare(strict_types=1);
|
|||||||
namespace StaticPHP\Package;
|
namespace StaticPHP\Package;
|
||||||
|
|
||||||
use StaticPHP\Config\PackageConfig;
|
use StaticPHP\Config\PackageConfig;
|
||||||
|
use StaticPHP\DI\ApplicationContext;
|
||||||
use StaticPHP\Exception\PatchException;
|
use StaticPHP\Exception\PatchException;
|
||||||
|
use StaticPHP\Exception\SPCInternalException;
|
||||||
|
use StaticPHP\Exception\ValidationException;
|
||||||
|
use StaticPHP\Runtime\SystemTarget;
|
||||||
|
use StaticPHP\Util\DependencyResolver;
|
||||||
|
use StaticPHP\Util\DirDiff;
|
||||||
use StaticPHP\Util\FileSystem;
|
use StaticPHP\Util\FileSystem;
|
||||||
use StaticPHP\Util\SPCConfigUtil;
|
use StaticPHP\Util\SPCConfigUtil;
|
||||||
|
|
||||||
@ -160,6 +166,114 @@ class LibraryPackage extends Package
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register default stages if not already defined by attributes.
|
||||||
|
* This is called after all attributes have been loaded.
|
||||||
|
*
|
||||||
|
* @internal Called by PackageLoader after loading attributes
|
||||||
|
*/
|
||||||
|
public function registerDefaultStages(): void
|
||||||
|
{
|
||||||
|
if (!$this->hasStage('packPrebuilt')) {
|
||||||
|
$this->addStage('packPrebuilt', [$this, 'packPrebuilt']);
|
||||||
|
}
|
||||||
|
// counting files before build stage
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pack the prebuilt library into an archive.
|
||||||
|
*
|
||||||
|
* @internal this function is intended to be called by the dev:pack-lib command only
|
||||||
|
*/
|
||||||
|
public function packPrebuilt(): void
|
||||||
|
{
|
||||||
|
$target_dir = WORKING_DIR . '/dist';
|
||||||
|
$placeholder_file = BUILD_ROOT_PATH . '/.spc-extract-placeholder.json';
|
||||||
|
|
||||||
|
if (!ApplicationContext::has(DirDiff::class)) {
|
||||||
|
throw new SPCInternalException('pack-dirdiff context not found for packPrebuilt stage. You cannot call "packPrebuilt" function manually.');
|
||||||
|
}
|
||||||
|
// check whether this library has correctly installed files
|
||||||
|
if (!$this->isInstalled()) {
|
||||||
|
throw new ValidationException("Cannot pack prebuilt library [{$this->getName()}] because it is not fully installed.");
|
||||||
|
}
|
||||||
|
// get after-build buildroot file list
|
||||||
|
$increase_files = ApplicationContext::get(DirDiff::class)->getIncrementFiles(true);
|
||||||
|
|
||||||
|
FileSystem::createDir($target_dir);
|
||||||
|
|
||||||
|
// before pack, check if the dependency tree contains lib-suggests
|
||||||
|
$libraries = DependencyResolver::resolve([$this], include_suggests: true);
|
||||||
|
foreach ($libraries as $lib) {
|
||||||
|
if (PackageConfig::get($lib, 'suggests', []) !== []) {
|
||||||
|
throw new ValidationException("The library {$lib} has lib-suggests, packing [{$this->name}] is not safe, abort !");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$origin_files = [];
|
||||||
|
|
||||||
|
// get pack placehoder defines
|
||||||
|
$placehoder = get_pack_replace();
|
||||||
|
|
||||||
|
// patch pkg-config and la files with absolute path
|
||||||
|
foreach ($increase_files as $file) {
|
||||||
|
if (str_ends_with($file, '.pc') || str_ends_with($file, '.la')) {
|
||||||
|
$content = FileSystem::readFile(BUILD_ROOT_PATH . '/' . $file);
|
||||||
|
$origin_files[$file] = $content;
|
||||||
|
// replace relative paths with absolute paths
|
||||||
|
$content = str_replace(
|
||||||
|
array_keys($placehoder),
|
||||||
|
array_values($placehoder),
|
||||||
|
$content
|
||||||
|
);
|
||||||
|
FileSystem::writeFile(BUILD_ROOT_PATH . '/' . $file, $content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add .spc-extract-placeholder.json in BUILD_ROOT_PATH
|
||||||
|
file_put_contents($placeholder_file, json_encode(array_keys($origin_files), JSON_PRETTY_PRINT));
|
||||||
|
$increase_files[] = '.spc-extract-placeholder.json';
|
||||||
|
|
||||||
|
// every file mapped with BUILD_ROOT_PATH
|
||||||
|
// get BUILD_ROOT_PATH last dir part
|
||||||
|
$buildroot_part = basename(BUILD_ROOT_PATH);
|
||||||
|
$increase_files = array_map(fn ($file) => $buildroot_part . '/' . $file, $increase_files);
|
||||||
|
// write list to packlib_files.txt
|
||||||
|
FileSystem::writeFile(WORKING_DIR . '/packlib_files.txt', implode("\n", $increase_files));
|
||||||
|
// pack
|
||||||
|
$filename = match (SystemTarget::getTargetOS()) {
|
||||||
|
'Windows' => '{name}-{arch}-{os}.tgz',
|
||||||
|
'Darwin' => '{name}-{arch}-{os}.txz',
|
||||||
|
'Linux' => '{name}-{arch}-{os}-{libc}-{libcver}.txz',
|
||||||
|
};
|
||||||
|
$replace = [
|
||||||
|
'{name}' => $this->getName(),
|
||||||
|
'{arch}' => arch2gnu(php_uname('m')),
|
||||||
|
'{os}' => strtolower(PHP_OS_FAMILY),
|
||||||
|
'{libc}' => SystemTarget::getLibc() ?? 'default',
|
||||||
|
'{libcver}' => SystemTarget::getLibcVersion() ?? 'default',
|
||||||
|
];
|
||||||
|
// detect suffix, for proper tar option
|
||||||
|
$tar_option = $this->getTarOptionFromSuffix($filename);
|
||||||
|
$filename = str_replace(array_keys($replace), array_values($replace), $filename);
|
||||||
|
$filename = $target_dir . '/' . $filename;
|
||||||
|
f_passthru("tar {$tar_option} {$filename} -T " . WORKING_DIR . '/packlib_files.txt');
|
||||||
|
logger()->info('Pack library ' . $this->getName() . ' to ' . $filename . ' complete.');
|
||||||
|
|
||||||
|
// remove temp files
|
||||||
|
unlink($placeholder_file);
|
||||||
|
|
||||||
|
foreach ($origin_files as $file => $content) {
|
||||||
|
// restore original files
|
||||||
|
if (file_exists(BUILD_ROOT_PATH . '/' . $file)) {
|
||||||
|
FileSystem::writeFile(BUILD_ROOT_PATH . '/' . $file, $content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove dirdiff
|
||||||
|
ApplicationContext::set(DirDiff::class, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get static library files for current package and its dependencies.
|
* Get static library files for current package and its dependencies.
|
||||||
*/
|
*/
|
||||||
@ -215,4 +329,30 @@ class LibraryPackage extends Package
|
|||||||
{
|
{
|
||||||
return BUILD_BIN_PATH;
|
return BUILD_BIN_PATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get tar compress options from suffix
|
||||||
|
*
|
||||||
|
* @param string $name Package file name
|
||||||
|
* @return string Tar options for packaging libs
|
||||||
|
*/
|
||||||
|
private function getTarOptionFromSuffix(string $name): string
|
||||||
|
{
|
||||||
|
if (str_ends_with($name, '.tar')) {
|
||||||
|
return '-cf';
|
||||||
|
}
|
||||||
|
if (str_ends_with($name, '.tar.gz') || str_ends_with($name, '.tgz')) {
|
||||||
|
return '-czf';
|
||||||
|
}
|
||||||
|
if (str_ends_with($name, '.tar.bz2') || str_ends_with($name, '.tbz2')) {
|
||||||
|
return '-cjf';
|
||||||
|
}
|
||||||
|
if (str_ends_with($name, '.tar.xz') || str_ends_with($name, '.txz')) {
|
||||||
|
return '-cJf';
|
||||||
|
}
|
||||||
|
if (str_ends_with($name, '.tar.lz') || str_ends_with($name, '.tlz')) {
|
||||||
|
return '-c --lzma -f';
|
||||||
|
}
|
||||||
|
return '-cf';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ use StaticPHP\Exception\WrongUsageException;
|
|||||||
use StaticPHP\Registry\PackageLoader;
|
use StaticPHP\Registry\PackageLoader;
|
||||||
use StaticPHP\Runtime\SystemTarget;
|
use StaticPHP\Runtime\SystemTarget;
|
||||||
use StaticPHP\Util\DependencyResolver;
|
use StaticPHP\Util\DependencyResolver;
|
||||||
|
use StaticPHP\Util\DirDiff;
|
||||||
use StaticPHP\Util\FileSystem;
|
use StaticPHP\Util\FileSystem;
|
||||||
use StaticPHP\Util\GlobalEnvManager;
|
use StaticPHP\Util\GlobalEnvManager;
|
||||||
use StaticPHP\Util\InteractiveTerm;
|
use StaticPHP\Util\InteractiveTerm;
|
||||||
@ -71,6 +72,9 @@ class PackageInstaller
|
|||||||
if (!$package->hasStage('build')) {
|
if (!$package->hasStage('build')) {
|
||||||
throw new WrongUsageException("Target package '{$package->getName()}' does not define build process for current OS: " . PHP_OS_FAMILY . '.');
|
throw new WrongUsageException("Target package '{$package->getName()}' does not define build process for current OS: " . PHP_OS_FAMILY . '.');
|
||||||
}
|
}
|
||||||
|
if (($this->options['pack-mode'] ?? false) === true && !empty($this->build_packages)) {
|
||||||
|
throw new WrongUsageException("In 'pack-mode', only one package can be built at a time. Cannot add package '{$package->getName()}' to build list.");
|
||||||
|
}
|
||||||
$this->build_packages[$package->getName()] = $package;
|
$this->build_packages[$package->getName()] = $package;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -195,8 +199,16 @@ class PackageInstaller
|
|||||||
InteractiveTerm::indicateProgress('Building package: ' . ConsoleColor::yellow($package->getName()));
|
InteractiveTerm::indicateProgress('Building package: ' . ConsoleColor::yellow($package->getName()));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
if ($is_to_build && ($this->options['pack-mode'] ?? false) === true) {
|
||||||
|
$dirdiff = new DirDiff(BUILD_ROOT_PATH, false);
|
||||||
|
ApplicationContext::set(DirDiff::class, $dirdiff);
|
||||||
|
}
|
||||||
/** @var LibraryPackage $package */
|
/** @var LibraryPackage $package */
|
||||||
$status = $builder->buildPackage($package, $this->isBuildPackage($package));
|
$status = $builder->buildPackage($package, $this->isBuildPackage($package));
|
||||||
|
|
||||||
|
if ($is_to_build && ($this->options['pack-mode'] ?? false) === true) {
|
||||||
|
$package->runStage('packPrebuilt');
|
||||||
|
}
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
if ($interactive) {
|
if ($interactive) {
|
||||||
InteractiveTerm::finish('Building package failed: ' . ConsoleColor::red($package->getName()), false);
|
InteractiveTerm::finish('Building package failed: ' . ConsoleColor::red($package->getName()), false);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user