diff --git a/.github/workflows/build-unix.yml b/.github/workflows/build-unix.yml index bfcf098e..0ec63e24 100644 --- a/.github/workflows/build-unix.yml +++ b/.github/workflows/build-unix.yml @@ -15,7 +15,7 @@ on: php-version: required: true description: PHP version to compile - default: '8.3' + default: '8.4' type: choice options: - '8.4' diff --git a/bin/spc-gnu-docker b/bin/spc-gnu-docker index e589b8ba..a3af1431 100755 --- a/bin/spc-gnu-docker +++ b/bin/spc-gnu-docker @@ -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 $@ diff --git a/config/env.ini b/config/env.ini index 9582946e..0acb903c 100644 --- a/config/env.ini +++ b/config/env.ini @@ -35,7 +35,6 @@ ; 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`) -; SPC_PHP_DEFAULT_LD_LIBRARY_PATH_CMD: the default LD_LIBRARY_PATH for php. (linux: `LD_LIBRARY_PATH=/usr/local/musl/$GNU_ARCH-linux-musl/lib`, default: empty) [global] @@ -45,6 +44,14 @@ SPC_CONCURRENCY=${CPU_COUNT} 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 +; default paths +; Ubuntu/Debian: /usr/lib/php/{PHP_VERSION}/ +; RHEL: /usr/lib64/php/modules +; Alpine: /usr/lib/php{PHP_VERSION}/modules +; where {PHP_VERSION} is 84 for php 8.4 +EXTENSION_DIR= [windows] ; php-sdk-binary-tools path @@ -63,7 +70,7 @@ CXX=${SPC_LINUX_DEFAULT_CXX} AR=${SPC_LINUX_DEFAULT_AR} LD=ld.gold ; default compiler flags, used in CMake toolchain file, openssl and pkg-config build -SPC_DEFAULT_C_FLAGS= +SPC_DEFAULT_C_FLAGS="-fPIC" SPC_DEFAULT_CXX_FLAGS= ; extra libs for building php executable, used in `make` command for building php (this value may changed by extension build process, space separated) SPC_EXTRA_LIBS= @@ -76,7 +83,7 @@ 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 --with-pic" +SPC_CMD_PREFIX_PHP_CONFIGURE="./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) @@ -117,8 +124,6 @@ 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 @@ -131,6 +136,8 @@ SPC_CMD_VAR_PHP_CONFIGURE_LDFLAGS="-L${BUILD_LIB_PATH}" SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="${SPC_PHP_DEFAULT_OPTIMIZE_CFLAGS}" ; EXTRA_LIBS for `make` php SPC_CMD_VAR_PHP_MAKE_EXTRA_LIBS="-lresolv" +; embed type for php, static (libphp.a) or shared (libphp.dylib) +SPC_CMD_VAR_PHP_EMBED_TYPE="static" [freebsd] ; compiler environments diff --git a/config/lib.json b/config/lib.json index cfe41927..53c26d2c 100644 --- a/config/lib.json +++ b/config/lib.json @@ -9,8 +9,13 @@ "type": "root", "source": "php-src", "lib-depends": [ - "micro", - "lib-base" + "lib-base", + "micro" + ], + "lib-depends-linux": [ + "lib-base", + "libacl", + "micro" ] }, "micro": { @@ -24,6 +29,12 @@ "pkg-config" ] }, + "attr": { + "source": "attr", + "static-libs-unix": [ + "libattr.a" + ] + }, "brotli": { "source": "brotli", "static-libs-unix": [ @@ -234,6 +245,15 @@ "libsodium" ] }, + "libacl": { + "source": "libacl", + "static-libs-unix": [ + "libacl.a" + ], + "lib-depends": [ + "attr" + ] + }, "libaom": { "source": "libaom", "static-libs-unix": [ diff --git a/config/source.json b/config/source.json index b97ab139..e42fc0e7 100644 --- a/config/source.json +++ b/config/source.json @@ -36,6 +36,16 @@ "path": "LICENSE" } }, + "attr": { + "type": "git", + "rev": "v2.5.2", + "url": "https://git.savannah.nongnu.org/git/attr.git", + "provide-pre-built": true, + "license": { + "type": "file", + "path": "doc/COPYING" + } + }, "brotli": { "type": "ghtar", "repo": "google/brotli", @@ -323,6 +333,16 @@ "path": "LICENSE" } }, + "libacl": { + "type": "git", + "rev": "v2.3.2", + "url": "https://git.savannah.nongnu.org/git/acl.git", + "provide-pre-built": true, + "license": { + "type": "file", + "path": "doc/COPYING" + } + }, "libaom": { "type": "git", "rev": "main", diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 4cdc796c..a7886cd8 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -139,7 +139,8 @@ class Extension /** * Patch code before ./buildconf - * If you need to patch some code, overwrite this and return true + * If you need to patch some code, overwrite this + * return true if you patched something, false if not */ public function patchBeforeBuildconf(): bool { @@ -148,7 +149,8 @@ class Extension /** * Patch code before ./configure - * If you need to patch some code, overwrite this and return true + * If you need to patch some code, overwrite this + * return true if you patched something, false if not */ public function patchBeforeConfigure(): bool { @@ -157,7 +159,8 @@ class Extension /** * Patch code before make - * If you need to patch some code, overwrite this and return true + * If you need to patch some code, overwrite this + * return true if you patched something, false if not */ public function patchBeforeMake(): bool { diff --git a/src/SPC/builder/LibraryBase.php b/src/SPC/builder/LibraryBase.php index e0500cbe..d76aa209 100644 --- a/src/SPC/builder/LibraryBase.php +++ b/src/SPC/builder/LibraryBase.php @@ -113,7 +113,7 @@ abstract class LibraryBase /* Rules: If it is a Windows system, try the following dependencies in order: lib-depends-windows, lib-depends-win, lib-depends. - If it is a macOS system, try the following dependencies in order: lib-depends-darwin, lib-depends-unix, lib-depends. + If it is a macOS system, try the following dependencies in order: lib-depends-macos, lib-depends-unix, lib-depends. If it is a Linux system, try the following dependencies in order: lib-depends-linux, lib-depends-unix, lib-depends. */ foreach (Config::getLib(static::NAME, 'lib-depends', []) as $dep_name) { @@ -261,14 +261,6 @@ abstract class LibraryBase return LIB_STATUS_ALREADY; } - /** - * Patch before build, overwrite this and return true to patch libs. - */ - public function patchBeforeBuild(): bool - { - return false; - } - public function validate(): void { // do nothing, just throw wrong usage exception if not valid @@ -294,6 +286,46 @@ abstract class LibraryBase // do something before pack, default do nothing. overwrite this method to do something (e.g. modify pkg-config file) } + /** + * Patch code before build + * If you need to patch some code, overwrite this + * return true if you patched something, false if not + */ + public function patchBeforeBuild(): bool + { + return false; + } + + /** + * Patch code before ./buildconf + * If you need to patch some code, overwrite this + * return true if you patched something, false if not + */ + public function patchBeforeBuildconf(): bool + { + return false; + } + + /** + * Patch code before ./configure + * If you need to patch some code, overwrite this + * return true if you patched something, false if not + */ + public function patchBeforeConfigure(): bool + { + return false; + } + + /** + * Patch code before make + * If you need to patch some code, overwrite this + * return true if you patched something, false if not + */ + public function patchBeforeMake(): bool + { + return false; + } + /** * Build this library. * diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index b809a005..c72f618b 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -37,9 +37,13 @@ class LinuxBuilder extends UnixBuilderBase 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)) { + if (!filter_var(getenv('SPC_NO_MUSL_PATH'), FILTER_VALIDATE_BOOLEAN) && $this->libc !== LIBC_GLIBC) { $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')) { @@ -174,7 +178,7 @@ class LinuxBuilder extends UnixBuilderBase ->exec( getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' . ($enable_cli ? '--enable-cli ' : '--disable-cli ') . - ($enable_fpm ? '--enable-fpm ' : '--disable-fpm ') . + ($enable_fpm ? '--enable-fpm ' . ($this->getLib('libacl') !== null ? '--with-fpm-acl ' : '') : '--disable-fpm ') . ($enable_embed ? "--enable-embed={$embed_type} " : '--disable-embed ') . ($enable_micro ? '--enable-micro=all-static ' : '--disable-micro ') . $config_file_path . diff --git a/src/SPC/builder/linux/library/attr.php b/src/SPC/builder/linux/library/attr.php new file mode 100644 index 00000000..da29d48f --- /dev/null +++ b/src/SPC/builder/linux/library/attr.php @@ -0,0 +1,12 @@ +cd($this->source_dir) ->exec('chmod +x ./configure') ->exec('chmod +x ./install-sh') - ->setEnv(['CFLAGS' => $this->getLibExtraCFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->setEnv([ + 'CFLAGS' => trim($this->getLibExtraCFlags() . ' ' . $this->builder->arch_c_flags), + 'LDFLAGS' => $this->getLibExtraLdFlags(), + 'LIBS' => $this->getLibExtraLibs(), + ]) ->execWithEnv( 'LDFLAGS="-L' . BUILD_LIB_PATH . '" ' . './configure ' . diff --git a/src/SPC/builder/unix/library/attr.php b/src/SPC/builder/unix/library/attr.php new file mode 100644 index 00000000..a7d6d26f --- /dev/null +++ b/src/SPC/builder/unix/library/attr.php @@ -0,0 +1,28 @@ +cd($this->source_dir) + ->setEnv([ + 'CFLAGS' => trim('-I' . BUILD_INCLUDE_PATH . ' ' . $this->getLibExtraCFlags()), + 'LDFLAGS' => trim('-L' . BUILD_LIB_PATH . ' ' . $this->getLibExtraLdFlags()), + 'LIBS' => $this->getLibExtraLibs(), + ])->execWithEnv('./autogen.sh') + ->execWithEnv('./configure --prefix= --enable-static --disable-shared') + ->execWithEnv("make -j {$this->builder->concurrency}") + ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + + $this->patchPkgconfPrefix(['libattr.pc'], PKGCONF_PATCH_PREFIX); + } +} diff --git a/src/SPC/builder/unix/library/curl.php b/src/SPC/builder/unix/library/curl.php index 96a5bf05..fbe6ca20 100644 --- a/src/SPC/builder/unix/library/curl.php +++ b/src/SPC/builder/unix/library/curl.php @@ -4,6 +4,7 @@ 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; @@ -52,9 +53,14 @@ 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(), 'LDFLAGS' => $this->getLibExtraLdFlags(), 'LIBS' => $this->getLibExtraLibs()]) + ->setEnv([ + 'CFLAGS' => trim($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/libacl.php b/src/SPC/builder/unix/library/libacl.php new file mode 100644 index 00000000..e43cc2fc --- /dev/null +++ b/src/SPC/builder/unix/library/libacl.php @@ -0,0 +1,45 @@ +cd($this->source_dir) + ->setEnv([ + 'CFLAGS' => trim('-I' . BUILD_INCLUDE_PATH . ' ' . $this->getLibExtraCFlags()), + 'LDFLAGS' => trim('-L' . BUILD_LIB_PATH . ' ' . $this->getLibExtraLdFlags()), + 'LIBS' => $this->getLibExtraLibs(), + ]) + ->execWithEnv('./autogen.sh') + ->execWithEnv('./configure --prefix= --enable-static --disable-shared --disable-tests --disable-nls') + ->execWithEnv("make -j {$this->builder->concurrency}") + ->exec('make install DESTDIR=' . BUILD_ROOT_PATH); + + $this->patchPkgconfPrefix(['libacl.pc'], PKGCONF_PATCH_PREFIX); + } +} diff --git a/src/SPC/builder/unix/library/pkgconfig.php b/src/SPC/builder/unix/library/pkgconfig.php index 4a060f02..796fe96b 100644 --- a/src/SPC/builder/unix/library/pkgconfig.php +++ b/src/SPC/builder/unix/library/pkgconfig.php @@ -10,7 +10,7 @@ trait pkgconfig { protected function build(): void { - $cflags = PHP_OS_FAMILY !== 'Linux' ? '-Wimplicit-function-declaration -Wno-int-conversion' : ''; + $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'; shell()->cd($this->source_dir) diff --git a/src/SPC/command/BuildCliCommand.php b/src/SPC/command/BuildCliCommand.php index d991719f..cee98b73 100644 --- a/src/SPC/command/BuildCliCommand.php +++ b/src/SPC/command/BuildCliCommand.php @@ -108,6 +108,9 @@ class BuildCliCommand extends BuildCommand $include_suggest_ext = $this->getOption('with-suggested-exts'); $include_suggest_lib = $this->getOption('with-suggested-libs'); [$extensions, $libraries, $not_included] = DependencyUtil::getExtsAndLibs($extensions, $libraries, $include_suggest_ext, $include_suggest_lib); + if (PHP_OS_FAMILY !== 'Linux' || !($rule & BUILD_TARGET_FPM)) { + $libraries = array_filter($libraries, fn ($lib) => !in_array($lib, ['attr', 'libacl'])); + } $display_libs = array_filter($libraries, fn ($lib) => in_array(Config::getLib($lib, 'type', 'lib'), ['lib', 'package'])); // print info diff --git a/src/SPC/doctor/item/LinuxToolCheckList.php b/src/SPC/doctor/item/LinuxToolCheckList.php index 0e4b236a..810614be 100644 --- a/src/SPC/doctor/item/LinuxToolCheckList.php +++ b/src/SPC/doctor/item/LinuxToolCheckList.php @@ -17,7 +17,7 @@ class LinuxToolCheckList public const TOOLS_ALPINE = [ 'make', 'bison', 'flex', - 'git', 'autoconf', 'automake', + 'git', 'autoconf', 'automake', 'gettext-dev', 'tar', 'unzip', 'gzip', 'bzip2', 'cmake', 'gcc', 'g++', 'patch', 'binutils-gold', @@ -26,7 +26,7 @@ class LinuxToolCheckList public const TOOLS_DEBIAN = [ 'make', 'bison', 'flex', - 'git', 'autoconf', 'automake', + 'git', 'autoconf', 'automake', 'autopoint', 'tar', 'unzip', 'gzip', 'bzip2', 'cmake', 'patch', 'xz', 'libtoolize', diff --git a/src/SPC/store/SourcePatcher.php b/src/SPC/store/SourcePatcher.php index 5c7db38f..bbb07a8f 100644 --- a/src/SPC/store/SourcePatcher.php +++ b/src/SPC/store/SourcePatcher.php @@ -29,6 +29,7 @@ class SourcePatcher FileSystem::addSourceExtractHook('php-src', [SourcePatcher::class, 'patchImapLicense']); FileSystem::addSourceExtractHook('ext-imagick', [SourcePatcher::class, 'patchImagickWith84']); FileSystem::addSourceExtractHook('libaom', [SourcePatcher::class, 'patchLibaomForAlpine']); + FileSystem::addSourceExtractHook('attr', [SourcePatcher::class, 'patchAttrForAlpine']); } /** @@ -46,6 +47,11 @@ class SourcePatcher logger()->info('Extension [' . $ext->getName() . '] patched before buildconf'); } } + foreach ($builder->getLibs() as $lib) { + if ($lib->patchBeforeBuildconf() === true) { + logger()->info('Library [' . $lib->getName() . '] patched before buildconf'); + } + } // patch windows php 8.1 bug if (PHP_OS_FAMILY === 'Windows' && $builder->getPHPVersionID() >= 80100 && $builder->getPHPVersionID() < 80200) { logger()->info('Patching PHP 8.1 windows Fiber bug'); @@ -84,6 +90,11 @@ class SourcePatcher logger()->info('Extension [' . $ext->getName() . '] patched before configure'); } } + foreach ($builder->getLibs() as $lib) { + if ($lib->patchBeforeConfigure() === true) { + logger()->info('Library [' . $lib->getName() . '] patched before configure'); + } + } // patch capstone FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/have_capstone="yes"/', 'have_capstone="no"'); if ($builder instanceof LinuxBuilder && $builder->libc === 'glibc') { @@ -246,6 +257,11 @@ class SourcePatcher logger()->info('Extension [' . $ext->getName() . '] patched before make'); } } + foreach ($builder->getLibs() as $lib) { + if ($lib->patchBeforeMake() === true) { + logger()->info('Library [' . $lib->getName() . '] patched before make'); + } + } } /** @@ -407,6 +423,15 @@ class SourcePatcher return false; } + public static function patchAttrForAlpine(): bool + { + if (PHP_OS_FAMILY === 'Linux' && SystemUtil::isMuslDist() || PHP_OS_FAMILY === 'Darwin') { + SourcePatcher::patchFile('attr_alpine_gethostname.patch', SOURCE_PATH . '/attr'); + return true; + } + return false; + } + /** * Patch cli SAPI Makefile for Windows. * diff --git a/src/SPC/util/GlobalEnvManager.php b/src/SPC/util/GlobalEnvManager.php index 49f334d9..a82c2669 100644 --- a/src/SPC/util/GlobalEnvManager.php +++ b/src/SPC/util/GlobalEnvManager.php @@ -108,11 +108,6 @@ class GlobalEnvManager 'BSD' => self::applyConfig($ini['freebsd']), default => null, }; - - if (PHP_OS_FAMILY === 'Linux' && !filter_var(getenv('SPC_NO_MUSL_PATH'), FILTER_VALIDATE_BOOLEAN)) { - self::putenv("SPC_PHP_DEFAULT_LD_LIBRARY_PATH_CMD=LD_LIBRARY_PATH=/usr/local/musl/{$arch}-linux-musl/lib"); - self::putenv("PATH=/usr/local/musl/bin:/usr/local/musl/{$arch}-linux-musl/bin:" . getenv('PATH')); - } } public static function putenv(string $val): void diff --git a/src/globals/patch/attr_alpine_gethostname.patch b/src/globals/patch/attr_alpine_gethostname.patch new file mode 100644 index 00000000..ee6e4bdd --- /dev/null +++ b/src/globals/patch/attr_alpine_gethostname.patch @@ -0,0 +1,11 @@ +diff --git a/tools/attr.c b/tools/attr.c +index 312aef1..8e82810 100644 +--- a/tools/attr.c ++++ b/tools/attr.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include \ No newline at end of file