mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-17 22:05:35 +08:00
Compare commits
63 Commits
2.6.1
...
2ef64e4597
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ef64e4597 | ||
|
|
6c18862fd1 | ||
|
|
6c109c52f6 | ||
|
|
c7762a5b65 | ||
|
|
d07fadde76 | ||
|
|
ac7a09edd1 | ||
|
|
f30f095f00 | ||
|
|
d91a66ee8d | ||
|
|
7db7ed97ee | ||
|
|
6b9d49eb71 | ||
|
|
7c9e8e3e40 | ||
|
|
5586f627d3 | ||
|
|
e4921087d9 | ||
|
|
005b78413c | ||
|
|
3d45890a2d | ||
|
|
bb5eb64b28 | ||
|
|
e6a050de82 | ||
|
|
7e7eb844a7 | ||
|
|
e56c628bec | ||
|
|
c604f88685 | ||
|
|
83db186972 | ||
|
|
9af3b745a2 | ||
|
|
a5cd5fcb31 | ||
|
|
ec153fa6ff | ||
|
|
dd72b32559 | ||
|
|
a5d26d6517 | ||
|
|
e5ea32e9c0 | ||
|
|
5bc4504e37 | ||
|
|
4cb4c9c6a5 | ||
|
|
9190335a70 | ||
|
|
4e244789a2 | ||
|
|
6de7b8e63b | ||
|
|
68e500eea0 | ||
|
|
840e09a684 | ||
|
|
d00a5223d3 | ||
|
|
3965a899c7 | ||
|
|
956667bf08 | ||
|
|
51e23d21cd | ||
|
|
44c6d6288e | ||
|
|
e5848086c3 | ||
|
|
138e5588e9 | ||
|
|
ab5828a560 | ||
|
|
e1e48922de | ||
|
|
956688d9f4 | ||
|
|
7f45f4aeec | ||
|
|
fcaa7c5f42 | ||
|
|
e36800b951 | ||
|
|
977fbaa8ef | ||
|
|
0598eff9c5 | ||
|
|
a6364389ba | ||
|
|
c23c5ae614 | ||
|
|
454b5a77ad | ||
|
|
8145a7536b | ||
|
|
e41d7899c7 | ||
|
|
88d99a7dea | ||
|
|
90823e3b17 | ||
|
|
3357f286ab | ||
|
|
ad080da026 | ||
|
|
25c2def710 | ||
|
|
604131b31d | ||
|
|
924da6ae69 | ||
|
|
12aadf18cc | ||
|
|
1409d1b47b |
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
return (new PhpCsFixer\Config())
|
||||
->setRiskyAllowed(true)
|
||||
->setUnsupportedPhpVersionAllowed(true)
|
||||
->setRules([
|
||||
'@PSR12' => true,
|
||||
'@Symfony' => true,
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
**static-php-cli**是一个用于静态编译、构建 PHP 解释器的工具,支持众多流行扩展。
|
||||
|
||||
目前 static-php-cli 支持 `cli`、`fpm`、`embed` 和 `micro` SAPI。
|
||||
目前 static-php-cli 支持 `cli`、`fpm`、`embed`、`micro` 和 `frankenphp` SAPI。
|
||||
|
||||
**static-php-cli**也支持将 PHP 代码和 PHP 运行时打包为一个文件并运行。
|
||||
|
||||
@@ -292,6 +292,12 @@ bin/spc micro:combine my-app.phar -I "memory_limit=4G" -I "disable_functions=sys
|
||||
|
||||
你可以在 [我的个人赞助页](https://github.com/crazywhalecc/crazywhalecc/blob/master/FUNDING.md) 支持我和我的项目。你捐赠的一部分将会被用于维护 **static-php.dev** 服务器。
|
||||
|
||||
**特别赞助商**:
|
||||
|
||||
<a href="https://beyondco.de/"><img src="/docs/public/images/beyondcode-seeklogo.png" width="300" alt="Beyond Code Logo" /></a>
|
||||
|
||||
<a href="https://nativephp.com/"><img src="/docs/public/images/nativephp-logo.svg" width="300" alt="NativePHP Logo" /></a>
|
||||
|
||||
## 开源协议
|
||||
|
||||
本项目采用 MIT License 许可开源,下面是类似的项目:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
**static-php-cli** is a powerful tool designed for building static, standalone PHP runtime
|
||||
with popular extensions.
|
||||
|
||||
Static PHP built by **static-php-cli** supports `cli`, `fpm`, `embed` and `micro` SAPI.
|
||||
Static PHP built by **static-php-cli** supports `cli`, `fpm`, `embed`, `micro` and `frankenphp` SAPI.
|
||||
|
||||
**static-php-cli** also has the ability to package PHP projects
|
||||
along with the PHP interpreter into one single executable file.
|
||||
@@ -317,6 +317,12 @@ Now there is a [static-php](https://github.com/static-php) organization, which i
|
||||
|
||||
You can sponsor me or my project from [GitHub Sponsor](https://github.com/crazywhalecc). A portion of your donation will be used to maintain the **static-php.dev** server.
|
||||
|
||||
**Special thanks to sponsors below**:
|
||||
|
||||
<a href="https://beyondco.de/"><img src="/docs/public/images/beyondcode-seeklogo.png" width="300" alt="Beyond Code Logo" /></a>
|
||||
|
||||
<a href="https://nativephp.com/"><img src="/docs/public/images/nativephp-logo.svg" width="300" alt="NativePHP Logo" /></a>
|
||||
|
||||
## Open-Source License
|
||||
|
||||
This project itself is based on MIT License,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
set -e
|
||||
|
||||
# This file is using docker to run commands
|
||||
SPC_DOCKER_VERSION=v4
|
||||
SPC_DOCKER_VERSION=v5
|
||||
|
||||
# Detect docker can run
|
||||
if ! which docker >/dev/null; then
|
||||
@@ -53,9 +53,9 @@ aarch64|arm64)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
# if ALPINE_FROM is not set, use alpine:edge
|
||||
# if ALPINE_FROM is not set, use alpine:3.21
|
||||
if [ -z "$ALPINE_FROM" ]; then
|
||||
ALPINE_FROM=alpine:edge
|
||||
ALPINE_FROM=alpine:3.21
|
||||
fi
|
||||
if [ "$SPC_USE_ARCH" != "$CURRENT_ARCH" ]; then
|
||||
echo "* Using different arch needs to setup qemu-static for docker !"
|
||||
@@ -64,7 +64,7 @@ if [ "$SPC_USE_ARCH" != "$CURRENT_ARCH" ]; then
|
||||
$DOCKER_EXECUTABLE run --rm --privileged multiarch/qemu-user-static:register --reset > /dev/null
|
||||
fi
|
||||
else
|
||||
ALPINE_FROM=alpine:edge
|
||||
ALPINE_FROM=alpine:3.21
|
||||
fi
|
||||
|
||||
if [ "$SPC_USE_MIRROR" = "yes" ]; then
|
||||
|
||||
@@ -64,7 +64,7 @@ fi
|
||||
# Detect docker env is setup
|
||||
if ! $DOCKER_EXECUTABLE images | grep -q cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION; then
|
||||
echo "Docker container does not exist. Building docker image ..."
|
||||
$DOCKER_EXECUTABLE buildx build $PLATFORM_ARG --no-cache -t cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION -f- . <<EOF
|
||||
$DOCKER_EXECUTABLE buildx build $PLATFORM_ARG -t cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION -f- . <<EOF
|
||||
FROM centos:7
|
||||
RUN sed -i 's/mirror.centos.org/vault.centos.org/g' /etc/yum.repos.d/*.repo && \
|
||||
sed -i 's/^#.*baseurl=http/baseurl=http/g' /etc/yum.repos.d/*.repo && \
|
||||
@@ -96,7 +96,7 @@ RUN curl -fsSL -o patchelf.tgz https://github.com/NixOS/patchelf/releases/downlo
|
||||
tar -xzf patchelf.tgz -C /patchelf --strip-components=1 && \
|
||||
cp /patchelf/bin/patchelf /usr/bin/
|
||||
|
||||
RUN curl -o cmake.tgz -fsSL https://github.com/Kitware/CMake/releases/download/v3.31.4/cmake-3.31.4-linux-$SPC_USE_ARCH.tar.gz && \
|
||||
RUN curl -o cmake.tgz -#fSL https://github.com/Kitware/CMake/releases/download/v3.31.4/cmake-3.31.4-linux-$SPC_USE_ARCH.tar.gz && \
|
||||
mkdir /cmake && \
|
||||
tar -xzf cmake.tgz -C /cmake --strip-components 1
|
||||
|
||||
@@ -107,8 +107,8 @@ 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
|
||||
ENV PATH="/app/bin:/cmake/bin:$PATH"
|
||||
ENV SPC_LIBC=glibc
|
||||
ENV PATH="/app/bin:/cmake/bin:/opt/rh/devtoolset-10/root/usr/bin:\$PATH"
|
||||
|
||||
ADD ./config/env.ini /app/config/env.ini
|
||||
RUN CC=gcc bin/spc doctor --auto-fix --debug
|
||||
@@ -128,7 +128,6 @@ RUN curl -o automake.tgz -fsSL https://ftp.gnu.org/gnu/automake/automake-1.17.ta
|
||||
make && \
|
||||
make install && \
|
||||
ln -sf /usr/local/bin/automake /usr/bin/automake
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
@@ -154,11 +153,7 @@ if [ -f "$(pwd)/craft.yml" ]; then
|
||||
fi
|
||||
|
||||
# Apply env in temp env file
|
||||
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=-fPIC' >> /tmp/spc-gnu-docker.env
|
||||
echo 'SPC_DEFAULT_C_FLAGS=-fPIC' > /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
|
||||
|
||||
@@ -55,14 +55,29 @@ SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES="--with github.com/dunglas/frankenphp/cadd
|
||||
; EXTENSION_DIR=
|
||||
|
||||
[windows]
|
||||
; build target: win7-static
|
||||
SPC_TARGET=native-windows
|
||||
; php-sdk-binary-tools path
|
||||
PHP_SDK_PATH="${WORKING_DIR}\php-sdk-binary-tools"
|
||||
; upx executable path
|
||||
UPX_EXEC="${PKG_ROOT_PATH}\bin\upx.exe"
|
||||
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches
|
||||
SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static
|
||||
; Windows static linking system libs
|
||||
SPC_EXTRA_LIBS=""
|
||||
|
||||
[linux]
|
||||
; Linux can use different build toolchain, but the toolchain can not be changed in this file:
|
||||
; - musl (default): used for general linux distros, can build `musl-static` target only.
|
||||
; - zig (WIP): used for general linux distros, can build `musl` and `glibc` targets.
|
||||
; - musl-native: used for alpine linux, can build `musl-static` and `musl`(WIP) target.
|
||||
; - gnu-native (assume): used for general linux distros, can build `glibc` target only and have portability issues.
|
||||
|
||||
; build target:
|
||||
; - musl-static (default): pure static linking, using musl-libc, can run on any linux distro.
|
||||
; - musl: static linking with dynamic linking to musl-libc, can run on musl-based linux distro.
|
||||
; - glibc: static linking with dynamic linking to glibc, can run on glibc-based linux distro.
|
||||
|
||||
; include PATH for musl libc.
|
||||
SPC_LIBC=musl
|
||||
; compiler environments
|
||||
@@ -78,7 +93,7 @@ SPC_EXTRA_LIBS=
|
||||
; upx executable path
|
||||
UPX_EXEC=${PKG_ROOT_PATH}/bin/upx
|
||||
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches
|
||||
SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream
|
||||
SPC_MICRO_PATCHES=cli_checks,disable_huge_page
|
||||
|
||||
; *** default build command for building php ***
|
||||
; buildconf command
|
||||
@@ -109,6 +124,9 @@ SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=""
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM="-all-static -Wl,-O1 -pie"
|
||||
|
||||
[macos]
|
||||
; build target: macho or macho (possibly we could support macho-universal in the future)
|
||||
; Currently we do not support universal and cross-compilation for macOS.
|
||||
SPC_TARGET=native-macos
|
||||
; compiler environments
|
||||
CC=clang
|
||||
CXX=clang++
|
||||
@@ -118,7 +136,7 @@ SPC_DEFAULT_CXX_FLAGS="--target=${MAC_ARCH}-apple-darwin -Os"
|
||||
; extra libs for building php executable, used in `make` command for building php (this value may changed by extension build process, space separated)
|
||||
SPC_EXTRA_LIBS=
|
||||
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches
|
||||
SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,macos_iconv
|
||||
SPC_MICRO_PATCHES=cli_checks,macos_iconv
|
||||
|
||||
; *** default build command for building php ***
|
||||
; buildconf command
|
||||
|
||||
@@ -240,7 +240,8 @@
|
||||
"zstd",
|
||||
"xz",
|
||||
"libzip",
|
||||
"libxml2"
|
||||
"libxml2",
|
||||
"libjxl"
|
||||
]
|
||||
},
|
||||
"imap": {
|
||||
@@ -252,6 +253,18 @@
|
||||
"openssl"
|
||||
]
|
||||
},
|
||||
"jbig": {
|
||||
"source": "jbig",
|
||||
"static-libs-unix": [
|
||||
"libjbig.a",
|
||||
"libjbig85.a"
|
||||
],
|
||||
"headers": [
|
||||
"jbig.h",
|
||||
"jbig85.h",
|
||||
"jbig_ar.h"
|
||||
]
|
||||
},
|
||||
"ldap": {
|
||||
"source": "ldap",
|
||||
"static-libs-unix": [
|
||||
@@ -265,6 +278,13 @@
|
||||
"libsodium"
|
||||
]
|
||||
},
|
||||
"lerc": {
|
||||
"source": "lerc",
|
||||
"static-libs-unix": [
|
||||
"libLerc.a"
|
||||
],
|
||||
"cpp-library": true
|
||||
},
|
||||
"libacl": {
|
||||
"source": "libacl",
|
||||
"static-libs-unix": [
|
||||
@@ -400,6 +420,20 @@
|
||||
"zlib"
|
||||
]
|
||||
},
|
||||
"libjxl": {
|
||||
"source": "libjxl",
|
||||
"static-libs-unix": [
|
||||
"libjxl.a",
|
||||
"libjxl_dec.a"
|
||||
],
|
||||
"lib-depends": [
|
||||
"brotli",
|
||||
"libgif",
|
||||
"libjpeg",
|
||||
"libpng",
|
||||
"libwebp"
|
||||
]
|
||||
},
|
||||
"liblz4": {
|
||||
"source": "liblz4",
|
||||
"static-libs-unix": [
|
||||
@@ -478,6 +512,7 @@
|
||||
"static-libs-windows": [
|
||||
"libssh2.lib"
|
||||
],
|
||||
"provide-pre-built": true,
|
||||
"headers": [
|
||||
"libssh2.h",
|
||||
"libssh2_publickey.h",
|
||||
@@ -485,9 +520,6 @@
|
||||
],
|
||||
"lib-depends": [
|
||||
"openssl"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"zlib"
|
||||
]
|
||||
},
|
||||
"libtiff": {
|
||||
@@ -498,6 +530,13 @@
|
||||
"lib-depends": [
|
||||
"zlib",
|
||||
"libjpeg"
|
||||
],
|
||||
"lib-suggests-unix": [
|
||||
"lerc",
|
||||
"libwebp",
|
||||
"jbig",
|
||||
"xz",
|
||||
"zstd"
|
||||
]
|
||||
},
|
||||
"libuuid": {
|
||||
@@ -813,6 +852,15 @@
|
||||
"libiconv"
|
||||
]
|
||||
},
|
||||
"watcher": {
|
||||
"source": "watcher",
|
||||
"static-libs-unix": [
|
||||
"libwatcher-c.a"
|
||||
],
|
||||
"headers": [
|
||||
"wtr/watcher-c.h"
|
||||
]
|
||||
},
|
||||
"xz": {
|
||||
"source": "xz",
|
||||
"static-libs-unix": [
|
||||
@@ -866,14 +914,5 @@
|
||||
"zstd.h",
|
||||
"zstd_errors.h"
|
||||
]
|
||||
},
|
||||
"watcher": {
|
||||
"source": "watcher",
|
||||
"static-libs-unix": [
|
||||
"libwatcher-c.a"
|
||||
],
|
||||
"headers": [
|
||||
"wtr/watcher-c.h"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"alt": false
|
||||
},
|
||||
"amqp": {
|
||||
"type": "url",
|
||||
@@ -387,6 +388,15 @@
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"jbig": {
|
||||
"type": "url",
|
||||
"url": "https://www.cl.cam.ac.uk/~mgk25/jbigkit/download/jbigkit-2.1.tar.gz",
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
}
|
||||
},
|
||||
"ldap": {
|
||||
"type": "filelist",
|
||||
"url": "https://www.openldap.org/software/download/OpenLDAP/openldap-release/",
|
||||
@@ -396,6 +406,16 @@
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"lerc": {
|
||||
"type": "ghtar",
|
||||
"repo": "Esri/lerc",
|
||||
"prefer-stable": true,
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"libacl": {
|
||||
"alt": {
|
||||
"type": "url",
|
||||
@@ -533,6 +553,14 @@
|
||||
"path": "LICENSE.md"
|
||||
}
|
||||
},
|
||||
"libjxl": {
|
||||
"type": "ghtar",
|
||||
"repo": "libjxl/libjxl",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"liblz4": {
|
||||
"type": "ghrel",
|
||||
"repo": "lz4/lz4",
|
||||
@@ -605,7 +633,6 @@
|
||||
"type": "filelist",
|
||||
"url": "https://download.osgeo.org/libtiff/",
|
||||
"regex": "/href=\"(?<file>tiff-(?<version>[^\"]+)\\.tar\\.xz)\"/",
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE.md"
|
||||
@@ -998,6 +1025,15 @@
|
||||
"path": "COPYING"
|
||||
}
|
||||
},
|
||||
"watcher": {
|
||||
"type": "ghtar",
|
||||
"repo": "e-dant/watcher",
|
||||
"prefer-stable": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "license"
|
||||
}
|
||||
},
|
||||
"xdebug": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/xdebug",
|
||||
@@ -1078,14 +1114,5 @@
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"watcher": {
|
||||
"type": "ghtar",
|
||||
"repo": "e-dant/watcher",
|
||||
"prefer-stable": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "license"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,10 @@ export default {
|
||||
nav: [],
|
||||
socialLinks: [
|
||||
{icon: 'github', link: 'https://github.com/crazywhalecc/static-php-cli'}
|
||||
]
|
||||
],
|
||||
footer: {
|
||||
message: 'Released under the MIT License.',
|
||||
copyright: 'Copyright © 2023-present crazywhalecc'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
import {inBrowser, useData} from "vitepress";
|
||||
import {watchEffect} from "vue";
|
||||
import './style.css';
|
||||
|
||||
export default {
|
||||
...DefaultTheme,
|
||||
@@ -13,4 +14,4 @@ export default {
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
6
docs/.vitepress/theme/style.css
Normal file
6
docs/.vitepress/theme/style.css
Normal file
@@ -0,0 +1,6 @@
|
||||
/** override default styles */
|
||||
.vp-sponsor-grid-image {
|
||||
max-height:36px !important;
|
||||
max-width: 1000px !important;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ and this extension cannot be compiled into php by static linking, so it cannot b
|
||||
|
||||
## xdebug
|
||||
|
||||
1. Xdebug is only buildable as a shared extension. On Linux, you need to use static-php-cli with SPC_LIBC=glibc.
|
||||
1. Xdebug is only buildable as a shared extension. You need to use a build target other than `musl-static` for SPC_TARGET.
|
||||
2. When using Linux/glibc or macOS, you can compile Xdebug as a shared extension using --build-shared="xdebug".
|
||||
The compiled `./php` binary can be configured and run by specifying the INI, eg `./php -d 'zend_extension=/path/to/xdebug.so' your-code.php`.
|
||||
|
||||
|
||||
@@ -21,3 +21,16 @@ features:
|
||||
- title: Dependency Management
|
||||
details: static-php-cli comes with dependency management and supports installation of different types of PHP extensions.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import {VPSponsors} from "vitepress/theme";
|
||||
const sponsors = [
|
||||
{ name: 'Beyond Code', img: '/images/beyondcode-seeklogo.png', url: 'https://beyondco.de/' },
|
||||
{ name: 'NativePHP', img: '/images/nativephp-logo.svg', url: 'https://nativephp.com/' },
|
||||
];
|
||||
</script>
|
||||
|
||||
## Special Sponsors
|
||||
|
||||
<VPSponsors :data="sponsors"/>
|
||||
|
||||
|
||||
BIN
docs/public/images/beyondcode-seeklogo.png
Normal file
BIN
docs/public/images/beyondcode-seeklogo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
6
docs/public/images/nativephp-logo.svg
Normal file
6
docs/public/images/nativephp-logo.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 764 100">
|
||||
<path fill="#505b93" d="M29.5,98.4H0V1.2h29.5V98.4z"/>
|
||||
<path fill="#00aaa6" d="M96.7,98.4H67.2V1.2h29.5V98.4z"/>
|
||||
<path fill="#272d48" d="M96.7,98.4H29.5V1.2L96.7,98.4z"/>
|
||||
<path fill="#272d48" d="M102.6,54.5c0-6.2,1.3-11.8,4.1-16.7c2.7-5,6.7-8.8,11.9-11.6c5.2-2.8,11.4-4.2,18.6-4.2c1.1,0,2.8,0.1,5.2,0.3 c4.9,0.4,9.1,1.3,12.5,2.8c3.4,1.5,6.4,3.4,9.1,5.9v-7.2h25.8v74.7h-25.8v-7.2c-2.5,2.6-5.6,4.6-9.4,6.1c-3.8,1.5-7.9,2.4-12.1,2.6 c-0.9,0.1-2.3,0.1-4.1,0.1c-7.2,0-13.4-1.4-18.8-4.1c-5.4-2.7-9.5-6.6-12.4-11.5c-2.9-4.9-4.3-10.5-4.3-16.6V54.5z M128.4,63.9 c0,9.2,5.9,13.8,17.7,13.8c11.8,0,17.7-4.6,17.7-13.8v-5.6c0-9.3-5.9-14-17.7-14c-11.8,0-17.7,4.7-17.7,14V63.9z M208.3,98.4V47h-12.8V23.7l12.8-0.2V1.2h25.9l0.1,22.4h18.3V47h-18.4v51.4 M287.3,98.4h-25.9V23.6h25.9V98.4z M351,98.4H325l-31-74.8H320L338,68l18-44.5h25.9L351,98.4z M454.9,87.6c-4.1,4.2-8.8,7.3-14.1,9.3c-5.3,2-11.8,2.9-19.5,2.9c-8,0-15.1-1.4-21.3-4.2 c-6.2-2.8-11.1-6.7-14.7-11.6c-3.5-5-5.3-10.6-5.3-17V54.6c0-6.5,1.7-12.2,5.2-17.1c3.4-4.9,8.2-8.7,14.2-11.3c6-2.7,12.7-4,20-4 c8,0,15,1.5,21.2,4.3c6.1,2.9,10.9,7,14.4,12.4c3.4,5.4,5.2,11.6,5.2,18.7c0,1.7-0.2,4.2-0.7,7.7l-54.2,0.1v2.1 c0,4.1,1.5,7.3,4.4,9.4c2.9,2.2,6.9,3.2,11.8,3.2c4.6,0,8.5-0.6,11.8-1.8c3.2-1.2,6.4-3.5,9.4-6.8L454.9,87.6z M434.4,51.4 c0-3.1-1.4-5.5-4.2-7.1c-2.8-1.6-6.4-2.4-10.8-2.4s-7.9,0.8-10.5,2.4c-2.6,1.6-3.8,4-3.8,7.1H434.4z M466,98.4V1.2h56c9.9,0,17.8,1.9,23.7,5.6c5.9,3.7,10,8.2,12.2,13.3c2.3,5.1,3.4,10.1,3.4,15 c0,4.8-1.2,9.7-3.5,14.7c-2.3,5-6.4,9.2-12.2,12.8c-5.8,3.6-13.7,5.4-23.7,5.4h-30.2v30.5H466z M522,44.6c9,0,13.6-3.3,13.6-9.9 c0-6.9-4.6-10.3-13.7-10.3h-30.1v20.2H522z M593,98.4h-25.8V1.2H593v38h43.9v-38h25.8v97.2h-25.8V59.9H593V98.4z M668.6,98.4V1.2h56c9.9,0,17.8,1.9,23.7,5.6c5.9,3.7,10,8.2,12.2,13.3c2.3,5.1,3.4,10.1,3.4,15 c0,4.8-1.2,9.7-3.5,14.7c-2.3,5-6.4,9.2-12.2,12.8c-5.8,3.6-13.7,5.4-23.7,5.4h-30.2v30.5H668.6z M724.6,44.6c9,0,13.6-3.3,13.6-9.9 c0-6.9-4.6-10.3-13.7-10.3h-30.1v20.2H724.6z M291.1,20.2h-33.5V0h33.5V20.2z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -76,7 +76,7 @@ bin/spc build gd --with-libs=freetype,libjpeg,libavif,libwebp --build-cli
|
||||
|
||||
## xdebug
|
||||
|
||||
1. Xdebug 只能作为共享扩展进行构建。在 Linux 上,您需要使用 static-php-cli 并设置 SPC_LIBC=glibc。
|
||||
1. Xdebug 只能作为共享扩展进行构建。您需要使用除了 `musl-static` 外的其他 `SPC_TARGET` 构建目标。
|
||||
2. 使用 Linux/glibc 或 macOS 时,您可以使用 `--build-shared=xdebug` 将 Xdebug 编译为共享扩展。
|
||||
编译后的 `./php` 二进制文件可以通过指定 INI 文件进行配置和运行,例如 `./php -d 'zend_extension=/path/to/xdebug.so' your-code.php`。
|
||||
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
>
|
||||
<php>
|
||||
<env name="SPC_IGNORE_BAD_HASH" value="yes" force="true" />
|
||||
<env name="SPC_SKIP_TOOLCHAIN_CHECK" value="yes" force="true" />
|
||||
</php>
|
||||
</phpunit>
|
||||
|
||||
@@ -9,6 +9,7 @@ use SPC\command\BuildPHPCommand;
|
||||
use SPC\command\CraftCommand;
|
||||
use SPC\command\DeleteDownloadCommand;
|
||||
use SPC\command\dev\AllExtCommand;
|
||||
use SPC\command\dev\EnvCommand;
|
||||
use SPC\command\dev\ExtVerCommand;
|
||||
use SPC\command\dev\GenerateExtDepDocsCommand;
|
||||
use SPC\command\dev\GenerateExtDocCommand;
|
||||
@@ -70,6 +71,7 @@ final class ConsoleApplication extends Application
|
||||
new GenerateExtDepDocsCommand(),
|
||||
new GenerateLibDepDocsCommand(),
|
||||
new PackLibCommand(),
|
||||
new EnvCommand(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\LockFile;
|
||||
use SPC\store\SourceManager;
|
||||
use SPC\store\SourcePatcher;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
abstract class BuilderBase
|
||||
@@ -203,6 +204,8 @@ abstract class BuilderBase
|
||||
$this->emitPatchPoint('before-exts-extract');
|
||||
SourceManager::initSource(exts: [...$static_extensions, ...$shared_extensions]);
|
||||
$this->emitPatchPoint('after-exts-extract');
|
||||
// patch micro
|
||||
SourcePatcher::patchMicro();
|
||||
}
|
||||
|
||||
foreach ([...$static_extensions, ...$shared_extensions] as $extension) {
|
||||
|
||||
@@ -10,6 +10,7 @@ use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\SPCConfigUtil;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
class Extension
|
||||
{
|
||||
@@ -532,6 +533,11 @@ class Extension
|
||||
$sharedLibString .= '-l' . $lib . ' ';
|
||||
}
|
||||
}
|
||||
// move static libstdc++ to shared if we are on non-full-static build target
|
||||
if (!SPCTarget::isStatic() && in_array(SPCTarget::getLibc(), SPCTarget::LIBC_LIST)) {
|
||||
$staticLibString .= ' -lstdc++';
|
||||
$sharedLibString = str_replace('-lstdc++', '', $sharedLibString);
|
||||
}
|
||||
return [trim($staticLibString), trim($sharedLibString)];
|
||||
}
|
||||
|
||||
|
||||
@@ -332,6 +332,15 @@ abstract class LibraryBase
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch php-config after embed was built
|
||||
* Example: imap requires -lcrypt
|
||||
*/
|
||||
public function patchPhpConfig(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build this library.
|
||||
*
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace SPC\builder\extension;
|
||||
use SPC\builder\Extension;
|
||||
use SPC\builder\linux\LinuxBuilder;
|
||||
use SPC\builder\macos\MacOSBuilder;
|
||||
use SPC\builder\windows\WindowsBuilder;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
@@ -57,6 +58,17 @@ class curl extends Extension
|
||||
return true;
|
||||
}
|
||||
|
||||
public function patchBeforeMake(): bool
|
||||
{
|
||||
$extra_libs = getenv('SPC_EXTRA_LIBS');
|
||||
if ($this->builder instanceof WindowsBuilder && !str_contains($extra_libs, 'secur32.lib')) {
|
||||
$extra_libs .= ' secur32.lib';
|
||||
putenv('SPC_EXTRA_LIBS=' . trim($extra_libs));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function patchBeforeSharedConfigure(): bool
|
||||
{
|
||||
$file = $this->source_dir . '/config.m4';
|
||||
|
||||
@@ -10,34 +10,9 @@ use SPC\util\CustomExt;
|
||||
#[CustomExt('imagick')]
|
||||
class imagick extends Extension
|
||||
{
|
||||
public function patchBeforeMake(): bool
|
||||
{
|
||||
if (PHP_OS_FAMILY !== 'Linux') {
|
||||
return false;
|
||||
}
|
||||
if (getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10')) {
|
||||
return false;
|
||||
}
|
||||
// imagick with calls omp_pause_all, which requires openmp, on non-musl we build imagick without openmp
|
||||
$extra_libs = trim(getenv('SPC_EXTRA_LIBS') . ' -lgomp');
|
||||
f_putenv('SPC_EXTRA_LIBS=' . $extra_libs);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getUnixConfigureArg(bool $shared = false): string
|
||||
{
|
||||
$disable_omp = !(getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10')) ? '' : ' ac_cv_func_omp_pause_resource_all=no';
|
||||
$disable_omp = ' ac_cv_func_omp_pause_resource_all=no';
|
||||
return '--with-imagick=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . $disable_omp;
|
||||
}
|
||||
|
||||
protected function getStaticAndSharedLibs(): array
|
||||
{
|
||||
// on centos 7, it will use the symbol _ZTINSt6thread6_StateE, which is not defined in system libstdc++.so.6
|
||||
[$static, $shared] = parent::getStaticAndSharedLibs();
|
||||
if (getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10')) {
|
||||
$static .= ' -lstdc++';
|
||||
$shared = str_replace('-lstdc++', '', $shared);
|
||||
}
|
||||
return [$static, $shared];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
@@ -41,4 +42,14 @@ class imap extends Extension
|
||||
}
|
||||
return $arg;
|
||||
}
|
||||
|
||||
public function patchBeforeMake(): bool
|
||||
{
|
||||
if (PHP_OS_FAMILY !== 'Linux' || SystemUtil::isMuslDist()) {
|
||||
return false;
|
||||
}
|
||||
$extra_libs = trim(getenv('SPC_EXTRA_LIBS') . ' -lcrypt');
|
||||
f_putenv('SPC_EXTRA_LIBS=' . $extra_libs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,22 +25,8 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
{
|
||||
$this->options = $options;
|
||||
|
||||
// check musl-cross make installed if we use musl-cross-make
|
||||
$arch = arch2gnu(php_uname('m'));
|
||||
|
||||
GlobalEnvManager::init();
|
||||
|
||||
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\"");
|
||||
$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 (!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)');
|
||||
}
|
||||
}
|
||||
GlobalEnvManager::afterInit();
|
||||
|
||||
// concurrency
|
||||
$this->concurrency = intval(getenv('SPC_CONCURRENCY'));
|
||||
|
||||
@@ -188,12 +188,12 @@ class SystemUtil
|
||||
/**
|
||||
* Get libc version string from ldd
|
||||
*/
|
||||
public static function getLibcVersionIfExists(): ?string
|
||||
public static function getLibcVersionIfExists(string $libc): ?string
|
||||
{
|
||||
if (self::$libc_version !== null) {
|
||||
return self::$libc_version;
|
||||
}
|
||||
if (PHP_OS_FAMILY === 'Linux' && getenv('SPC_LIBC') === 'glibc') {
|
||||
if ($libc === 'glibc') {
|
||||
$result = shell()->execWithResult('ldd --version', false);
|
||||
if ($result[0] !== 0) {
|
||||
return null;
|
||||
@@ -208,7 +208,7 @@ class SystemUtil
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (PHP_OS_FAMILY === 'Linux' && getenv('SPC_LIBC') === 'musl') {
|
||||
if ($libc === 'musl') {
|
||||
if (self::isMuslDist()) {
|
||||
$result = shell()->execWithResult('ldd 2>&1', false);
|
||||
} else {
|
||||
|
||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
class icu extends LinuxLibraryBase
|
||||
{
|
||||
@@ -16,7 +17,7 @@ class icu extends LinuxLibraryBase
|
||||
{
|
||||
$cppflags = 'CPPFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=1 -DU_STATIC_IMPLEMENTATION=1 -DPIC -fPIC"';
|
||||
$cxxflags = 'CXXFLAGS="-std=c++17 -DPIC -fPIC -fno-ident"';
|
||||
$ldflags = getenv('SPC_LIBC') !== 'glibc' ? 'LDFLAGS="-static"' : '';
|
||||
$ldflags = SPCTarget::isStatic() ? 'LDFLAGS="-static"' : '';
|
||||
shell()->cd($this->source_dir . '/source')->initializeEnv($this)
|
||||
->exec(
|
||||
"{$cppflags} {$cxxflags} {$ldflags} " .
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace SPC\builder\linux\library;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
class imap extends LinuxLibraryBase
|
||||
{
|
||||
@@ -34,6 +35,15 @@ class imap extends LinuxLibraryBase
|
||||
return true;
|
||||
}
|
||||
|
||||
public function patchPhpConfig(): bool
|
||||
{
|
||||
if (SPCTarget::getLibc() === 'glibc') {
|
||||
FileSystem::replaceFileRegex(BUILD_BIN_PATH . '/php-config', '/^libs="(.*)"$/m', 'libs="$1 -lcrypt"');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
@@ -44,6 +54,8 @@ class imap extends LinuxLibraryBase
|
||||
} else {
|
||||
$ssl_options = 'SSLTYPE=none';
|
||||
}
|
||||
$libcVer = SPCTarget::getLibcVersion();
|
||||
$extraLibs = $libcVer && version_compare($libcVer, '2.17', '<=') ? 'EXTRALDFLAGS="-ldl -lrt -lpthread"' : '';
|
||||
shell()->cd($this->source_dir)
|
||||
->exec('make clean')
|
||||
->exec('touch ip6')
|
||||
@@ -51,9 +63,7 @@ class imap extends LinuxLibraryBase
|
||||
->exec('chmod +x tools/ua')
|
||||
->exec('chmod +x src/osdep/unix/drivers')
|
||||
->exec('chmod +x src/osdep/unix/mkauths')
|
||||
->exec(
|
||||
"yes | make slx {$ssl_options} EXTRACFLAGS='-fPIC -fpermissive'"
|
||||
);
|
||||
->exec("yes | make slx {$ssl_options} EXTRACFLAGS='-fPIC -fpermissive' {$extraLibs}");
|
||||
try {
|
||||
shell()
|
||||
->exec("cp -rf {$this->source_dir}/c-client/c-client.a " . BUILD_LIB_PATH . '/libc-client.a')
|
||||
|
||||
12
src/SPC/builder/linux/library/jbig.php
Normal file
12
src/SPC/builder/linux/library/jbig.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class jbig extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\jbig;
|
||||
|
||||
public const NAME = 'jbig';
|
||||
}
|
||||
12
src/SPC/builder/linux/library/lerc.php
Normal file
12
src/SPC/builder/linux/library/lerc.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class lerc extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\lerc;
|
||||
|
||||
public const NAME = 'lerc';
|
||||
}
|
||||
12
src/SPC/builder/linux/library/libjxl.php
Normal file
12
src/SPC/builder/linux/library/libjxl.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class libjxl extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\libjxl;
|
||||
|
||||
public const NAME = 'libjxl';
|
||||
}
|
||||
@@ -29,6 +29,7 @@ class MacOSBuilder extends UnixBuilderBase
|
||||
|
||||
// apply global environment variables
|
||||
GlobalEnvManager::init();
|
||||
GlobalEnvManager::afterInit();
|
||||
|
||||
// ---------- set necessary compile vars ----------
|
||||
// concurrency
|
||||
|
||||
12
src/SPC/builder/macos/library/jbig.php
Normal file
12
src/SPC/builder/macos/library/jbig.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class jbig extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\jbig;
|
||||
|
||||
public const NAME = 'jbig';
|
||||
}
|
||||
12
src/SPC/builder/macos/library/lerc.php
Normal file
12
src/SPC/builder/macos/library/lerc.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class lerc extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\lerc;
|
||||
|
||||
public const NAME = 'lerc';
|
||||
}
|
||||
12
src/SPC/builder/macos/library/libjxl.php
Normal file
12
src/SPC/builder/macos/library/libjxl.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class libjxl extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\libjxl;
|
||||
|
||||
public const NAME = 'libjxl';
|
||||
}
|
||||
@@ -17,6 +17,7 @@ use SPC\store\Downloader;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\DependencyUtil;
|
||||
use SPC\util\SPCConfigUtil;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
abstract class UnixBuilderBase extends BuilderBase
|
||||
{
|
||||
@@ -200,7 +201,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' && getenv('SPC_LIBC') === 'musl') {
|
||||
if (SPCTarget::isStatic()) {
|
||||
$lens .= ' -static';
|
||||
}
|
||||
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens);
|
||||
@@ -293,6 +294,11 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
$php_config_str = preg_replace('/(libs=")(.*?)\s*(-lstdc\+\+)\s*(.*?)"/', '$1$2 $4 $3"', $php_config_str);
|
||||
FileSystem::writeFile(BUILD_BIN_PATH . '/php-config', $php_config_str);
|
||||
}
|
||||
foreach ($this->getLibs() as $lib) {
|
||||
if ($lib->patchPhpConfig()) {
|
||||
logger()->debug("Library {$lib->getName()} patched php-config");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,7 +340,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
$debugFlags = $this->getOption('no-strip') ? "'-w -s' " : '';
|
||||
$extLdFlags = "-extldflags '-pie'";
|
||||
$muslTags = '';
|
||||
if (PHP_OS_FAMILY === 'Linux' && getenv('SPC_LIBC') === 'musl') {
|
||||
if (SPCTarget::isStatic()) {
|
||||
$extLdFlags = "-extldflags '-static-pie -Wl,-z,stack-size=0x80000'";
|
||||
$muslTags = 'static_build,';
|
||||
}
|
||||
|
||||
@@ -4,18 +4,19 @@ 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\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\executor\UnixAutoconfExecutor;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
trait imagemagick
|
||||
{
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
@@ -31,18 +32,17 @@ trait imagemagick
|
||||
->optionalLib('zstd', ...ac_with_args('zstd'))
|
||||
->optionalLib('freetype', ...ac_with_args('freetype'))
|
||||
->optionalLib('bzip2', ...ac_with_args('bzlib'))
|
||||
->optionalLib('libjxl', ...ac_with_args('jxl'))
|
||||
->addConfigureArgs(
|
||||
// TODO: glibc rh 10 toolset's libgomp.a was built without -fPIC so we can't use openmp without depending on libgomp.so
|
||||
getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10') ? '--disable-openmp' : '--enable-openmp',
|
||||
'--without-jxl',
|
||||
'--disable-openmp',
|
||||
'--without-x',
|
||||
);
|
||||
|
||||
// special: linux musl needs `-static`
|
||||
$ldflags = ($this instanceof LinuxLibraryBase) && getenv('SPC_LIBC') !== 'glibc' ? ('-static -ldl') : '-ldl';
|
||||
// special: linux-static target needs `-static`
|
||||
$ldflags = SPCTarget::isStatic() ? ('-static -ldl') : '-ldl';
|
||||
|
||||
// special: macOS needs -iconv
|
||||
$libs = $this instanceof MacOSLibraryBase ? '-liconv' : '';
|
||||
$libs = SPCTarget::getTargetOS() === 'Darwin' ? '-liconv' : '';
|
||||
|
||||
$ac->appendEnv([
|
||||
'LDFLAGS' => $ldflags,
|
||||
|
||||
35
src/SPC/builder/unix/library/jbig.php
Normal file
35
src/SPC/builder/unix/library/jbig.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
trait jbig
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public function patchBeforeBuild(): bool
|
||||
{
|
||||
FileSystem::replaceFileStr($this->source_dir . '/Makefile', 'CFLAGS = -O2 -W -Wno-unused-result', 'CFLAGS = -O2 -W -Wno-unused-result -fPIC');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
shell()->cd($this->source_dir)->initializeEnv($this)
|
||||
->exec("make -j{$this->builder->concurrency} {$this->builder->getEnvString()} lib")
|
||||
->exec('cp libjbig/libjbig.a ' . BUILD_LIB_PATH)
|
||||
->exec('cp libjbig/libjbig85.a ' . BUILD_LIB_PATH)
|
||||
->exec('cp libjbig/jbig.h ' . BUILD_INCLUDE_PATH)
|
||||
->exec('cp libjbig/jbig85.h ' . BUILD_INCLUDE_PATH)
|
||||
->exec('cp libjbig/jbig_ar.h ' . BUILD_INCLUDE_PATH);
|
||||
}
|
||||
}
|
||||
@@ -6,12 +6,13 @@ namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\executor\UnixAutoconfExecutor;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
trait ldap
|
||||
{
|
||||
public function patchBeforeBuild(): bool
|
||||
{
|
||||
$extra = getenv('SPC_LIBC') === 'glibc' ? '-ldl -lpthread -lm -lresolv -lutil' : '';
|
||||
$extra = SPCTarget::getLibc() === 'glibc' ? '-ldl -lpthread -lm -lresolv -lutil' : '';
|
||||
FileSystem::replaceFileStr($this->source_dir . '/configure', '"-lssl -lcrypto', '"-lssl -lcrypto -lz ' . $extra);
|
||||
return true;
|
||||
}
|
||||
|
||||
22
src/SPC/builder/unix/library/lerc.php
Normal file
22
src/SPC/builder/unix/library/lerc.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\util\executor\UnixCMakeExecutor;
|
||||
|
||||
trait lerc
|
||||
{
|
||||
/**
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
UnixCMakeExecutor::create($this)
|
||||
->build();
|
||||
}
|
||||
}
|
||||
24
src/SPC/builder/unix/library/libjxl.php
Normal file
24
src/SPC/builder/unix/library/libjxl.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\util\executor\UnixCMakeExecutor;
|
||||
|
||||
trait libjxl
|
||||
{
|
||||
protected function build(): void
|
||||
{
|
||||
UnixCMakeExecutor::create($this)
|
||||
->addConfigureArgs('-DJPEGXL_ENABLE_TOOLS=OFF')
|
||||
->addConfigureArgs('-DJPEGXL_ENABLE_EXAMPLES=OFF')
|
||||
->addConfigureArgs('-DJPEGXL_ENABLE_MANPAGES=OFF')
|
||||
->addConfigureArgs('-DJPEGXL_ENABLE_BENCHMARK=OFF')
|
||||
->addConfigureArgs('-DJPEGXL_ENABLE_PLUGINS=OFF')
|
||||
->addConfigureArgs('-DJPEGXL_ENABLE_SJPEG=OFF')
|
||||
->addConfigureArgs('-DJPEGXL_STATIC=ON')
|
||||
->addConfigureArgs('-DBUILD_TESTING=OFF')
|
||||
->build();
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,9 @@ namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\executor\UnixAutoconfExecutor;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
trait libtiff
|
||||
{
|
||||
@@ -16,6 +18,9 @@ trait libtiff
|
||||
*/
|
||||
protected function build(): void
|
||||
{
|
||||
$libcpp = SPCTarget::getTargetOS() === 'Darwin' ? '-lc++' : '-lstdc++';
|
||||
FileSystem::replaceFileStr($this->source_dir . '/configure', '-lwebp', '-lwebp -lsharpyuv');
|
||||
FileSystem::replaceFileStr($this->source_dir . '/configure', '-l"$lerc_lib_name"', '-l"$lerc_lib_name" ' . $libcpp);
|
||||
UnixAutoconfExecutor::create($this)
|
||||
->configure(
|
||||
// zlib deps
|
||||
@@ -24,17 +29,21 @@ trait libtiff
|
||||
"--with-zlib-lib-dir={$this->getLibDir()}",
|
||||
// libjpeg deps
|
||||
'--enable-jpeg',
|
||||
'--disable-old-jpeg',
|
||||
'--disable-jpeg12',
|
||||
"--with-jpeg-include-dir={$this->getIncludeDir()}",
|
||||
"--with-jpeg-lib-dir={$this->getLibDir()}",
|
||||
// We disabled lzma, zstd, webp, libdeflate by default to reduce the size of the binary
|
||||
'--disable-lzma',
|
||||
'--disable-zstd',
|
||||
'--disable-webp',
|
||||
'--disable-old-jpeg',
|
||||
'--disable-jpeg12',
|
||||
'--disable-libdeflate',
|
||||
'--disable-tools',
|
||||
'--disable-contrib',
|
||||
'--disable-cxx',
|
||||
'--without-x',
|
||||
)
|
||||
->optionalLib('lerc', '--enable-lerc', '--disable-lerc')
|
||||
->optionalLib('zstd', '--enable-zstd', '--disable-zstd')
|
||||
->optionalLib('webp', '--enable-webp', '--disable-webp')
|
||||
->optionalLib('xz', '--enable-lzma', '--disable-lzma')
|
||||
->optionalLib('jbig', '--enable-jbig', '--disable-jbig')
|
||||
->make();
|
||||
$this->patchPkgconfPrefix(['libtiff-4.pc']);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,13 @@ trait libxslt
|
||||
'--without-debugger',
|
||||
"--with-libxml-prefix={$this->getBuildRootPath()}",
|
||||
);
|
||||
$ac->exec("{$this->builder->getOption('library_path')} {$this->builder->getOption('ld_library_path')} ./configure {$ac->getConfigureArgsString()}")->make();
|
||||
if (getenv('SPC_LINUX_DEFAULT_LD_LIBRARY_PATH') && getenv('SPC_LINUX_DEFAULT_LIBRARY_PATH')) {
|
||||
$ac->appendEnv([
|
||||
'LD_LIBRARY_PATH' => getenv('SPC_LINUX_DEFAULT_LD_LIBRARY_PATH'),
|
||||
'LIBRARY_PATH' => getenv('SPC_LINUX_DEFAULT_LIBRARY_PATH'),
|
||||
]);
|
||||
}
|
||||
$ac->configure()->make();
|
||||
|
||||
$this->patchPkgconfPrefix(['libexslt.pc']);
|
||||
$this->patchLaDependencyPrefix();
|
||||
|
||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\util\executor\UnixCMakeExecutor;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
trait mimalloc
|
||||
{
|
||||
@@ -13,9 +14,9 @@ trait mimalloc
|
||||
$cmake = UnixCMakeExecutor::create($this)
|
||||
->addConfigureArgs(
|
||||
'-DMI_BUILD_SHARED=OFF',
|
||||
'-DMI_INSTALL_TOPLEVEL=ON'
|
||||
'-DMI_INSTALL_TOPLEVEL=ON',
|
||||
);
|
||||
if (getenv('SPC_LIBC') === 'musl') {
|
||||
if (SPCTarget::getLibc() === 'musl') {
|
||||
$cmake->addConfigureArgs('-DMI_LIBC_MUSL=ON');
|
||||
}
|
||||
$cmake->build();
|
||||
|
||||
@@ -4,8 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\builder\linux\library\LinuxLibraryBase;
|
||||
use SPC\util\executor\UnixAutoconfExecutor;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
trait pkgconfig
|
||||
{
|
||||
@@ -14,7 +14,7 @@ trait pkgconfig
|
||||
UnixAutoconfExecutor::create($this)
|
||||
->appendEnv([
|
||||
'CFLAGS' => PHP_OS_FAMILY !== 'Linux' ? '-Wimplicit-function-declaration -Wno-int-conversion' : '',
|
||||
'LDFLAGS' => !($this instanceof LinuxLibraryBase) || getenv('SPC_LIBC') === 'glibc' ? '' : '--static',
|
||||
'LDFLAGS' => SPCTarget::isStatic() ? '--static' : '',
|
||||
])
|
||||
->configure(
|
||||
'--with-internal-glib',
|
||||
|
||||
@@ -8,6 +8,7 @@ use SPC\builder\linux\library\LinuxLibraryBase;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
trait postgresql
|
||||
{
|
||||
@@ -50,7 +51,7 @@ trait postgresql
|
||||
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
|
||||
if (!empty($output[1][0])) {
|
||||
$ldflags = $output[1][0];
|
||||
$envs .= !($this instanceof LinuxLibraryBase) || getenv('SPC_LIBC') === 'glibc' ? " LDFLAGS=\"{$ldflags}\" " : " LDFLAGS=\"{$ldflags} -static\" ";
|
||||
$envs .= SPCTarget::isStatic() ? " LDFLAGS=\"{$ldflags} -static\" " : " LDFLAGS=\"{$ldflags}\" ";
|
||||
}
|
||||
$output = shell()->execWithResult("pkg-config --libs-only-l --static {$packages}");
|
||||
$error_exec_cnt += $output[0] === 0 ? 0 : 1;
|
||||
|
||||
@@ -34,6 +34,7 @@ class WindowsBuilder extends BuilderBase
|
||||
$this->options = $options;
|
||||
|
||||
GlobalEnvManager::init();
|
||||
GlobalEnvManager::afterInit();
|
||||
|
||||
// ---------- set necessary options ----------
|
||||
// set sdk (require visual studio 16 or 17)
|
||||
@@ -60,11 +61,6 @@ class WindowsBuilder extends BuilderBase
|
||||
*/
|
||||
public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
|
||||
{
|
||||
// ---------- Update extra-libs ----------
|
||||
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
|
||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', $this->getAllStaticLibFiles());
|
||||
f_putenv('SPC_EXTRA_LIBS=' . $extra_libs);
|
||||
|
||||
$enableCli = ($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI;
|
||||
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
|
||||
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
|
||||
@@ -161,8 +157,10 @@ class WindowsBuilder extends BuilderBase
|
||||
{
|
||||
SourcePatcher::patchWindowsCLITarget();
|
||||
|
||||
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
|
||||
|
||||
// add nmake wrapper
|
||||
FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_cli_wrapper.bat', "nmake /nologo LIBS_CLI=\"{$this->getOption('extra-libs')} ws2_32.lib shell32.lib\" EXTRA_LD_FLAGS_PROGRAM= %*");
|
||||
FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_cli_wrapper.bat', "nmake /nologo LIBS_CLI=\"ws2_32.lib shell32.lib {$extra_libs}\" EXTRA_LD_FLAGS_PROGRAM= %*");
|
||||
|
||||
cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_cli_wrapper.bat --task-args php.exe");
|
||||
|
||||
@@ -196,9 +194,11 @@ class WindowsBuilder extends BuilderBase
|
||||
}
|
||||
FileSystem::writeFile(SOURCE_PATH . '\php-src\Makefile', $makefile);
|
||||
|
||||
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
|
||||
|
||||
// add nmake wrapper
|
||||
$fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' /DPHP_MICRO_FAKE_CLI" ' : '';
|
||||
$wrapper = "nmake /nologo LIBS_MICRO=\"{$this->getOption('extra-libs')} ws2_32.lib shell32.lib\" CFLAGS_MICRO=\"/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1{$fake_cli}\" %*";
|
||||
$wrapper = "nmake /nologo LIBS_MICRO=\"ws2_32.lib shell32.lib {$extra_libs}\" CFLAGS_MICRO=\"/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1{$fake_cli}\" %*";
|
||||
FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_micro_wrapper.bat', $wrapper);
|
||||
|
||||
// phar patch for micro
|
||||
|
||||
@@ -37,6 +37,7 @@ class curl extends WindowsLibraryBase
|
||||
'-DBUILD_EXAMPLES=OFF ' . // disable examples
|
||||
'-DUSE_LIBIDN2=OFF ' . // disable libidn2
|
||||
'-DCURL_USE_LIBPSL=OFF ' . // disable libpsl
|
||||
'-DUSE_WINDOWS_SSPI=ON ' . // use Schannel instead of OpenSSL
|
||||
'-DCURL_USE_SCHANNEL=ON ' . // use Schannel instead of OpenSSL
|
||||
'-DCURL_USE_OPENSSL=OFF ' . // disable openssl due to certificate issue
|
||||
'-DCURL_ENABLE_SSL=ON ' .
|
||||
|
||||
@@ -99,6 +99,7 @@ abstract class BaseCommand extends Command
|
||||
// init GlobalEnv
|
||||
if (!$this instanceof BuildCommand) {
|
||||
GlobalEnvManager::init();
|
||||
f_putenv('SPC_SKIP_TOOLCHAIN_CHECK=yes');
|
||||
}
|
||||
if ($this->shouldExecute()) {
|
||||
try {
|
||||
|
||||
@@ -13,6 +13,7 @@ use SPC\store\SourcePatcher;
|
||||
use SPC\util\DependencyUtil;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
use SPC\util\LicenseDumper;
|
||||
use SPC\util\SPCTarget;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
@@ -63,8 +64,8 @@ class BuildPHPCommand extends BuildCommand
|
||||
|
||||
// check dynamic extension build env
|
||||
// linux must build with glibc
|
||||
if (!empty($shared_extensions) && PHP_OS_FAMILY === 'Linux' && getenv('SPC_LIBC') !== 'glibc') {
|
||||
$this->output->writeln('Linux does not support dynamic extension loading with musl-libc full-static build, please build with glibc!');
|
||||
if (!empty($shared_extensions) && SPCTarget::isStatic()) {
|
||||
$this->output->writeln('Linux does not support dynamic extension loading with musl-libc full-static build, please build with shared target!');
|
||||
return static::FAILURE;
|
||||
}
|
||||
$static_and_shared = array_intersect($static_extensions, $shared_extensions);
|
||||
@@ -133,6 +134,8 @@ class BuildPHPCommand extends BuildCommand
|
||||
// print info
|
||||
$indent_texts = [
|
||||
'Build OS' => PHP_OS_FAMILY . ' (' . php_uname('m') . ')',
|
||||
'Build Target' => getenv('SPC_TARGET'),
|
||||
'Build Toolchain' => getenv('SPC_TOOLCHAIN'),
|
||||
'Build SAPI' => $builder->getBuildTypeName($rule),
|
||||
'Static Extensions (' . count($static_extensions) . ')' => implode(',', $static_extensions),
|
||||
'Shared Extensions (' . count($shared_extensions) . ')' => implode(',', $shared_extensions),
|
||||
|
||||
@@ -10,7 +10,7 @@ use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
#[AsCommand('craft', 'Build static-php from craft.yml')]
|
||||
class CraftCommand extends BaseCommand
|
||||
class CraftCommand extends BuildCommand
|
||||
{
|
||||
public function configure(): void
|
||||
{
|
||||
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\command;
|
||||
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\builder\traits\UnixSystemUtilTrait;
|
||||
use SPC\exception\DownloaderException;
|
||||
use SPC\exception\FileSystemException;
|
||||
@@ -14,6 +13,7 @@ use SPC\store\Config;
|
||||
use SPC\store\Downloader;
|
||||
use SPC\store\LockFile;
|
||||
use SPC\util\DependencyUtil;
|
||||
use SPC\util\SPCTarget;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
@@ -223,8 +223,8 @@ class DownloadCommand extends BaseCommand
|
||||
'{name}' => $source,
|
||||
'{arch}' => arch2gnu(php_uname('m')),
|
||||
'{os}' => strtolower(PHP_OS_FAMILY),
|
||||
'{libc}' => getenv('SPC_LIBC') ?: 'default',
|
||||
'{libcver}' => PHP_OS_FAMILY === 'Linux' ? (SystemUtil::getLibcVersionIfExists() ?? 'default') : 'default',
|
||||
'{libc}' => SPCTarget::getLibc() ?? 'default',
|
||||
'{libcver}' => SPCTarget::getLibcVersion() ?? 'default',
|
||||
];
|
||||
$find = str_replace(array_keys($replace), array_values($replace), Config::getPreBuilt('match-pattern'));
|
||||
// find filename in asset list
|
||||
@@ -245,11 +245,15 @@ class DownloadCommand extends BaseCommand
|
||||
}
|
||||
// if download failed, we will try to download alternative sources
|
||||
logger()->warning("Download failed: {$e->getMessage()}");
|
||||
logger()->notice("Trying to download alternative sources for {$source}");
|
||||
$alt_sources = Config::getSource($source)['alt'] ?? null;
|
||||
if ($alt_sources === null) {
|
||||
logger()->warning("No alternative sources found for {$source}, using default alternative source");
|
||||
$alt_config = array_merge($config, $this->getDefaultAlternativeSource($source));
|
||||
} elseif ($alt_sources === false) {
|
||||
logger()->warning("No alternative sources found for {$source}, skipping alternative download");
|
||||
throw $e;
|
||||
} else {
|
||||
logger()->notice("Trying to download alternative sources for {$source}");
|
||||
$alt_config = array_merge($config, $alt_sources);
|
||||
}
|
||||
Downloader::downloadSource($source, $alt_config, $force_all || in_array($source, $force_list));
|
||||
|
||||
@@ -11,7 +11,7 @@ use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
#[AsCommand('spc-config', 'Build dependencies')]
|
||||
class SPCConfigCommand extends BuildCommand
|
||||
class SPCConfigCommand extends BaseCommand
|
||||
{
|
||||
protected bool $no_motd = true;
|
||||
|
||||
|
||||
37
src/SPC/command/dev/EnvCommand.php
Normal file
37
src/SPC/command/dev/EnvCommand.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\command\dev;
|
||||
|
||||
use SPC\command\BaseCommand;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
#[AsCommand('dev:env', 'Returns the internally defined environment variables')]
|
||||
class EnvCommand extends BaseCommand
|
||||
{
|
||||
public function configure()
|
||||
{
|
||||
$this->addArgument('env', InputArgument::REQUIRED, 'The environment variable to show, if not set, all will be shown');
|
||||
}
|
||||
|
||||
public function initialize(InputInterface $input, OutputInterface $output): void
|
||||
{
|
||||
$this->no_motd = true;
|
||||
parent::initialize($input, $output);
|
||||
}
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$env = $this->getArgument('env');
|
||||
if (($val = getenv($env)) === false) {
|
||||
$this->output->writeln("<error>Environment variable '{$env}' is not set.</error>");
|
||||
return static::FAILURE;
|
||||
}
|
||||
$this->output->writeln("<info>{$val}</info>");
|
||||
return static::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ namespace SPC\command\dev;
|
||||
|
||||
use SPC\builder\BuilderProvider;
|
||||
use SPC\builder\LibraryBase;
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\command\BuildCommand;
|
||||
use SPC\exception\ExceptionHandler;
|
||||
use SPC\exception\FileSystemException;
|
||||
@@ -16,6 +15,7 @@ use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\LockFile;
|
||||
use SPC\util\DependencyUtil;
|
||||
use SPC\util\SPCTarget;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
|
||||
@@ -42,6 +42,15 @@ class PackLibCommand extends BuildCommand
|
||||
|
||||
$builder->proveLibs($libraries);
|
||||
$builder->validateLibsAndExts();
|
||||
|
||||
// before pack, check if the dependency tree contains lib-suggests
|
||||
foreach ($libraries as $lib) {
|
||||
if (Config::getLib($lib, 'lib-suggests', []) !== []) {
|
||||
logger()->critical("The library {$lib} has lib-suggests, packing [{$lib_name}] is not safe, abort !");
|
||||
return static::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($builder->getLibs() as $lib) {
|
||||
if ($lib->getName() !== $lib_name) {
|
||||
// other dependencies: install or build, both ok
|
||||
@@ -76,8 +85,8 @@ class PackLibCommand extends BuildCommand
|
||||
'{name}' => $lib->getName(),
|
||||
'{arch}' => arch2gnu(php_uname('m')),
|
||||
'{os}' => strtolower(PHP_OS_FAMILY),
|
||||
'{libc}' => getenv('SPC_LIBC') ?: 'default',
|
||||
'{libcver}' => PHP_OS_FAMILY === 'Linux' ? (SystemUtil::getLibcVersionIfExists() ?? 'default') : 'default',
|
||||
'{libc}' => SPCTarget::getLibc() ?? 'default',
|
||||
'{libcver}' => SPCTarget::getLibcVersion() ?? 'default',
|
||||
];
|
||||
// detect suffix, for proper tar option
|
||||
$tar_option = $this->getTarOptionFromSuffix(Config::getPreBuilt('match-pattern'));
|
||||
|
||||
@@ -72,6 +72,14 @@ final class CheckListHandler
|
||||
{
|
||||
foreach (FileSystem::getClassesPsr4(__DIR__ . '/item', 'SPC\doctor\item') as $class) {
|
||||
$ref = new \ReflectionClass($class);
|
||||
$optional = $ref->getAttributes(OptionalCheck::class)[0] ?? null;
|
||||
if ($optional !== null) {
|
||||
/** @var OptionalCheck $instance */
|
||||
$instance = $optional->newInstance();
|
||||
if (is_callable($instance->check) && !call_user_func($instance->check)) {
|
||||
continue; // skip this class if optional check is false
|
||||
}
|
||||
}
|
||||
foreach ($ref->getMethods() as $method) {
|
||||
foreach ($method->getAttributes() as $a) {
|
||||
if (is_a($a->getName(), AsCheckItem::class, true)) {
|
||||
|
||||
11
src/SPC/doctor/OptionalCheck.php
Normal file
11
src/SPC/doctor/OptionalCheck.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\doctor;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)]
|
||||
class OptionalCheck
|
||||
{
|
||||
public function __construct(public array $check) {}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\doctor\item;
|
||||
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\doctor\AsCheckItem;
|
||||
use SPC\doctor\AsFixItem;
|
||||
use SPC\doctor\CheckResult;
|
||||
use SPC\doctor\OptionalCheck;
|
||||
use SPC\exception\DownloaderException;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
@@ -16,20 +16,20 @@ use SPC\store\Downloader;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\PackageManager;
|
||||
use SPC\store\SourcePatcher;
|
||||
use SPC\toolchain\MuslToolchain;
|
||||
|
||||
#[OptionalCheck([self::class, 'optionalCheck'])]
|
||||
class LinuxMuslCheck
|
||||
{
|
||||
public static function optionalCheck(): bool
|
||||
{
|
||||
return getenv('SPC_TOOLCHAIN') === MuslToolchain::class;
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
#[AsCheckItem('if musl-wrapper is installed', limit_os: 'Linux', level: 800)]
|
||||
public function checkMusl(): CheckResult
|
||||
{
|
||||
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')) {
|
||||
return CheckResult::ok();
|
||||
@@ -40,13 +40,6 @@ class LinuxMuslCheck
|
||||
#[AsCheckItem('if musl-cross-make is installed', limit_os: 'Linux', level: 799)]
|
||||
public function checkMuslCrossMake(): CheckResult
|
||||
{
|
||||
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";
|
||||
|
||||
@@ -51,6 +51,7 @@ class LinuxToolCheckList
|
||||
'binutils-gold' => 'ld.gold',
|
||||
'base-devel' => 'automake',
|
||||
'gettext-devel' => 'gettextize',
|
||||
'gettext-dev' => 'gettextize',
|
||||
];
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
|
||||
@@ -4,13 +4,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\store;
|
||||
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\exception\DownloaderException;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\pkg\CustomPackage;
|
||||
use SPC\store\source\CustomSourceBase;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
/**
|
||||
* Source Downloader.
|
||||
@@ -591,7 +591,12 @@ class Downloader
|
||||
|
||||
public static function getPreBuiltLockName(string $source): string
|
||||
{
|
||||
return "{$source}-" . PHP_OS_FAMILY . '-' . getenv('GNU_ARCH') . '-' . (getenv('SPC_LIBC') ?: 'default') . '-' . (SystemUtil::getLibcVersionIfExists() ?? 'default');
|
||||
$os_family = PHP_OS_FAMILY;
|
||||
$gnu_arch = getenv('GNU_ARCH') ?: 'unknown';
|
||||
$libc = SPCTarget::getLibc();
|
||||
$libc_version = SPCTarget::getLibcVersion() ?? 'default';
|
||||
|
||||
return "{$source}-{$os_family}-{$gnu_arch}-{$libc}-{$libc_version}";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -66,7 +66,7 @@ class SourceManager
|
||||
$check = LockFile::getExtractPath($lock_name, SOURCE_PATH . '/' . $source);
|
||||
// $check = $lock[$lock_name]['move_path'] === null ? (SOURCE_PATH . '/' . $source) : (SOURCE_PATH . '/' . $lock[$lock_name]['move_path']);
|
||||
if (!is_dir($check)) {
|
||||
logger()->debug('Extracting source [' . $source . '] to ' . $check . ' ...');
|
||||
logger()->debug("Extracting source [{$source}] to {$check} ...");
|
||||
$filename = LockFile::getLockFullPath($lock_content);
|
||||
FileSystem::extractSource($source, $lock_content['source_type'], $filename, $check);
|
||||
LockFile::putLockSourceHash($lock_content, $check);
|
||||
@@ -81,7 +81,14 @@ class SourceManager
|
||||
|
||||
// when source already extracted, detect if the extracted source hash is the same as the lock file one
|
||||
if (file_exists("{$check}/.spc-hash") && FileSystem::readFile("{$check}/.spc-hash") === $hash) {
|
||||
logger()->debug('Source [' . $source . '] already extracted in ' . $check . ', skip !');
|
||||
logger()->debug("Source [{$source}] already extracted in {$check}, skip !");
|
||||
continue;
|
||||
}
|
||||
|
||||
// ext imap was included in php < 8.4 which we should not extract,
|
||||
// but since it's not simple to compare php version, for now we just skip it
|
||||
if ($source === 'ext-imap') {
|
||||
logger()->debug("Source [ext-imap] already extracted in {$check}, skip !");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,13 +11,13 @@ use SPC\builder\unix\UnixBuilderBase;
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
class SourcePatcher
|
||||
{
|
||||
public static function init(): void
|
||||
{
|
||||
// FileSystem::addSourceExtractHook('swow', [SourcePatcher::class, 'patchSwow']);
|
||||
FileSystem::addSourceExtractHook('micro', [SourcePatcher::class, 'patchMicro']);
|
||||
FileSystem::addSourceExtractHook('openssl', [SourcePatcher::class, 'patchOpenssl11Darwin']);
|
||||
FileSystem::addSourceExtractHook('swoole', [SourcePatcher::class, 'patchSwoole']);
|
||||
FileSystem::addSourceExtractHook('php-src', [SourcePatcher::class, 'patchPhpLibxml212']);
|
||||
@@ -105,7 +105,7 @@ class SourcePatcher
|
||||
* @throws RuntimeException
|
||||
* @throws FileSystemException
|
||||
*/
|
||||
public static function patchMicro(string $name = '', string $target = '', ?array $items = null): bool
|
||||
public static function patchMicro(?array $items = null): bool
|
||||
{
|
||||
if (!file_exists(SOURCE_PATH . '/php-src/sapi/micro/php_micro.c')) {
|
||||
return false;
|
||||
@@ -152,11 +152,7 @@ class SourcePatcher
|
||||
|
||||
foreach ($patches as $patch) {
|
||||
logger()->info("Patching micro with {$patch}");
|
||||
$patchesStr = str_replace('/', DIRECTORY_SEPARATOR, $patch);
|
||||
f_passthru(
|
||||
'cd ' . SOURCE_PATH . '/php-src && ' .
|
||||
(PHP_OS_FAMILY === 'Windows' ? 'type' : 'cat') . ' ' . $patchesStr . ' | patch -p1 '
|
||||
);
|
||||
self::patchFile(SOURCE_PATH . "/php-src/{$patch}", SOURCE_PATH . '/php-src');
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -165,24 +161,32 @@ class SourcePatcher
|
||||
/**
|
||||
* Use existing patch file for patching
|
||||
*
|
||||
* @param string $patch_name Patch file name in src/globals/patch/
|
||||
* @param string $patch_name Patch file name in src/globals/patch/ or absolute path
|
||||
* @param string $cwd Working directory for patch command
|
||||
* @param bool $reverse Reverse patches (default: False)
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public static function patchFile(string $patch_name, string $cwd, bool $reverse = false): bool
|
||||
{
|
||||
if (!file_exists(ROOT_DIR . "/src/globals/patch/{$patch_name}")) {
|
||||
if (FileSystem::isRelativePath($patch_name)) {
|
||||
$patch_file = ROOT_DIR . "/src/globals/patch/{$patch_name}";
|
||||
} else {
|
||||
$patch_file = $patch_name;
|
||||
}
|
||||
if (!file_exists($patch_file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$patch_file = ROOT_DIR . "/src/globals/patch/{$patch_name}";
|
||||
$patch_str = str_replace('/', DIRECTORY_SEPARATOR, $patch_file);
|
||||
$patch_str = FileSystem::convertPath($patch_file);
|
||||
if (!file_exists($patch_str)) {
|
||||
throw new RuntimeException("Patch file [{$patch_str}] does not exist");
|
||||
}
|
||||
|
||||
// Copy patch from phar
|
||||
if (\Phar::running() !== '') {
|
||||
file_put_contents(SOURCE_PATH . '/' . $patch_name, file_get_contents($patch_file));
|
||||
$patch_str = str_replace('/', DIRECTORY_SEPARATOR, SOURCE_PATH . '/' . $patch_name);
|
||||
if (str_starts_with($patch_str, 'phar://')) {
|
||||
$filename = pathinfo($patch_file, PATHINFO_BASENAME);
|
||||
file_put_contents(SOURCE_PATH . "/{$filename}", file_get_contents($patch_file));
|
||||
$patch_str = FileSystem::convertPath(SOURCE_PATH . "/{$filename}");
|
||||
}
|
||||
|
||||
// detect
|
||||
@@ -456,7 +460,7 @@ class SourcePatcher
|
||||
|
||||
public static function patchFfiCentos7FixO3strncmp(): bool
|
||||
{
|
||||
if (PHP_OS_FAMILY !== 'Linux' || SystemUtil::getLibcVersionIfExists() > '2.17') {
|
||||
if (!($ver = SPCTarget::getLibcVersion()) || version_compare($ver, '2.17', '>')) {
|
||||
return false;
|
||||
}
|
||||
if (!file_exists(SOURCE_PATH . '/php-src/main/php_version.h')) {
|
||||
|
||||
@@ -7,7 +7,6 @@ namespace SPC\store\pkg;
|
||||
use SPC\store\Downloader;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\LockFile;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
|
||||
class GoXcaddy extends CustomPackage
|
||||
{
|
||||
@@ -62,7 +61,6 @@ class GoXcaddy extends CustomPackage
|
||||
|
||||
FileSystem::extractPackage($name, $source_type, $filename, $extract);
|
||||
|
||||
GlobalEnvManager::init();
|
||||
// install xcaddy
|
||||
shell()
|
||||
->appendEnv([
|
||||
|
||||
38
src/SPC/toolchain/ClangNativeToolchain.php
Normal file
38
src/SPC/toolchain/ClangNativeToolchain.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\toolchain;
|
||||
|
||||
use SPC\builder\freebsd\SystemUtil as FreeBSDSystemUtil;
|
||||
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
|
||||
use SPC\builder\macos\SystemUtil as MacOSSystemUtil;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
|
||||
class ClangNativeToolchain implements ToolchainInterface
|
||||
{
|
||||
public function initEnv(): void
|
||||
{
|
||||
GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_CC=clang');
|
||||
GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_CXX=clang++');
|
||||
GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_AR=ar');
|
||||
GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_LD=ld');
|
||||
}
|
||||
|
||||
public function afterInit(): void
|
||||
{
|
||||
foreach (['CC', 'CXX', 'AR', 'LD'] as $env) {
|
||||
$command = getenv($env);
|
||||
if (!$command || is_file($command)) {
|
||||
continue;
|
||||
}
|
||||
match (PHP_OS_FAMILY) {
|
||||
'Linux' => LinuxSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."),
|
||||
'Darwin' => MacOSSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."),
|
||||
'BSD' => FreeBSDSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."),
|
||||
default => throw new \RuntimeException(__CLASS__ . ' is not supported on ' . PHP_OS_FAMILY . '.'),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/SPC/toolchain/GccNativeToolchain.php
Normal file
38
src/SPC/toolchain/GccNativeToolchain.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\toolchain;
|
||||
|
||||
use SPC\builder\freebsd\SystemUtil as FreeBSDSystemUtil;
|
||||
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
|
||||
use SPC\builder\macos\SystemUtil as MacOSSystemUtil;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
|
||||
class GccNativeToolchain implements ToolchainInterface
|
||||
{
|
||||
public function initEnv(): void
|
||||
{
|
||||
GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_CC=gcc');
|
||||
GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_CXX=g++');
|
||||
GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_AR=ar');
|
||||
GlobalEnvManager::putenv('SPC_LINUX_DEFAULT_LD=ld.gold');
|
||||
}
|
||||
|
||||
public function afterInit(): void
|
||||
{
|
||||
foreach (['CC', 'CXX', 'AR', 'LD'] as $env) {
|
||||
$command = getenv($env);
|
||||
if (!$command || is_file($command)) {
|
||||
continue;
|
||||
}
|
||||
match (PHP_OS_FAMILY) {
|
||||
'Linux' => LinuxSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."),
|
||||
'Darwin' => MacOSSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."),
|
||||
'BSD' => FreeBSDSystemUtil::findCommand($command) ?? throw new WrongUsageException("{$command} not found, please install it or set {$env} to a valid path."),
|
||||
default => throw new \RuntimeException(__CLASS__ . ' is not supported on ' . PHP_OS_FAMILY . '.'),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/SPC/toolchain/MSVCToolchain.php
Normal file
12
src/SPC/toolchain/MSVCToolchain.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\toolchain;
|
||||
|
||||
class MSVCToolchain implements ToolchainInterface
|
||||
{
|
||||
public function initEnv(): void {}
|
||||
|
||||
public function afterInit(): void {}
|
||||
}
|
||||
39
src/SPC/toolchain/MuslToolchain.php
Normal file
39
src/SPC/toolchain/MuslToolchain.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\toolchain;
|
||||
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
|
||||
class MuslToolchain implements ToolchainInterface
|
||||
{
|
||||
public function initEnv(): void
|
||||
{
|
||||
$arch = getenv('GNU_ARCH');
|
||||
// Set environment variables for musl toolchain
|
||||
GlobalEnvManager::putenv("SPC_LINUX_DEFAULT_CC={$arch}-linux-musl-gcc");
|
||||
GlobalEnvManager::putenv("SPC_LINUX_DEFAULT_CXX={$arch}-linux-musl-g++");
|
||||
GlobalEnvManager::putenv("SPC_LINUX_DEFAULT_AR={$arch}-linux-musl-ar");
|
||||
GlobalEnvManager::putenv("SPC_LINUX_DEFAULT_LD={$arch}-linux-musl-ld");
|
||||
GlobalEnvManager::addPathIfNotExists('/usr/local/musl/bin');
|
||||
GlobalEnvManager::addPathIfNotExists("/usr/local/musl/{$arch}-linux-musl/bin");
|
||||
|
||||
GlobalEnvManager::putenv("SPC_LINUX_DEFAULT_LD_LIBRARY_PATH=/usr/local/musl/lib:/usr/local/musl/{$arch}-linux-musl/lib");
|
||||
GlobalEnvManager::putenv("SPC_LINUX_DEFAULT_LIBRARY_PATH=/usr/local/musl/lib:/usr/local/musl/{$arch}-linux-musl/lib");
|
||||
}
|
||||
|
||||
public function afterInit(): void
|
||||
{
|
||||
$arch = getenv('GNU_ARCH');
|
||||
// append LD_LIBRARY_PATH to $configure = getenv('SPC_CMD_PREFIX_PHP_CONFIGURE');
|
||||
$configure = getenv('SPC_CMD_PREFIX_PHP_CONFIGURE');
|
||||
$ld_library_path = getenv('SPC_LINUX_DEFAULT_LD_LIBRARY_PATH');
|
||||
GlobalEnvManager::putenv("SPC_CMD_PREFIX_PHP_CONFIGURE=LD_LIBRARY_PATH=\"{$ld_library_path}\" {$configure}");
|
||||
|
||||
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)');
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/SPC/toolchain/ToolchainInterface.php
Normal file
18
src/SPC/toolchain/ToolchainInterface.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\toolchain;
|
||||
|
||||
interface ToolchainInterface
|
||||
{
|
||||
/**
|
||||
* Initialize the environment for the given target.
|
||||
*/
|
||||
public function initEnv(): void;
|
||||
|
||||
/**
|
||||
* Perform actions after the environment has been initialized for the given target.
|
||||
*/
|
||||
public function afterInit(): void;
|
||||
}
|
||||
52
src/SPC/toolchain/ToolchainManager.php
Normal file
52
src/SPC/toolchain/ToolchainManager.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\toolchain;
|
||||
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
|
||||
class ToolchainManager
|
||||
{
|
||||
public const array OS_DEFAULT_TOOLCHAIN = [
|
||||
'Linux' => MuslToolchain::class, // use musl toolchain by default, after zig pr merged, change this to ZigToolchain::class
|
||||
'Windows' => MSVCToolchain::class,
|
||||
'Darwin' => ClangNativeToolchain::class,
|
||||
'BSD' => ClangNativeToolchain::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function initToolchain(): void
|
||||
{
|
||||
$libc = getenv('SPC_LIBC');
|
||||
if ($libc !== false) {
|
||||
// uncomment this when zig pr is merged
|
||||
// logger()->warning('SPC_LIBC is deprecated, please use SPC_TARGET instead.');
|
||||
$toolchain = match ($libc) {
|
||||
'musl' => SystemUtil::isMuslDist() ? GccNativeToolchain::class : MuslToolchain::class,
|
||||
'glibc' => !SystemUtil::isMuslDist() ? GccNativeToolchain::class : throw new WrongUsageException('SPC_TARGET must be musl-static or musl for musl dist.'),
|
||||
default => throw new WrongUsageException('Unsupported SPC_LIBC value: ' . $libc),
|
||||
};
|
||||
} else {
|
||||
$toolchain = self::OS_DEFAULT_TOOLCHAIN[PHP_OS_FAMILY];
|
||||
}
|
||||
$toolchainClass = $toolchain;
|
||||
/* @var ToolchainInterface $toolchainClass */
|
||||
(new $toolchainClass())->initEnv();
|
||||
GlobalEnvManager::putenv("SPC_TOOLCHAIN={$toolchain}");
|
||||
}
|
||||
|
||||
public static function afterInitToolchain(): void
|
||||
{
|
||||
if (!getenv('SPC_TOOLCHAIN')) {
|
||||
throw new WrongUsageException('SPC_TOOLCHAIN not set');
|
||||
}
|
||||
$toolchain = getenv('SPC_TOOLCHAIN');
|
||||
/* @var ToolchainInterface $toolchain */
|
||||
(new $toolchain())->afterInit();
|
||||
}
|
||||
}
|
||||
12
src/SPC/toolchain/ZigToolchain.php
Normal file
12
src/SPC/toolchain/ZigToolchain.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\toolchain;
|
||||
|
||||
class ZigToolchain implements ToolchainInterface
|
||||
{
|
||||
public function initEnv(): void {}
|
||||
|
||||
public function afterInit(): void {}
|
||||
}
|
||||
@@ -4,9 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\util;
|
||||
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\exception\RuntimeException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\toolchain\ToolchainManager;
|
||||
|
||||
/**
|
||||
* Environment variable manager
|
||||
@@ -40,24 +40,6 @@ class GlobalEnvManager
|
||||
self::putenv('PKG_CONFIG_PATH=' . BUILD_ROOT_PATH . '/lib/pkgconfig');
|
||||
}
|
||||
|
||||
// Define env vars for linux
|
||||
if (PHP_OS_FAMILY === 'Linux') {
|
||||
$arch = getenv('GNU_ARCH');
|
||||
if (SystemUtil::isMuslDist() || getenv('SPC_LIBC') === 'glibc') {
|
||||
self::putenv('SPC_LINUX_DEFAULT_CC=gcc');
|
||||
self::putenv('SPC_LINUX_DEFAULT_CXX=g++');
|
||||
self::putenv('SPC_LINUX_DEFAULT_AR=ar');
|
||||
self::putenv('SPC_LINUX_DEFAULT_LD=ld.gold');
|
||||
} else {
|
||||
self::putenv("SPC_LINUX_DEFAULT_CC={$arch}-linux-musl-gcc");
|
||||
self::putenv("SPC_LINUX_DEFAULT_CXX={$arch}-linux-musl-g++");
|
||||
self::putenv("SPC_LINUX_DEFAULT_AR={$arch}-linux-musl-ar");
|
||||
self::putenv("SPC_LINUX_DEFAULT_LD={$arch}-linux-musl-ld");
|
||||
self::addPathIfNotExists('/usr/local/musl/bin');
|
||||
self::addPathIfNotExists("/usr/local/musl/{$arch}-linux-musl/bin");
|
||||
}
|
||||
}
|
||||
|
||||
$ini = self::readIniFile();
|
||||
|
||||
$default_put_list = [];
|
||||
@@ -80,6 +62,9 @@ class GlobalEnvManager
|
||||
self::putenv("{$k}={$v}");
|
||||
}
|
||||
}
|
||||
|
||||
ToolchainManager::initToolchain();
|
||||
|
||||
// apply second time
|
||||
$ini2 = self::readIniFile();
|
||||
|
||||
@@ -108,13 +93,26 @@ class GlobalEnvManager
|
||||
self::$env_cache[] = $val;
|
||||
}
|
||||
|
||||
private static function addPathIfNotExists(string $path): void
|
||||
public static function addPathIfNotExists(string $path): void
|
||||
{
|
||||
if (is_unix() && !str_contains(getenv('PATH'), $path)) {
|
||||
self::putenv("PATH={$path}:" . getenv('PATH'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the toolchain after the environment variables are set.
|
||||
* The toolchain or environment availability check is done here.
|
||||
*
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function afterInit(): void
|
||||
{
|
||||
if (!filter_var(getenv('SPC_SKIP_TOOLCHAIN_CHECK'), FILTER_VALIDATE_BOOL)) {
|
||||
ToolchainManager::afterInitToolchain();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
|
||||
@@ -55,7 +55,7 @@ class SPCConfigUtil
|
||||
ob_get_clean();
|
||||
$ldflags = $this->getLdflagsString();
|
||||
$libs = $this->getLibsString($libraries, $with_dependencies);
|
||||
if (PHP_OS_FAMILY === 'Darwin') {
|
||||
if (SPCTarget::getTargetOS() === 'Darwin') {
|
||||
$libs .= " {$this->getFrameworksString($extensions)}";
|
||||
}
|
||||
$cflags = $this->getIncludesString();
|
||||
@@ -145,9 +145,8 @@ class SPCConfigUtil
|
||||
}
|
||||
}
|
||||
}
|
||||
// patch: imagick (imagemagick wrapper) for linux needs libgomp
|
||||
if (in_array('imagemagick', $libraries) && PHP_OS_FAMILY === 'Linux' && !(getenv('SPC_LIBC') === 'glibc' && str_contains(getenv('CC'), 'devtoolset-10'))) {
|
||||
$short_name[] = '-lgomp';
|
||||
if (in_array('imap', $libraries) && SPCTarget::getLibc() === 'glibc') {
|
||||
$short_name[] = '-lcrypt';
|
||||
}
|
||||
return implode(' ', $short_name);
|
||||
}
|
||||
|
||||
87
src/SPC/util/SPCTarget.php
Normal file
87
src/SPC/util/SPCTarget.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\util;
|
||||
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\exception\WrongUsageException;
|
||||
|
||||
/**
|
||||
* SPC build target constants and toolchain initialization.
|
||||
* format: {target_name}[-{libc_subtype}]
|
||||
*/
|
||||
class SPCTarget
|
||||
{
|
||||
public const array LIBC_LIST = [
|
||||
'musl',
|
||||
'glibc',
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns whether the target is a full-static target.
|
||||
*/
|
||||
public static function isStatic(): bool
|
||||
{
|
||||
$env = getenv('SPC_TARGET');
|
||||
$libc = getenv('SPC_LIBC');
|
||||
// if SPC_LIBC is set, it means the target is static, remove it when 3.0 is released
|
||||
if ($libc === 'musl') {
|
||||
return true;
|
||||
}
|
||||
// TODO: add zig target parser here
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the libc type if set, for other OS, it will always return null.
|
||||
*/
|
||||
public static function getLibc(): ?string
|
||||
{
|
||||
$env = getenv('SPC_TARGET');
|
||||
$libc = getenv('SPC_LIBC');
|
||||
if ($libc !== false) {
|
||||
return $libc;
|
||||
}
|
||||
// TODO: zig target parser
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the libc version if set, for other OS, it will always return null.
|
||||
*/
|
||||
public static function getLibcVersion(): ?string
|
||||
{
|
||||
$env = getenv('SPC_TARGET');
|
||||
$libc = getenv('SPC_LIBC');
|
||||
if ($libc !== false) {
|
||||
// legacy method: get a version from system
|
||||
return SystemUtil::getLibcVersionIfExists($libc);
|
||||
}
|
||||
// TODO: zig target parser
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target OS family, e.g. Linux, Darwin, Windows, BSD.
|
||||
* Currently, we only support native building.
|
||||
*
|
||||
* @return 'BSD'|'Darwin'|'Linux'|'Windows'
|
||||
* @throws WrongUsageException
|
||||
*/
|
||||
public static function getTargetOS(): string
|
||||
{
|
||||
$target = getenv('SPC_TARGET');
|
||||
if ($target === false) {
|
||||
return PHP_OS_FAMILY;
|
||||
}
|
||||
// TODO: zig target parser like below?
|
||||
return match (true) {
|
||||
str_contains($target, 'linux') => 'Linux',
|
||||
str_contains($target, 'macos') => 'Darwin',
|
||||
str_contains($target, 'windows') => 'Windows',
|
||||
default => throw new WrongUsageException('Cannot parse target.'),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -14,22 +14,22 @@ declare(strict_types=1);
|
||||
// test php version (8.1 ~ 8.4 available, multiple for matrix)
|
||||
$test_php_version = [
|
||||
'8.1',
|
||||
'8.2',
|
||||
'8.3',
|
||||
// '8.2',
|
||||
// '8.3',
|
||||
'8.4',
|
||||
];
|
||||
|
||||
// test os (macos-13, macos-14, macos-15, ubuntu-latest, windows-latest are available)
|
||||
$test_os = [
|
||||
// 'macos-13',
|
||||
// 'macos-14',
|
||||
// 'macos-15',
|
||||
// 'ubuntu-latest',
|
||||
// 'ubuntu-22.04',
|
||||
// 'ubuntu-24.04',
|
||||
// 'ubuntu-22.04-arm',
|
||||
// 'ubuntu-24.04-arm',
|
||||
'windows-latest',
|
||||
'macos-13', // bin/spc for x86_64
|
||||
// 'macos-14', // bin/spc for arm64
|
||||
'macos-15', // bin/spc for arm64
|
||||
'ubuntu-latest', // bin/spc-alpine-docker for x86_64
|
||||
'ubuntu-22.04', // bin/spc-gnu-docker for x86_64
|
||||
// 'ubuntu-24.04', // bin/spc for x86_64
|
||||
'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64
|
||||
// 'ubuntu-24.04-arm', // bin/spc for arm64
|
||||
// 'windows-latest', // .\bin\spc.ps1
|
||||
];
|
||||
|
||||
// whether enable thread safe
|
||||
@@ -44,23 +44,23 @@ $upx = false;
|
||||
$frankenphp = false;
|
||||
|
||||
// prefer downloading pre-built packages to speed up the build process
|
||||
$prefer_pre_built = true;
|
||||
$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' => 'curl',
|
||||
'Linux', 'Darwin' => 'imagick',
|
||||
'Windows' => 'intl',
|
||||
};
|
||||
|
||||
// If you want to test shared extensions, add them below (comma separated, example `bcmath,openssl`).
|
||||
$shared_extensions = match (PHP_OS_FAMILY) {
|
||||
'Linux' => 'uv',
|
||||
'Linux' => '',
|
||||
'Darwin' => '',
|
||||
'Windows' => '',
|
||||
};
|
||||
|
||||
// If you want to test lib-suggests for all extensions and libraries, set it to true.
|
||||
$with_suggested_libs = false;
|
||||
$with_suggested_libs = true;
|
||||
|
||||
// If you want to test extra libs for extensions, add them below (comma separated, example `libwebp,libavif`). Unnecessary, when $with_suggested_libs is true.
|
||||
$with_libs = match (PHP_OS_FAMILY) {
|
||||
|
||||
Reference in New Issue
Block a user