From 156bb62367b48eb532fa8be9a27f0a571fee27e3 Mon Sep 17 00:00:00 2001 From: Christopher Vagnetoft Date: Tue, 10 Jan 2017 13:50:11 +0100 Subject: [PATCH] Comments, readme, bugfixes --- README.md | 69 ++++++++++++++++++++++++++++++++++++ src/MakePhar/Application.php | 2 +- src/MakePhar/PharBuilder.php | 34 ++++++++++++++++-- 3 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..71e487c --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +MakePhar mk2 +============ + +This is a rewrite of my old MakePhar utility, with cleaner code and added +portability. Besides being able to pack executables, this version can also +create libraries, such as portable plugins. + + +## Executables + +If your project is using composer, and your main stub is located in the +source directory as specified in the composer.json, you can create a +manifest easily: + + $ makephar -n > makephar.sdl + +Now, just update `makephar.sdl` to make sure the **stub** points to the +executable stub. Here is an example: + + phar "my-project.phar" { + include { + dir "src"; + dir "vendor"; + } + stub "src/boot.php"; + } + +To build this into a .phar archive, just call `makephar`: + + $ makephar + +The output file `my-project.phar` should be created and be executable out of +the box. + + +## Libraries + +Libraries work like executables, with the difference that they **require** a +composer project, or rather it requires a file named `vendor/autoload.php` in +the package. + +To load your own bootstrap using composer, add them as file autoloaders: + + ... + "autoload": { + "psr-4": ... + "files": [ "src/my-library-stub.php" ] + } + +Next, make sure you have a line in your `makephar.sdl` that reads: + + library true; + +You should now be able to create a library phar by invoking `makephar`. + +It is recommended that you add a check in your main stub to make sure that +the plugin or library has what is needed, such as checking a define or making +sure that a method or class already exists. + + +## Pro Tips + +* You can have multiple `phar` blocks in your `makephar.conf`. This lets + you build a main executable, libraries etc in one go. You currently can't + pick the rule to build tho, but rather all defined phars will be built. +* MakePhar will minify your files using `php_strip_whitespace()` before adding + them to the archive. This shouldn't be an issue, but if your code depends on + a specific character index in a specific php file, you might want to use + another tool for the time being. diff --git a/src/MakePhar/Application.php b/src/MakePhar/Application.php index 5b7978e..0d462bd 100644 --- a/src/MakePhar/Application.php +++ b/src/MakePhar/Application.php @@ -52,7 +52,7 @@ class Application } if ($this->config->init) { if (!file_exists("composer.json")) { - log_error("No composer.json in current directory"); + error_log("No composer.json in current directory"); return 1; } $proj = json_decode(file_get_contents("composer.json")); diff --git a/src/MakePhar/PharBuilder.php b/src/MakePhar/PharBuilder.php index 4cf5070..a4c317a 100644 --- a/src/MakePhar/PharBuilder.php +++ b/src/MakePhar/PharBuilder.php @@ -4,6 +4,7 @@ namespace MakePhar; class PharBuilder { + protected $tempFile; protected $manifest; @@ -16,23 +17,34 @@ class PharBuilder $this->manifest = $manifest; } + /** + * Collect files and prepare to build the .phar + * + */ public function prepare() { log_debug("Finding files to add..."); $this->files = $this->manifest->findSourceFiles(); log_debug("Found %d files", count($this->files)); + + $this->tempFile = "/tmp/".uniqid("phar").".phar"; } + /** + * Build the .phar archive + * + */ public function build() { // Create the phar - $phar = new \Phar("/tmp/output.phar"); + $phar = new \Phar($this->tempFile); $vo = posix_isatty(STDOUT); // Add files log_debug("Adding files to phar archive..."); $t = count($this->files); $i = 0; $lp = null; $phar->startBuffering(); + $size_tot = 0; $size_min = 0; foreach ($this->files as $file) { $i++; $tp = dirname($file->src); @@ -41,7 +53,10 @@ class PharBuilder printf("\r\e[K%d/%d %s", $i, $t, $tp); } if (fnmatch("*.php",$file->src)) { - $phar->addFromString($file->dest?:$file->src, php_strip_whitespace($file->src)); + $min = php_strip_whitespace($file->src); + $size_tot += filesize($file->src); + $size_min += strlen($min); + $phar->addFromString($file->dest?:$file->src, $min); } else { $phar->addFile($file->dest?:$file->src, $file->src); } @@ -49,6 +64,15 @@ class PharBuilder ($vo) && printf("\r\e[K"); $phar->stopBuffering(); + $formatSize = function ($s) { + $u = [ 'B', 'KB', 'MB', 'GB' ]; + while (count($u)>1 && ($s > 1024)) { $s /= 1024; array_shift($u); } + return sprintf("%.2f%s", $s, array_shift($u)); + }; + $str_tot = $formatSize($size_tot); + $str_min = $formatSize($size_min); + log_debug("Size: {$str_tot}, Minified: {$str_min}"); + // Create stub if ($this->manifest->getIsLibrary()) { log_debug("Creating library stub..."); @@ -78,6 +102,10 @@ class PharBuilder $phar = null; } + /** + * Move the built .phar into its target location. + * + */ public function finalize() { $output = $this->manifest->getOutput(); @@ -86,7 +114,7 @@ class PharBuilder unlink($output); } log_debug("Writing %s", $output); - rename("/tmp/output.phar", $output); + rename($this->tempFile, $output); if (!$this->manifest->getIsLibrary()) { chmod($output, 0777);