From 75ee69b07d9683c139b4de92b8a831681205213a Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 28 Jan 2025 19:37:50 +0800 Subject: [PATCH 01/14] Add gnu based static binary support --- bin/spc-gnu-docker | 104 ++++++++++++++++++ config/env.custom.ini | 14 +++ src/SPC/builder/linux/LinuxBuilder.php | 13 ++- src/SPC/builder/linux/SystemUtil.php | 8 ++ src/SPC/builder/linux/library/libpng.php | 9 +- src/SPC/builder/linux/library/openssl.php | 3 +- .../builder/traits/UnixSystemUtilTrait.php | 1 + src/SPC/builder/unix/library/bzip2.php | 8 ++ src/SPC/builder/unix/library/curl.php | 6 +- src/SPC/builder/unix/library/gmp.php | 2 +- src/SPC/builder/unix/library/onig.php | 7 +- src/SPC/builder/unix/library/pkgconfig.php | 4 +- src/SPC/command/BuildCliCommand.php | 2 +- src/SPC/command/BuildCommand.php | 2 + src/SPC/doctor/item/LinuxToolCheckList.php | 3 +- src/SPC/store/SourcePatcher.php | 3 + src/SPC/util/GlobalEnvManager.php | 21 ++++ src/globals/defines.php | 5 + src/globals/ext-tests/openssl.php | 4 +- 19 files changed, 201 insertions(+), 18 deletions(-) create mode 100755 bin/spc-gnu-docker create mode 100644 config/env.custom.ini diff --git a/bin/spc-gnu-docker b/bin/spc-gnu-docker new file mode 100755 index 00000000..362242b6 --- /dev/null +++ b/bin/spc-gnu-docker @@ -0,0 +1,104 @@ +#!/usr/bin/env bash + +# This file is using docker to run commands +set -e + +# Detect docker can run +if ! which docker >/dev/null; then + echo "Docker is not installed, please install docker first !" + exit 1 +fi +DOCKER_EXECUTABLE="docker" +# shellcheck disable=SC2046 +if [ $(id -u) -ne 0 ]; then + if ! docker info > /dev/null 2>&1; then + if [ "$SPC_USE_SUDO" != "yes" ]; then + echo "Docker command requires sudo" + # shellcheck disable=SC2039 + echo -n 'To use sudo to run docker, run "export SPC_USE_SUDO=yes" and run command again' + exit 1 + fi + DOCKER_EXECUTABLE="sudo docker" + fi +fi + + + +# to check if qemu-docker run +if [ "$SPC_USE_ARCH" = "" ]; then + SPC_USE_ARCH=current +fi +case $SPC_USE_ARCH in +current) + BASE_ARCH=$(uname -m) + if [ "$BASE_ARCH" = "arm64" ]; then + BASE_ARCH=aarch64 + fi + ;; +aarch64) + BASE_ARCH=aarch64 + # shellcheck disable=SC2039 + echo -e "\e[033m* Using different arch needs to setup qemu-static for docker !\e[0m" + $DOCKER_EXECUTABLE run --rm --privileged multiarch/qemu-user-static:register --reset > /dev/null + ;; +*) + echo "Current arch is not supported to run in docker: $SPC_USE_ARCH" + exit 1 + ;; +esac + +# Detect docker env is setup +if ! $DOCKER_EXECUTABLE images | grep -q cwcc-spc-gnu-$SPC_USE_ARCH; then + echo "Docker container does not exist. Building docker image ..." + $DOCKER_EXECUTABLE build -t cwcc-spc-gnu-$SPC_USE_ARCH -f- . <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')); - // set library path, some libraries need it. (We cannot use `putenv` here, because cmake will be confused) - $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"); + if ($this->libc !== LIBC_GLIBC) { + // set library path, some libraries need it. (We cannot use `putenv` here, because cmake will be confused) + $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::init($this); diff --git a/src/SPC/builder/linux/SystemUtil.php b/src/SPC/builder/linux/SystemUtil.php index c0ae6766..aef748b8 100644 --- a/src/SPC/builder/linux/SystemUtil.php +++ b/src/SPC/builder/linux/SystemUtil.php @@ -182,4 +182,12 @@ 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); + } } diff --git a/src/SPC/builder/linux/library/libpng.php b/src/SPC/builder/linux/library/libpng.php index 5049a647..abc039c0 100644 --- a/src/SPC/builder/linux/library/libpng.php +++ b/src/SPC/builder/linux/library/libpng.php @@ -44,7 +44,8 @@ class libpng extends LinuxLibraryBase shell()->cd($this->source_dir) ->exec('chmod +x ./configure') ->exec('chmod +x ./install-sh') - ->exec( + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags() ?: $this->builder->arch_c_flags, 'LIBS' => $this->getLibExtraLibs()]) + ->execWithEnv( 'LDFLAGS="-L' . BUILD_LIB_PATH . '" ' . './configure ' . '--disable-shared ' . @@ -54,9 +55,9 @@ class libpng extends LinuxLibraryBase $optimizations . '--prefix=' ) - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency} DEFAULT_INCLUDES='-I{$this->source_dir} -I" . BUILD_INCLUDE_PATH . "' LIBS= libpng16.la") - ->exec('make install-libLTLIBRARIES install-data-am DESTDIR=' . BUILD_ROOT_PATH); + ->execWithEnv('make clean') + ->execWithEnv("make -j{$this->builder->concurrency} DEFAULT_INCLUDES='-I{$this->source_dir} -I" . BUILD_INCLUDE_PATH . "' LIBS= libpng16.la") + ->execWithEnv('make install-libLTLIBRARIES install-data-am DESTDIR=' . BUILD_ROOT_PATH); $this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX); $this->cleanLaFiles(); } diff --git a/src/SPC/builder/linux/library/openssl.php b/src/SPC/builder/linux/library/openssl.php index fb3ef045..4c83f2e7 100644 --- a/src/SPC/builder/linux/library/openssl.php +++ b/src/SPC/builder/linux/library/openssl.php @@ -43,7 +43,7 @@ class openssl extends LinuxLibraryBase $extra = ''; $ex_lib = '-ldl -pthread'; - $env = "CC='" . getenv('CC') . ' -static -idirafter ' . BUILD_INCLUDE_PATH . + $env = "CC='" . getenv('CC') . ' -idirafter ' . BUILD_INCLUDE_PATH . ' -idirafter /usr/include/ ' . ' -idirafter /usr/include/' . $this->builder->getOption('arch') . '-linux-gnu/ ' . "' "; @@ -70,7 +70,6 @@ class openssl extends LinuxLibraryBase '--prefix=/ ' . '--libdir=lib ' . '--openssldir=/etc/ssl ' . - '-static ' . "{$zlib_extra}" . 'no-legacy ' . "linux-{$this->builder->getOption('arch')}{$clang_postfix}" diff --git a/src/SPC/builder/traits/UnixSystemUtilTrait.php b/src/SPC/builder/traits/UnixSystemUtilTrait.php index 5aa325ab..22e18985 100644 --- a/src/SPC/builder/traits/UnixSystemUtilTrait.php +++ b/src/SPC/builder/traits/UnixSystemUtilTrait.php @@ -52,6 +52,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_EXE_LINKER_FLAGS "-ldl -lpthread -lm -lutil") CMAKE; // 有时候系统的 cmake 找不到 ar 命令,真奇怪 if (PHP_OS_FAMILY === 'Linux') { diff --git a/src/SPC/builder/unix/library/bzip2.php b/src/SPC/builder/unix/library/bzip2.php index 23428317..0241fb1b 100644 --- a/src/SPC/builder/unix/library/bzip2.php +++ b/src/SPC/builder/unix/library/bzip2.php @@ -4,8 +4,16 @@ declare(strict_types=1); namespace SPC\builder\unix\library; +use SPC\store\FileSystem; + trait bzip2 { + public function patchBeforeBuild(): bool + { + FileSystem::replaceFileStr($this->source_dir . '/Makefile', 'CFLAGS=-Wall', 'CFLAGS=-fPIC -Wall'); + return true; + } + protected function build(): void { shell()->cd($this->source_dir) diff --git a/src/SPC/builder/unix/library/curl.php b/src/SPC/builder/unix/library/curl.php index e01bec2c..3d63e5e7 100644 --- a/src/SPC/builder/unix/library/curl.php +++ b/src/SPC/builder/unix/library/curl.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace SPC\builder\unix\library; +use SPC\builder\linux\library\LinuxLibraryBase; +use SPC\builder\linux\LinuxBuilder; use SPC\exception\FileSystemException; use SPC\exception\RuntimeException; use SPC\store\FileSystem; @@ -51,9 +53,11 @@ trait curl $extra .= $this->builder->getLib('libcares') ? '-DENABLE_ARES=ON ' : ''; FileSystem::resetDir($this->source_dir . '/build'); + + $cflags = $this instanceof LinuxLibraryBase && $this->builder->libc === 'glibc' ? '-fPIC' : ''; // compile! shell()->cd($this->source_dir . '/build') - ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags() ?: $cflags, 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) ->exec('sed -i.save s@\${CMAKE_C_IMPLICIT_LINK_LIBRARIES}@@ ../CMakeLists.txt') ->execWithEnv("cmake {$this->builder->makeCmakeArgs()} -DBUILD_SHARED_LIBS=OFF -DBUILD_CURL_EXE=OFF -DBUILD_LIBCURL_DOCS=OFF {$extra} ..") ->execWithEnv("make -j{$this->builder->concurrency}") diff --git a/src/SPC/builder/unix/library/gmp.php b/src/SPC/builder/unix/library/gmp.php index 0748c870..49b207fb 100644 --- a/src/SPC/builder/unix/library/gmp.php +++ b/src/SPC/builder/unix/library/gmp.php @@ -16,7 +16,7 @@ trait gmp protected function build(): void { shell()->cd($this->source_dir) - ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags() ?: $this->builder->arch_c_flags, 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) ->execWithEnv( './configure ' . '--enable-static --disable-shared ' . diff --git a/src/SPC/builder/unix/library/onig.php b/src/SPC/builder/unix/library/onig.php index b43d14b3..60ea84fa 100644 --- a/src/SPC/builder/unix/library/onig.php +++ b/src/SPC/builder/unix/library/onig.php @@ -18,9 +18,10 @@ trait onig [,,$destdir] = SEPARATED_PATH; shell()->cd($this->source_dir) - ->exec('./configure --enable-static --disable-shared --prefix=') - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency}") + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags() ?: $this->builder->arch_c_flags, 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->execWithEnv('./configure --enable-static --disable-shared --prefix=') + ->execWithEnv('make clean') + ->execWithEnv("make -j{$this->builder->concurrency}") ->exec("make install DESTDIR={$destdir}"); $this->patchPkgconfPrefix(['oniguruma.pc']); } diff --git a/src/SPC/builder/unix/library/pkgconfig.php b/src/SPC/builder/unix/library/pkgconfig.php index ca93fd25..1f2584ac 100644 --- a/src/SPC/builder/unix/library/pkgconfig.php +++ b/src/SPC/builder/unix/library/pkgconfig.php @@ -4,12 +4,14 @@ declare(strict_types=1); namespace SPC\builder\unix\library; +use SPC\builder\linux\library\LinuxLibraryBase; + trait pkgconfig { protected function build(): void { $cflags = PHP_OS_FAMILY !== 'Linux' ? "{$this->builder->arch_c_flags} -Wimplicit-function-declaration -Wno-int-conversion" : ''; - $ldflags = PHP_OS_FAMILY !== 'Linux' ? '' : '--static'; + $ldflags = !($this instanceof LinuxLibraryBase) || $this->builder->libc === 'glibc' ? '' : '--static'; shell()->cd($this->source_dir) ->setEnv(['CFLAGS' => $this->getLibExtraCFlags() ?: $cflags, 'LDFLAGS' => $this->getLibExtraLdFlags() ?: $ldflags, 'LIBS' => $this->getLibExtraLibs()]) diff --git a/src/SPC/command/BuildCliCommand.php b/src/SPC/command/BuildCliCommand.php index bc214760..3892877c 100644 --- a/src/SPC/command/BuildCliCommand.php +++ b/src/SPC/command/BuildCliCommand.php @@ -191,7 +191,7 @@ class BuildCliCommand extends BuildCommand $fixed = ''; if (!empty(getenv('SPC_FIX_DEPLOY_ROOT'))) { str_replace($cwd, '', $build_root_path); - $build_root_path = getenv('SPC_FIX_DEPLOY_ROOT') . $build_root_path; + $build_root_path = getenv('SPC_FIX_DEPLOY_ROOT') . '/' . basename($build_root_path); $fixed = ' (host system)'; } if (($rule & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) { diff --git a/src/SPC/command/BuildCommand.php b/src/SPC/command/BuildCommand.php index bea9c119..ad391840 100644 --- a/src/SPC/command/BuildCommand.php +++ b/src/SPC/command/BuildCommand.php @@ -19,6 +19,8 @@ abstract class BuildCommand extends BaseCommand $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'); diff --git a/src/SPC/doctor/item/LinuxToolCheckList.php b/src/SPC/doctor/item/LinuxToolCheckList.php index e605c73b..d75d0fe8 100644 --- a/src/SPC/doctor/item/LinuxToolCheckList.php +++ b/src/SPC/doctor/item/LinuxToolCheckList.php @@ -57,7 +57,8 @@ class LinuxToolCheckList $required = match ($distro['dist']) { 'alpine' => self::TOOLS_ALPINE, - 'redhat', 'centos' => self::TOOLS_RHEL, + 'redhat' => self::TOOLS_RHEL, + 'centos' => array_merge(self::TOOLS_RHEL, ['perl-IPC-Cmd']), 'arch' => self::TOOLS_ARCH, default => self::TOOLS_DEBIAN, }; diff --git a/src/SPC/store/SourcePatcher.php b/src/SPC/store/SourcePatcher.php index f6044927..5c7db38f 100644 --- a/src/SPC/store/SourcePatcher.php +++ b/src/SPC/store/SourcePatcher.php @@ -86,6 +86,9 @@ class SourcePatcher } // patch capstone FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/have_capstone="yes"/', 'have_capstone="no"'); + if ($builder instanceof LinuxBuilder && $builder->libc === 'glibc') { + FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/Zend/zend_operators.h', '# define ZEND_USE_ASM_ARITHMETIC 1', '# define ZEND_USE_ASM_ARITHMETIC 0'); + } } /** diff --git a/src/SPC/util/GlobalEnvManager.php b/src/SPC/util/GlobalEnvManager.php index 6c6c9820..d3bebbd6 100644 --- a/src/SPC/util/GlobalEnvManager.php +++ b/src/SPC/util/GlobalEnvManager.php @@ -70,6 +70,10 @@ class GlobalEnvManager WORKING_DIR . '/config/env.ini', ROOT_DIR . '/config/env.ini', ]; + $ini_custom = [ + WORKING_DIR . '/config/env.custom.ini', + ROOT_DIR . '/config/env.custom.ini', + ]; $ini = null; foreach ($ini_files as $ini_file) { if (file_exists($ini_file)) { @@ -83,6 +87,23 @@ class GlobalEnvManager if ($ini === false || !isset($ini['global'])) { throw new WrongUsageException('Failed to parse ' . $ini_file); } + // apply custom env + foreach ($ini_custom as $ini_file) { + if (file_exists($ini_file)) { + $ini_custom = parse_ini_file($ini_file, true); + if ($ini_custom !== false) { + $ini['global'] = array_merge($ini['global'], $ini_custom['global'] ?? []); + match (PHP_OS_FAMILY) { + 'Windows' => $ini['windows'] = array_merge($ini['windows'], $ini_custom['windows'] ?? []), + 'Darwin' => $ini['macos'] = array_merge($ini['macos'], $ini_custom['macos'] ?? []), + 'Linux' => $ini['linux'] = array_merge($ini['linux'], $ini_custom['linux'] ?? []), + 'BSD' => $ini['freebsd'] = array_merge($ini['freebsd'], $ini_custom['freebsd'] ?? []), + default => null, + }; + } + break; + } + } self::applyConfig($ini['global']); match (PHP_OS_FAMILY) { 'Windows' => self::applyConfig($ini['windows']), diff --git a/src/globals/defines.php b/src/globals/defines.php index 956e5a9b..bbc2bd2f 100644 --- a/src/globals/defines.php +++ b/src/globals/defines.php @@ -83,4 +83,9 @@ 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%'; diff --git a/src/globals/ext-tests/openssl.php b/src/globals/ext-tests/openssl.php index 8c42202d..3b3452b3 100644 --- a/src/globals/ext-tests/openssl.php +++ b/src/globals/ext-tests/openssl.php @@ -4,4 +4,6 @@ declare(strict_types=1); assert(function_exists('openssl_digest')); assert(openssl_digest('123456', 'md5') === 'e10adc3949ba59abbe56e057f20f883e'); -assert(file_get_contents('https://example.com/') !== false); +if (file_exists('/etc/ssl/openssl.cnf')) { + assert(file_get_contents('https://example.com/') !== false); +} From daa6196afc6090417f073d123728758ae6d117f4 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 28 Jan 2025 19:41:06 +0800 Subject: [PATCH 02/14] cs-fix --- src/SPC/builder/unix/library/curl.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SPC/builder/unix/library/curl.php b/src/SPC/builder/unix/library/curl.php index 3d63e5e7..28083600 100644 --- a/src/SPC/builder/unix/library/curl.php +++ b/src/SPC/builder/unix/library/curl.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace SPC\builder\unix\library; use SPC\builder\linux\library\LinuxLibraryBase; -use SPC\builder\linux\LinuxBuilder; use SPC\exception\FileSystemException; use SPC\exception\RuntimeException; use SPC\store\FileSystem; From 0aab10ba31611a6aa1aff220b76ee6aac94b8703 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 4 Feb 2025 17:20:27 +0800 Subject: [PATCH 03/14] Add docs for gnu static build --- docs/.vitepress/sidebar.en.ts | 12 +++-- docs/.vitepress/sidebar.zh.ts | 4 +- docs/en/guide/build-with-glibc.md | 83 +++++++++++++++++++++++++++++++ docs/zh/guide/build-with-glibc.md | 71 ++++++++++++++++++++++++++ 4 files changed, 164 insertions(+), 6 deletions(-) create mode 100644 docs/en/guide/build-with-glibc.md create mode 100644 docs/zh/guide/build-with-glibc.md diff --git a/docs/.vitepress/sidebar.en.ts b/docs/.vitepress/sidebar.en.ts index b9c80aae..8efcc265 100644 --- a/docs/.vitepress/sidebar.en.ts +++ b/docs/.vitepress/sidebar.en.ts @@ -1,22 +1,24 @@ export default { '/en/guide/': [ { - text: 'Guide', + text: 'Basic Build Guides', items: [ {text: 'Guide', link: '/en/guide/'}, - {text: 'Actions Build', link: '/en/guide/action-build'}, - {text: 'Manual Build', link: '/en/guide/manual-build'}, - {text: 'Extension List', link: '/en/guide/extensions'}, + {text: 'Build (Local)', link: '/en/guide/manual-build'}, + {text: 'Build (CI)', link: '/en/guide/action-build'}, + {text: 'Supported Extensions', link: '/en/guide/extensions'}, {text: 'Extension Notes', link: '/en/guide/extension-notes'}, - {text: 'Command Generator', link: '/en/guide/cli-generator'}, + {text: 'Build Command Generator', link: '/en/guide/cli-generator'}, {text: 'Environment Variables', link: '/en/guide/env-vars', collapsed: true,}, {text: 'Dependency Table', link: '/en/guide/deps-map'}, ] }, { + text: 'Extended Build Guides', items: [ {text: 'Troubleshooting', link: '/en/guide/troubleshooting'}, {text: 'Build on Windows', link: '/en/guide/build-on-windows'}, + {text: 'Build with glibc (experimental)', link: '/en/guide/build-with-glibc'}, ], } ], diff --git a/docs/.vitepress/sidebar.zh.ts b/docs/.vitepress/sidebar.zh.ts index a17ac0f0..36910c60 100644 --- a/docs/.vitepress/sidebar.zh.ts +++ b/docs/.vitepress/sidebar.zh.ts @@ -4,8 +4,8 @@ export default { text: '构建指南', items: [ {text: '指南', link: '/zh/guide/'}, - {text: 'Actions 构建', link: '/zh/guide/action-build'}, {text: '本地构建', link: '/zh/guide/manual-build'}, + {text: 'Actions 构建', link: '/zh/guide/action-build'}, {text: '扩展列表', link: '/zh/guide/extensions'}, {text: '扩展注意事项', link: '/zh/guide/extension-notes'}, {text: '编译命令生成器', link: '/zh/guide/cli-generator'}, @@ -14,9 +14,11 @@ export default { ] }, { + text: '扩展构建指南', items: [ {text: '故障排除', link: '/zh/guide/troubleshooting'}, {text: '在 Windows 上构建', link: '/zh/guide/build-on-windows'}, + {text: '构建 glibc 兼容的二进制', link: '/zh/guide/build-with-glibc'}, ], } ], diff --git a/docs/en/guide/build-with-glibc.md b/docs/en/guide/build-with-glibc.md new file mode 100644 index 00000000..f8c307b1 --- /dev/null +++ b/docs/en/guide/build-with-glibc.md @@ -0,0 +1,83 @@ +# Build glibc Compatible Linux Binary + +## Why Build glibc Compatible Binary + +Currently, the binaries built by static-php-cli on Linux by default are based on musl-libc (statically linked). +musl-libc is a lightweight libc implementation +that aims to be compatible with glibc and provides good support for pure static linking. +This means that the compiled static PHP executable can be used on almost any Linux distribution without worrying about the versions of libc, libstdc++, etc. + +However, there are some issues with pure static linking of musl-libc binaries on Linux: + +- The `dl()` function in PHP cannot be used to load dynamic libraries and external PHP extensions. +- The FFI extension in PHP cannot be used. +- In some extreme cases, performance issues may occur. See [musl-libc performance issues](https://github.com/php/php-src/issues/13648). + +Different Linux distributions use different default libc. F +or example, Alpine Linux uses musl libc, while most Linux distributions use glibc. +However, even so, we cannot directly use any distribution using glibc to build portable static binaries because glibc has some issues: + +- Binaries built with gcc and other tools on newer versions of distributions cannot run on older versions of distributions. +- glibc is not recommended to be statically linked because some of its features require the support of dynamic libraries. + +However, we can use Docker to solve this problem. +The final output is a binary **dynamically linked with glibc** and some necessary libraries, +but **statically linked with all other dependencies**. + +1. Use an older version of a Linux distribution (such as CentOS 7.x), which has an older version of glibc but can run on most modern Linux distributions. +2. Build the static binary of PHP in this container so that it can run on most modern Linux distributions. + +> Using glibc static binaries can run on most modern Linux distributions but cannot run on musl libc distributions, such as CentOS 6, Alpine Linux, etc. + +## Build glibc Compatible Linux Binary + +The latest version of static-php-cli includes the `bin/spc-gnu-docker` script, +which can create a CentOS 7.x (glibc-2.17) Docker container with one click and build a glibc compatible PHP static binary in the container. + +First, clone the repository of this project and add the following content to the `config/env.custom.ini` file: + +```ini +; Modify this file name to `env.custom.ini`, and run `bin/spc-gnu-docker`, +; you can compile a GNU libc based static binary ! +[global] +SPC_SKIP_DOCTOR_CHECK_ITEMS="if musl-wrapper is installed,if musl-cross-make is installed" + +[linux] +CC=gcc +CXX=g++ +AR=ar +LD=ld +SPC_DEFAULT_C_FLAGS=-fPIC +SPC_NO_MUSL_PATH=yes +SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-Wl,-O1 -pie" +SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm -lresolv -lutil" +``` + +Then, run the following command once. +The first run will take a long time because it needs to download the CentOS 7.x image and some build tools. + +```bash +bin/spc-gnu-docker +``` + +After the image is built, you will see the same command help menu as `bin/spc`, which means the container is ready. + +After the container is ready, you can refer to the [local build](./manual-build) section to build your PHP static binary. +Just replace `bin/spc` or `./spc` with `bin/spc-gnu-docker`. + +Unlike the default build, when building in the glibc environment, you **must** add the parameter `--libc=glibc`, such as: + +```bash +bin/spc-gnu-docker --libc=glibc build bcmath,ctype,openssl,pdo,phar,posix,session,tokenizer,xml,zip --build-cli --debug +``` + +## Notes + +In rare cases, glibc-based static PHP may encounter segment faults and other errors, but there are currently few examples. +If you encounter any issues, please submit an issue. + +glibc build is an extended feature and is not part of the default static-php support. +If you have related issues or requirements, please indicate that you are building based on glibc when submitting an issue. + +If you need to build glibc-based binaries without using Docker, +please refer to the `bin/spc-gnu-docker` script to manually create a similar environment. diff --git a/docs/zh/guide/build-with-glibc.md b/docs/zh/guide/build-with-glibc.md new file mode 100644 index 00000000..75e25d66 --- /dev/null +++ b/docs/zh/guide/build-with-glibc.md @@ -0,0 +1,71 @@ +# 构建 glibc 兼容的 Linux 二进制 + +## 为什么要构建 glibc 兼容的二进制 + +目前,static-php-cli 在默认条件下在 Linux 系统构建的二进制都是基于 musl-libc(静态链接)的。 +musl-libc 是一个轻量级的 libc 实现,它的目标是与 glibc 兼容,并且提供良好的纯静态链接支持。 +这意味着,编译出来的静态 PHP 可执行文件在几乎任何 Linux 发行版都可以使用,而不需要考虑 libc、libstdc++ 等库的版本问题。 + +但是,Linux 系统的纯静态链接 musl-libc 二进制文件存在以下问题: + +- 无法使用 PHP 的 `dl()` 函数加载动态链接库和外部 PHP 扩展。 +- 无法使用 PHP 的 FFI 扩展。 +- 部分极端情况下,可能会出现性能问题,参见 [musl-libc 的性能问题](https://github.com/php/php-src/issues/13648)。 + +对于不同的 Linux 发行版,它们使用的默认 libc 可能不同,比如 Alpine Linux 使用 musl libc,而大多数 Linux 发行版使用 glibc。 +但即便如此,我们也不能直接使用任意的发行版和 glibc 构建便携的静态二进制文件,因为 glibc 有一些问题: + +- 基于新版本的发行版在使用 gcc 等工具构建的二进制,无法在旧版本的发行版上运行。 +- glibc 不推荐被静态链接,因为它的一些特性需要动态链接库的支持。 + +但是,我们可以使用 Docker 容器来解决这个问题,最终输出的结果是一个动态链接 glibc 和一些必要库的二进制,但它静态链接所有其他依赖。 + +1. 使用一个旧版本的 Linux 发行版(如 CentOS 7.x),它的 glibc 版本比较旧,但是可以在大多数现代 Linux 发行版上运行。 +2. 在这个容器中构建 PHP 的静态二进制文件,这样就可以在大多数现代 Linux 发行版上运行了。 + +> 使用 glibc 的静态二进制文件,可以在大多数现代 Linux 发行版上运行,但是不能在 musl libc 的发行版上运行,如 CentOS 6、Alpine Linux 等。 + +## 构建 glibc 兼容的 Linux 二进制 + +最新版的 static-php-cli 内置了 `bin/spc-gnu-docker` 脚本,可以一键创建一个 CentOS 7.x (glibc-2.17) 的 Docker 容器,并在容器中构建 glibc 兼容的 PHP 静态二进制文件。 + +请先克隆本项目的仓库,并将下面的内容添加到 `config/env.custom.ini` 文件中: + +```ini +; Modify this file name to `env.custom.ini`, and run `bin/spc-gnu-docker`, +; you can compile a GNU libc based static binary ! +[global] +SPC_SKIP_DOCTOR_CHECK_ITEMS="if musl-wrapper is installed,if musl-cross-make is installed" + +[linux] +CC=gcc +CXX=g++ +AR=ar +LD=ld +SPC_DEFAULT_C_FLAGS=-fPIC +SPC_NO_MUSL_PATH=yes +SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-Wl,-O1 -pie" +SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm -lresolv -lutil" +``` + +然后,先运行一次以下命令。首次运行时时间较长,因为需要下载 CentOS 7.x 的镜像和一些编译工具。 + +```bash +bin/spc-gnu-docker +``` + +构建镜像完成后,你将看到和 `bin/spc` 一样的命令帮助菜单,这时说明容器已经准备好了。 + +在容器准备好后,你可以参考 [本地构建](./manual-build) 章节的内容,构建你的 PHP 静态二进制文件。仅需要把 `bin/spc` 或 `./spc` 替换为 `bin/spc-gnu-docker` 即可。 + +与默认构建不同的是,在 glibc 环境构建时**必须添加**参数 `--libc=glibc`,如: + +```bash +bin/spc-gnu-docker --libc=glibc build bcmath,ctype,openssl,pdo,phar,posix,session,tokenizer,xml,zip --build-cli --debug +``` + +## 注意事项 + +- 极少数情况下,基于 glibc 的静态 PHP 可能会出现 segment fault 等错误,但目前例子较少,如果遇到问题请提交 issue。 +- glibc 构建为扩展的特性,不属于默认 static-php 的支持范围。如果有相关问题或需求,请在提交 Issue 时注明你是基于 glibc 构建的。 +- 如果你需要不使用 Docker 构建基于 glibc 的二进制,请参考 `bin/spc-gnu-docker` 脚本,手动构建一个类似的环境。 From 4beea4ad39c024fe758ae5d57906994cea1c0053 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 4 Feb 2025 17:23:47 +0800 Subject: [PATCH 04/14] Add issue content --- docs/en/guide/build-with-glibc.md | 4 ++++ docs/zh/guide/build-with-glibc.md | 11 ++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/en/guide/build-with-glibc.md b/docs/en/guide/build-with-glibc.md index f8c307b1..62ef80b4 100644 --- a/docs/en/guide/build-with-glibc.md +++ b/docs/en/guide/build-with-glibc.md @@ -81,3 +81,7 @@ If you have related issues or requirements, please indicate that you are buildin If you need to build glibc-based binaries without using Docker, please refer to the `bin/spc-gnu-docker` script to manually create a similar environment. + +Since glibc binaries are not the main goal of the project, +we generally do not test the compatibility of various libraries and extensions under glibc. +If any specific library builds successfully on musl-libc but fails on glibc, please submit an issue. diff --git a/docs/zh/guide/build-with-glibc.md b/docs/zh/guide/build-with-glibc.md index 75e25d66..6d13cf72 100644 --- a/docs/zh/guide/build-with-glibc.md +++ b/docs/zh/guide/build-with-glibc.md @@ -66,6 +66,11 @@ bin/spc-gnu-docker --libc=glibc build bcmath,ctype,openssl,pdo,phar,posix,sessio ## 注意事项 -- 极少数情况下,基于 glibc 的静态 PHP 可能会出现 segment fault 等错误,但目前例子较少,如果遇到问题请提交 issue。 -- glibc 构建为扩展的特性,不属于默认 static-php 的支持范围。如果有相关问题或需求,请在提交 Issue 时注明你是基于 glibc 构建的。 -- 如果你需要不使用 Docker 构建基于 glibc 的二进制,请参考 `bin/spc-gnu-docker` 脚本,手动构建一个类似的环境。 +极少数情况下,基于 glibc 的静态 PHP 可能会出现 segment fault 等错误,但目前例子较少,如果遇到问题请提交 issue。 + +glibc 构建为扩展的特性,不属于默认 static-php 的支持范围。如果有相关问题或需求,请在提交 Issue 时注明你是基于 glibc 构建的。 + +如果你需要不使用 Docker 构建基于 glibc 的二进制,请参考 `bin/spc-gnu-docker` 脚本,手动构建一个类似的环境。 + +由于 glibc 二进制不是项目的主要目标,一般情况下我们不会额外测试 glibc 下的各个库和扩展的兼容性。 +任何特定库如果在 musl-libc 上构建成功,但在 glibc 上构建失败,请提交 issue,我们将会单独解决。 \ No newline at end of file From 9c878ce61306e6ee9aee2689fbdc172dc6450a94 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 4 Feb 2025 17:24:28 +0800 Subject: [PATCH 05/14] Remove env.custom.ini --- config/env.custom.ini | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 config/env.custom.ini diff --git a/config/env.custom.ini b/config/env.custom.ini deleted file mode 100644 index a2ae8b42..00000000 --- a/config/env.custom.ini +++ /dev/null @@ -1,14 +0,0 @@ -; Modify this file name to `env.custom.ini`, and run `bin/spc-gnu-docker`, -; you can compile a GNU libc based static binary ! -[global] -SPC_SKIP_DOCTOR_CHECK_ITEMS="if musl-wrapper is installed,if musl-cross-make is installed" - -[linux] -CC=gcc -CXX=g++ -AR=ar -LD=ld -SPC_DEFAULT_C_FLAGS=-fPIC -SPC_NO_MUSL_PATH=yes -SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-Wl,-O1 -pie" -SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm -lresolv -lutil" From cb73222e21ac3be0b3050d1adc510ad7f5fd8cba Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 4 Feb 2025 17:34:47 +0800 Subject: [PATCH 06/14] Fix embed sanity check on glibc mode --- src/SPC/builder/unix/UnixBuilderBase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 347e1f16..ab95aa33 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -186,7 +186,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') { + if (PHP_OS_FAMILY === 'Linux' && $this->getOption('libc') !== 'glibc') { $lens .= ' -static'; } [$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens); From 7b1e2fb89e5d4f512ee0365dba9450b89033029e Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Tue, 4 Feb 2025 17:34:53 +0800 Subject: [PATCH 07/14] Update docs --- docs/.vitepress/sidebar.en.ts | 2 +- docs/.vitepress/sidebar.zh.ts | 2 +- docs/en/guide/build-with-glibc.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/.vitepress/sidebar.en.ts b/docs/.vitepress/sidebar.en.ts index 8efcc265..1bd0686d 100644 --- a/docs/.vitepress/sidebar.en.ts +++ b/docs/.vitepress/sidebar.en.ts @@ -18,7 +18,7 @@ export default { items: [ {text: 'Troubleshooting', link: '/en/guide/troubleshooting'}, {text: 'Build on Windows', link: '/en/guide/build-on-windows'}, - {text: 'Build with glibc (experimental)', link: '/en/guide/build-with-glibc'}, + {text: 'Build with GNU libc', link: '/en/guide/build-with-glibc'}, ], } ], diff --git a/docs/.vitepress/sidebar.zh.ts b/docs/.vitepress/sidebar.zh.ts index 36910c60..cf1630b1 100644 --- a/docs/.vitepress/sidebar.zh.ts +++ b/docs/.vitepress/sidebar.zh.ts @@ -18,7 +18,7 @@ export default { items: [ {text: '故障排除', link: '/zh/guide/troubleshooting'}, {text: '在 Windows 上构建', link: '/zh/guide/build-on-windows'}, - {text: '构建 glibc 兼容的二进制', link: '/zh/guide/build-with-glibc'}, + {text: '构建 GNU libc 兼容的二进制', link: '/zh/guide/build-with-glibc'}, ], } ], diff --git a/docs/en/guide/build-with-glibc.md b/docs/en/guide/build-with-glibc.md index 62ef80b4..b633e8fb 100644 --- a/docs/en/guide/build-with-glibc.md +++ b/docs/en/guide/build-with-glibc.md @@ -13,8 +13,8 @@ However, there are some issues with pure static linking of musl-libc binaries on - The FFI extension in PHP cannot be used. - In some extreme cases, performance issues may occur. See [musl-libc performance issues](https://github.com/php/php-src/issues/13648). -Different Linux distributions use different default libc. F -or example, Alpine Linux uses musl libc, while most Linux distributions use glibc. +Different Linux distributions use different default libc. +For example, Alpine Linux uses musl libc, while most Linux distributions use glibc. However, even so, we cannot directly use any distribution using glibc to build portable static binaries because glibc has some issues: - Binaries built with gcc and other tools on newer versions of distributions cannot run on older versions of distributions. From d047176fc96a6edbc6201f8781f27da0bf96e399 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Thu, 6 Feb 2025 11:25:22 +0800 Subject: [PATCH 08/14] Update docs --- docs/en/guide/env-vars.md | 15 +++++++++++++++ docs/en/guide/index.md | 8 ++------ docs/en/guide/troubleshooting.md | 2 ++ docs/zh/guide/env-vars.md | 13 +++++++++++++ docs/zh/guide/troubleshooting.md | 2 ++ 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/docs/en/guide/env-vars.md b/docs/en/guide/env-vars.md index 10581733..11cf9339 100644 --- a/docs/en/guide/env-vars.md +++ b/docs/en/guide/env-vars.md @@ -39,6 +39,21 @@ Or, if you need to modify an environment variable for a long time, you can modif For example, if you need to modify the `./configure` command for compiling PHP, you can find the `SPC_CMD_PREFIX_PHP_CONFIGURE` environment variable in the `config/env.ini` file, and then modify its value. +If your build conditions are more complex and require multiple `env.ini` files to switch, +we recommend that you use the `config/env.custom.ini` file. +In this way, you can specify your environment variables by writing additional override items +without modifying the default `config/env.ini` file. + +```ini +; This is an example of `config/env.custom.ini` file, +; we modify the `SPC_CONCURRENCY` and linux default CFLAGS passing to libs and PHP +[global] +SPC_CONCURRENCY=4 + +[linux] +SPC_DEFAULT_C_FLAGS="-O3" +``` + ## Library environment variables (Unix only) Starting from 2.2.0, static-php-cli supports custom environment variables for all compilation dependent library commands of macOS, Linux, FreeBSD and other Unix systems. diff --git a/docs/en/guide/index.md b/docs/en/guide/index.md index 6ae37db7..9f9bee4c 100644 --- a/docs/en/guide/index.md +++ b/docs/en/guide/index.md @@ -5,14 +5,10 @@ currently supporting Linux and macOS systems. In the guide section, you will learn how to use static php cli to build standalone PHP programs. -- [GitHub Action Build](./action-build) -- [Manual Build](./manual-build) +- [Build (local)](./manual-build) +- [Build (GitHub Actions)](./action-build) - [Supported Extensions](./extensions) -::: tip -If you are a native English speaker, some corrections to the documentation are welcome. -::: - ## Compilation Environment The following is the architecture support situation, where :gear: represents support for GitHub Action build, diff --git a/docs/en/guide/troubleshooting.md b/docs/en/guide/troubleshooting.md index 0dbb17d5..57898ed3 100644 --- a/docs/en/guide/troubleshooting.md +++ b/docs/en/guide/troubleshooting.md @@ -31,3 +31,5 @@ and then determine the command that reported the error. The error terminal output is very important for fixing compilation errors. When submitting an issue, please upload the last error fragment of the terminal log (or the entire terminal log output), and include the `spc` command and parameters used. + +If you are rebuilding, please refer to the [Local Build - Multiple Builds](./manual-build#multiple-builds) section. diff --git a/docs/zh/guide/env-vars.md b/docs/zh/guide/env-vars.md index 7a42d32c..9a2f9deb 100644 --- a/docs/zh/guide/env-vars.md +++ b/docs/zh/guide/env-vars.md @@ -36,6 +36,19 @@ SPC_CONCURRENCY=4 bin/spc build mbstring,pcntl --build-cli 例如,你需要修改编译 PHP 的 `./configure` 命令,你可以在 `config/env.ini` 文件中找到 `SPC_CMD_PREFIX_PHP_CONFIGURE` 环境变量,然后修改其值即可。 +但如果你的构建条件比较复杂,需要多种 env.ini 进行切换,我们推荐你使用 `config/env.custom.ini` 文件,这样你可以在不修改默认的 `config/env.ini` 文件的情况下, +通过写入额外的重载项目指定你的环境变量。 + +```ini +; This is an example of `config/env.custom.ini` file, +; we modify the `SPC_CONCURRENCY` and linux default CFLAGS passing to libs and PHP +[global] +SPC_CONCURRENCY=4 + +[linux] +SPC_DEFAULT_C_FLAGS="-O3" +``` + ## 编译依赖库的环境变量(仅限 Unix 系统) 从 2.2.0 开始,static-php-cli 对所有 macOS、Linux、FreeBSD 等 Unix 系统的编译依赖库的命令均支持自定义环境变量。 diff --git a/docs/zh/guide/troubleshooting.md b/docs/zh/guide/troubleshooting.md index 22b36f81..566850cf 100644 --- a/docs/zh/guide/troubleshooting.md +++ b/docs/zh/guide/troubleshooting.md @@ -18,3 +18,5 @@ 遇到编译错误时,如果没有开启 `--debug` 日志,请先开启调试日志,然后确定报错的命令。 报错的终端输出对于修复编译错误非常重要,请在提交 Issue 时一并将终端日志的最后报错片段(或整个终端日志输出)上传,并且包含使用的 `spc` 命令和参数。 + +如果你是重复构建,请参考 [本地构建 - 多次构建](./manual-build#多次构建) 章节,清理构建缓存后再次构建。 From 4eeb48cdc24bb7f26b2e3d7014644bba982a5365 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Sun, 9 Mar 2025 20:30:22 +0800 Subject: [PATCH 09/14] Update gnu-docker and fix icu build on glibc --- bin/spc | 5 +++++ bin/spc-alpine-docker | 6 ++++- bin/spc-gnu-docker | 32 +++++++++++++++++++++++++-- docs/en/guide/build-with-glibc.md | 19 ---------------- docs/zh/guide/build-with-glibc.md | 21 +----------------- src/SPC/builder/linux/library/icu.php | 2 +- 6 files changed, 42 insertions(+), 43 deletions(-) diff --git a/bin/spc b/bin/spc index c1f7331f..18dd3a38 100755 --- a/bin/spc +++ b/bin/spc @@ -4,6 +4,11 @@ use SPC\ConsoleApplication; use SPC\exception\ExceptionHandler; +// Load custom php if exists +if (PHP_OS_FAMILY !== 'Windows' && PHP_BINARY !== (__DIR__ . '/php') && file_exists(__DIR__ . '/php') && is_executable(__DIR__ . '/php')) { + pcntl_exec(__DIR__ . '/php', $argv); +} + if (file_exists(dirname(__DIR__) . '/vendor/autoload.php')) { // Current: ./bin (git/project mode) require_once dirname(__DIR__) . '/vendor/autoload.php'; diff --git a/bin/spc-alpine-docker b/bin/spc-alpine-docker index 9beb694f..bee9d13c 100755 --- a/bin/spc-alpine-docker +++ b/bin/spc-alpine-docker @@ -119,4 +119,8 @@ MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/pkgroot:/app/pkgroot" # shellcheck disable=SC2068 # shellcheck disable=SC2086 # shellcheck disable=SC2090 -$DOCKER_EXECUTABLE run --rm $INTERACT -e SPC_FIX_DEPLOY_ROOT="$(pwd)" $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-v2 bin/spc $@ +if [ "$SPC_DOCKER_DEBUG" = "yes" ]; then + $DOCKER_EXECUTABLE run --rm $INTERACT -e SPC_FIX_DEPLOY_ROOT="$(pwd)" $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-v2 +else + $DOCKER_EXECUTABLE run --rm $INTERACT -e SPC_FIX_DEPLOY_ROOT="$(pwd)" $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-v2 bin/spc $@ +fi diff --git a/bin/spc-gnu-docker b/bin/spc-gnu-docker index 362242b6..c9af23c1 100755 --- a/bin/spc-gnu-docker +++ b/bin/spc-gnu-docker @@ -59,6 +59,22 @@ RUN yum clean all && \ yum makecache && \ yum update -y +RUN yum install -y centos-release-scl + +RUN if [ "$BASE_ARCH" = "aarch64" ]; then \ + sed -i 's|mirror.centos.org/centos|vault.centos.org/altarch|g' /etc/yum.repos.d/CentOS-SCLo-scl-rh.repo ; \ + sed -i 's|mirror.centos.org/centos|vault.centos.org/altarch|g' /etc/yum.repos.d/CentOS-SCLo-scl.repo ; \ + else \ + sed -i 's/mirror.centos.org/vault.centos.org/g' /etc/yum.repos.d/*.repo ; \ + fi +RUN sed -i 's/^#.*baseurl=http/baseurl=http/g' /etc/yum.repos.d/*.repo && \ + sed -i 's/^mirrorlist=http/#mirrorlist=http/g' /etc/yum.repos.d/*.repo + +RUN yum update -y && \ + yum install -y devtoolset-7-gcc-* +RUN echo "source scl_source enable devtoolset-7" >> /etc/bashrc +RUN source /etc/bashrc + RUN curl -o cmake.tgz -fsSL https://github.com/Kitware/CMake/releases/download/v3.31.4/cmake-3.31.4-linux-$BASE_ARCH.tar.gz && \ mkdir /cmake && \ tar -xzf cmake.tgz -C /cmake --strip-components 1 @@ -73,9 +89,9 @@ RUN /app/bin/php /app/bin/composer install --no-dev --classmap-authoritative ENV PATH="/app/bin:/cmake/bin:$PATH" ENV SPC_SKIP_DOCTOR_CHECK_ITEMS="if musl-wrapper is installed,if musl-cross-make is installed" - ADD ./config/env.ini /app/config/env.ini RUN bin/spc doctor --auto-fix --debug +RUN git clone https://github.com/dunglas/frankenphp.git --depth=1 /frankenphp EOF fi @@ -97,8 +113,20 @@ MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/dist:/app/dist" MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/downloads:/app/downloads" MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/pkgroot:/app/pkgroot" +# Apply env in temp env file +echo 'SPC_SKIP_DOCTOR_CHECK_ITEMS="if musl-wrapper is installed,if musl-cross-make is installed"' > /tmp/spc-gnu-docker.env +echo 'CC=/opt/rh/devtoolset-7/root/usr/bin/gcc' >> /tmp/spc-gnu-docker.env +echo 'CXX=/opt/rh/devtoolset-7/root/usr/bin/g++' >> /tmp/spc-gnu-docker.env +echo 'AR=/opt/rh/devtoolset-7/root/usr/bin/ar' >> /tmp/spc-gnu-docker.env +echo 'LD=/opt/rh/devtoolset-7/root/usr/bin/ld' >> /tmp/spc-gnu-docker.env +echo 'SPC_DEFAULT_C_FLAGS=-fPIC' >> /tmp/spc-gnu-docker.env +echo 'SPC_NO_MUSL_PATH=yes' >> /tmp/spc-gnu-docker.env +echo 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-Wl,-O1 -pie"' >> /tmp/spc-gnu-docker.env +echo 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm -lresolv -lutil"' >> /tmp/spc-gnu-docker.env + # Run docker # shellcheck disable=SC2068 # shellcheck disable=SC2086 # shellcheck disable=SC2090 -$DOCKER_EXECUTABLE run --rm $INTERACT -e SPC_FIX_DEPLOY_ROOT="$(pwd)" $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH bin/spc $@ + +$DOCKER_EXECUTABLE run --rm $INTERACT -e SPC_FIX_DEPLOY_ROOT="$(pwd)" --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH # bin/spc $@ diff --git a/docs/en/guide/build-with-glibc.md b/docs/en/guide/build-with-glibc.md index b633e8fb..9573511b 100644 --- a/docs/en/guide/build-with-glibc.md +++ b/docs/en/guide/build-with-glibc.md @@ -34,25 +34,6 @@ but **statically linked with all other dependencies**. The latest version of static-php-cli includes the `bin/spc-gnu-docker` script, which can create a CentOS 7.x (glibc-2.17) Docker container with one click and build a glibc compatible PHP static binary in the container. -First, clone the repository of this project and add the following content to the `config/env.custom.ini` file: - -```ini -; Modify this file name to `env.custom.ini`, and run `bin/spc-gnu-docker`, -; you can compile a GNU libc based static binary ! -[global] -SPC_SKIP_DOCTOR_CHECK_ITEMS="if musl-wrapper is installed,if musl-cross-make is installed" - -[linux] -CC=gcc -CXX=g++ -AR=ar -LD=ld -SPC_DEFAULT_C_FLAGS=-fPIC -SPC_NO_MUSL_PATH=yes -SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-Wl,-O1 -pie" -SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm -lresolv -lutil" -``` - Then, run the following command once. The first run will take a long time because it needs to download the CentOS 7.x image and some build tools. diff --git a/docs/zh/guide/build-with-glibc.md b/docs/zh/guide/build-with-glibc.md index 6d13cf72..98883f3b 100644 --- a/docs/zh/guide/build-with-glibc.md +++ b/docs/zh/guide/build-with-glibc.md @@ -29,25 +29,6 @@ musl-libc 是一个轻量级的 libc 实现,它的目标是与 glibc 兼容, 最新版的 static-php-cli 内置了 `bin/spc-gnu-docker` 脚本,可以一键创建一个 CentOS 7.x (glibc-2.17) 的 Docker 容器,并在容器中构建 glibc 兼容的 PHP 静态二进制文件。 -请先克隆本项目的仓库,并将下面的内容添加到 `config/env.custom.ini` 文件中: - -```ini -; Modify this file name to `env.custom.ini`, and run `bin/spc-gnu-docker`, -; you can compile a GNU libc based static binary ! -[global] -SPC_SKIP_DOCTOR_CHECK_ITEMS="if musl-wrapper is installed,if musl-cross-make is installed" - -[linux] -CC=gcc -CXX=g++ -AR=ar -LD=ld -SPC_DEFAULT_C_FLAGS=-fPIC -SPC_NO_MUSL_PATH=yes -SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-Wl,-O1 -pie" -SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm -lresolv -lutil" -``` - 然后,先运行一次以下命令。首次运行时时间较长,因为需要下载 CentOS 7.x 的镜像和一些编译工具。 ```bash @@ -73,4 +54,4 @@ glibc 构建为扩展的特性,不属于默认 static-php 的支持范围。 如果你需要不使用 Docker 构建基于 glibc 的二进制,请参考 `bin/spc-gnu-docker` 脚本,手动构建一个类似的环境。 由于 glibc 二进制不是项目的主要目标,一般情况下我们不会额外测试 glibc 下的各个库和扩展的兼容性。 -任何特定库如果在 musl-libc 上构建成功,但在 glibc 上构建失败,请提交 issue,我们将会单独解决。 \ No newline at end of file +任何特定库如果在 musl-libc 上构建成功,但在 glibc 上构建失败,请提交 issue,我们将会单独解决。 diff --git a/src/SPC/builder/linux/library/icu.php b/src/SPC/builder/linux/library/icu.php index 05458a4e..7f9a978b 100644 --- a/src/SPC/builder/linux/library/icu.php +++ b/src/SPC/builder/linux/library/icu.php @@ -16,7 +16,7 @@ class icu extends LinuxLibraryBase { $cppflags = 'CPPFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=1 -DU_STATIC_IMPLEMENTATION=1"'; $cxxflags = 'CXXFLAGS="-std=c++17"'; - $ldflags = 'LDFLAGS="-static"'; + $ldflags = $this->builder->libc !== 'glibc' ? 'LDFLAGS="-static"' : ''; shell()->cd($this->source_dir . '/source') ->exec( "{$cppflags} {$cxxflags} {$ldflags} " . From 2a9cd436b692d042504f2d06e639ffd8dd21eeba Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Mon, 10 Mar 2025 00:39:20 +0800 Subject: [PATCH 10/14] Support -fPIC and -fPIE for most libs and PHP --- .gitignore | 1 + config/env.ini | 6 +++--- src/SPC/builder/linux/LinuxBuilder.php | 1 + src/SPC/builder/linux/library/icu.php | 2 +- src/SPC/builder/linux/library/libpng.php | 2 +- src/SPC/builder/macos/library/glfw.php | 2 +- src/SPC/builder/traits/UnixLibraryTrait.php | 6 +++++- src/SPC/builder/traits/UnixSystemUtilTrait.php | 6 ++++-- src/SPC/builder/unix/UnixBuilderBase.php | 8 ++++---- src/SPC/builder/unix/library/brotli.php | 8 ++++++-- src/SPC/builder/unix/library/curl.php | 6 ++---- src/SPC/builder/unix/library/gettext.php | 2 +- src/SPC/builder/unix/library/gmssl.php | 2 +- src/SPC/builder/unix/library/imagemagick.php | 2 +- src/SPC/builder/unix/library/ldap.php | 3 ++- src/SPC/builder/unix/library/libavif.php | 2 +- src/SPC/builder/unix/library/libiconv.php | 9 +++++---- src/SPC/builder/unix/library/libjpeg.php | 2 +- src/SPC/builder/unix/library/liblz4.php | 7 ++++--- src/SPC/builder/unix/library/libssh2.php | 7 +++++-- src/SPC/builder/unix/library/libtiff.php | 9 +++++---- src/SPC/builder/unix/library/libuv.php | 2 +- src/SPC/builder/unix/library/libwebp.php | 2 +- src/SPC/builder/unix/library/libzip.php | 6 ++++-- src/SPC/builder/unix/library/ncurses.php | 9 +++++---- src/SPC/builder/unix/library/nghttp2.php | 9 +++++---- src/SPC/builder/unix/library/pkgconfig.php | 4 ++-- src/SPC/builder/unix/library/postgresql.php | 5 ++--- src/SPC/builder/unix/library/readline.php | 9 +++++---- src/SPC/builder/unix/library/snappy.php | 3 +-- src/SPC/builder/unix/library/sqlite.php | 9 +++++---- src/SPC/builder/unix/library/tidy.php | 2 +- src/SPC/builder/unix/library/zlib.php | 9 +++++---- src/SPC/builder/unix/library/zstd.php | 2 +- src/SPC/doctor/item/LinuxToolCheckList.php | 2 +- src/SPC/util/SPCConfigUtil.php | 2 +- src/globals/test-extensions.php | 2 +- 37 files changed, 96 insertions(+), 74 deletions(-) diff --git a/.gitignore b/.gitignore index 14d4ae81..0560542f 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ packlib_files.txt !/bin/setup-runtime* !/bin/spc-alpine-docker !/bin/php-cs-fixer-wrapper +!/bin/build-static-frankenphp # exclude windows build tools /php-sdk-binary-tools/ diff --git a/config/env.ini b/config/env.ini index 3d504baf..85ca6821 100644 --- a/config/env.ini +++ b/config/env.ini @@ -76,13 +76,13 @@ SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime ; buildconf command SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force" ; configure command -SPC_CMD_PREFIX_PHP_CONFIGURE="${SPC_PHP_DEFAULT_LD_LIBRARY_PATH_CMD} ./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg" +SPC_CMD_PREFIX_PHP_CONFIGURE="${SPC_PHP_DEFAULT_LD_LIBRARY_PATH_CMD} ./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg --with-pic" ; make command SPC_CMD_PREFIX_PHP_MAKE="make -j${CPU_COUNT}" ; *** default build vars for building php *** ; CFLAGS for configuring php -SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS="${SPC_DEFAULT_C_FLAGS}" +SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS="${SPC_DEFAULT_C_FLAGS} -fPIE" ; CPPFLAGS for configuring php SPC_CMD_VAR_PHP_CONFIGURE_CPPFLAGS="-I${BUILD_INCLUDE_PATH}" ; LDFLAGS for configuring php @@ -90,7 +90,7 @@ SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS="-L${BUILD_LIB_PATH}" ; LIBS for configuring php SPC_CMD_VAR_PHP_CONFIGURE_LIBS="-ldl -lpthread -lm" ; EXTRA_CFLAGS for `make` php -SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="${SPC_PHP_DEFAULT_OPTIMIZE_CFLAGS} -fno-ident -fPIE" +SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="${SPC_PHP_DEFAULT_OPTIMIZE_CFLAGS} -fno-ident -fPIE -fPIC" ; EXTRA_LIBS for `make` php SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="" ; EXTRA_LDFLAGS_PROGRAM for `make` php diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index 523edd98..556638e9 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -120,6 +120,7 @@ class LinuxBuilder extends UnixBuilderBase $extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lstdc++ ' : ''); f_putenv('SPC_EXTRA_LIBS=' . $extra_libs); $cflags = $this->arch_c_flags; + f_putenv('CFLAGS=' . $cflags); $this->emitPatchPoint('before-php-buildconf'); SourcePatcher::patchBeforeBuildconf($this); diff --git a/src/SPC/builder/linux/library/icu.php b/src/SPC/builder/linux/library/icu.php index 7f9a978b..77bd081d 100644 --- a/src/SPC/builder/linux/library/icu.php +++ b/src/SPC/builder/linux/library/icu.php @@ -14,7 +14,7 @@ class icu extends LinuxLibraryBase protected function build(): void { - $cppflags = 'CPPFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=1 -DU_STATIC_IMPLEMENTATION=1"'; + $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"' : ''; shell()->cd($this->source_dir . '/source') diff --git a/src/SPC/builder/linux/library/libpng.php b/src/SPC/builder/linux/library/libpng.php index abc039c0..617f42a2 100644 --- a/src/SPC/builder/linux/library/libpng.php +++ b/src/SPC/builder/linux/library/libpng.php @@ -44,7 +44,7 @@ class libpng extends LinuxLibraryBase shell()->cd($this->source_dir) ->exec('chmod +x ./configure') ->exec('chmod +x ./install-sh') - ->setEnv(['CFLAGS' => $this->getLibExtraCFlags() ?: $this->builder->arch_c_flags, 'LIBS' => $this->getLibExtraLibs()]) + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LIBS' => $this->getLibExtraLibs()]) ->execWithEnv( 'LDFLAGS="-L' . BUILD_LIB_PATH . '" ' . './configure ' . diff --git a/src/SPC/builder/macos/library/glfw.php b/src/SPC/builder/macos/library/glfw.php index 91e8cb70..355785ed 100644 --- a/src/SPC/builder/macos/library/glfw.php +++ b/src/SPC/builder/macos/library/glfw.php @@ -21,7 +21,7 @@ class glfw extends MacOSLibraryBase shell()->cd(SOURCE_PATH . '/ext-glfw/vendor/glfw') ->exec("cmake . {$this->builder->makeCmakeArgs()} -DBUILD_SHARED_LIBS=OFF -DGLFW_BUILD_EXAMPLES=OFF -DGLFW_BUILD_TESTS=OFF") ->exec("make -j{$this->builder->concurrency}") - ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + ->exec('make install'); // patch pkgconf $this->patchPkgconfPrefix(['glfw3.pc']); } diff --git a/src/SPC/builder/traits/UnixLibraryTrait.php b/src/SPC/builder/traits/UnixLibraryTrait.php index d5a19209..8e69f6d3 100644 --- a/src/SPC/builder/traits/UnixLibraryTrait.php +++ b/src/SPC/builder/traits/UnixLibraryTrait.php @@ -102,7 +102,11 @@ trait UnixLibraryTrait public function getLibExtraCFlags(): string { - return getenv($this->getSnakeCaseName() . '_CFLAGS') ?: ''; + $env = getenv($this->getSnakeCaseName() . '_CFLAGS') ?: ''; + if (!str_contains($env, $this->builder->arch_c_flags)) { + $env .= $this->builder->arch_c_flags; + } + return $env; } public function getLibExtraLdFlags(): string diff --git a/src/SPC/builder/traits/UnixSystemUtilTrait.php b/src/SPC/builder/traits/UnixSystemUtilTrait.php index 22e18985..8b8cb743 100644 --- a/src/SPC/builder/traits/UnixSystemUtilTrait.php +++ b/src/SPC/builder/traits/UnixSystemUtilTrait.php @@ -33,11 +33,11 @@ trait UnixSystemUtilTrait $root = BUILD_ROOT_PATH; $ccLine = ''; if ($cc) { - $ccLine = 'SET(CMAKE_C_COMPILER ' . self::findCommand($cc) . ')'; + $ccLine = 'SET(CMAKE_C_COMPILER ' . $cc . ')'; } $cxxLine = ''; if ($cxx) { - $cxxLine = 'SET(CMAKE_CXX_COMPILER ' . self::findCommand($cxx) . ')'; + $cxxLine = 'SET(CMAKE_CXX_COMPILER ' . $cxx . ')'; } $toolchain = <<cmake_toolchain_file}"; } diff --git a/src/SPC/builder/unix/library/brotli.php b/src/SPC/builder/unix/library/brotli.php index fddcfbae..9e764fcb 100644 --- a/src/SPC/builder/unix/library/brotli.php +++ b/src/SPC/builder/unix/library/brotli.php @@ -21,12 +21,16 @@ trait brotli ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) ->execWithEnv( 'cmake ' . - "{$this->builder->makeCmakeArgs()} " . + '-DCMAKE_BUILD_TYPE=Release ' . + "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . + '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' . + '-DCMAKE_INSTALL_LIBDIR=lib ' . + '-DSHARE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' . '-DBUILD_SHARED_LIBS=OFF ' . '..' ) ->execWithEnv("cmake --build . -j {$this->builder->concurrency}") - ->execWithEnv('make install DESTDIR=' . BUILD_ROOT_PATH); + ->execWithEnv('make install'); $this->patchPkgconfPrefix(['libbrotlicommon.pc', 'libbrotlidec.pc', 'libbrotlienc.pc']); shell()->cd(BUILD_ROOT_PATH . '/lib')->exec('ln -sf libbrotlicommon.a libbrotli.a'); foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) { diff --git a/src/SPC/builder/unix/library/curl.php b/src/SPC/builder/unix/library/curl.php index 28083600..96a5bf05 100644 --- a/src/SPC/builder/unix/library/curl.php +++ b/src/SPC/builder/unix/library/curl.php @@ -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,14 +52,13 @@ 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' => $this->getLibExtraCFlags() ?: $cflags, 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) ->exec('sed -i.save s@\${CMAKE_C_IMPLICIT_LINK_LIBRARIES}@@ ../CMakeLists.txt') ->execWithEnv("cmake {$this->builder->makeCmakeArgs()} -DBUILD_SHARED_LIBS=OFF -DBUILD_CURL_EXE=OFF -DBUILD_LIBCURL_DOCS=OFF {$extra} ..") ->execWithEnv("make -j{$this->builder->concurrency}") - ->execWithEnv('make install DESTDIR=' . BUILD_ROOT_PATH); + ->execWithEnv('make install'); // patch pkgconf $this->patchPkgconfPrefix(['libcurl.pc']); shell()->cd(BUILD_LIB_PATH . '/cmake/CURL/') diff --git a/src/SPC/builder/unix/library/gettext.php b/src/SPC/builder/unix/library/gettext.php index 281207f7..277df171 100644 --- a/src/SPC/builder/unix/library/gettext.php +++ b/src/SPC/builder/unix/library/gettext.php @@ -17,7 +17,7 @@ trait gettext $ldflags = $this->builder->getOption('enable-zts') ? '-lpthread' : ''; shell()->cd($this->source_dir) - ->setEnv(['CFLAGS' => $this->getLibExtraCFlags() ?: $cflags, 'LDFLAGS' => $this->getLibExtraLdFlags() ?: $ldflags, 'LIBS' => $this->getLibExtraLibs()]) + ->setEnv(['CFLAGS' => "{$this->getLibExtraCFlags()} {$cflags}", 'LDFLAGS' => $this->getLibExtraLdFlags() ?: $ldflags, 'LIBS' => $this->getLibExtraLibs()]) ->execWithEnv( './configure ' . '--enable-static ' . diff --git a/src/SPC/builder/unix/library/gmssl.php b/src/SPC/builder/unix/library/gmssl.php index 0c18c69d..1d946621 100644 --- a/src/SPC/builder/unix/library/gmssl.php +++ b/src/SPC/builder/unix/library/gmssl.php @@ -23,6 +23,6 @@ trait gmssl ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) ->execWithEnv("cmake {$this->builder->makeCmakeArgs()} -DBUILD_SHARED_LIBS=OFF ..") ->execWithEnv("cmake --build . -j {$this->builder->concurrency}") - ->execWithEnv('make install DESTDIR=' . BUILD_ROOT_PATH); + ->execWithEnv('make install'); } } diff --git a/src/SPC/builder/unix/library/imagemagick.php b/src/SPC/builder/unix/library/imagemagick.php index ed08c667..639225a8 100644 --- a/src/SPC/builder/unix/library/imagemagick.php +++ b/src/SPC/builder/unix/library/imagemagick.php @@ -39,7 +39,7 @@ trait imagemagick } } - $ldflags = $this instanceof LinuxLibraryBase ? ('-static') : ''; + $ldflags = ($this instanceof LinuxLibraryBase) && $this->builder->libc !== 'glibc' ? ('-static -ldl') : '-ldl'; // libxml iconv patch $required_libs .= $this instanceof MacOSLibraryBase ? ('-liconv') : ''; diff --git a/src/SPC/builder/unix/library/ldap.php b/src/SPC/builder/unix/library/ldap.php index a061ce7f..c1896be6 100644 --- a/src/SPC/builder/unix/library/ldap.php +++ b/src/SPC/builder/unix/library/ldap.php @@ -10,7 +10,8 @@ trait ldap { public function patchBeforeBuild(): bool { - FileSystem::replaceFileStr($this->source_dir . '/configure', '"-lssl -lcrypto', '"-lssl -lcrypto -lz'); + $extra = ($this->builder->libc ?? '') === 'glibc' ? '-ldl -lpthread -lm -lresolv -lutil' : ''; + FileSystem::replaceFileStr($this->source_dir . '/configure', '"-lssl -lcrypto', '"-lssl -lcrypto -lz ' . $extra); return true; } diff --git a/src/SPC/builder/unix/library/libavif.php b/src/SPC/builder/unix/library/libavif.php index f8fcdbb8..c2aaafcd 100644 --- a/src/SPC/builder/unix/library/libavif.php +++ b/src/SPC/builder/unix/library/libavif.php @@ -25,7 +25,7 @@ trait libavif ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) ->execWithEnv("cmake {$this->builder->makeCmakeArgs()} -DBUILD_SHARED_LIBS=OFF -DAVIF_LIBYUV=OFF ..") ->execWithEnv("cmake --build . -j {$this->builder->concurrency}") - ->execWithEnv('make install DESTDIR=' . BUILD_ROOT_PATH); + ->execWithEnv('make install'); // patch pkgconfig $this->patchPkgconfPrefix(['libavif.pc']); $this->cleanLaFiles(); diff --git a/src/SPC/builder/unix/library/libiconv.php b/src/SPC/builder/unix/library/libiconv.php index 69c98862..a587c472 100644 --- a/src/SPC/builder/unix/library/libiconv.php +++ b/src/SPC/builder/unix/library/libiconv.php @@ -11,16 +11,17 @@ trait libiconv [,,$destdir] = SEPARATED_PATH; shell()->cd($this->source_dir) - ->exec( + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->execWithEnv( './configure ' . '--enable-static ' . '--disable-shared ' . '--enable-extra-encodings ' . '--prefix=' ) - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency}") - ->exec('make install DESTDIR=' . $destdir); + ->execWithEnv('make clean') + ->execWithEnv("make -j{$this->builder->concurrency}") + ->execWithEnv('make install DESTDIR=' . $destdir); if (file_exists(BUILD_BIN_PATH . '/iconv')) { unlink(BUILD_BIN_PATH . '/iconv'); diff --git a/src/SPC/builder/unix/library/libjpeg.php b/src/SPC/builder/unix/library/libjpeg.php index df02bd13..c4f9833d 100644 --- a/src/SPC/builder/unix/library/libjpeg.php +++ b/src/SPC/builder/unix/library/libjpeg.php @@ -29,7 +29,7 @@ trait libjpeg '..' ) ->exec("cmake --build . -j {$this->builder->concurrency}") - ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + ->exec('make install'); // patch pkgconfig $this->patchPkgconfPrefix(['libjpeg.pc', 'libturbojpeg.pc']); $this->cleanLaFiles(); diff --git a/src/SPC/builder/unix/library/liblz4.php b/src/SPC/builder/unix/library/liblz4.php index 697f8ed3..45e803bf 100644 --- a/src/SPC/builder/unix/library/liblz4.php +++ b/src/SPC/builder/unix/library/liblz4.php @@ -18,9 +18,10 @@ trait liblz4 protected function build(): void { shell()->cd($this->source_dir) - ->exec("make PREFIX='' clean") - ->exec("make -j{$this->builder->concurrency} PREFIX=''") - ->exec("make install PREFIX='' DESTDIR=" . BUILD_ROOT_PATH); + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->execWithEnv("make PREFIX='' clean") + ->execWithEnv("make -j{$this->builder->concurrency} PREFIX=''") + ->execWithEnv("make install PREFIX='' DESTDIR=" . BUILD_ROOT_PATH); $this->patchPkgconfPrefix(['liblz4.pc']); diff --git a/src/SPC/builder/unix/library/libssh2.php b/src/SPC/builder/unix/library/libssh2.php index 32d96b9a..9e999ca9 100644 --- a/src/SPC/builder/unix/library/libssh2.php +++ b/src/SPC/builder/unix/library/libssh2.php @@ -22,7 +22,10 @@ trait libssh2 shell()->cd($this->source_dir . '/build') ->exec( 'cmake ' . - "{$this->builder->makeCmakeArgs()} " . + '-DCMAKE_BUILD_TYPE=Release ' . + "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . + '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' . + '-DCMAKE_INSTALL_LIBDIR=lib ' . '-DBUILD_SHARED_LIBS=OFF ' . '-DBUILD_EXAMPLES=OFF ' . '-DBUILD_TESTING=OFF ' . @@ -30,7 +33,7 @@ trait libssh2 '..' ) ->exec("cmake --build . -j {$this->builder->concurrency}") - ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + ->exec('make install'); $this->patchPkgconfPrefix(['libssh2.pc']); } } diff --git a/src/SPC/builder/unix/library/libtiff.php b/src/SPC/builder/unix/library/libtiff.php index 9adcfab6..5d2cb4c1 100644 --- a/src/SPC/builder/unix/library/libtiff.php +++ b/src/SPC/builder/unix/library/libtiff.php @@ -23,7 +23,8 @@ trait libtiff $extra_libs .= ' --disable-lzma --disable-zstd --disable-webp --disable-libdeflate'; $shell = shell()->cd($this->source_dir) - ->exec( + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->execWithEnv( './configure ' . '--enable-static --disable-shared ' . "{$extra_libs} " . @@ -33,12 +34,12 @@ trait libtiff // TODO: Remove this check when https://gitlab.com/libtiff/libtiff/-/merge_requests/635 will be merged and released if (file_exists($this->source_dir . '/html')) { - $shell->exec('make clean'); + $shell->execWithEnv('make clean'); } $shell - ->exec("make -j{$this->builder->concurrency}") - ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + ->execWithEnv("make -j{$this->builder->concurrency}") + ->execWithEnv('make install DESTDIR=' . BUILD_ROOT_PATH); $this->patchPkgconfPrefix(['libtiff-4.pc']); } } diff --git a/src/SPC/builder/unix/library/libuv.php b/src/SPC/builder/unix/library/libuv.php index 8429b297..fda11c0a 100644 --- a/src/SPC/builder/unix/library/libuv.php +++ b/src/SPC/builder/unix/library/libuv.php @@ -22,7 +22,7 @@ trait libuv shell()->cd($this->source_dir . '/build') ->exec("cmake {$this->builder->makeCmakeArgs()} -DLIBUV_BUILD_SHARED=OFF ..") ->exec("cmake --build . -j {$this->builder->concurrency}") - ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + ->exec('make install'); // patch pkgconfig $this->patchPkgconfPrefix(['libuv-static.pc']); } diff --git a/src/SPC/builder/unix/library/libwebp.php b/src/SPC/builder/unix/library/libwebp.php index 52eb8071..efb78a68 100644 --- a/src/SPC/builder/unix/library/libwebp.php +++ b/src/SPC/builder/unix/library/libwebp.php @@ -30,7 +30,7 @@ trait libwebp '..' ) ->exec("cmake --build . -j {$this->builder->concurrency}") - ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + ->exec('make install'); // patch pkgconfig $this->patchPkgconfPrefix(['libsharpyuv.pc', 'libwebp.pc', 'libwebpdecoder.pc', 'libwebpdemux.pc', 'libwebpmux.pc'], PKGCONF_PATCH_PREFIX | PKGCONF_PATCH_LIBDIR); $this->patchPkgconfPrefix(['libsharpyuv.pc'], PKGCONF_PATCH_CUSTOM, ['/^includedir=.*$/m', 'includedir=${prefix}/include/webp']); diff --git a/src/SPC/builder/unix/library/libzip.php b/src/SPC/builder/unix/library/libzip.php index 83e0600c..5e2bd0d6 100644 --- a/src/SPC/builder/unix/library/libzip.php +++ b/src/SPC/builder/unix/library/libzip.php @@ -30,7 +30,9 @@ trait libzip shell()->cd($this->source_dir . '/build') ->exec( 'cmake ' . - "{$this->builder->makeCmakeArgs()} " . + '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' . + "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . + '-DCMAKE_BUILD_TYPE=Release ' . '-DENABLE_GNUTLS=OFF ' . '-DENABLE_MBEDTLS=OFF ' . '-DBUILD_SHARED_LIBS=OFF ' . @@ -42,7 +44,7 @@ trait libzip '..' ) ->exec("make -j{$this->builder->concurrency}") - ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + ->exec('make install'); $this->patchPkgconfPrefix(['libzip.pc'], PKGCONF_PATCH_PREFIX); } } diff --git a/src/SPC/builder/unix/library/ncurses.php b/src/SPC/builder/unix/library/ncurses.php index 721d5de6..a44ac175 100644 --- a/src/SPC/builder/unix/library/ncurses.php +++ b/src/SPC/builder/unix/library/ncurses.php @@ -12,7 +12,8 @@ trait ncurses { $filelist = FileSystem::scanDirFiles(BUILD_BIN_PATH, relative: true); shell()->cd($this->source_dir) - ->exec( + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->execWithEnv( './configure ' . '--enable-static ' . '--disable-shared ' . @@ -32,9 +33,9 @@ trait ncurses '--libdir=' . BUILD_ROOT_PATH . '/lib ' . '--prefix=' . BUILD_ROOT_PATH ) - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency}") - ->exec('make install'); + ->execWithEnv('make clean') + ->execWithEnv("make -j{$this->builder->concurrency}") + ->execWithEnv('make install'); $final = FileSystem::scanDirFiles(BUILD_BIN_PATH, relative: true); // Remove the new files diff --git a/src/SPC/builder/unix/library/nghttp2.php b/src/SPC/builder/unix/library/nghttp2.php index 0334beba..8f764c2a 100644 --- a/src/SPC/builder/unix/library/nghttp2.php +++ b/src/SPC/builder/unix/library/nghttp2.php @@ -36,7 +36,8 @@ trait nghttp2 [,,$destdir] = SEPARATED_PATH; shell()->cd($this->source_dir) - ->exec( + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->execWithEnv( './configure ' . '--enable-static ' . '--disable-shared ' . @@ -45,9 +46,9 @@ trait nghttp2 $args . ' ' . '--prefix=' ) - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency}") - ->exec("make install DESTDIR={$destdir}"); + ->execWithEnv('make clean') + ->execWithEnv("make -j{$this->builder->concurrency}") + ->execWithEnv("make install DESTDIR={$destdir}"); $this->patchPkgconfPrefix(['libnghttp2.pc']); } } diff --git a/src/SPC/builder/unix/library/pkgconfig.php b/src/SPC/builder/unix/library/pkgconfig.php index 1f2584ac..4a060f02 100644 --- a/src/SPC/builder/unix/library/pkgconfig.php +++ b/src/SPC/builder/unix/library/pkgconfig.php @@ -10,11 +10,11 @@ trait pkgconfig { protected function build(): void { - $cflags = PHP_OS_FAMILY !== 'Linux' ? "{$this->builder->arch_c_flags} -Wimplicit-function-declaration -Wno-int-conversion" : ''; + $cflags = PHP_OS_FAMILY !== 'Linux' ? '-Wimplicit-function-declaration -Wno-int-conversion' : ''; $ldflags = !($this instanceof LinuxLibraryBase) || $this->builder->libc === 'glibc' ? '' : '--static'; shell()->cd($this->source_dir) - ->setEnv(['CFLAGS' => $this->getLibExtraCFlags() ?: $cflags, 'LDFLAGS' => $this->getLibExtraLdFlags() ?: $ldflags, 'LIBS' => $this->getLibExtraLibs()]) + ->setEnv(['CFLAGS' => "{$this->getLibExtraCFlags()} {$cflags}", 'LDFLAGS' => "{$this->getLibExtraLdFlags()} {$ldflags}", 'LIBS' => $this->getLibExtraLibs()]) ->execWithEnv( './configure ' . '--disable-shared ' . diff --git a/src/SPC/builder/unix/library/postgresql.php b/src/SPC/builder/unix/library/postgresql.php index ce3679e9..9b92fee4 100644 --- a/src/SPC/builder/unix/library/postgresql.php +++ b/src/SPC/builder/unix/library/postgresql.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace SPC\builder\unix\library; use SPC\builder\linux\library\LinuxLibraryBase; -use SPC\builder\macos\library\MacOSLibraryBase; use SPC\exception\FileSystemException; use SPC\exception\RuntimeException; use SPC\store\FileSystem; @@ -42,13 +41,13 @@ trait postgresql $error_exec_cnt += $output[0] === 0 ? 0 : 1; if (!empty($output[1][0])) { $cppflags = $output[1][0]; - $envs .= " CPPFLAGS=\"{$cppflags}\""; + $envs .= " CPPFLAGS=\"{$cppflags} -fPIC -fPIE -fno-ident\""; } $output = shell()->execWithResult("pkg-config --libs-only-L --static {$packages}"); $error_exec_cnt += $output[0] === 0 ? 0 : 1; if (!empty($output[1][0])) { $ldflags = $output[1][0]; - $envs .= $this instanceof MacOSLibraryBase ? " LDFLAGS=\"{$ldflags}\" " : " LDFLAGS=\"{$ldflags} -static\" "; + $envs .= !($this instanceof LinuxLibraryBase) || $this->builder->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; diff --git a/src/SPC/builder/unix/library/readline.php b/src/SPC/builder/unix/library/readline.php index 4f725129..d0369c1a 100644 --- a/src/SPC/builder/unix/library/readline.php +++ b/src/SPC/builder/unix/library/readline.php @@ -16,7 +16,8 @@ trait readline protected function build(): void { shell()->cd($this->source_dir) - ->exec( + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->execWithEnv( './configure ' . '--enable-static=yes ' . '--enable-shared=no ' . @@ -24,9 +25,9 @@ trait readline '--with-curses ' . '--enable-multibyte=yes' ) - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency}") - ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + ->execWithEnv('make clean') + ->execWithEnv("make -j{$this->builder->concurrency}") + ->execWithEnv('make install DESTDIR=' . BUILD_ROOT_PATH); $this->patchPkgconfPrefix(['readline.pc']); } } diff --git a/src/SPC/builder/unix/library/snappy.php b/src/SPC/builder/unix/library/snappy.php index d7a5ade0..f1b4c825 100644 --- a/src/SPC/builder/unix/library/snappy.php +++ b/src/SPC/builder/unix/library/snappy.php @@ -21,13 +21,12 @@ trait snappy shell()->cd($this->source_dir . '/cmake/build') ->exec( 'cmake ' . - "-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " . "{$this->builder->makeCmakeArgs()} " . '-DSNAPPY_BUILD_TESTS=OFF ' . '-DSNAPPY_BUILD_BENCHMARKS=OFF ' . '../..' ) ->exec("cmake --build . -j {$this->builder->concurrency}") - ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + ->exec('make install'); } } diff --git a/src/SPC/builder/unix/library/sqlite.php b/src/SPC/builder/unix/library/sqlite.php index d679a386..ee814702 100644 --- a/src/SPC/builder/unix/library/sqlite.php +++ b/src/SPC/builder/unix/library/sqlite.php @@ -9,10 +9,11 @@ trait sqlite protected function build(): void { shell()->cd($this->source_dir) - ->exec('./configure --enable-static --disable-shared --prefix=') - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency}") - ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->execWithEnv('./configure --enable-static --disable-shared --prefix=') + ->execWithEnv('make clean') + ->execWithEnv("make -j{$this->builder->concurrency}") + ->execWithEnv('make install DESTDIR=' . BUILD_ROOT_PATH); $this->patchPkgconfPrefix(['sqlite3.pc']); } } diff --git a/src/SPC/builder/unix/library/tidy.php b/src/SPC/builder/unix/library/tidy.php index 6bb957c0..31c851d1 100644 --- a/src/SPC/builder/unix/library/tidy.php +++ b/src/SPC/builder/unix/library/tidy.php @@ -26,7 +26,7 @@ trait tidy '..' ) ->exec("cmake --build . -j {$this->builder->concurrency}") - ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + ->exec('make install'); $this->patchPkgconfPrefix(['tidy.pc']); } } diff --git a/src/SPC/builder/unix/library/zlib.php b/src/SPC/builder/unix/library/zlib.php index b380f8b0..f764de91 100644 --- a/src/SPC/builder/unix/library/zlib.php +++ b/src/SPC/builder/unix/library/zlib.php @@ -18,10 +18,11 @@ trait zlib [,,$destdir] = SEPARATED_PATH; shell()->cd($this->source_dir) - ->exec('./configure --static --prefix=') - ->exec('make clean') - ->exec("make -j{$this->builder->concurrency}") - ->exec("make install DESTDIR={$destdir}"); + ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->execWithEnv('./configure --static --prefix=') + ->execWithEnv('make clean') + ->execWithEnv("make -j{$this->builder->concurrency}") + ->execWithEnv("make install DESTDIR={$destdir}"); $this->patchPkgconfPrefix(['zlib.pc']); } } diff --git a/src/SPC/builder/unix/library/zstd.php b/src/SPC/builder/unix/library/zstd.php index 399eeedc..1990f658 100644 --- a/src/SPC/builder/unix/library/zstd.php +++ b/src/SPC/builder/unix/library/zstd.php @@ -26,7 +26,7 @@ trait zstd '..' ) ->exec("cmake --build . -j {$this->builder->concurrency}") - ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + ->exec('make install'); $this->patchPkgconfPrefix(['libzstd.pc']); } } diff --git a/src/SPC/doctor/item/LinuxToolCheckList.php b/src/SPC/doctor/item/LinuxToolCheckList.php index d75d0fe8..0e4b236a 100644 --- a/src/SPC/doctor/item/LinuxToolCheckList.php +++ b/src/SPC/doctor/item/LinuxToolCheckList.php @@ -37,7 +37,7 @@ class LinuxToolCheckList 'git', 'autoconf', 'automake', 'tar', 'unzip', 'gzip', 'gcc', 'bzip2', 'cmake', 'patch', - 'xz', + 'xz', 'libtool', ]; public const TOOLS_ARCH = [ diff --git a/src/SPC/util/SPCConfigUtil.php b/src/SPC/util/SPCConfigUtil.php index 1e60aa5a..2961ef90 100644 --- a/src/SPC/util/SPCConfigUtil.php +++ b/src/SPC/util/SPCConfigUtil.php @@ -36,7 +36,7 @@ class SPCConfigUtil $libs = '-lphp -lc ' . $libs; $extra_env = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS'); if (is_string($extra_env)) { - $libs .= ' ' . $extra_env; + $libs .= ' ' . trim($extra_env, '"'); } // c++ if ($this->builder->hasCpp()) { diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index 78c3421a..0a07a521 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -38,7 +38,7 @@ $prefer_pre_built = false; // If you want to test your added extensions and libs, add below (comma separated, example `bcmath,openssl`). $extensions = match (PHP_OS_FAMILY) { - 'Linux', 'Darwin' => 'imap,openssl,zlib,memcache', + 'Linux', 'Darwin' => 'apcu,bcmath,bz2,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,ftp,gd,gmp,gettext,iconv,igbinary,imagick,intl,ldap,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,parallel,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,posix,protobuf,readline,redis,session,shmop,simplexml,soap,sockets,sodium,sqlite3,ssh2,sysvmsg,sysvsem,sysvshm,tidy,tokenizer,xlswriter,xml,xmlreader,xmlwriter,zip,zlib,yaml,zstd', 'Windows' => 'gettext', }; From 7e462d6625b4e07beacf15c05d4c5b875ad3b9aa Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Mon, 10 Mar 2025 00:39:59 +0800 Subject: [PATCH 11/14] Update spc-gnu-docker with gcc10, add build-static-frankenphp --- bin/build-static-frankenphp | 150 ++++++++++++++++++++++++++++++++++++ bin/spc-gnu-docker | 30 +++++--- 2 files changed, 169 insertions(+), 11 deletions(-) create mode 100755 bin/build-static-frankenphp diff --git a/bin/build-static-frankenphp b/bin/build-static-frankenphp new file mode 100755 index 00000000..1de01c39 --- /dev/null +++ b/bin/build-static-frankenphp @@ -0,0 +1,150 @@ +#!/usr/bin/env bash + +# This file is using docker to run commands +set -e + +# Detect docker can run +if ! which docker >/dev/null; then + echo "Docker is not installed, please install docker first !" + exit 1 +fi +DOCKER_EXECUTABLE="docker" +# shellcheck disable=SC2046 +if [ $(id -u) -ne 0 ]; then + if ! docker info > /dev/null 2>&1; then + if [ "$SPC_USE_SUDO" != "yes" ]; then + echo "Docker command requires sudo" + # shellcheck disable=SC2039 + echo -n 'To use sudo to run docker, run "export SPC_USE_SUDO=yes" and run command again' + exit 1 + fi + DOCKER_EXECUTABLE="sudo docker" + fi +fi + + + +# to check if qemu-docker run +if [ "$SPC_USE_ARCH" = "" ]; then + SPC_USE_ARCH=current +fi +case $SPC_USE_ARCH in +current) + BASE_ARCH=$(uname -m) + if [ "$BASE_ARCH" = "arm64" ]; then + BASE_ARCH=aarch64 + GO_ARCH=arm64 + else + GO_ARCH=amd64 + fi + ;; +aarch64) + BASE_ARCH=aarch64 + GO_ARCH=arm64 + # shellcheck disable=SC2039 + echo -e "\e[033m* Using different arch needs to setup qemu-static for docker !\e[0m" + $DOCKER_EXECUTABLE run --rm --privileged multiarch/qemu-user-static:register --reset > /dev/null + ;; +*) + echo "Current arch is not supported to run in docker: $SPC_USE_ARCH" + exit 1 + ;; +esac + +# Detect docker env is setup +if ! $DOCKER_EXECUTABLE images | grep -q cwcc-frankenphp-gnu-$SPC_USE_ARCH; then + echo "Docker container does not exist. Building docker image ..." + $DOCKER_EXECUTABLE build -t cwcc-frankenphp-gnu-$SPC_USE_ARCH -f- . <> /etc/bashrc +RUN source /etc/bashrc + +RUN curl -o cmake.tgz -fsSL https://github.com/Kitware/CMake/releases/download/v3.31.4/cmake-3.31.4-linux-$BASE_ARCH.tar.gz && \ + mkdir /cmake && \ + tar -xzf cmake.tgz -C /cmake --strip-components 1 + +WORKDIR /app +ADD ./src /app/src +COPY ./composer.* /app/ +ADD ./bin/setup-runtime /app/bin/setup-runtime +ADD ./bin/spc /app/bin/spc +RUN /app/bin/setup-runtime +RUN /app/bin/php /app/bin/composer install --no-dev --classmap-authoritative +ENV PATH="/app/bin:/cmake/bin:/usr/local/go/bin:$PATH" +ENV SPC_SKIP_DOCTOR_CHECK_ITEMS="if musl-wrapper is installed,if musl-cross-make is installed" + +ADD ./config/env.ini /app/config/env.ini +RUN bin/spc doctor --auto-fix --debug + +RUN curl -o make.tgz -fsSL https://ftp.gnu.org/gnu/make/make-4.4.tar.gz && \ + tar -zxvf make.tgz && \ + cd make-4.4 && \ + ./configure && \ + make && \ + make install && \ + ln -sf /usr/local/bin/make /usr/bin/make + +RUN git clone https://github.com/static-php/gnu-frankenphp --depth=1 /frankenphp +WORKDIR /frankenphp + +RUN curl -o go.tgz -fsSL https://go.dev/dl/go1.24.1.linux-$GO_ARCH.tar.gz && \ + rm -rf /usr/local/go && tar -C /usr/local -xzf go.tgz +EOF +fi + +# Check if in ci (local terminal can execute with -it) +if [ -t 0 ]; then + INTERACT=-it +else + INTERACT='' +fi + +# Mounting volumes +MOUNT_LIST="" +# shellcheck disable=SC2089 +MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/config:/app/config" +MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/src:/app/src" +MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/buildroot:/app/buildroot" +MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/source:/app/source" +MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/dist:/app/dist" +MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/downloads:/app/downloads" +MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/pkgroot:/app/pkgroot" +MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/dist:/frankenphp/dist" + +# Apply env in temp env file +echo 'SPC_SKIP_DOCTOR_CHECK_ITEMS=if musl-wrapper is installed,if musl-cross-make is installed' > /tmp/spc-gnu-docker.env +echo 'CC=/opt/rh/devtoolset-10/root/usr/bin/gcc' >> /tmp/spc-gnu-docker.env +echo 'CXX=/opt/rh/devtoolset-10/root/usr/bin/g++' >> /tmp/spc-gnu-docker.env +echo 'AR=/opt/rh/devtoolset-10/root/usr/bin/ar' >> /tmp/spc-gnu-docker.env +echo 'LD=/opt/rh/devtoolset-10/root/usr/bin/ld' >> /tmp/spc-gnu-docker.env +echo 'SPC_DEFAULT_C_FLAGS=-fPIE' >> /tmp/spc-gnu-docker.env +echo 'SPC_NO_MUSL_PATH=yes' >> /tmp/spc-gnu-docker.env +echo 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-Wl,-O1 -pie"' >> /tmp/spc-gnu-docker.env +echo 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm -lresolv -lutil -lrt"' >> /tmp/spc-gnu-docker.env + +# Run docker +# shellcheck disable=SC2068 +# shellcheck disable=SC2086 +# shellcheck disable=SC2090 + +$DOCKER_EXECUTABLE run --rm $INTERACT -e SPC_FIX_DEPLOY_ROOT="$(pwd)" --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-frankenphp-gnu-$SPC_USE_ARCH ./build-static.sh diff --git a/bin/spc-gnu-docker b/bin/spc-gnu-docker index c9af23c1..33420cca 100755 --- a/bin/spc-gnu-docker +++ b/bin/spc-gnu-docker @@ -71,8 +71,8 @@ RUN sed -i 's/^#.*baseurl=http/baseurl=http/g' /etc/yum.repos.d/*.repo && \ sed -i 's/^mirrorlist=http/#mirrorlist=http/g' /etc/yum.repos.d/*.repo RUN yum update -y && \ - yum install -y devtoolset-7-gcc-* -RUN echo "source scl_source enable devtoolset-7" >> /etc/bashrc + yum install -y devtoolset-10-gcc-* && \ +RUN echo "source scl_source enable devtoolset-10" >> /etc/bashrc RUN source /etc/bashrc RUN curl -o cmake.tgz -fsSL https://github.com/Kitware/CMake/releases/download/v3.31.4/cmake-3.31.4-linux-$BASE_ARCH.tar.gz && \ @@ -91,7 +91,15 @@ ENV SPC_SKIP_DOCTOR_CHECK_ITEMS="if musl-wrapper is installed,if musl-cross-make ADD ./config/env.ini /app/config/env.ini RUN bin/spc doctor --auto-fix --debug -RUN git clone https://github.com/dunglas/frankenphp.git --depth=1 /frankenphp + +RUN curl -o make.tgz -fsSL https://ftp.gnu.org/gnu/make/make-4.4.tar.gz && \ + tar -zxvf make.tgz && \ + cd make-4.4 && \ + ./configure && \ + make && \ + make install && \ + ln -sf /usr/local/bin/make /usr/bin/make + EOF fi @@ -114,19 +122,19 @@ MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/downloads:/app/downloads" MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/pkgroot:/app/pkgroot" # Apply env in temp env file -echo 'SPC_SKIP_DOCTOR_CHECK_ITEMS="if musl-wrapper is installed,if musl-cross-make is installed"' > /tmp/spc-gnu-docker.env -echo 'CC=/opt/rh/devtoolset-7/root/usr/bin/gcc' >> /tmp/spc-gnu-docker.env -echo 'CXX=/opt/rh/devtoolset-7/root/usr/bin/g++' >> /tmp/spc-gnu-docker.env -echo 'AR=/opt/rh/devtoolset-7/root/usr/bin/ar' >> /tmp/spc-gnu-docker.env -echo 'LD=/opt/rh/devtoolset-7/root/usr/bin/ld' >> /tmp/spc-gnu-docker.env -echo 'SPC_DEFAULT_C_FLAGS=-fPIC' >> /tmp/spc-gnu-docker.env +echo 'SPC_SKIP_DOCTOR_CHECK_ITEMS=if musl-wrapper is installed,if musl-cross-make is installed' > /tmp/spc-gnu-docker.env +echo 'CC=/opt/rh/devtoolset-10/root/usr/bin/gcc' >> /tmp/spc-gnu-docker.env +echo 'CXX=/opt/rh/devtoolset-10/root/usr/bin/g++' >> /tmp/spc-gnu-docker.env +echo 'AR=/opt/rh/devtoolset-10/root/usr/bin/ar' >> /tmp/spc-gnu-docker.env +echo 'LD=/opt/rh/devtoolset-10/root/usr/bin/ld' >> /tmp/spc-gnu-docker.env +echo 'SPC_DEFAULT_C_FLAGS=-fPIE' >> /tmp/spc-gnu-docker.env echo 'SPC_NO_MUSL_PATH=yes' >> /tmp/spc-gnu-docker.env echo 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-Wl,-O1 -pie"' >> /tmp/spc-gnu-docker.env -echo 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm -lresolv -lutil"' >> /tmp/spc-gnu-docker.env +echo 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm -lresolv -lutil -lrt"' >> /tmp/spc-gnu-docker.env # Run docker # shellcheck disable=SC2068 # shellcheck disable=SC2086 # shellcheck disable=SC2090 -$DOCKER_EXECUTABLE run --rm $INTERACT -e SPC_FIX_DEPLOY_ROOT="$(pwd)" --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH # bin/spc $@ +$DOCKER_EXECUTABLE run --rm $INTERACT -e SPC_FIX_DEPLOY_ROOT="$(pwd)" --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH bin/spc $@ From b6324fd71e6e7710bc481090207c95517285cae9 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Mon, 10 Mar 2025 15:54:43 +0800 Subject: [PATCH 12/14] Fix syntax on Dockerfile --- bin/spc-gnu-docker | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/spc-gnu-docker b/bin/spc-gnu-docker index 33420cca..e589b8ba 100755 --- a/bin/spc-gnu-docker +++ b/bin/spc-gnu-docker @@ -71,7 +71,7 @@ RUN sed -i 's/^#.*baseurl=http/baseurl=http/g' /etc/yum.repos.d/*.repo && \ sed -i 's/^mirrorlist=http/#mirrorlist=http/g' /etc/yum.repos.d/*.repo RUN yum update -y && \ - yum install -y devtoolset-10-gcc-* && \ + yum install -y devtoolset-10-gcc-* RUN echo "source scl_source enable devtoolset-10" >> /etc/bashrc RUN source /etc/bashrc @@ -127,7 +127,7 @@ echo 'CC=/opt/rh/devtoolset-10/root/usr/bin/gcc' >> /tmp/spc-gnu-docker.env echo 'CXX=/opt/rh/devtoolset-10/root/usr/bin/g++' >> /tmp/spc-gnu-docker.env echo 'AR=/opt/rh/devtoolset-10/root/usr/bin/ar' >> /tmp/spc-gnu-docker.env echo 'LD=/opt/rh/devtoolset-10/root/usr/bin/ld' >> /tmp/spc-gnu-docker.env -echo 'SPC_DEFAULT_C_FLAGS=-fPIE' >> /tmp/spc-gnu-docker.env +echo 'SPC_DEFAULT_C_FLAGS=-fPIE -fPIC' >> /tmp/spc-gnu-docker.env echo 'SPC_NO_MUSL_PATH=yes' >> /tmp/spc-gnu-docker.env echo 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-Wl,-O1 -pie"' >> /tmp/spc-gnu-docker.env echo 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm -lresolv -lutil -lrt"' >> /tmp/spc-gnu-docker.env @@ -137,4 +137,4 @@ echo 'SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-ldl -lpthread -lm -lresolv -lutil -lrt"' # shellcheck disable=SC2086 # shellcheck disable=SC2090 -$DOCKER_EXECUTABLE run --rm $INTERACT -e SPC_FIX_DEPLOY_ROOT="$(pwd)" --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH bin/spc $@ +$DOCKER_EXECUTABLE run --rm $INTERACT -e SPC_FIX_DEPLOY_ROOT="$(pwd)" --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH # bin/spc $@ From 1ce1c326b2ddeb42dccb18f4591b136d88c11e31 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Mon, 10 Mar 2025 16:15:47 +0800 Subject: [PATCH 13/14] Add SPC_CMD_VAR_PHP_EMBED_TYPE for embed building in glibc mode --- config/env.ini | 4 ++++ src/SPC/builder/linux/LinuxBuilder.php | 3 ++- src/SPC/builder/macos/MacOSBuilder.php | 3 ++- src/SPC/builder/unix/UnixBuilderBase.php | 10 +++++++++- src/SPC/store/FileSystem.php | 7 +++++++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/config/env.ini b/config/env.ini index 85ca6821..1849a371 100644 --- a/config/env.ini +++ b/config/env.ini @@ -79,6 +79,8 @@ SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force" SPC_CMD_PREFIX_PHP_CONFIGURE="${SPC_PHP_DEFAULT_LD_LIBRARY_PATH_CMD} ./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-cgi --disable-phpdbg --with-pic" ; make command SPC_CMD_PREFIX_PHP_MAKE="make -j${CPU_COUNT}" +; embed type for php, static (libphp.a) or shared (libphp.so) +SPC_CMD_VAR_PHP_EMBED_TYPE="shared" ; *** default build vars for building php *** ; CFLAGS for configuring php @@ -115,6 +117,8 @@ 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" ; make command SPC_CMD_PREFIX_PHP_MAKE="make -j${CPU_COUNT}" +; embed type for php, static or shared +SPC_CMD_VAR_PHP_EMBED_TYPE="static" ; *** default build vars for building php *** ; CFLAGS for configuring php diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index 556638e9..b809a005 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -169,12 +169,13 @@ class LinuxBuilder extends UnixBuilderBase // micro latest needs do strip and upx pack later (strip, upx, cut binary manually supported) } + $embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static'; shell()->cd(SOURCE_PATH . '/php-src') ->exec( getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' . ($enable_cli ? '--enable-cli ' : '--disable-cli ') . ($enable_fpm ? '--enable-fpm ' : '--disable-fpm ') . - ($enable_embed ? '--enable-embed=static ' : '--disable-embed ') . + ($enable_embed ? "--enable-embed={$embed_type} " : '--disable-embed ') . ($enable_micro ? '--enable-micro=all-static ' : '--disable-micro ') . $config_file_path . $config_file_scan_dir . diff --git a/src/SPC/builder/macos/MacOSBuilder.php b/src/SPC/builder/macos/MacOSBuilder.php index 95aa2c5e..dba0cd43 100644 --- a/src/SPC/builder/macos/MacOSBuilder.php +++ b/src/SPC/builder/macos/MacOSBuilder.php @@ -162,12 +162,13 @@ class MacOSBuilder extends UnixBuilderBase ); } + $embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static'; shell()->cd(SOURCE_PATH . '/php-src') ->exec( getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' . ($enableCli ? '--enable-cli ' : '--disable-cli ') . ($enableFpm ? '--enable-fpm ' : '--disable-fpm ') . - ($enableEmbed ? '--enable-embed=static ' : '--disable-embed ') . + ($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') . ($enableMicro ? '--enable-micro ' : '--disable-micro ') . $config_file_path . $config_file_scan_dir . diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 08bab8a0..785b2087 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -192,7 +192,15 @@ abstract class UnixBuilderBase extends BuilderBase if ($ret !== 0) { throw new RuntimeException('embed failed sanity check: build failed. Error message: ' . implode("\n", $out)); } - [$ret, $output] = shell()->cd($sample_file_path)->execWithResult('./embed'); + // if someone changed to --enable-embed=shared, we need to add LD_LIBRARY_PATH + if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') { + $ext_path = 'LD_LIBRARY_PATH=' . BUILD_ROOT_PATH . '/lib:$LD_LIBRARY_PATH '; + FileSystem::removeFileIfExists(BUILD_ROOT_PATH . '/lib/libphp.a'); + } else { + $ext_path = ''; + FileSystem::removeFileIfExists(BUILD_ROOT_PATH . '/lib/libphp.so'); + } + [$ret, $output] = shell()->cd($sample_file_path)->execWithResult($ext_path . './embed'); if ($ret !== 0 || trim(implode('', $output)) !== 'hello') { throw new RuntimeException('embed failed sanity check: run failed. Error message: ' . implode("\n", $output)); } diff --git a/src/SPC/store/FileSystem.php b/src/SPC/store/FileSystem.php index 5780a216..67b21ec4 100644 --- a/src/SPC/store/FileSystem.php +++ b/src/SPC/store/FileSystem.php @@ -454,6 +454,13 @@ class FileSystem unlink($path . '.bak'); } + public static function removeFileIfExists(string $string): void + { + if (file_exists($string)) { + unlink($string); + } + } + /** * @throws RuntimeException * @throws FileSystemException From 2afd39fbf127c43876b6260effda7e3613a1605a Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Mon, 10 Mar 2025 16:19:24 +0800 Subject: [PATCH 14/14] Fix test-extensions --- src/globals/test-extensions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index 0a07a521..0c29ff45 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -26,7 +26,7 @@ $test_os = [ ]; // whether enable thread safe -$zts = false; +$zts = true; $no_strip = false;