diff --git a/config/env.ini b/config/env.ini index afbce73c..375ee13c 100644 --- a/config/env.ini +++ b/config/env.ini @@ -89,7 +89,7 @@ LD=${SPC_LINUX_DEFAULT_LD} SPC_DEFAULT_C_FLAGS="-fPIC -Os" SPC_DEFAULT_CXX_FLAGS="-fPIC -Os" ; extra libs for building php executable, used in `make` command for building php (this value may changed by extension build process, space separated) -SPC_EXTRA_LIBS= +SPC_EXTRA_LIBS="" ; upx executable path UPX_EXEC=${PKG_ROOT_PATH}/bin/upx ; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches @@ -119,7 +119,7 @@ SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE ; EXTRA_LIBS for `make` php SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm" ; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so -SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS="" +SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS="-L${BUILD_LIB_PATH}" ; EXTRA_LDFLAGS_PROGRAM for `make` php SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-all-static -Wl,-O1 -pie" @@ -134,7 +134,7 @@ CXX=clang++ SPC_DEFAULT_C_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os" SPC_DEFAULT_CXX_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os" ; extra libs for building php executable, used in `make` command for building php (this value may changed by extension build process, space separated) -SPC_EXTRA_LIBS= +SPC_EXTRA_LIBS="" ; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches SPC_MICRO_PATCHES=cli_checks,macos_iconv diff --git a/config/lib.json b/config/lib.json index 28775535..26910ec0 100644 --- a/config/lib.json +++ b/config/lib.json @@ -737,8 +737,8 @@ "openssl": { "source": "openssl", "static-libs-unix": [ - "libssl.a", - "libcrypto.a" + "libcrypto.a", + "libssl.a" ], "static-libs-windows": [ "libssl.lib", diff --git a/src/SPC/builder/freebsd/BSDBuilder.php b/src/SPC/builder/freebsd/BSDBuilder.php index 65ebea57..3e9cc80b 100644 --- a/src/SPC/builder/freebsd/BSDBuilder.php +++ b/src/SPC/builder/freebsd/BSDBuilder.php @@ -63,18 +63,6 @@ class BSDBuilder extends UnixBuilderBase */ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void { - // ---------- Update extra-libs ---------- - $extra_libs = $this->getOption('extra-libs', ''); - // add libc++, some extensions or libraries need it (C++ cannot be linked statically) - $extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lc++ ' : ''); - if (!$this->getOption('bloat', false)) { - $extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', $this->getAllStaticLibFiles()); - } else { - logger()->info('bloat linking'); - $extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', array_map(fn ($x) => "-Wl,-force_load,{$x}", array_filter($this->getAllStaticLibFiles()))); - } - $this->setOption('extra-libs', $extra_libs); - $this->emitPatchPoint('before-php-buildconf'); SourcePatcher::patchBeforeBuildconf($this); diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index 94d8a41e..869f088f 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -11,6 +11,7 @@ use SPC\exception\WrongUsageException; use SPC\store\FileSystem; use SPC\store\SourcePatcher; use SPC\util\GlobalEnvManager; +use SPC\util\SPCConfigUtil; class LinuxBuilder extends UnixBuilderBase { @@ -56,17 +57,6 @@ class LinuxBuilder extends UnixBuilderBase */ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void { - // ---------- Update extra-libs ---------- - $extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; - // bloat means force-load all static libraries, even if they are not used - if (!$this->getOption('bloat', false)) { - $extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', $this->getAllStaticLibFiles()); - } else { - $extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", array_filter($this->getAllStaticLibFiles()))); - } - // add libstdc++, some extensions or libraries need it - $extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lstdc++ ' : ''); - f_putenv('SPC_EXTRA_LIBS=' . $extra_libs); $cflags = $this->arch_c_flags; f_putenv('CFLAGS=' . $cflags); @@ -308,9 +298,10 @@ class LinuxBuilder extends UnixBuilderBase private function getMakeExtraVars(): array { + $config = (new SPCConfigUtil($this, ['libs_only_deps' => true, 'absolute_libs' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs')); return [ 'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), - 'EXTRA_LIBS' => getenv('SPC_EXTRA_LIBS') . ' ' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS'), + 'EXTRA_LIBS' => $config['libs'], 'EXTRA_LDFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'), 'EXTRA_LDFLAGS_PROGRAM' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM'), ]; diff --git a/src/SPC/builder/macos/MacOSBuilder.php b/src/SPC/builder/macos/MacOSBuilder.php index 362a68fe..50efa013 100644 --- a/src/SPC/builder/macos/MacOSBuilder.php +++ b/src/SPC/builder/macos/MacOSBuilder.php @@ -12,6 +12,7 @@ use SPC\exception\WrongUsageException; use SPC\store\FileSystem; use SPC\store\SourcePatcher; use SPC\util\GlobalEnvManager; +use SPC\util\SPCConfigUtil; class MacOSBuilder extends UnixBuilderBase { @@ -88,21 +89,6 @@ class MacOSBuilder extends UnixBuilderBase */ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void { - $extra_libs = getenv('SPC_EXTRA_LIBS') ?: ''; - // ---------- Update extra-libs ---------- - // add macOS frameworks - $extra_libs .= (empty($extra_libs) ? '' : ' ') . $this->getFrameworks(true); - // add libc++, some extensions or libraries need it (C++ cannot be linked statically) - $extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lc++ ' : ''); - // bloat means force-load all static libraries, even if they are not used - if (!$this->getOption('bloat', false)) { - $extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', $this->getAllStaticLibFiles()); - } else { - logger()->info('bloat linking'); - $extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', array_map(fn ($x) => "-Wl,-force_load,{$x}", array_filter($this->getAllStaticLibFiles()))); - } - f_putenv('SPC_EXTRA_LIBS=' . $extra_libs); - $this->emitPatchPoint('before-php-buildconf'); SourcePatcher::patchBeforeBuildconf($this); @@ -291,9 +277,10 @@ class MacOSBuilder extends UnixBuilderBase private function getMakeExtraVars(): array { + $config = (new SPCConfigUtil($this, ['libs_only_deps' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs')); return [ 'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'), - 'EXTRA_LIBS' => getenv('SPC_EXTRA_LIBS') . ' ' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS'), + 'EXTRA_LIBS' => $config['libs'], ]; } } diff --git a/src/SPC/command/BuildCommand.php b/src/SPC/command/BuildCommand.php index 6020931f..0285c333 100644 --- a/src/SPC/command/BuildCommand.php +++ b/src/SPC/command/BuildCommand.php @@ -18,7 +18,6 @@ abstract class BuildCommand extends BaseCommand } $this->addOption('with-clean', null, null, 'fresh build, remove `source` and `buildroot` dir before build'); - $this->addOption('bloat', null, null, 'add all libraries into binary'); $this->addOption('rebuild', 'r', null, 'Delete old build and rebuild'); $this->addOption('enable-zts', null, null, 'enable ZTS support'); } diff --git a/src/SPC/command/SPCConfigCommand.php b/src/SPC/command/SPCConfigCommand.php index 8a54a862..4b6d1bc4 100644 --- a/src/SPC/command/SPCConfigCommand.php +++ b/src/SPC/command/SPCConfigCommand.php @@ -23,6 +23,8 @@ class SPCConfigCommand extends BaseCommand $this->addOption('with-suggested-exts', 'E', null, 'Build with suggested extensions for selected exts'); $this->addOption('includes', null, null, 'Add additional include path'); $this->addOption('libs', null, null, 'Add additional libs path'); + $this->addOption('libs-only-deps', null, null, 'Output dependent libraries with -l prefix'); + $this->addOption('absolute-libs', null, null, 'Output absolute paths for libraries'); $this->addOption('no-php', null, null, 'Do not link to PHP library'); } @@ -38,16 +40,19 @@ class SPCConfigCommand extends BaseCommand $include_suggest_ext = $this->getOption('with-suggested-exts'); $include_suggest_lib = $this->getOption('with-suggested-libs'); - $util = new SPCConfigUtil(link_php: !$this->getOption('no-php')); + $util = new SPCConfigUtil(options: [ + 'no_php' => $this->getOption('no-php'), + 'libs_only_deps' => $this->getOption('libs-only-deps'), + 'absolute_libs' => $this->getOption('absolute-libs'), + ]); $config = $util->config($extensions, $libraries, $include_suggest_ext, $include_suggest_lib); - if ($this->getOption('includes')) { - $this->output->writeln($config['cflags']); - } elseif ($this->getOption('libs')) { - $this->output->writeln("{$config['ldflags']} {$config['libs']}"); - } else { - $this->output->writeln("{$config['cflags']} {$config['ldflags']} {$config['libs']}"); - } + $this->output->writeln(match (true) { + $this->getOption('includes') => $config['cflags'], + $this->getOption('libs-only-deps') => $config['libs'], + $this->getOption('libs') => "{$config['ldflags']} {$config['libs']}", + default => "{$config['cflags']} {$config['ldflags']} {$config['libs']}", + }); return 0; } diff --git a/src/SPC/util/PkgConfigUtil.php b/src/SPC/util/PkgConfigUtil.php index 84c2c3c6..d4a4ebed 100644 --- a/src/SPC/util/PkgConfigUtil.php +++ b/src/SPC/util/PkgConfigUtil.php @@ -32,7 +32,7 @@ class PkgConfigUtil * @return array Unique libs array, e.g. [-lz, -lxml, ...] * @throws RuntimeException */ - public static function getLibsArray(string $pkg_config_str): array + public static function getLibsArray(string $pkg_config_str, bool $force_short_name = true): array { // Use this instead of shell() to avoid unnecessary outputs $result = self::execWithResult("pkg-config --static --libs-only-l {$pkg_config_str}"); @@ -44,7 +44,7 @@ class PkgConfigUtil $exp = explode(' ', trim($result)); foreach ($exp as $item) { // if item ends with .a, convert it to -lxxx - if (str_ends_with($item, '.a') && str_starts_with($item, 'lib')) { + if (str_ends_with($item, '.a') && str_starts_with($item, 'lib') && $force_short_name) { $name = pathinfo($item, PATHINFO_BASENAME); $name = substr($name, 3, -2); // remove 'lib' prefix and '.a' suffix $libs[] = "-l{$name}"; diff --git a/src/SPC/util/SPCConfigUtil.php b/src/SPC/util/SPCConfigUtil.php index d967543f..bb808a7c 100644 --- a/src/SPC/util/SPCConfigUtil.php +++ b/src/SPC/util/SPCConfigUtil.php @@ -6,7 +6,6 @@ namespace SPC\util; use SPC\builder\BuilderBase; use SPC\builder\BuilderProvider; -use SPC\builder\macos\MacOSBuilder; use SPC\exception\FileSystemException; use SPC\exception\RuntimeException; use SPC\exception\WrongUsageException; @@ -17,11 +16,27 @@ class SPCConfigUtil { private ?BuilderBase $builder = null; - public function __construct(?BuilderBase $builder = null, private bool $link_php = true) + private bool $no_php; + + private bool $libs_only_deps; + + private bool $absolute_libs; + + /** + * @param array{ + * no_php?: bool, + * libs_only_deps?: bool, + * absolute_libs?: bool + * } $options Options pass to spc-config + */ + public function __construct(?BuilderBase $builder = null, array $options = []) { if ($builder !== null) { $this->builder = $builder; // BuilderProvider::makeBuilderByInput($input ?? new ArgvInput()); } + $this->no_php = $options['no_php'] ?? false; + $this->libs_only_deps = $options['libs_only_deps'] ?? false; + $this->absolute_libs = $options['absolute_libs'] ?? false; } /** @@ -54,24 +69,35 @@ class SPCConfigUtil } ob_get_clean(); $ldflags = $this->getLdflagsString(); - $libs = $this->getLibsString($libraries); - if (SPCTarget::getTargetOS() === 'Darwin') { - $libs .= " {$this->getFrameworksString($extensions)}"; - } $cflags = $this->getIncludesString($libraries); + $libs = $this->getLibsString($libraries, !$this->absolute_libs); - $libs = trim("-lc {$libs}"); - // embed - if ($this->link_php) { - $libs = "-lphp {$libs}"; - } + // additional OS-specific libraries (e.g. macOS -lresolv) $extra_env = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS'); if (is_string($extra_env)) { $libs .= ' ' . trim($extra_env, '"'); } - // c++ - if ($this->builder->hasCpp()) { - $libs .= $this->builder instanceof MacOSBuilder ? ' -lc++' : ' -lstdc++'; + $extra_env = getenv('SPC_EXTRA_LIBS'); + if (is_string($extra_env)) { + $libs .= " {$extra_env}"; + } + // extension frameworks + if (SPCTarget::getTargetOS() === 'Darwin') { + $libs .= " {$this->getFrameworksString($extensions)}"; + } + + if ($this->libs_only_deps) { + return [ + 'cflags' => trim(getenv('CFLAGS') . ' ' . $cflags), + 'ldflags' => trim(getenv('LDFLAGS') . ' ' . $ldflags), + 'libs' => trim(getenv('LIBS') . ' ' . $libs), + ]; + } + + $libs = trim("-lc {$libs}"); + // embed + if (!$this->no_php) { + $libs = "-lphp {$libs}"; } // mimalloc must come first if (str_contains($libs, BUILD_LIB_PATH . '/mimalloc.o')) { @@ -90,7 +116,7 @@ class SPCConfigUtil $includes = ["-I{$base}"]; // link with libphp - if ($this->link_php) { + if (!$this->no_php) { $includes = [ ...$includes, "-I{$base}/php", @@ -118,9 +144,9 @@ class SPCConfigUtil return '-L' . BUILD_LIB_PATH; } - private function getLibsString(array $libraries): string + private function getLibsString(array $libraries, bool $use_short_libs = true): string { - $short_name = []; + $lib_names = []; $frameworks = []; foreach ($libraries as $library) { @@ -131,7 +157,7 @@ class SPCConfigUtil if (!file_exists(BUILD_LIB_PATH . "/{$lib}")) { throw new WrongUsageException("Library file '{$lib}' for lib [{$library}] does not exist in '" . BUILD_LIB_PATH . "'. Please build it first."); } - $short_name[] = $this->getShortLibName($lib); + $lib_names[] = $use_short_libs ? $this->getShortLibName($lib) : (BUILD_LIB_PATH . "/{$lib}"); } // add frameworks for macOS if (SPCTarget::getTargetOS() === 'Darwin') { @@ -146,29 +172,29 @@ class SPCConfigUtil } $pkg_configs = implode(' ', $pkg_configs); if ($pkg_configs !== '') { - $pc_libs = PkgConfigUtil::getLibsArray($pkg_configs); - $short_name = [...$short_name, ...$pc_libs]; + $pc_libs = array_reverse(PkgConfigUtil::getLibsArray($pkg_configs, $use_short_libs)); + $lib_names = [...$lib_names, ...$pc_libs]; } } // post-process - $short_name = array_unique(array_reverse($short_name)); - $frameworks = array_unique(array_reverse($frameworks)); + $lib_names = array_unique(array_reverse($lib_names)); + $frameworks = array_unique($frameworks); // process frameworks to short_name if (SPCTarget::getTargetOS() === 'Darwin') { foreach ($frameworks as $fw) { $ks = '-framework ' . $fw; - if (!in_array($ks, $short_name)) { - $short_name[] = $ks; + if (!in_array($ks, $lib_names)) { + $lib_names[] = $ks; } } } if (in_array('imap', $libraries) && SPCTarget::getLibc() === 'glibc') { - $short_name[] = '-lcrypt'; + $lib_names[] = '-lcrypt'; } - return implode(' ', $short_name); + return implode(' ', $lib_names); } private function getShortLibName(string $lib): string diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index 0358f870..94953bf4 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -13,7 +13,7 @@ declare(strict_types=1); // test php version (8.1 ~ 8.4 available, multiple for matrix) $test_php_version = [ - '8.1', + // '8.1', // '8.2', // '8.3', '8.4', @@ -24,16 +24,16 @@ $test_os = [ 'macos-13', // bin/spc for x86_64 // 'macos-14', // bin/spc for arm64 'macos-15', // bin/spc for arm64 - // 'ubuntu-latest', // bin/spc-alpine-docker for x86_64 + 'ubuntu-latest', // bin/spc-alpine-docker for x86_64 'ubuntu-22.04', // bin/spc-gnu-docker for x86_64 - // 'ubuntu-24.04', // bin/spc for x86_64 - 'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64 + 'ubuntu-24.04', // bin/spc for x86_64 + // 'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64 // 'ubuntu-24.04-arm', // bin/spc for arm64 // 'windows-latest', // .\bin\spc.ps1 ]; // whether enable thread safe -$zts = true; +$zts = false; $no_strip = false; @@ -54,7 +54,7 @@ $extensions = match (PHP_OS_FAMILY) { // If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`). $shared_extensions = match (PHP_OS_FAMILY) { - 'Linux' => 'imagick', + 'Linux' => '', 'Darwin' => '', 'Windows' => '', }; @@ -72,7 +72,7 @@ $with_libs = match (PHP_OS_FAMILY) { // You can use `common`, `bulk`, `minimal` or `none`. // note: combination is only available for *nix platform. Windows must use `none` combination $base_combination = match (PHP_OS_FAMILY) { - 'Linux', 'Darwin' => 'minimal', + 'Linux', 'Darwin' => 'bulk', 'Windows' => 'none', };