Remove SPC_NO_MUSL_PATH, remove --libc, use SPC_LIBC instead (#642)

* Remove SPC_NO_MUSL_PATH, remove --libc, use SPC_LIBC instead

* Fix tests

* Internally use GNU_ARCH for unified

* Update EXTENSION_DIR comments for env.ini

* Remove redundant -fPIC cflags in curl
This commit is contained in:
Jerry Ma
2025-03-14 18:22:50 +08:00
committed by GitHub
parent 91a3a01c39
commit b4f3657323
32 changed files with 80 additions and 117 deletions

View File

@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace SPC;
use SPC\command\BuildCliCommand;
use SPC\command\BuildLibsCommand;
use SPC\command\BuildPHPCommand;
use SPC\command\DeleteDownloadCommand;
use SPC\command\dev\AllExtCommand;
use SPC\command\dev\ExtVerCommand;
@@ -44,7 +44,7 @@ final class ConsoleApplication extends Application
$this->addCommands(
[
// Common commands
new BuildCliCommand(),
new BuildPHPCommand(),
new BuildLibsCommand(),
new DoctorCommand(),
new DownloadCommand(),

View File

@@ -15,8 +15,6 @@ use SPC\util\GlobalEnvManager;
class LinuxBuilder extends UnixBuilderBase
{
public string $libc;
/** @var bool Micro patch phar flag */
private bool $phar_patched = false;
@@ -27,27 +25,23 @@ class LinuxBuilder extends UnixBuilderBase
public function __construct(array $options = [])
{
$this->options = $options;
SystemUtil::initLibcVar($this->options['libc'] ?? null);
$this->libc = getenv('SPC_LIBC') ?: LIBC_MUSL_WRAPPER;
// check musl-cross make installed if we use musl-cross-make
$arch = arch2gnu(php_uname('m'));
GlobalEnvManager::init($this);
// set library path, some libraries need it. (We cannot use `putenv` here, because cmake will be confused)
if (!filter_var(getenv('SPC_NO_MUSL_PATH'), FILTER_VALIDATE_BOOLEAN) && $this->libc !== LIBC_GLIBC) {
if (getenv('SPC_LIBC') === 'musl' && !SystemUtil::isMuslDist()) {
$this->setOptionIfNotExist('library_path', "LIBRARY_PATH=\"/usr/local/musl/{$arch}-linux-musl/lib\"");
$this->setOptionIfNotExist('ld_library_path', "LD_LIBRARY_PATH=\"/usr/local/musl/{$arch}-linux-musl/lib\"");
GlobalEnvManager::putenv("PATH=/usr/local/musl/bin:/usr/local/musl/{$arch}-linux-musl/bin:" . getenv('PATH'));
$configure = getenv('SPC_CMD_PREFIX_PHP_CONFIGURE');
$configure = "LD_LIBRARY_PATH=\"/usr/local/musl/{$arch}-linux-musl/lib\" " . $configure;
GlobalEnvManager::putenv("SPC_CMD_PREFIX_PHP_CONFIGURE={$configure}");
}
if (str_ends_with(getenv('CC'), 'linux-musl-gcc') && !file_exists("/usr/local/musl/bin/{$arch}-linux-musl-gcc") && (getenv('SPC_NO_MUSL_PATH') !== 'yes')) {
throw new WrongUsageException('musl-cross-make not installed, please install it first. (You can use `doctor` command to install it)');
if (!file_exists("/usr/local/musl/{$arch}-linux-musl/lib/libc.a")) {
throw new WrongUsageException('You are building with musl-libc target in glibc distro, but musl-toolchain is not installed, please install musl-toolchain first. (You can use `doctor` command to install it)');
}
}
// concurrency
@@ -216,10 +210,8 @@ class LinuxBuilder extends UnixBuilderBase
$this->buildEmbed();
}
if (php_uname('m') === $this->getOption('arch')) {
$this->emitPatchPoint('before-sanity-check');
$this->sanityCheck($build_target);
}
$this->emitPatchPoint('before-sanity-check');
$this->sanityCheck($build_target);
}
/**

View File

@@ -182,12 +182,4 @@ class SystemUtil
'arch', 'manjaro',
];
}
public static function initLibcVar(?string $libc = null): void
{
if ($libc === null) {
$libc = self::isMuslDist() ? 'musl' : 'musl-wrapper';
}
f_putenv('SPC_LIBC=' . $libc);
}
}

View File

@@ -16,7 +16,7 @@ class icu extends LinuxLibraryBase
{
$cppflags = 'CPPFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=1 -DU_STATIC_IMPLEMENTATION=1 -fPIC -fPIE -fno-ident"';
$cxxflags = 'CXXFLAGS="-std=c++17"';
$ldflags = $this->builder->libc !== 'glibc' ? 'LDFLAGS="-static"' : '';
$ldflags = getenv('SPC_LIBC') !== 'glibc' ? 'LDFLAGS="-static"' : '';
shell()->cd($this->source_dir . '/source')
->exec(
"{$cppflags} {$cxxflags} {$ldflags} " .

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
class libffi extends LinuxLibraryBase
@@ -12,28 +13,21 @@ class libffi extends LinuxLibraryBase
/**
* @throws RuntimeException
* @throws FileSystemException
*/
public function build(): void
{
[$lib, , $destdir] = SEPARATED_PATH;
/*$env = $this->builder->pkgconf_env . ' CFLAGS="' . $this->builder->arch_c_flags . '"';
$env .= match ($this->builder->libc) {
'musl_wrapper' => " CC='{$this->builder->getOption('cc')} --static -idirafter " . BUILD_INCLUDE_PATH .
($this->builder->getOption('arch') === php_uname('m') ? '-idirafter /usr/include/ ' : '') .
"-idirafter /usr/include/{$this->builder->getOption('arch')}-linux-gnu/'",
'musl', 'glibc' => " CC='{$this->builder->getOption('cc')}'",
default => throw new RuntimeException('unsupported libc: ' . $this->builder->libc),
};*/
$arch = getenv('SPC_ARCH');
shell()->cd($this->source_dir)
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
"--host={$this->builder->getOption('arch')}-unknown-linux " .
"--target={$this->builder->getOption('arch')}-unknown-linux " .
"--host={$arch}-unknown-linux " .
"--target={$arch}-unknown-linux " .
'--prefix= ' . // use prefix=/
"--libdir={$lib}"
)

View File

@@ -36,9 +36,9 @@ class libpng extends LinuxLibraryBase
*/
public function build(): void
{
$optimizations = match ($this->builder->getOption('arch')) {
$optimizations = match (getenv('SPC_ARCH')) {
'x86_64' => '--enable-intel-sse ',
'arm64' => '--enable-arm-neon ',
'aarch64' => '--enable-arm-neon ',
default => '',
};
shell()->cd($this->source_dir)

View File

@@ -42,10 +42,11 @@ class openssl extends LinuxLibraryBase
$extra = '';
$ex_lib = '-ldl -pthread';
$arch = getenv('SPC_ARCH');
$env = "CC='" . getenv('CC') . ' -idirafter ' . BUILD_INCLUDE_PATH .
' -idirafter /usr/include/ ' .
' -idirafter /usr/include/' . $this->builder->getOption('arch') . '-linux-gnu/ ' .
' -idirafter /usr/include/' . getenv('SPC_ARCH') . '-linux-gnu/ ' .
"' ";
// lib:zlib
$zlib = $this->builder->getLib('zlib');
@@ -72,7 +73,7 @@ class openssl extends LinuxLibraryBase
'--openssldir=/etc/ssl ' .
"{$zlib_extra}" .
'no-legacy ' .
"linux-{$this->builder->getOption('arch')}{$clang_postfix}"
"linux-{$arch}{$clang_postfix}"
)
->exec('make clean')
->execWithEnv("make -j{$this->builder->concurrency} CNF_EX_LIBS=\"{$ex_lib}\"")

View File

@@ -37,7 +37,7 @@ class MacOSBuilder extends UnixBuilderBase
$this->arch_c_flags = getenv('SPC_DEFAULT_C_FLAGS');
$this->arch_cxx_flags = getenv('SPC_DEFAULT_CXX_FLAGS');
// cmake toolchain
$this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile('Darwin', $this->getOption('arch', php_uname('m')), $this->arch_c_flags);
$this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile('Darwin', getenv('SPC_ARCH'), $this->arch_c_flags);
// create pkgconfig and include dir (some libs cannot create them automatically)
f_mkdir(BUILD_LIB_PATH . '/pkgconfig', recursive: true);
@@ -203,10 +203,8 @@ class MacOSBuilder extends UnixBuilderBase
$this->buildEmbed();
}
if (php_uname('m') === $this->getOption('arch')) {
$this->emitPatchPoint('before-sanity-check');
$this->sanityCheck($build_target);
}
$this->emitPatchPoint('before-sanity-check');
$this->sanityCheck($build_target);
}
/**

View File

@@ -18,13 +18,14 @@ class libffi extends MacOSLibraryBase
protected function build(): void
{
[, , $destdir] = SEPARATED_PATH;
$arch = getenv('SPC_ARCH');
shell()->cd($this->source_dir)
->exec(
'./configure ' .
'--enable-static ' .
'--disable-shared ' .
"--host={$this->builder->getOption('arch')}-apple-darwin " .
"--target={$this->builder->getOption('arch')}-apple-darwin " .
"--host={$arch}-apple-darwin " .
"--target={$arch}-apple-darwin " .
'--prefix= ' // use prefix=/
)
->exec('make clean')

View File

@@ -47,6 +47,7 @@ class openssl extends MacOSLibraryBase
$extra = 'zlib';
$ex_lib = trim($zlib->getStaticLibFiles() . ' ' . $ex_lib);
}
$arch = getenv('SPC_ARCH');
shell()->cd($this->source_dir)
->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()])
@@ -55,7 +56,7 @@ class openssl extends MacOSLibraryBase
'--prefix=/ ' . // use prefix=/
"--libdir={$lib} " .
'--openssldir=/etc/ssl ' .
"darwin64-{$this->builder->getOption('arch')}-cc"
"darwin64-{$arch}-cc"
)
->exec('make clean')
->execWithEnv("make -j{$this->builder->concurrency} CNF_EX_LIBS=\"{$ex_lib}\"")

View File

@@ -185,7 +185,7 @@ abstract class UnixBuilderBase extends BuilderBase
$util = new SPCConfigUtil($this);
$config = $util->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
$lens = "{$config['cflags']} {$config['ldflags']} {$config['libs']}";
if (PHP_OS_FAMILY === 'Linux' && $this->getOption('libc') !== 'glibc') {
if (PHP_OS_FAMILY === 'Linux' && getenv('SPC_LIBC') === 'musl') {
$lens .= ' -static';
}
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens);

View File

@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\builder\linux\library\LinuxLibraryBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
@@ -53,11 +52,10 @@ trait curl
FileSystem::resetDir($this->source_dir . '/build');
$cflags = $this instanceof LinuxLibraryBase && $this->builder->libc === 'glibc' ? '-fPIC' : '';
// compile
shell()->cd($this->source_dir . '/build')
->setEnv([
'CFLAGS' => trim($this->getLibExtraCFlags() . ' ' . $cflags),
'CFLAGS' => $this->getLibExtraCFlags(),
'LDFLAGS' => $this->getLibExtraLdFlags(),
'LIBS' => $this->getLibExtraLibs(),
])

View File

@@ -39,7 +39,7 @@ trait imagemagick
}
}
$ldflags = ($this instanceof LinuxLibraryBase) && $this->builder->libc !== 'glibc' ? ('-static -ldl') : '-ldl';
$ldflags = ($this instanceof LinuxLibraryBase) && getenv('SPC_LIBC') !== 'glibc' ? ('-static -ldl') : '-ldl';
// libxml iconv patch
$required_libs .= $this instanceof MacOSLibraryBase ? ('-liconv') : '';

View File

@@ -10,7 +10,7 @@ trait ldap
{
public function patchBeforeBuild(): bool
{
$extra = ($this->builder->libc ?? '') === 'glibc' ? '-ldl -lpthread -lm -lresolv -lutil' : '';
$extra = getenv('SPC_LIBC') === 'glibc' ? '-ldl -lpthread -lm -lresolv -lutil' : '';
FileSystem::replaceFileStr($this->source_dir . '/configure', '"-lssl -lcrypto', '"-lssl -lcrypto -lz ' . $extra);
return true;
}

View File

@@ -11,7 +11,7 @@ trait pkgconfig
protected function build(): void
{
$cflags = PHP_OS_FAMILY !== 'Linux' ? "{$this->builder->arch_c_flags} -Wimplicit-function-declaration -Wno-int-conversion" : '';
$ldflags = !($this instanceof LinuxLibraryBase) || $this->builder->libc === 'glibc' ? '' : '--static';
$ldflags = !($this instanceof LinuxLibraryBase) || getenv('SPC_LIBC') === 'glibc' ? '' : '--static';
shell()->cd($this->source_dir)
->setEnv(['CFLAGS' => "{$this->getLibExtraCFlags()} {$cflags}", 'LDFLAGS' => "{$this->getLibExtraLdFlags()} {$ldflags}", 'LIBS' => $this->getLibExtraLibs()])

View File

@@ -47,7 +47,7 @@ trait postgresql
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
if (!empty($output[1][0])) {
$ldflags = $output[1][0];
$envs .= !($this instanceof LinuxLibraryBase) || $this->builder->libc === 'glibc' ? " LDFLAGS=\"{$ldflags}\" " : " LDFLAGS=\"{$ldflags} -static\" ";
$envs .= !($this instanceof LinuxLibraryBase) || getenv('SPC_LIBC') === 'glibc' ? " LDFLAGS=\"{$ldflags}\" " : " LDFLAGS=\"{$ldflags} -static\" ";
}
$output = shell()->execWithResult("pkg-config --libs-only-l --static {$packages}");
$error_exec_cnt += $output[0] === 0 ? 0 : 1;

View File

@@ -12,25 +12,12 @@ abstract class BuildCommand extends BaseCommand
{
parent::__construct($name);
switch (PHP_OS_FAMILY) {
case 'Windows':
$this->addOption('with-sdk-binary-dir', null, InputOption::VALUE_REQUIRED, 'path to binary sdk');
$this->addOption('vs-ver', null, InputOption::VALUE_REQUIRED, 'vs version, e.g. "17" for Visual Studio 2022');
$this->addOption('arch', null, InputOption::VALUE_REQUIRED, 'architecture, "x64" or "arm64"', 'x64');
break;
case 'Linux':
$this->addOption('libc', null, InputOption::VALUE_REQUIRED, 'glibc, musl or musl-wrapper', 'musl-wrapper');
// no break
case 'Darwin':
$this->addOption('cc', null, InputOption::VALUE_REQUIRED, 'C compiler');
$this->addOption('cxx', null, InputOption::VALUE_REQUIRED, 'C++ compiler');
$this->addOption('ar', null, InputOption::VALUE_REQUIRED, 'ar');
$this->addOption('ld', null, InputOption::VALUE_REQUIRED, 'ld');
$this->addOption('arch', null, InputOption::VALUE_REQUIRED, 'architecture', php_uname('m'));
break;
if (PHP_OS_FAMILY === 'Windows') {
$this->addOption('with-sdk-binary-dir', null, InputOption::VALUE_REQUIRED, 'path to binary sdk');
$this->addOption('vs-ver', null, InputOption::VALUE_REQUIRED, 'vs version, e.g. "17" for Visual Studio 2022');
}
$this->addOption('with-clean', null, null, 'fresh build, remove `source` dir before `make`');
$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');

View File

@@ -19,7 +19,7 @@ use Symfony\Component\Console\Input\InputOption;
use ZM\Logger\ConsoleColor;
#[AsCommand('build', 'build PHP', ['build:php'])]
class BuildCliCommand extends BuildCommand
class BuildPHPCommand extends BuildCommand
{
public function configure(): void
{
@@ -29,8 +29,8 @@ class BuildCliCommand extends BuildCommand
$this->addOption('with-libs', null, InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', '');
$this->addOption('build-micro', null, null, 'Build micro SAPI');
$this->addOption('build-cli', null, null, 'Build cli SAPI');
$this->addOption('build-fpm', null, null, 'Build fpm SAPI');
$this->addOption('build-embed', null, null, 'Build embed SAPI');
$this->addOption('build-fpm', null, null, 'Build fpm SAPI (not available on Windows)');
$this->addOption('build-embed', null, null, 'Build embed SAPI (not available on Windows)');
$this->addOption('build-all', null, null, 'Build all SAPI');
$this->addOption('no-strip', null, null, 'build without strip, in order to debug and load external extensions');
$this->addOption('disable-opcache-jit', null, null, 'disable opcache jit');
@@ -155,14 +155,17 @@ class BuildCliCommand extends BuildCommand
$builder->proveExts($extensions);
// validate libs and exts
$builder->validateLibsAndExts();
// clean builds and sources
if ($this->input->getOption('with-clean')) {
logger()->info('Cleaning source and previous build dir...');
FileSystem::removeDir(SOURCE_PATH);
FileSystem::removeDir(BUILD_ROOT_PATH);
}
// build or install libraries
$builder->setupLibs();
if ($this->input->getOption('with-clean')) {
logger()->info('Cleaning source dir...');
FileSystem::removeDir(SOURCE_PATH);
}
// Process -I option
$custom_ini = [];
foreach ($this->input->getOption('with-hardcoded-ini') as $value) {

View File

@@ -26,6 +26,9 @@ class LinuxMuslCheck
if (SystemUtil::isMuslDist()) {
return CheckResult::ok('musl-based distro, skipped');
}
if (getenv('SPC_LIBC') === 'glibc') {
return CheckResult::ok('Building with glibc, skipped');
}
$musl_wrapper_lib = sprintf('/lib/ld-musl-%s.so.1', php_uname('m'));
if (file_exists($musl_wrapper_lib) && file_exists('/usr/local/musl/lib/libc.a')) {
@@ -40,6 +43,10 @@ class LinuxMuslCheck
if (SystemUtil::isMuslDist()) {
return CheckResult::ok('musl-based distro, skipped');
}
if (getenv('SPC_LIBC') === 'glibc') {
return CheckResult::ok('Building with glibc, skipped');
}
$arch = arch2gnu(php_uname('m'));
$cross_compile_lib = "/usr/local/musl/{$arch}-linux-musl/lib/libc.a";
$cross_compile_gcc = "/usr/local/musl/bin/{$arch}-linux-musl-gcc";

View File

@@ -40,7 +40,7 @@ class MacOSToolCheckList
if (($path = $this->findCommand('brew')) === null) {
return CheckResult::fail('Homebrew is not installed', 'brew');
}
if ($path !== '/opt/homebrew/bin/brew' && php_uname('m') === 'arm64') {
if ($path !== '/opt/homebrew/bin/brew' && getenv('GNU_ARCH') === 'aarch64') {
return CheckResult::fail('Current homebrew (/usr/local/bin/homebrew) is not installed for M1 Mac, please re-install homebrew in /opt/homebrew/ !');
}
return CheckResult::ok();

View File

@@ -98,7 +98,7 @@ class SourcePatcher
}
// patch capstone
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/have_capstone="yes"/', 'have_capstone="no"');
if ($builder instanceof LinuxBuilder && $builder->libc === 'glibc') {
if ($builder instanceof LinuxBuilder && getenv('SPC_LIBC') === 'glibc') {
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Zend/zend_operators.h', '# define ZEND_USE_ASM_ARITHMETIC 1', '# define ZEND_USE_ASM_ARITHMETIC 0');
}
}

View File

@@ -47,7 +47,7 @@ class GlobalEnvManager
// Define env vars for linux
if (PHP_OS_FAMILY === 'Linux') {
$arch = arch2gnu(php_uname('m'));
$arch = getenv('GNU_ARCH');
if (SystemUtil::isMuslDist()) {
self::putenv('SPC_LINUX_DEFAULT_CC=gcc');
self::putenv('SPC_LINUX_DEFAULT_CXX=g++');

View File

@@ -83,9 +83,5 @@ const AUTOCONF_CPPFLAGS = 4;
const AUTOCONF_LDFLAGS = 8;
const AUTOCONF_ALL = 15;
const LIBC_MUSL_WRAPPER = 'musl-wrapper';
const LIBC_MUSL = 'musl';
const LIBC_GLIBC = 'glibc';
ConsoleLogger::$date_format = 'H:i:s';
ConsoleLogger::$format = '[%date%] [I] %body%';

View File

@@ -45,5 +45,6 @@ GlobalEnvManager::putenv('PKG_ROOT_PATH=' . PKG_ROOT_PATH);
GlobalEnvManager::putenv('SOURCE_PATH=' . SOURCE_PATH);
GlobalEnvManager::putenv('DOWNLOAD_PATH=' . DOWNLOAD_PATH);
GlobalEnvManager::putenv('CPU_COUNT=' . CPU_COUNT);
GlobalEnvManager::putenv('SPC_ARCH=' . php_uname('m'));
GlobalEnvManager::putenv('GNU_ARCH=' . GNU_ARCH);
GlobalEnvManager::putenv('MAC_ARCH=' . MAC_ARCH);