Fix php74 upx bug (#450)

* fix php74 cannot compile with no-strip or with-upx-pack (including lint some code)

* use captainhook installer instead of plugin composer

* use captainhook installer instead of plugin composer

* add [no build test] flag

* update actions/cache version [no build test]

* test update actions/cache version

* test update actions/cache version

* test update actions/cache version
This commit is contained in:
Jerry Ma 2024-05-16 10:51:31 +08:00 committed by GitHub
parent 1632c25223
commit 3e84becf77
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 1349 additions and 646 deletions

View File

@ -48,7 +48,7 @@ jobs:
- name: "Cache Composer packages" - name: "Cache Composer packages"
id: composer-cache id: composer-cache
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: vendor path: vendor
key: ${{ runner.os }}-phpstan-${{ hashFiles('**/composer.lock') }} key: ${{ runner.os }}-phpstan-${{ hashFiles('**/composer.lock') }}
@ -86,7 +86,7 @@ jobs:
- name: "Cache Composer packages" - name: "Cache Composer packages"
id: composer-cache id: composer-cache
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: vendor path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
@ -136,9 +136,9 @@ jobs:
echo "GITHUB_TOKEN=${{ secrets.TEST_GH_TOKEN }}" >> $GITHUB_ENV echo "GITHUB_TOKEN=${{ secrets.TEST_GH_TOKEN }}" >> $GITHUB_ENV
fi fi
- name: "Cache Composer packages" - name: "Cache composer packages"
id: composer-cache id: composer-cache
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: vendor path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}

View File

