Separate env to env.ini file

This commit is contained in:
crazywhalecc
2024-10-01 15:37:37 +08:00
committed by Jerry Ma
parent 2f320507ae
commit 4e88dba630
9 changed files with 267 additions and 179 deletions

View File

@@ -30,12 +30,15 @@ use Symfony\Component\Console\Application;
*/
final class ConsoleApplication extends Application
{
public const VERSION = '2.3.4';
public const VERSION = '2.3.5';
public function __construct()
{
parent::__construct('static-php-cli', self::VERSION);
// Define internal env vars and constants
require_once ROOT_DIR . '/src/globals/internal-env.php';
$this->addCommands(
[
// Common commands

View File

@@ -10,6 +10,7 @@ use Psr\Log\LogLevel;
use SPC\ConsoleApplication;
use SPC\exception\ExceptionHandler;
use SPC\exception\WrongUsageException;
use SPC\util\GlobalEnvManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputInterface;
@@ -94,6 +95,11 @@ abstract class BaseCommand extends Command
$question = new ConfirmationQuestion($prompt->label . $case, $prompt->default);
return $helper->ask($input, $output, $question);
});
// init GlobalEnv
if (!$this instanceof BuildCommand) {
GlobalEnvManager::init();
}
if ($this->shouldExecute()) {
try {
// show raw argv list for logger()->debug

View File

@@ -23,6 +23,8 @@ class DoctorCommand extends BaseCommand
{
try {
$checker = new CheckListHandler();
// skipped items
$skip_items = array_filter(explode(',', getenv('SPC_SKIP_DOCTOR_CHECK_ITEMS') ?: ''));
$fix_policy = $this->input->getOption('auto-fix') ? FIX_POLICY_AUTOFIX : FIX_POLICY_PROMPT;
foreach ($checker->runChecks() as $check) {
@@ -32,13 +34,12 @@ class DoctorCommand extends BaseCommand
$this->output->write('Checking <comment>' . $check->item_name . '</comment> ... ');
$result = call_user_func($check->callback);
if ($result === null) {
// check if this item is skipped
if (in_array($check->item_name, $skip_items) || ($result = call_user_func($check->callback)) === null) {
$this->output->writeln('skipped');
} elseif ($result instanceof CheckResult) {
if ($result->isOK()) {
$this->output->writeln($result->getMessage() ?? 'ok');
continue;
}

View File

@@ -5,11 +5,9 @@ declare(strict_types=1);
namespace SPC\util;
use SPC\builder\BuilderBase;
use SPC\builder\freebsd\SystemUtil as BSDSystemUtil;
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
use SPC\builder\macos\SystemUtil as MacOSSystemUtil;
use SPC\builder\windows\SystemUtil as WindowsSystemUtil;
use SPC\builder\linux\SystemUtil;
use SPC\exception\RuntimeException;
use SPC\exception\WrongUsageException;
/**
* Environment variable manager
@@ -29,168 +27,78 @@ class GlobalEnvManager
* @param BuilderBase $builder Builder
* @throws RuntimeException
*/
public static function init(BuilderBase $builder): void
public static function init(?BuilderBase $builder = null): void
{
// Init global env, build related path
self::putenv('BUILD_ROOT_PATH=' . BUILD_ROOT_PATH);
self::putenv('BUILD_INCLUDE_PATH=' . BUILD_INCLUDE_PATH);
self::putenv('BUILD_LIB_PATH=' . BUILD_LIB_PATH);
self::putenv('BUILD_BIN_PATH=' . BUILD_BIN_PATH);
self::putenv('PKG_ROOT_PATH=' . PKG_ROOT_PATH);
self::putenv('SOURCE_PATH=' . SOURCE_PATH);
self::putenv('DOWNLOAD_PATH=' . DOWNLOAD_PATH);
// Check pre-defined env vars exists
if (getenv('BUILD_ROOT_PATH') === false) {
throw new RuntimeException('You must include src/globals/internal-env.php before using GlobalEnvManager');
}
// Init SPC env
self::initIfNotExists('SPC_CONCURRENCY', match (PHP_OS_FAMILY) {
'Windows' => (string) WindowsSystemUtil::getCpuCount(),
'Darwin' => (string) MacOSSystemUtil::getCpuCount(),
'Linux' => (string) LinuxSystemUtil::getCpuCount(),
'BSD' => (string) BSDSystemUtil::getCpuCount(),
default => '1',
});
// Init system-specific env
match (PHP_OS_FAMILY) {
'Windows' => self::initWindowsEnv(),
'Darwin' => self::initDarwinEnv($builder),
'Linux' => self::initLinuxEnv($builder),
'BSD' => 'TODO',
default => logger()->warning('Unknown OS: ' . PHP_OS_FAMILY),
};
}
private static function initWindowsEnv(): void
{
// Windows need php-sdk binary tools
self::initIfNotExists('PHP_SDK_PATH', WORKING_DIR . DIRECTORY_SEPARATOR . 'php-sdk-binary-tools');
self::initIfNotExists('UPX_EXEC', PKG_ROOT_PATH . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'upx.exe');
self::initIfNotExists('SPC_MICRO_PATCHES', 'static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static');
}
private static function initLinuxEnv(BuilderBase $builder): void
{
// Init C Compiler and C++ Compiler (alpine)
if (LinuxSystemUtil::isMuslDist()) {
self::initIfNotExists('CC', 'gcc');
self::initIfNotExists('CXX', 'g++');
self::initIfNotExists('AR', 'ar');
self::initIfNotExists('LD', 'ld.gold');
} else {
$arch = arch2gnu(php_uname('m'));
self::initIfNotExists('CC', "{$arch}-linux-musl-gcc");
self::initIfNotExists('CXX', "{$arch}-linux-musl-g++");
self::initIfNotExists('AR', "{$arch}-linux-musl-ar");
self::initIfNotExists('LD', 'ld.gold');
if (getenv('SPC_NO_MUSL_PATH') !== 'yes') {
self::putenv("PATH=/usr/local/musl/bin:/usr/local/musl/{$arch}-linux-musl/bin:" . getenv('PATH'));
// Define env vars for unix
if (is_unix()) {
self::putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH'));
self::putenv('PKG_CONFIG=' . BUILD_BIN_PATH . '/pkg-config');
self::putenv('PKG_CONFIG_PATH=' . BUILD_ROOT_PATH . '/lib/pkgconfig');
if ($builder instanceof BuilderBase) {
self::putenv('SPC_PHP_DEFAULT_OPTIMIZE_CFLAGS=' . ($builder->getOption('no-strip') ? '-g -O0' : '-g -Os'));
}
}
// Init arch-specific cflags
self::initIfNotExists('SPC_DEFAULT_C_FLAGS', '');
self::initIfNotExists('SPC_DEFAULT_CXX_FLAGS', '');
self::initIfNotExists('SPC_EXTRA_LIBS', '');
// Define env vars for linux
if (PHP_OS_FAMILY === 'Linux') {
$arch = GNU_ARCH;
if (SystemUtil::isMuslDist()) {
self::putenv('SPC_LINUX_DEFAULT_CC=gcc');
self::putenv('SPC_LINUX_DEFAULT_CXX=g++');
self::putenv('SPC_LINUX_DEFAULT_AR=ar');
} else {
self::putenv("SPC_LINUX_DEFAULT_CC={$arch}-linux-musl-gcc");
self::putenv("SPC_LINUX_DEFAULT_CXX={$arch}-linux-musl-g++");
self::putenv("SPC_LINUX_DEFAULT_AR={$arch}-linux-musl-ar");
}
self::putenv("SPC_PHP_DEFAULT_LD_LIBRARY_PATH=/usr/local/musl/{$arch}-linux-musl/lib");
}
// SPC_MICRO_PATCHES for linux
self::initIfNotExists('SPC_MICRO_PATCHES', 'static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream');
// Init linux-only env
self::initIfNotExists('UPX_EXEC', PKG_ROOT_PATH . '/bin/upx');
self::initIfNotExists('GNU_ARCH', arch2gnu(php_uname('m')));
// optimization flags with different strip option
$php_extra_cflags_optimize = $builder->getOption('no-strip') ? '-g -O0' : '-g -Os';
// optimization flags with different c compiler
$clang_use_lld = str_ends_with(getenv('CC'), 'clang') && LinuxSystemUtil::findCommand('lld') ? '-Xcompiler -fuse-ld=lld ' : '';
$init_spc_cmd_maps = [
// Init default build command prefix
'SPC_CMD_PREFIX_PHP_BUILDCONF' => './buildconf --force',
'SPC_CMD_PREFIX_PHP_CONFIGURE' => $builder->getOption('ld_library_path') . ' ./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg',
'SPC_CMD_PREFIX_PHP_MAKE' => 'make -j' . getenv('SPC_CONCURRENCY'),
// Init default build vars for build command
'SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS' => getenv('SPC_DEFAULT_C_FLAGS'),
'SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH,
'SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS' => '-L' . BUILD_LIB_PATH,
'SPC_CMD_VAR_PHP_CONFIGURE_LIBS' => '-ldl -lpthread -lm',
'SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS' => $php_extra_cflags_optimize . ' -fno-ident -fPIE',
'SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS' => '',
'SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM' => $clang_use_lld . '-all-static',
// Init env.ini file, read order:
// WORKING_DIR/config/env.ini
// ROOT_DIR/config/env.ini
$ini_files = [
WORKING_DIR . '/config/env.ini',
ROOT_DIR . '/config/env.ini',
];
foreach ($init_spc_cmd_maps as $name => $value) {
self::initIfNotExists($name, $value);
$ini = null;
foreach ($ini_files as $ini_file) {
if (file_exists($ini_file)) {
$ini = parse_ini_file($ini_file, true);
break;
}
}
self::initUnixEnv($builder);
}
private static function initDarwinEnv(BuilderBase $builder): void
{
// Init C Compiler and C++ Compiler
self::initIfNotExists('CC', 'clang');
self::initIfNotExists('CXX', 'clang++');
// Init arch-specific cflags
self::initIfNotExists('SPC_DEFAULT_C_FLAGS', match (php_uname('m')) {
'arm64', 'aarch64' => '--target=arm64-apple-darwin',
default => '--target=x86_64-apple-darwin',
});
// Init arch-specific cxxflags
self::initIfNotExists('SPC_DEFAULT_CXX_FLAGS', match (php_uname('m')) {
'arm64', 'aarch64' => '--target=arm64-apple-darwin',
default => '--target=x86_64-apple-darwin',
});
// Init extra libs (will be appended before `before-php-buildconf` event point)
self::initIfNotExists('SPC_EXTRA_LIBS', '');
// SPC_MICRO_PATCHES for macOS
self::initIfNotExists('SPC_MICRO_PATCHES', 'static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,macos_iconv');
$init_spc_cmd_maps = [
// Init default build command prefix
'SPC_CMD_PREFIX_PHP_BUILDCONF' => './buildconf --force',
'SPC_CMD_PREFIX_PHP_CONFIGURE' => './configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg',
'SPC_CMD_PREFIX_PHP_MAKE' => 'make -j' . getenv('SPC_CONCURRENCY'),
// Init default build vars for build command
'SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS' => getenv('SPC_DEFAULT_C_FLAGS') . ' -Werror=unknown-warning-option',
'SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH,
'SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS' => '-L' . BUILD_LIB_PATH,
'SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS' => $builder->getOption('no-strip') ? '-g -O0' : '-g -Os',
'SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS' => '-lresolv',
];
foreach ($init_spc_cmd_maps as $name => $value) {
self::initIfNotExists($name, $value);
if ($ini === null) {
throw new WrongUsageException('env.ini not found');
}
self::initUnixEnv($builder);
}
private static function initUnixEnv(BuilderBase $builder): void
{
self::putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH'));
self::putenv('PKG_CONFIG=' . BUILD_BIN_PATH . '/pkg-config');
self::putenv('PKG_CONFIG_PATH=' . BUILD_ROOT_PATH . '/lib/pkgconfig');
}
/**
* Initialize the environment variable if it does not exist
*
* @param string $name Environment variable name
* @param string $value Environment variable value
*/
private static function initIfNotExists(string $name, string $value): void
{
if (($val = getenv($name)) === false) {
self::putenv($name . '=' . $value);
} else {
logger()->debug("env [{$name}] existing: {$val}");
if ($ini === false || !isset($ini['global'])) {
throw new WrongUsageException('Failed to parse ' . $ini_file);
}
self::applyConfig($ini['global']);
match (PHP_OS_FAMILY) {
'Windows' => self::applyConfig($ini['windows']),
'Darwin' => self::applyConfig($ini['macos']),
'Linux' => self::applyConfig($ini['linux']),
'BSD' => self::applyConfig($ini['freebsd']),
default => null,
};
}
private static function putenv(string $val): void
public static function putenv(string $val): void
{
f_putenv($val);
self::$env_cache[] = $val;
}
private static function applyConfig(array $ini): void
{
foreach ($ini as $k => $v) {
self::putenv($k . '=' . $v);
}
}
}