From b4f365732395e670073cf75f660b0aec0fdbc964 Mon Sep 17 00:00:00 2001 From: Jerry Ma Date: Fri, 14 Mar 2025 18:22:50 +0800 Subject: [PATCH] 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 --- .github/workflows/tests.yml | 5 ++--- bin/build-static-frankenphp | 7 +++---- bin/spc-gnu-docker | 7 +++---- config/env.ini | 19 ++++++++--------- docs/en/faq/index.md | 2 +- docs/en/guide/build-with-glibc.md | 4 +--- docs/zh/faq/index.md | 2 +- docs/zh/guide/build-with-glibc.md | 4 +--- src/SPC/ConsoleApplication.php | 4 ++-- src/SPC/builder/linux/LinuxBuilder.php | 20 ++++++------------ src/SPC/builder/linux/SystemUtil.php | 8 ------- src/SPC/builder/linux/library/icu.php | 2 +- src/SPC/builder/linux/library/libffi.php | 16 +++++--------- src/SPC/builder/linux/library/libpng.php | 4 ++-- src/SPC/builder/linux/library/openssl.php | 5 +++-- src/SPC/builder/macos/MacOSBuilder.php | 8 +++---- src/SPC/builder/macos/library/libffi.php | 5 +++-- src/SPC/builder/macos/library/openssl.php | 3 ++- src/SPC/builder/unix/UnixBuilderBase.php | 2 +- src/SPC/builder/unix/library/curl.php | 4 +--- src/SPC/builder/unix/library/imagemagick.php | 2 +- src/SPC/builder/unix/library/ldap.php | 2 +- src/SPC/builder/unix/library/pkgconfig.php | 2 +- src/SPC/builder/unix/library/postgresql.php | 2 +- src/SPC/command/BuildCommand.php | 21 ++++--------------- ...uildCliCommand.php => BuildPHPCommand.php} | 19 ++++++++++------- src/SPC/doctor/item/LinuxMuslCheck.php | 7 +++++++ src/SPC/doctor/item/MacOSToolCheckList.php | 2 +- src/SPC/store/SourcePatcher.php | 2 +- src/SPC/util/GlobalEnvManager.php | 2 +- src/globals/defines.php | 4 ---- src/globals/internal-env.php | 1 + 32 files changed, 80 insertions(+), 117 deletions(-) rename src/SPC/command/{BuildCliCommand.php => BuildPHPCommand.php} (98%) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7ab8f8b3..29f195bb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -100,14 +100,13 @@ jobs: path: vendor key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} restore-keys: | - ${{ runner.os }}-php- + ${{ runner.os }}-php - name: "Install Dependencies" run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist - name: "Run PHPUnit Tests" - run: | - SPC_NO_MUSL_PATH=yes vendor/bin/phpunit tests/ --no-coverage + run: SPC_LIBC=glibc vendor/bin/phpunit tests/ --no-coverage define-matrix: name: "Define Matrix" diff --git a/bin/build-static-frankenphp b/bin/build-static-frankenphp index 3341b712..10a693a7 100755 --- a/bin/build-static-frankenphp +++ b/bin/build-static-frankenphp @@ -92,7 +92,7 @@ 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" +ENV SPC_LIBC=glibc ADD ./config/env.ini /app/config/env.ini RUN bin/spc doctor --auto-fix --debug @@ -141,13 +141,12 @@ MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/pkgroot:/app/pkgroot" MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/frankenphp-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 '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 -fPIC' >> /tmp/spc-gnu-docker.env -echo 'SPC_NO_MUSL_PATH=yes' >> /tmp/spc-gnu-docker.env +echo 'SPC_LIBC=glibc' >> /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 diff --git a/bin/spc-gnu-docker b/bin/spc-gnu-docker index 0b5c45c2..fa84e58c 100755 --- a/bin/spc-gnu-docker +++ b/bin/spc-gnu-docker @@ -88,7 +88,7 @@ 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:$PATH" -ENV SPC_SKIP_DOCTOR_CHECK_ITEMS="if musl-wrapper is installed,if musl-cross-make is installed" +ENV SPC_LIBC=glibc ADD ./config/env.ini /app/config/env.ini RUN bin/spc doctor --auto-fix --debug @@ -131,13 +131,12 @@ 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-10/root/usr/bin/gcc' >> /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 -fPIC' >> /tmp/spc-gnu-docker.env -echo 'SPC_NO_MUSL_PATH=yes' >> /tmp/spc-gnu-docker.env +echo 'SPC_LIBC=glibc' >> /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 diff --git a/config/env.ini b/config/env.ini index 0acb903c..652b0fe6 100644 --- a/config/env.ini +++ b/config/env.ini @@ -7,8 +7,11 @@ ; ; We need to use some pre-defined internal env vars, like `BUILD_ROOT_PATH`, `DOWNLOAD_PATH`, etc. ; Please note that these vars cannot be defined in this file, they are only be defined before static-php-cli running. -; Here's a list of these pre-defined internal env vars, these vars are only be defined in the static-php-cli build process if not set in the shell environment: ; +; Here's a list of env vars, these value cannot be changed anywhere: +; +; WORKING_DIR: the working directory of the build process. (default: `$(pwd)`) +; ROOT_DIR: the root directory of static-php-cli. (default: `/path/to/static-php-cli`, when running in phar or micro mode: `phar://path/to/spc.phar`) ; BUILD_ROOT_PATH: the root path of the build process. (default: `$(pwd)/buildroot`) ; BUILD_INCLUDE_PATH: the path of the include files. (default: `$BUILD_ROOT_PATH/include`) ; BUILD_LIB_PATH: the path of the lib files. (default: `$BUILD_ROOT_PATH/lib`) @@ -17,21 +20,17 @@ ; SOURCE_PATH: the path of the source files. (default: `$(pwd)/source`) ; DOWNLOAD_PATH: the path of the download files. (default: `$(pwd)/downloads`) ; CPU_COUNT: the count of the CPU cores. (default: `$(nproc)`) +; SPC_ARCH: the arch of the current system, for some libraries needed `--host=XXX` args. (default: `$(uname -m)`, e.g. `x86_64`, `aarch64`, `arm64`) ; GNU_ARCH: the GNU arch of the current system. (default: `$(uname -m)`, e.g. `x86_64`, `aarch64`) ; MAC_ARCH: the MAC arch of the current system. (default: `$(uname -m)`, e.g. `x86_64`, `arm64`) ; -; Here's a list of env vars, these value cannot be changed anywhere: -; -; WORKING_DIR: the working directory of the build process. (default: `$(pwd)`) -; ROOT_DIR: the root directory of static-php-cli. (default: `/path/to/static-php-cli`, when running in phar or micro mode: `phar://path/to/spc.phar`) -; -; * These vars are only be defined in Unix (macOS, Linux, FreeBSD)Builder * +; * These vars are only be defined in Unix (macOS, Linux, FreeBSD)Builder and cannot be changed anywhere: ; PATH: static-php-cli will add `$BUILD_BIN_PATH` to PATH. ; PKG_CONFIG: static-php-cli will set `$BUILD_BIN_PATH/pkg-config` to PKG_CONFIG. ; PKG_CONFIG_PATH: static-php-cli will set `$BUILD_LIB_PATH/pkgconfig` to PKG_CONFIG_PATH. ; SPC_PHP_DEFAULT_OPTIMIZE_CFLAGS: the default optimization CFLAGS for compiling php. (if --no-strip option is set: `-g -O0`, else: `-g -Os`) ; -; * These vars are only be defined in LinuxBuilder * +; * These vars are only be defined in LinuxBuilder and cannot be changed anywhere: ; SPC_LINUX_DEFAULT_CC: the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`) ; SPC_LINUX_DEFAULT_CXX: the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`) ; SPC_LINUX_DEFAULT_AR: the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`) @@ -45,7 +44,7 @@ SPC_SKIP_PHP_VERSION_CHECK="no" ; Ignore some check item for bin/spc doctor command, comma separated (e.g. SPC_SKIP_DOCTOR_CHECK_ITEMS="if homebrew has installed") SPC_SKIP_DOCTOR_CHECK_ITEMS="" ; EXTENSION_DIR where the built php will look for extension when a .ini instructs to load them -; only useful for builds targeting glibc --libc=glibc +; only useful for builds targeting not pure-static linking ; default paths ; Ubuntu/Debian: /usr/lib/php/{PHP_VERSION}/ ; RHEL: /usr/lib64/php/modules @@ -63,7 +62,7 @@ SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime [linux] ; include PATH for musl libc. -SPC_NO_MUSL_PATH=no +SPC_LIBC=musl ; compiler environments CC=${SPC_LINUX_DEFAULT_CC} CXX=${SPC_LINUX_DEFAULT_CXX} diff --git a/docs/en/faq/index.md b/docs/en/faq/index.md index 4ab14408..1e8e0a47 100644 --- a/docs/en/faq/index.md +++ b/docs/en/faq/index.md @@ -32,7 +32,7 @@ supporting FFI extensions and loading the `xdebug.so` extension of the same PHP ```bash bin/spc-gnu-docker download --for-extensions=ffi,xml --with-php=8.4 -bin/spc-gnu-docker build --libc=glibc ffi,xml --build-cli --debug +bin/spc-gnu-docker build ffi,xml --build-cli --debug buildroot/bin/php -d "zend_extension=/path/to/php{PHP_VER}-{ts/nts}/xdebug.so" --ri xdebug ``` diff --git a/docs/en/guide/build-with-glibc.md b/docs/en/guide/build-with-glibc.md index 9573511b..0d6c1736 100644 --- a/docs/en/guide/build-with-glibc.md +++ b/docs/en/guide/build-with-glibc.md @@ -46,10 +46,8 @@ After the image is built, you will see the same command help menu as `bin/spc`, 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 +bin/spc-gnu-docker build bcmath,ctype,openssl,pdo,phar,posix,session,tokenizer,xml,zip --build-cli --debug ``` ## Notes diff --git a/docs/zh/faq/index.md b/docs/zh/faq/index.md index 8a898169..4367b35b 100644 --- a/docs/zh/faq/index.md +++ b/docs/zh/faq/index.md @@ -29,7 +29,7 @@ PHP 默认也会从 [其他标准位置](https://www.php.net/manual/zh/configura ```bash bin/spc-gnu-docker download --for-extensions=ffi,xml --with-php=8.4 -bin/spc-gnu-docker build --libc=glibc ffi,xml --build-cli --debug +bin/spc-gnu-docker build ffi,xml --build-cli --debug buildroot/bin/php -d "zend_extension=/path/to/php{PHP_VER}-{ts/nts}/xdebug.so" --ri xdebug ``` diff --git a/docs/zh/guide/build-with-glibc.md b/docs/zh/guide/build-with-glibc.md index 98883f3b..b025769b 100644 --- a/docs/zh/guide/build-with-glibc.md +++ b/docs/zh/guide/build-with-glibc.md @@ -39,10 +39,8 @@ bin/spc-gnu-docker 在容器准备好后,你可以参考 [本地构建](./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 +bin/spc-gnu-docker build bcmath,ctype,openssl,pdo,phar,posix,session,tokenizer,xml,zip --build-cli --debug ``` ## 注意事项 diff --git a/src/SPC/ConsoleApplication.php b/src/SPC/ConsoleApplication.php index 342e7f73..752cb999 100644 --- a/src/SPC/ConsoleApplication.php +++ b/src/SPC/ConsoleApplication.php @@ -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(), diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index 5518e6e3..671bb28b 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -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); } /** diff --git a/src/SPC/builder/linux/SystemUtil.php b/src/SPC/builder/linux/SystemUtil.php index aef748b8..c0ae6766 100644 --- a/src/SPC/builder/linux/SystemUtil.php +++ b/src/SPC/builder/linux/SystemUtil.php @@ -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); - } } diff --git a/src/SPC/builder/linux/library/icu.php b/src/SPC/builder/linux/library/icu.php index 77bd081d..519c0734 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 -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} " . diff --git a/src/SPC/builder/linux/library/libffi.php b/src/SPC/builder/linux/library/libffi.php index df85ef3e..870ece63 100644 --- a/src/SPC/builder/linux/library/libffi.php +++ b/src/SPC/builder/linux/library/libffi.php @@ -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}" ) diff --git a/src/SPC/builder/linux/library/libpng.php b/src/SPC/builder/linux/library/libpng.php index 9ffb7c75..56daee55 100644 --- a/src/SPC/builder/linux/library/libpng.php +++ b/src/SPC/builder/linux/library/libpng.php @@ -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) diff --git a/src/SPC/builder/linux/library/openssl.php b/src/SPC/builder/linux/library/openssl.php index 4c83f2e7..5c07ec7e 100644 --- a/src/SPC/builder/linux/library/openssl.php +++ b/src/SPC/builder/linux/library/openssl.php @@ -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}\"") diff --git a/src/SPC/builder/macos/MacOSBuilder.php b/src/SPC/builder/macos/MacOSBuilder.php index dba0cd43..ce82ab10 100644 --- a/src/SPC/builder/macos/MacOSBuilder.php +++ b/src/SPC/builder/macos/MacOSBuilder.php @@ -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); } /** diff --git a/src/SPC/builder/macos/library/libffi.php b/src/SPC/builder/macos/library/libffi.php index 94903f67..fb054b81 100644 --- a/src/SPC/builder/macos/library/libffi.php +++ b/src/SPC/builder/macos/library/libffi.php @@ -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') diff --git a/src/SPC/builder/macos/library/openssl.php b/src/SPC/builder/macos/library/openssl.php index d05d2a3d..e0e3919f 100644 --- a/src/SPC/builder/macos/library/openssl.php +++ b/src/SPC/builder/macos/library/openssl.php @@ -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}\"") diff --git a/src/SPC/builder/unix/UnixBuilderBase.php b/src/SPC/builder/unix/UnixBuilderBase.php index 785b2087..ed07a725 100644 --- a/src/SPC/builder/unix/UnixBuilderBase.php +++ b/src/SPC/builder/unix/UnixBuilderBase.php @@ -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); diff --git a/src/SPC/builder/unix/library/curl.php b/src/SPC/builder/unix/library/curl.php index fbe6ca20..c37dedf6 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,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(), ]) diff --git a/src/SPC/builder/unix/library/imagemagick.php b/src/SPC/builder/unix/library/imagemagick.php index 639225a8..53f7953e 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) && $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') : ''; diff --git a/src/SPC/builder/unix/library/ldap.php b/src/SPC/builder/unix/library/ldap.php index c1896be6..2831f094 100644 --- a/src/SPC/builder/unix/library/ldap.php +++ b/src/SPC/builder/unix/library/ldap.php @@ -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; } diff --git a/src/SPC/builder/unix/library/pkgconfig.php b/src/SPC/builder/unix/library/pkgconfig.php index 796fe96b..b489bbba 100644 --- a/src/SPC/builder/unix/library/pkgconfig.php +++ b/src/SPC/builder/unix/library/pkgconfig.php @@ -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()]) diff --git a/src/SPC/builder/unix/library/postgresql.php b/src/SPC/builder/unix/library/postgresql.php index 9b92fee4..e92d32c9 100644 --- a/src/SPC/builder/unix/library/postgresql.php +++ b/src/SPC/builder/unix/library/postgresql.php @@ -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; diff --git a/src/SPC/command/BuildCommand.php b/src/SPC/command/BuildCommand.php index 0bb8054f..6020931f 100644 --- a/src/SPC/command/BuildCommand.php +++ b/src/SPC/command/BuildCommand.php @@ -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'); diff --git a/src/SPC/command/BuildCliCommand.php b/src/SPC/command/BuildPHPCommand.php similarity index 98% rename from src/SPC/command/BuildCliCommand.php rename to src/SPC/command/BuildPHPCommand.php index d991719f..6bafce54 100644 --- a/src/SPC/command/BuildCliCommand.php +++ b/src/SPC/command/BuildPHPCommand.php @@ -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) { diff --git a/src/SPC/doctor/item/LinuxMuslCheck.php b/src/SPC/doctor/item/LinuxMuslCheck.php index f1f6e7b8..bd89c0d7 100644 --- a/src/SPC/doctor/item/LinuxMuslCheck.php +++ b/src/SPC/doctor/item/LinuxMuslCheck.php @@ -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"; diff --git a/src/SPC/doctor/item/MacOSToolCheckList.php b/src/SPC/doctor/item/MacOSToolCheckList.php index 6defdb2a..b4043a1d 100644 --- a/src/SPC/doctor/item/MacOSToolCheckList.php +++ b/src/SPC/doctor/item/MacOSToolCheckList.php @@ -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(); diff --git a/src/SPC/store/SourcePatcher.php b/src/SPC/store/SourcePatcher.php index 0ff19a93..d3ffc302 100644 --- a/src/SPC/store/SourcePatcher.php +++ b/src/SPC/store/SourcePatcher.php @@ -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'); } } diff --git a/src/SPC/util/GlobalEnvManager.php b/src/SPC/util/GlobalEnvManager.php index a82c2669..7988244f 100644 --- a/src/SPC/util/GlobalEnvManager.php +++ b/src/SPC/util/GlobalEnvManager.php @@ -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++'); diff --git a/src/globals/defines.php b/src/globals/defines.php index bbc2bd2f..46c98915 100644 --- a/src/globals/defines.php +++ b/src/globals/defines.php @@ -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%'; diff --git a/src/globals/internal-env.php b/src/globals/internal-env.php index 60ea8370..34b1ed99 100644 --- a/src/globals/internal-env.php +++ b/src/globals/internal-env.php @@ -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);