@ -16,8 +16,8 @@
"zhamao/logger": "^1.0" "zhamao/logger": "^1.0"
}, },
"require-dev": { "require-dev": {
"captainhook/captainhook": "^5.10", "captainhook/captainhook-phar": "^5.23",
"captainhook/plugin-composer": "^5.3", "captainhook/hook-installer": "^1.0",
"friendsofphp/php-cs-fixer": "^3.25", "friendsofphp/php-cs-fixer": "^3.25",
"humbug/box": "^4.5", "humbug/box": "^4.5",
"nunomaduro/collision": "^7.8", "nunomaduro/collision": "^7.8",
@ -50,7 +50,9 @@
"config": { "config": {
"allow-plugins": { "allow-plugins": {
"phpstan/extension-installer": true, "phpstan/extension-installer": true,
"captainhook/plugin-composer": true "captainhook/hook-installer": true,
"captainhook/plugin-composer": true,
"captainhook/captainhook-phar": true
}, },
"optimize-autoloader": true, "optimize-autoloader": true,
"sort-packages": true "sort-packages": true

1688
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -187,11 +187,6 @@
"icu" "icu"
] ]
}, },
"parallel": {
"type": "external",
"source": "parallel",
"arg-type-windows": "with"
},
"ldap": { "ldap": {
"type": "builtin", "type": "builtin",
"arg-type": "with-prefix", "arg-type": "with-prefix",

View File

@ -25,7 +25,7 @@ use Symfony\Component\Console\Command\ListCommand;
*/ */
final class ConsoleApplication extends Application final class ConsoleApplication extends Application
{ {
public const VERSION = '2.2.0'; public const VERSION = '2.2.1';
public function __construct() public function __construct()
{ {

View File

@ -28,7 +28,7 @@ class BSDBuilder extends UnixBuilderBase
// ---------- set necessary options ---------- // ---------- set necessary options ----------
// set C Compiler (default: clang) // set C Compiler (default: clang)
f_putenv('CC=' . $this->getOption('cc', 'clang')); f_putenv('CC=' . $this->getOption('cc', 'clang'));
// set C++ Composer (default: clang++) // set C++ Compiler (default: clang++)
f_putenv('CXX=' . $this->getOption('cxx', 'clang++')); f_putenv('CXX=' . $this->getOption('cxx', 'clang++'));
// set PATH // set PATH
f_putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH')); f_putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH'));

View File

@ -92,6 +92,9 @@ class LinuxBuilder extends UnixBuilderBase
} }
/** /**
* Build PHP from source.
*
* @param int $build_target Build target, use `BUILD_TARGET_*` constants
* @throws RuntimeException * @throws RuntimeException
* @throws FileSystemException * @throws FileSystemException
* @throws WrongUsageException * @throws WrongUsageException
@ -131,10 +134,10 @@ class LinuxBuilder extends UnixBuilderBase
} }
$disable_jit = $this->getOption('disable-opcache-jit', false) ? '--disable-opcache-jit ' : ''; $disable_jit = $this->getOption('disable-opcache-jit', false) ? '--disable-opcache-jit ' : '';
$enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI; $enable_cli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM; $enable_fpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO; $enable_micro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED; $enable_embed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
// prepare build php envs // prepare build php envs
$envs_build_php = SystemUtil::makeEnvVarString([ $envs_build_php = SystemUtil::makeEnvVarString([
@ -144,49 +147,18 @@ class LinuxBuilder extends UnixBuilderBase
'LIBS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_LIBS'), 'LIBS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_LIBS'),
]); ]);
// upx pack and strip for micro // process micro upx patch if micro sapi enabled
// but always restore Makefile.frag.bak first if ($enable_micro) {
if (file_exists(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak')) { $this->processMicroUPX();
copy(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak', SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag');
}
if ($this->getOption('with-upx-pack', false)) {
// judge $(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)` count
// if 2, replace src/globals/extra/micro-triple-Makefile.frag file content
if (substr_count(FileSystem::readFile(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag'), '$(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)`') === 2) {
// bak first
copy(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag', SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak');
// replace Makefile.frag content
FileSystem::writeFile(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag', FileSystem::readFile(ROOT_DIR . '/src/globals/extra/micro-triple-Makefile.frag'));
}
// with upx pack always need strip
FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag',
'/POST_MICRO_BUILD_COMMANDS=.*/',
'POST_MICRO_BUILD_COMMANDS=\$(STRIP) \$(MICRO_STRIP_FLAGS) \$(SAPI_MICRO_PATH) && ' . getenv('UPX_EXEC') . ' --best \$(SAPI_MICRO_PATH)',
);
} elseif (!$this->getOption('no-strip', false)) {
// not-no-strip means strip (default behavior)
FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag',
'/POST_MICRO_BUILD_COMMANDS=.*/',
'POST_MICRO_BUILD_COMMANDS=\$(STRIP) \$(MICRO_STRIP_FLAGS) \$(SAPI_MICRO_PATH)',
);
} else {
// just no strip
FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag',
'/POST_MICRO_BUILD_COMMANDS=.*/',
'POST_MICRO_BUILD_COMMANDS=true',
);
} }
shell()->cd(SOURCE_PATH . '/php-src') shell()->cd(SOURCE_PATH . '/php-src')
->exec( ->exec(
getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' . getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' .
($enableCli ? '--enable-cli ' : '--disable-cli ') . ($enable_cli ? '--enable-cli ' : '--disable-cli ') .
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') . ($enable_fpm ? '--enable-fpm ' : '--disable-fpm ') .
($enableEmbed ? '--enable-embed=static ' : '--disable-embed ') . ($enable_embed ? '--enable-embed=static ' : '--disable-embed ') .
($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') . ($enable_micro ? '--enable-micro=all-static ' : '--disable-micro ') .
$disable_jit . $disable_jit .
$json_74 . $json_74 .
$zts . $zts .
@ -200,21 +172,21 @@ class LinuxBuilder extends UnixBuilderBase
$this->cleanMake(); $this->cleanMake();
if ($enableCli) { if ($enable_cli) {
logger()->info('building cli'); logger()->info('building cli');
$this->buildCli(); $this->buildCli();
} }
if ($enableFpm) { if ($enable_fpm) {
logger()->info('building fpm'); logger()->info('building fpm');
$this->buildFpm(); $this->buildFpm();
} }
if ($enableMicro) { if ($enable_micro) {
logger()->info('building micro'); logger()->info('building micro');
$this->buildMicro(); $this->buildMicro();
} }
if ($enableEmbed) { if ($enable_embed) {
logger()->info('building embed'); logger()->info('building embed');
if ($enableMicro) { if ($enable_micro) {
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Makefile', 'OVERALL_TARGET =', 'OVERALL_TARGET = libphp.la'); FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Makefile', 'OVERALL_TARGET =', 'OVERALL_TARGET = libphp.la');
} }
$this->buildEmbed(); $this->buildEmbed();
@ -330,4 +302,48 @@ class LinuxBuilder extends UnixBuilderBase
'EXTRA_LDFLAGS_PROGRAM' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM'), 'EXTRA_LDFLAGS_PROGRAM' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM'),
]; ];
} }
/**
* Apply option --no-strip and --with-upx-pack for micro sapi.
*
* @throws FileSystemException
*/
private function processMicroUPX(): void
{
// upx pack and strip for micro
// but always restore Makefile.frag.bak first
if (file_exists(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak')) {
copy(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak', SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag');
}
if ($this->getOption('with-upx-pack', false)) {
// judge $(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)` count
// if 2, replace src/globals/extra/micro-triple-Makefile.frag file content
if (substr_count(FileSystem::readFile(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag'), '$(MAKE) micro_2s_objs SFX_FILESIZE=`$(STAT_SIZE) $(SAPI_MICRO_PATH)`') === 2) {
// bak first
copy(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag', SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.bak');
// replace Makefile.frag content
FileSystem::writeFile(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag', FileSystem::readFile(ROOT_DIR . '/src/globals/extra/micro-triple-Makefile.frag'));
}
// with upx pack always need strip
FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag',
'/POST_MICRO_BUILD_COMMANDS=.*/',
'POST_MICRO_BUILD_COMMANDS=\$(STRIP) \$(MICRO_STRIP_FLAGS) \$(SAPI_MICRO_PATH) && ' . getenv('UPX_EXEC') . ' --best \$(SAPI_MICRO_PATH)',
);
} elseif (!$this->getOption('no-strip', false)) {
// not-no-strip means strip (default behavior)
FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag',
'/POST_MICRO_BUILD_COMMANDS=.*/',
'POST_MICRO_BUILD_COMMANDS=\$(STRIP) \$(MICRO_STRIP_FLAGS) \$(SAPI_MICRO_PATH)',
);
} else {
// just no strip
FileSystem::replaceFileRegex(
SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag',
'/POST_MICRO_BUILD_COMMANDS=.*/',
'POST_MICRO_BUILD_COMMANDS=true',
);
}
}
} }

