Skip to content

Commit

Permalink
[Bard] Adding ability to compile into a phar file
Browse files Browse the repository at this point in the history
  • Loading branch information
JoshuaEstes committed Oct 3, 2024
1 parent cab5a4f commit 9bed398
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ vendor/
/.php-cs-fixer.php
/.phpunit.result.cache
/.phpunit
bard.phar
composer.lock
phpunit.xml
composer.phar
Expand Down
11 changes: 11 additions & 0 deletions src/SonsOfPHP/Bard/bin/compile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env php
<?php

require __DIR__.'/../vendor/autoload.php';

use SonsOfPHP\Bard\Compiler;

//$dist = realpath(__DIR__ . '/../dist') . '/bard.phar';

$compiler = new Compiler();
$compiler->compile();
105 changes: 105 additions & 0 deletions src/SonsOfPHP/Bard/src/Compiler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

declare(strict_types=1);

namespace SonsOfPHP\Bard;

use Symfony\Component\Finder\Finder;

/**
* @author Joshua Estes <joshua@sonsofphp.com>
*/
final class Compiler
{
public function compile(string $pharFile = 'bard.phar'): void
{
if (file_exists($pharFile)) {
unlink($pharFile);
}

$phar = new \Phar($pharFile, 0, 'bard.phar');
$phar->setSignatureAlgorithm(\Phar::SHA512);
$phar->startBuffering();

// >>>
// Add source files
$finder = new Finder();
$finder->files()
->ignoreVCS(true)
->name('*.php')
->notPath('Tests')
->notName('Compiler.php')
->in(__DIR__)
;

/** @var \Symfony\Component\Finder\SplFileInfo $file */
foreach ($finder as $file) {
$this->addFile($phar, $file);
}

// <<<

// >>>
// Add vendor files
$finder = new Finder();
$finder->files()
->ignoreVCS(true)
->notPath('docs')
->notPath('Tests')
->notPath('tests')
->in(__DIR__ . '/../vendor')
;
/** @var \Symfony\Component\Finder\SplFileInfo $file */
foreach ($finder as $file) {
$this->addFile($phar, $file);
}

// <<<

$this->addBin($phar);
$this->setStub($phar);
$phar->stopBuffering();
}

private function addFile(\Phar $phar, \SplFileInfo $file): void
{
$contents = file_get_contents((string) $file);

$phar->addFromString($this->getLocalName($file), $contents);
}

private function getLocalName(\SplFileInfo $file): string
{
$realPath = $file->getRealPath();
$pathPrefix = dirname(__DIR__, 1) . DIRECTORY_SEPARATOR;
$pos = strpos($realPath, $pathPrefix);

$relativePath = ($pos !== false) ? substr_replace($realPath, '', $pos, strlen($pathPrefix)) : $realPath;

return strtr($relativePath, '\\', '/');
}

private function addBin(\Phar $phar): void
{
$contents = file_get_contents(__DIR__ . '/../bin/bard');
$contents = preg_replace('{^#!/usr/bin/env php\s*}', '', $contents);

$phar->addFromString('bin/bard', $contents);
}

private function setStub(\Phar $phar): void
{
$phar->setStub($this->getStub());
}

private function getStub(): string
{
return <<<'STUB'
#!/usr/bin/env php
<?php
Phar::mapPhar('bard.phar');
require 'phar://bard.phar/bin/bard';
__HALT_COMPILER();
STUB;
}
}

0 comments on commit 9bed398

Please sign in to comment.