diff --git a/README.md b/README.md index 71e487c..728e1d9 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,80 @@ the plugin or library has what is needed, such as checking a define or making sure that a method or class already exists. +## Sources and Stubs + +Source files are added in the `include` block as either a `file` or a `dir`. + + include { + dir "directory-to-add"; + file "file-to-add.php"; + } + +The stub is what is invoked when the executable is called, and it is defined in +the `phar` block, outside of the `include` block that is. The stub must however +be added through one of the rules in the `include` block. + + stub "src/stub.php"; + +In the future, it will also be possible to exclude files matching specific +patterns. + + +## Props + +The project properties are a set of key=value items that are defined in the stub, +and thus made available to the code in the phar. it can be read from a file, or +generated by a script or executable. Comments should be prefixed with a hash sign +(`#`): + + # Comment line + MYAPP_VERSION=1.0 + MYAPP_VARIANT=lite + MYAPP_BUILDDATE=2017-03-14 + +To add props from a file: + + props "app.props"; + +To evaluate props when building the archive: + + props exec="generate-props.php"; + +## Options and Tweaks + +Boolean options (such as `verbatim` and `library`) will have their value default +to *true* if omitted. So these two lines will have the same effect: + + verbatim; + verbatim true; + +The following options are currently available. Read the notes before using them +tho! + + +### library (bool) + +If set, the created phar will be a pure library, intended to be *included* into +other PHP projects. The library mode currently depends on composer, and it will +use `vendor/autoload.php` as the main stub. As such, you need to add any code +you want executed on load to `autoload/files` in your composer.json. + + +### verbatim (bool) + +If set, no minification will take place. Generally, the minification should not +cause any problems but lead to a file that can be up to half a megabyte smaller +as whitespace and comments are removed. + + +### compress (bool) + +Compress is a legacy option from MakePhar *mk1*, and is not yet implemented. It +will work in a similar fashion to how it did before: The resulting .phar will +be compressed, and the output will have a stub prepended to extract the .phar +into a temporary directory before running. But right now **it does nothing**. + + ## Pro Tips * You can have multiple `phar` blocks in your `makephar.conf`. This lets @@ -65,5 +139,5 @@ sure that a method or class already exists. 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. + a specific character index in a specific php file, you might want to specify + the `verbatim` option. diff --git a/makephar.sdl b/makephar.sdl index 3593127..dffab2f 100644 --- a/makephar.sdl +++ b/makephar.sdl @@ -4,9 +4,6 @@ phar "makephar.phar" { // Set to true to build a library-only phar library false; - // Set to 1, 2 or 3 to compress, doesn't work for libraries - compress false; - // Set stub stub "src/bootstrap.php"; diff --git a/src/MakePhar/Application.php b/src/MakePhar/Application.php index 0d462bd..076e68c 100644 --- a/src/MakePhar/Application.php +++ b/src/MakePhar/Application.php @@ -50,6 +50,9 @@ class Application $this->printHelp(); return; } + + log_info("MakePhar 2.0 - (c) 2016-2017, NoccyLabs"); + if ($this->config->init) { if (!file_exists("composer.json")) { error_log("No composer.json in current directory"); diff --git a/src/MakePhar/Manifest.php b/src/MakePhar/Manifest.php index 8eddbe6..d154474 100644 --- a/src/MakePhar/Manifest.php +++ b/src/MakePhar/Manifest.php @@ -19,6 +19,10 @@ class Manifest protected $stub = null; /** @var bool If true, the archive will be compressed */ protected $compress = false; + /** @var bool If true, the files will be added without minification */ + protected $verbatim = false; + /** @var array Properties to be defined in the main stub */ + protected $props = []; /** * Read manifests from a makephar.sdl file and return all the build targets @@ -51,10 +55,13 @@ class Manifest foreach ($tag->getChildren() as $child) switch ($child->getTagName()) { case 'library': - $mf->setIsLibrary($child->getValue()); + $mf->setIsLibrary($child->getValue()?:true); break; case 'compress': - $mf->setCompression($child->getValue()); + $mf->setCompression($child->getValue()?:true); + break; + case 'verbatim': + $mf->setVerbatim($child->getValue()?:true); break; case 'stub': $mf->setStubFile($child->getValue()); @@ -67,6 +74,38 @@ class Manifest break; } break; + case 'props': + if ($src = (string)$child->getValue()) { + if (!file_exists($src)) { + log_warn("Property file %s not found", $src); + continue; + } + log_info("Reading props from file %s", $src); + $props = file($src, FILE_SKIP_EMPTY_LINES|FILE_IGNORE_NEW_LINES); + } elseif ($script = (string)$child->getAttribute('exec')) { + log_info("Generating props using %s", $script); + if (fnmatch("*.php",$script)) $script = "php {$script}"; + exec($script, $props, $ret); + if ($ret>0) { + log_warn("Script exited with code %d", $ret); + continue; + } + } else { + log_warn("Props specified without either script or src. Properties will not be added."); + continue; + } + foreach ($props as $prop) { + $prop = trim($prop); + // skip comments and empty lines + if ($prop && $prop[0]=='#') continue; + if (strpos($prop,'=')===false) continue; + // extract key/value + list ($k,$v) = explode("=",$prop,2); + log_debug(" prop[%s] = %s", strtoupper($k),$v); + $mf->props[strtoupper($k)] = $v; + } + break; + } return $mf; @@ -117,6 +156,17 @@ class Manifest return $this->compress; } + public function setVerbatim($value) + { + $this->verbatim = $value; + return $this; + } + + public function getVerbatim() + { + return $this->verbatim; + } + public function addSource($type, $path, array $opts) { $this->sources[] = (object)[ @@ -151,4 +201,9 @@ class Manifest return $items; } + public function getProps() + { + return (array)$this->props; + } + } diff --git a/src/MakePhar/PharBuilder.php b/src/MakePhar/PharBuilder.php index 736ec14..175b0c9 100644 --- a/src/MakePhar/PharBuilder.php +++ b/src/MakePhar/PharBuilder.php @@ -38,7 +38,12 @@ class PharBuilder { // Create the phar $phar = new \Phar($this->tempFile); - $vo = posix_isatty(STDOUT); + + // verbatim add + $verbatim = $this->manifest->getVerbatim(); + if ($verbatim) { + log_debug("Note: Creating verbatim archive without minification"); + } // Add files log_debug("Adding files to phar archive..."); @@ -48,20 +53,23 @@ class PharBuilder foreach ($this->files as $file) { $i++; $tp = dirname($file->src); - if ($tp!=$lp) { + if (($tp!=$lp) && (IS_TTY)) { $lp=$tp; printf("\r\e[K%d/%d %s", $i, $t, $tp); } - if (fnmatch("*.php",$file->src)) { + + if (fnmatch("*.php",$file->src) && (!$verbatim)) { $min = php_strip_whitespace($file->src); $size_tot += filesize($file->src); $size_min += strlen($min); $phar->addFromString($file->dest?:$file->src, $min); } else { + $size_tot += filesize($file->src); + $size_min += filesize($file->src); $phar->addFile($file->dest?:$file->src, $file->src); } } - ($vo) && printf("\r\e[K"); + (IS_TTY) && printf("\r\e[K"); $phar->stopBuffering(); // Helper to format sizes @@ -72,9 +80,13 @@ class PharBuilder }; // Format the status $str_tot = $formatSize($size_tot); - $str_min = $formatSize($size_min); - $str_rat = sprintf("%.2f%%", 100/$str_tot*$str_min); - log_debug("Size: %s, Minified: %s (%s)", $str_tot, $str_min, $str_rat); + if (!$verbatim) { + $str_min = $formatSize($size_min); + $str_rat = sprintf("%.2f%%", 100/$str_tot*$str_min); + log_debug("Size: %s, Minified: %s (%s)", $str_tot, $str_min, $str_rat); + } else { + log_debug("Size: %s", $str_tot); + } // Create stub if ($this->manifest->getIsLibrary()) { @@ -82,6 +94,9 @@ class PharBuilder // Create library stub $stub = 'manifest->getProps() as $k=>$v) { + $stub.= sprintf('define(%s,%s);', var_export($k,true), var_export($v,true)); + } if (($stubfile = $this->manifest->getStubFile())) { $stub.= 'require_once __DIR__."/'.ltrim($stubfile,'/').'";'; } @@ -90,7 +105,11 @@ class PharBuilder log_debug("Creating application stub..."); // Write application stub $stubfile = $this->manifest->getStubFile(); - $stub = 'manifest->getProps() as $k=>$v) { + $stub.= sprintf('define(%s,%s);', var_export($k,true), var_export($v,true)); + } + $stub.= 'require_once __DIR__."/'.ltrim($stubfile,'/').'";'; $phar->addFromString("index.php", $stub); // Make the phar stub executable $mainstub = $phar->createDefaultStub("index.php"); @@ -116,7 +135,7 @@ class PharBuilder if (file_exists($output)) { unlink($output); } - log_debug("Writing %s", $output); + log_info("Writing %s", $output); rename($this->tempFile, $output); if (!$this->manifest->getIsLibrary()) { diff --git a/src/global.php b/src/global.php index 514e1db..4e42dac 100644 --- a/src/global.php +++ b/src/global.php @@ -6,6 +6,21 @@ class LogFuncs { if ($bound++) return; } } -function log_info($fmt,...$arg) { printf("[info] {$fmt}\n", ...$arg); } -function log_debug($fmt,...$arg) { printf("[debg] {$fmt}\n", ...$arg); } -function log_warn($fmt,...$arg) { printf("[warn] {$fmt}\n", ...$arg); } \ No newline at end of file + +if (@empty(STDOUT) || (!posix_isatty(STDOUT))) { + define("LF_INFO", ""); + define("LF_DEBUG", ""); + define("LF_WARN", ""); + define("LF_RESET", ""); + define("IS_TTY", false); +} else { + define("LF_INFO", "\e[32;1m"); + define("LF_DEBUG", "\e[32m"); + define("LF_WARN", "\e[31;1m"); + define("LF_RESET", "\e[0m"); + define("IS_TTY", true); +} + +function log_info($fmt,...$arg) { printf(LF_INFO."[info] {$fmt}".LF_RESET."\n", ...$arg); } +function log_debug($fmt,...$arg) { printf(LF_DEBUG."[debg] {$fmt}".LF_RESET."\n", ...$arg); } +function log_warn($fmt,...$arg) { printf(LF_WARN."[warn] {$fmt}".LF_RESET."\n", ...$arg); } \ No newline at end of file