View File

@ -132,4 +132,14 @@ abstract class BaseCommand extends Command
{ {
return true; return true;
} }
protected function logWithResult(bool $result, string $success_msg, string $fail_msg): int
{
if ($result) {
logger()->info($success_msg);
return static::SUCCESS;
}
logger()->error($fail_msg);
return static::FAILURE;
}
} }

View File

@ -17,7 +17,7 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use ZM\Logger\ConsoleColor; use ZM\Logger\ConsoleColor;
#[AsCommand('build', 'build PHP')] #[AsCommand('build', 'build PHP', ['build:php'])]
class BuildCliCommand extends BuildCommand class BuildCliCommand extends BuildCommand
{ {
public function configure(): void public function configure(): void

View File

@ -61,6 +61,8 @@ class BuildLibsCommand extends BuildCommand
$builder->setLibsOnly(); $builder->setLibsOnly();
// 编译和检查库完整 // 编译和检查库完整
$libraries = DependencyUtil::getLibs($libraries); $libraries = DependencyUtil::getLibs($libraries);
logger()->info('Building libraries: ' . implode(',', $libraries));
sleep(2);
$builder->buildLibs($libraries); $builder->buildLibs($libraries);
$time = round(microtime(true) - START_TIME, 3); $time = round(microtime(true) - START_TIME, 3);

View File

@ -57,8 +57,11 @@ class DumpLicenseCommand extends BaseCommand
$libraries = DependencyUtil::getLibs($libraries); $libraries = DependencyUtil::getLibs($libraries);
$dumper->addLibs($libraries); $dumper->addLibs($libraries);
$dumper->dump($this->getOption('dump-dir')); $dumper->dump($this->getOption('dump-dir'));
$this->output->writeln('Dump target dir: ' . $this->getOption('dump-dir')); return $this->logWithResult(
return static::SUCCESS; $dumper->dump($this->getOption('dump-dir')),
'Dump target dir: ' . $this->getOption('dump-dir'),
'Dump failed!'
);
} }
if ($this->getOption('for-sources') !== null) { if ($this->getOption('for-sources') !== null) {
$sources = array_map('trim', array_filter(explode(',', $this->getOption('for-sources')))); $sources = array_map('trim', array_filter(explode(',', $this->getOption('for-sources'))));

View File

@ -51,7 +51,7 @@ class GlobalEnvManager
// Init system-specific env // Init system-specific env
match (PHP_OS_FAMILY) { match (PHP_OS_FAMILY) {
'Windows' => self::initWindowsEnv($builder), 'Windows' => self::initWindowsEnv(),
'Darwin' => self::initDarwinEnv($builder), 'Darwin' => self::initDarwinEnv($builder),
'Linux' => self::initLinuxEnv($builder), 'Linux' => self::initLinuxEnv($builder),
'BSD' => 'TODO', 'BSD' => 'TODO',
@ -59,7 +59,7 @@ class GlobalEnvManager
}; };
} }
private static function initWindowsEnv(BuilderBase $builder): void private static function initWindowsEnv(): void
{ {
// Windows need php-sdk binary tools // Windows need php-sdk binary tools
self::initIfNotExists('PHP_SDK_PATH', WORKING_DIR . DIRECTORY_SEPARATOR . 'php-sdk-binary-tools'); self::initIfNotExists('PHP_SDK_PATH', WORKING_DIR . DIRECTORY_SEPARATOR . 'php-sdk-binary-tools');
@ -69,7 +69,7 @@ class GlobalEnvManager
private static function initLinuxEnv(BuilderBase $builder): void private static function initLinuxEnv(BuilderBase $builder): void
{ {
// Init C Compiler and C++ Compiler (alpine) // Init C Compiler and C++ Compiler (alpine)
if (\SPC\builder\linux\SystemUtil::isMuslDist()) { if (LinuxSystemUtil::isMuslDist()) {
self::initIfNotExists('CC', 'gcc'); self::initIfNotExists('CC', 'gcc');
self::initIfNotExists('CXX', 'g++'); self::initIfNotExists('CXX', 'g++');
self::initIfNotExists('AR', 'ar'); self::initIfNotExists('AR', 'ar');

View File

@ -10,6 +10,9 @@ use SPC\exception\WrongUsageException;
use SPC\store\Config; use SPC\store\Config;
use SPC\store\FileSystem; use SPC\store\FileSystem;
/**
* License dumper, dump source license files to target directory
*/
class LicenseDumper class LicenseDumper
{ {
private array $exts = []; private array $exts = [];
@ -37,6 +40,10 @@ class LicenseDumper
} }
/** /**
* Dump source licenses to target directory
*
* @param string $target_dir Target directory
* @return bool Success or not
* @throws WrongUsageException * @throws WrongUsageException
* @throws FileSystemException * @throws FileSystemException
* @throws RuntimeException * @throws RuntimeException
@ -55,20 +62,29 @@ class LicenseDumper
$source_name = Config::getExt($ext, 'source'); $source_name = Config::getExt($ext, 'source');
foreach ($this->getSourceLicenses($source_name) as $index => $license) { foreach ($this->getSourceLicenses($source_name) as $index => $license) {
file_put_contents("{$target_dir}/ext_{$ext}_{$index}.txt", $license); $result = file_put_contents("{$target_dir}/ext_{$ext}_{$index}.txt", $license);
if ($result === false) {
return false;
}
} }
} }
foreach ($this->libs as $lib) { foreach ($this->libs as $lib) {
$source_name = Config::getLib($lib, 'source'); $source_name = Config::getLib($lib, 'source');
foreach ($this->getSourceLicenses($source_name) as $index => $license) { foreach ($this->getSourceLicenses($source_name) as $index => $license) {
file_put_contents("{$target_dir}/lib_{$lib}_{$index}.txt", $license); $result = file_put_contents("{$target_dir}/lib_{$lib}_{$index}.txt", $license);
if ($result === false) {
return false;
}
} }
} }
foreach ($this->sources as $source) { foreach ($this->sources as $source) {
foreach ($this->getSourceLicenses($source) as $index => $license) { foreach ($this->getSourceLicenses($source) as $index => $license) {
file_put_contents("{$target_dir}/src_{$source}_{$index}.txt", $license); $result = file_put_contents("{$target_dir}/src_{$source}_{$index}.txt", $license);
if ($result === false) {
return false;
}
} }
} }
return true; return true;

View File

@ -1,38 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\util;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
class Patcher
{
/**
* @throws FileSystemException
* @throws RuntimeException
*/
public static function patchLinuxConfigHeader(string $libc): void
{
switch ($libc) {
case 'musl_wrapper':
// bad checks
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_STRLCPY 1$/m', '');
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_STRLCAT 1$/m', '');
// no break
case 'musl':
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_FUNC_ATTRIBUTE_IFUNC 1$/m', '');
break;
case 'glibc':
// avoid lcrypt dependency
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_CRYPT 1$/m', '');
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_CRYPT_R 1$/m', '');
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/main/php_config.h', '/^#define HAVE_CRYPT_H 1$/m', '');
break;
default:
throw new RuntimeException('not implemented');
}
}
}

View File

@ -15,6 +15,9 @@ class UnixShell
private array $env = []; private array $env = [];
/**
* @throws RuntimeException
*/
public function __construct(?bool $debug = null) public function __construct(?bool $debug = null)
{ {
if (PHP_OS_FAMILY === 'Windows') { if (PHP_OS_FAMILY === 'Windows') {

View File

@ -15,6 +15,9 @@ class WindowsCmd
private array $env = []; private array $env = [];
/**
* @throws RuntimeException
*/
public function __construct(?bool $debug = null) public function __construct(?bool $debug = null)
{ {
if (PHP_OS_FAMILY !== 'Windows') { if (PHP_OS_FAMILY !== 'Windows') {

View File

@ -47,6 +47,13 @@ function arch2gnu(string $arch): string
}; };
} }
/**
* Match pattern function
* Example: match_pattern('*.txt', 'test.txt') will return true.
*
* @param string $pattern Pattern string
* @param string $subject Subject string
*/
function match_pattern(string $pattern, string $subject): bool function match_pattern(string $pattern, string $subject): bool
{ {
$pattern = str_replace(['\*', '\\\\.*'], ['.*', '\*'], preg_quote($pattern, '/')); $pattern = str_replace(['\*', '\\\\.*'], ['.*', '\*'], preg_quote($pattern, '/'));
@ -54,6 +61,12 @@ function match_pattern(string $pattern, string $subject): bool
return preg_match($pattern, $subject) === 1; return preg_match($pattern, $subject) === 1;
} }
/**
* Quote a string with a quote character
*
* @param string $str String to quote
* @param string $quote Quote character, default: `"`
*/
function quote(string $str, string $quote = '"'): string function quote(string $str, string $quote = '"'): string
{ {
return $quote . $str . $quote; return $quote . $str . $quote;
@ -61,7 +74,6 @@ function quote(string $str, string $quote = '"'): string
/** /**
* Get Family name of current OS * Get Family name of current OS
*
* @throws WrongUsageException * @throws WrongUsageException
*/ */
function osfamily2dir(): string function osfamily2dir(): string
@ -76,6 +88,41 @@ function osfamily2dir(): string
}; };
} }
function shell(?bool $debug = null): UnixShell
{
/* @noinspection PhpUnhandledExceptionInspection */
return new UnixShell($debug);
}
function cmd(?bool $debug = null): WindowsCmd
{
/* @noinspection PhpUnhandledExceptionInspection */
return new WindowsCmd($debug);
}
/**
* Get current builder.
*
* @throws WrongUsageException
*/
function builder(): BuilderBase
{
return BuilderProvider::getBuilder();
}
/**
* Get current patch point.
*
* @throws WrongUsageException
*/
function patch_point(): string
{
return BuilderProvider::getBuilder()->getPatchPoint();
}
// ------- function f_* part -------
// f_ means standard function wrapper
/** /**
* Execute the shell command, and the output will be directly printed in the terminal. If there is an error, an exception will be thrown * Execute the shell command, and the output will be directly printed in the terminal. If there is an error, an exception will be thrown
* *
@ -126,33 +173,3 @@ function f_putenv(string $env): bool
logger()->debug('Setting env: ' . $env); logger()->debug('Setting env: ' . $env);
return putenv($env); return putenv($env);
} }
function shell(?bool $debug = null): UnixShell
{
return new UnixShell($debug);
}
function cmd(?bool $debug = null): WindowsCmd
{
return new WindowsCmd($debug);
}
/**
* Get current builder.
*
* @throws WrongUsageException
*/
function builder(): BuilderBase
{
return BuilderProvider::getBuilder();
}
/**
* Get current patch point.
*
* @throws WrongUsageException
*/
function patch_point(): string
{
return BuilderProvider::getBuilder()->getPatchPoint();
}