mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-03-17 20:34:51 +08:00
Compare commits
308 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4625c6a885 | ||
|
|
85b0cd8b4b | ||
|
|
1fcb74ad9b | ||
|
|
1049a3ce66 | ||
|
|
1b8b53d47f | ||
|
|
a232f578a4 | ||
|
|
70285cb53b | ||
|
|
a335d050cf | ||
|
|
ef4b2997a7 | ||
|
|
901da8fa41 | ||
|
|
e49a5d7a50 | ||
|
|
281b958075 | ||
|
|
e31f64864e | ||
|
|
92f5b56c74 | ||
|
|
2350d2d5ca | ||
|
|
086c855a43 | ||
|
|
4fa5292913 | ||
|
|
9634b8bcda | ||
|
|
5d5a50a33c | ||
|
|
1edf14e642 | ||
|
|
2277390a1a | ||
|
|
f93ad27c17 | ||
|
|
b690566b39 | ||
|
|
16e772e1a8 | ||
|
|
ad356b4a23 | ||
|
|
8c4e3d58a3 | ||
|
|
8a51d64685 | ||
|
|
055bc7bc3c | ||
|
|
7d7902e0e9 | ||
|
|
2a8fa7d155 | ||
|
|
67ef8f6608 | ||
|
|
d83a597689 | ||
|
|
5623fed37f | ||
|
|
38140d115f | ||
|
|
98117c3a04 | ||
|
|
b01d3ce12c | ||
|
|
608c915e14 | ||
|
|
c680299654 | ||
|
|
794ab16b32 | ||
|
|
661723c99a | ||
|
|
d9834d05c6 | ||
|
|
9a53ef3498 | ||
|
|
f680731f9d | ||
|
|
0fe1442f7e | ||
|
|
1e4780397b | ||
|
|
6b67cb90fc | ||
|
|
b89ff3c083 | ||
|
|
0cfa2036f0 | ||
|
|
c5882c1f8e | ||
|
|
4531c9fe57 | ||
|
|
223dd10ac6 | ||
|
|
1c28f0f455 | ||
|
|
b3c450291a | ||
|
|
372760e469 | ||
|
|
6cf4c40cd2 | ||
|
|
af75ffaf24 | ||
|
|
ae0217b3a1 | ||
|
|
1e2b4017ac | ||
|
|
19f941797e | ||
|
|
0b863cbc70 | ||
|
|
b09337de09 | ||
|
|
d902e70b4d | ||
|
|
cd2dc5bce4 | ||
|
|
34910d18e9 | ||
|
|
3a17cec521 | ||
|
|
94644d374f | ||
|
|
f8b0c2c980 | ||
|
|
6bbb3c969c | ||
|
|
76025b95c1 | ||
|
|
1be353fd13 | ||
|
|
54001ab868 | ||
|
|
890ff475f1 | ||
|
|
559a2909a9 | ||
|
|
fff2484529 | ||
|
|
d1b194999d | ||
|
|
64f7a3553e | ||
|
|
a06cc32491 | ||
|
|
022fdb2fc5 | ||
|
|
7688a55656 | ||
|
|
08388c0b15 | ||
|
|
e7a88f1df7 | ||
|
|
2f3122627e | ||
|
|
93a35908de | ||
|
|
5ef4623051 | ||
|
|
e952f1c76a | ||
|
|
09b89a30f9 | ||
|
|
9a681a9fa6 | ||
|
|
8650ce4f8f | ||
|
|
f7ca621efe | ||
|
|
6b5200002e | ||
|
|
53f7cdefe0 | ||
|
|
e1a14bbb9f | ||
|
|
9e051c8c80 | ||
|
|
e677be74d7 | ||
|
|
037d224fd7 | ||
|
|
ce44e00bd4 | ||
|
|
0247458853 | ||
|
|
656a58c3fa | ||
|
|
9fdfef5057 | ||
|
|
18c5ccfe9d | ||
|
|
d064e1353c | ||
|
|
3c89ce6c7f | ||
|
|
07ea1e2887 | ||
|
|
f0b5e4f59e | ||
|
|
a54021bf19 | ||
|
|
dce63d3c87 | ||
|
|
47ab5d7584 | ||
|
|
b2182b4fe1 | ||
|
|
1d5aec037b | ||
|
|
6b5f702719 | ||
|
|
7bdcda1d62 | ||
|
|
66840a8eed | ||
|
|
98773ee5a6 | ||
|
|
719d818fd1 | ||
|
|
b8444070ee | ||
|
|
5b4f4f8e55 | ||
|
|
22d263c0a8 | ||
|
|
150d866c15 | ||
|
|
c051a48d56 | ||
|
|
b965ffcd82 | ||
|
|
7f863d182f | ||
|
|
d1041c57dc | ||
|
|
14b822a185 | ||
|
|
7204d277b4 | ||
|
|
5a0fd40dc4 | ||
|
|
59a6e27532 | ||
|
|
6b3b841c0e | ||
|
|
e6591ffe9c | ||
|
|
e316971764 | ||
|
|
d55278714f | ||
|
|
cb7eca9049 | ||
|
|
5b8c9e6f09 | ||
|
|
5d1043334d | ||
|
|
f24cbcf909 | ||
|
|
76a07c32ba | ||
|
|
e0c69086dc | ||
|
|
5606b70c1c | ||
|
|
28ae4242a6 | ||
|
|
f14df1925c | ||
|
|
e9ad3c0011 | ||
|
|
e2ad31e858 | ||
|
|
af614cd7ce | ||
|
|
e21b0ec89d | ||
|
|
3069b51c09 | ||
|
|
1662ac4cf8 | ||
|
|
1e09017549 | ||
|
|
84e9f13688 | ||
|
|
2b0a0bdad9 | ||
|
|
e8d1970f55 | ||
|
|
6861e9c2c7 | ||
|
|
376b8e7569 | ||
|
|
875e1d05cd | ||
|
|
9382161b6f | ||
|
|
a1b8d201ae | ||
|
|
1fed8f2802 | ||
|
|
ecea6c12cd | ||
|
|
81dce02431 | ||
|
|
a33ca44ca9 | ||
|
|
aee733b51f | ||
|
|
54ceca8680 | ||
|
|
90981e3877 | ||
|
|
d69826eb4a | ||
|
|
dc83282019 | ||
|
|
23c0d6f4aa | ||
|
|
8e4d4b7be5 | ||
|
|
ee906aaff9 | ||
|
|
e2b80e7f03 | ||
|
|
09073c5517 | ||
|
|
00050f4d0e | ||
|
|
cff6ec17ea | ||
|
|
64079d9331 | ||
|
|
541889d17b | ||
|
|
c91128995d | ||
|
|
fd2b7af1dc | ||
|
|
081e2d2846 | ||
|
|
9edb9417a1 | ||
|
|
4ae4165ba2 | ||
|
|
e441a575ea | ||
|
|
1575016885 | ||
|
|
987ad4b846 | ||
|
|
f4b03ae835 | ||
|
|
d6de01d05c | ||
|
|
09b7159119 | ||
|
|
4198ddd5d1 | ||
|
|
8332ed87e0 | ||
|
|
f6b091498f | ||
|
|
a45f314447 | ||
|
|
8c8cb70174 | ||
|
|
f09c18e78f | ||
|
|
f5d93d2f54 | ||
|
|
7402fbf7c1 | ||
|
|
2c590e5895 | ||
|
|
463a98b1bf | ||
|
|
6d1c6d7f61 | ||
|
|
08362fb6e5 | ||
|
|
4d5641f6ec | ||
|
|
f34ecf9468 | ||
|
|
aa5c829fae | ||
|
|
fc118d709e | ||
|
|
589a4a9803 | ||
|
|
944e314bab | ||
|
|
0b17ce9e61 | ||
|
|
ed4978bb89 | ||
|
|
7a4f28e939 | ||
|
|
5cb6a75e7d | ||
|
|
757af25d8f | ||
|
|
5e3e7eccbf | ||
|
|
9738fcd6cd | ||
|
|
5a6a33303c | ||
|
|
ae15d6c5f5 | ||
|
|
ff15973a25 | ||
|
|
b88a68dab8 | ||
|
|
b05bdcd83d | ||
|
|
6a4ad34324 | ||
|
|
9a2d94cc33 | ||
|
|
f1d1d4fe10 | ||
|
|
fa6fa1c425 | ||
|
|
f8c8300c9c | ||
|
|
09198b431f | ||
|
|
f426ced789 | ||
|
|
bab330b64e | ||
|
|
b59a06face | ||
|
|
bb44e88c3b | ||
|
|
8649068159 | ||
|
|
5476385553 | ||
|
|
56bac35768 | ||
|
|
4cdc6a07ae | ||
|
|
c30b34ae5c | ||
|
|
da5c6fd084 | ||
|
|
a4b6499530 | ||
|
|
eb4445ea59 | ||
|
|
be51bcfdfc | ||
|
|
7bc4131c02 | ||
|
|
da8debdade | ||
|
|
ef5e664981 | ||
|
|
8e50af3a7e | ||
|
|
8e96c64918 | ||
|
|
8a9c8a279d | ||
|
|
72ca0cecd1 | ||
|
|
3564f6d0a7 | ||
|
|
d3e2b4b5b2 | ||
|
|
c6de6e7056 | ||
|
|
55322a282c | ||
|
|
6789ea81ff | ||
|
|
ac8a9af89c | ||
|
|
553b817b2a | ||
|
|
96592bce3e | ||
|
|
4e393886aa | ||
|
|
2e13be2a7a | ||
|
|
41fb29eba4 | ||
|
|
b519291fa2 | ||
|
|
dd752cd5be | ||
|
|
6a153f9aa0 | ||
|
|
bba390dbcc | ||
|
|
32efeb970c | ||
|
|
310335813f | ||
|
|
487980c9a8 | ||
|
|
f8801e224f | ||
|
|
5e229a0b01 | ||
|
|
49cfcbe92d | ||
|
|
4e4ce282db | ||
|
|
e2fd3e18d6 | ||
|
|
605c06f85c | ||
|
|
4cdefeab81 | ||
|
|
8ab09898f0 | ||
|
|
9c8b4d627c | ||
|
|
8923077120 | ||
|
|
29c31d90e5 | ||
|
|
e281d26a3a | ||
|
|
8ed68f481a | ||
|
|
b1abff61a5 | ||
|
|
15638cea4c | ||
|
|
9ed77c10e0 | ||
|
|
ccf262d202 | ||
|
|
4be894bc10 | ||
|
|
6440863ce4 | ||
|
|
25d7c72b6e | ||
|
|
dc4dd6ffa4 | ||
|
|
bf79134405 | ||
|
|
4f8b9d0f81 | ||
|
|
70bda268e5 | ||
|
|
e559dce9d5 | ||
|
|
6a98a6bf5e | ||
|
|
9b53133ba4 | ||
|
|
5b319b0df1 | ||
|
|
572bf919aa | ||
|
|
1d960a9084 | ||
|
|
4b28d1c2df | ||
|
|
9c8fd4d45d | ||
|
|
b62f029da7 | ||
|
|
c711a3666e | ||
|
|
487c6da4ac | ||
|
|
e942b13d73 | ||
|
|
26ccaa4449 | ||
|
|
f8d77b9b50 | ||
|
|
6594811536 | ||
|
|
cc7eb7cd84 | ||
|
|
330c3486af | ||
|
|
b9dfb5afe3 | ||
|
|
565ac87b65 | ||
|
|
f0c39c1770 | ||
|
|
896cf889e4 | ||
|
|
6b91570054 | ||
|
|
31906b36e5 | ||
|
|
4e2d4f3f05 | ||
|
|
ffdc2dc85a | ||
|
|
911bc74bf4 | ||
|
|
4d3501118e |
19
.github/workflows/build-unix.yml
vendored
19
.github/workflows/build-unix.yml
vendored
@ -46,6 +46,10 @@ on:
|
||||
description: Prefer pre-built binaries (reduce build time)
|
||||
type: boolean
|
||||
default: true
|
||||
with-suggested-libs:
|
||||
description: Build with suggested libs
|
||||
type: boolean
|
||||
default: false
|
||||
debug:
|
||||
description: Show full build logs
|
||||
type: boolean
|
||||
@ -86,6 +90,10 @@ on:
|
||||
description: Prefer pre-built binaries (reduce build time)
|
||||
type: boolean
|
||||
default: true
|
||||
with-suggested-libs:
|
||||
description: Include suggested libs
|
||||
type: boolean
|
||||
default: false
|
||||
debug:
|
||||
description: Show full build logs
|
||||
type: boolean
|
||||
@ -157,6 +165,9 @@ jobs:
|
||||
if [ ${{ inputs.prefer-pre-built }} == true ]; then
|
||||
DOWN_CMD="$DOWN_CMD --prefer-pre-built"
|
||||
fi
|
||||
if [ ${{ inputs.with-suggested-libs }} == true ]; then
|
||||
BUILD_CMD="$BUILD_CMD --with-suggested-libs"
|
||||
fi
|
||||
if [ ${{ inputs.build-cli }} == true ]; then
|
||||
BUILD_CMD="$BUILD_CMD --build-cli"
|
||||
fi
|
||||
@ -202,6 +213,14 @@ jobs:
|
||||
# if: ${{ failure() }}
|
||||
# uses: mxschmitt/action-tmate@v3
|
||||
|
||||
# Upload debug logs
|
||||
- if: ${{ inputs.debug && failure() }}
|
||||
name: "Upload build logs on failure"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: spc-logs-${{ inputs.php-version }}-${{ inputs.os }}
|
||||
path: log/*.log
|
||||
|
||||
# Upload cli executable
|
||||
- if: ${{ inputs.build-cli == true }}
|
||||
name: "Upload PHP cli SAPI"
|
||||
|
||||
8
.github/workflows/tests.yml
vendored
8
.github/workflows/tests.yml
vendored
@ -1,13 +1,9 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'src/globals/test-extensions.php'
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
types: [ opened, synchronize, reopened ]
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'config/**'
|
||||
@ -179,7 +175,7 @@ jobs:
|
||||
key: php-dependencies-${{ matrix.os }}
|
||||
|
||||
- name: "Install Dependencies"
|
||||
run: composer update -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
|
||||
run: composer update -vvv --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-plugins
|
||||
|
||||
- name: "Run Build Tests (doctor)"
|
||||
run: php src/globals/test-extensions.php doctor_cmd ${{ matrix.os }} ${{ matrix.php }}
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -22,6 +22,9 @@ docker/source/
|
||||
# default package root directory
|
||||
/pkgroot/**
|
||||
|
||||
# Windows PHP SDK binary tools
|
||||
/php-sdk-binary-tools/**
|
||||
|
||||
# default pack:lib and release directory
|
||||
/dist/**
|
||||
packlib_files.txt
|
||||
|
||||
@ -108,8 +108,7 @@ RUN apk update; \
|
||||
wget \
|
||||
xz \
|
||||
gettext-dev \
|
||||
binutils-gold \
|
||||
patchelf
|
||||
binutils-gold
|
||||
|
||||
RUN curl -#fSL https://dl.static-php.dev/static-php-cli/bulk/php-8.4.4-cli-linux-\$(uname -m).tar.gz | tar -xz -C /usr/local/bin && \
|
||||
chmod +x /usr/local/bin/php
|
||||
@ -150,6 +149,7 @@ MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/source:/app/source"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/dist:/app/dist"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/downloads:/app/downloads"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/pkgroot:/app/pkgroot"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/log:/app/log"
|
||||
if [ -f "$(pwd)/craft.yml" ]; then
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/craft.yml:/app/craft.yml"
|
||||
fi
|
||||
@ -161,6 +161,47 @@ if [ ! -z "$GITHUB_TOKEN" ]; then
|
||||
ENV_LIST="$ENV_LIST -e GITHUB_TOKEN=$GITHUB_TOKEN"
|
||||
fi
|
||||
|
||||
# Intercept and rewrite --with-frankenphp-app option, and mount host path to /app/app
|
||||
FRANKENPHP_APP_PATH=""
|
||||
NEW_ARGS=()
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--with-frankenphp-app=*)
|
||||
FRANKENPHP_APP_PATH="${1#*=}"
|
||||
NEW_ARGS+=("--with-frankenphp-app=/app/app")
|
||||
shift
|
||||
;;
|
||||
--with-frankenphp-app)
|
||||
if [ -n "${2:-}" ]; then
|
||||
FRANKENPHP_APP_PATH="$2"
|
||||
NEW_ARGS+=("--with-frankenphp-app=/app/app")
|
||||
shift 2
|
||||
else
|
||||
NEW_ARGS+=("$1")
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
NEW_ARGS+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Normalize the path and add mount if provided
|
||||
if [ -n "$FRANKENPHP_APP_PATH" ]; then
|
||||
# expand ~ to $HOME
|
||||
if [ "${FRANKENPHP_APP_PATH#~}" != "$FRANKENPHP_APP_PATH" ]; then
|
||||
FRANKENPHP_APP_PATH="$HOME${FRANKENPHP_APP_PATH#~}"
|
||||
fi
|
||||
# make absolute if relative
|
||||
case "$FRANKENPHP_APP_PATH" in
|
||||
/*) ABS_APP_PATH="$FRANKENPHP_APP_PATH" ;;
|
||||
*) ABS_APP_PATH="$(pwd)/$FRANKENPHP_APP_PATH" ;;
|
||||
esac
|
||||
MOUNT_LIST="$MOUNT_LIST -v $ABS_APP_PATH:/app/app"
|
||||
fi
|
||||
|
||||
# Run docker
|
||||
# shellcheck disable=SC2068
|
||||
# shellcheck disable=SC2086
|
||||
@ -182,5 +223,5 @@ if [ "$SPC_DOCKER_DEBUG" = "yes" ]; then
|
||||
set -ex
|
||||
$DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-$SPC_DOCKER_VERSION /bin/bash
|
||||
else
|
||||
$DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc $@
|
||||
$DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST $MOUNT_LIST cwcc-spc-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc "${NEW_ARGS[@]}"
|
||||
fi
|
||||
|
||||
@ -92,11 +92,6 @@ RUN echo "source scl_source enable devtoolset-10" >> /etc/bashrc
|
||||
RUN source /etc/bashrc
|
||||
RUN yum install -y which
|
||||
|
||||
RUN curl -fsSL -o patchelf.tgz https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0-$SPC_USE_ARCH.tar.gz && \
|
||||
mkdir -p /patchelf && \
|
||||
tar -xzf patchelf.tgz -C /patchelf --strip-components=1 && \
|
||||
cp /patchelf/bin/patchelf /usr/bin/
|
||||
|
||||
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
|
||||
@ -158,6 +153,7 @@ MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/source:/app/source"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/dist:/app/dist"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/downloads:/app/downloads"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/pkgroot:/app/pkgroot"
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/log:/app/log"
|
||||
if [ -f "$(pwd)/craft.yml" ]; then
|
||||
MOUNT_LIST="$MOUNT_LIST -v ""$(pwd)""/craft.yml:/app/craft.yml"
|
||||
fi
|
||||
@ -173,6 +169,47 @@ if [ ! -z "$GITHUB_TOKEN" ]; then
|
||||
ENV_LIST="$ENV_LIST -e GITHUB_TOKEN=$GITHUB_TOKEN"
|
||||
fi
|
||||
|
||||
# Intercept and rewrite --with-frankenphp-app option, and mount host path to /app/app
|
||||
FRANKENPHP_APP_PATH=""
|
||||
NEW_ARGS=()
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--with-frankenphp-app=*)
|
||||
FRANKENPHP_APP_PATH="${1#*=}"
|
||||
NEW_ARGS+=("--with-frankenphp-app=/app/app")
|
||||
shift
|
||||
;;
|
||||
--with-frankenphp-app)
|
||||
if [ -n "${2:-}" ]; then
|
||||
FRANKENPHP_APP_PATH="$2"
|
||||
NEW_ARGS+=("--with-frankenphp-app=/app/app")
|
||||
shift 2
|
||||
else
|
||||
NEW_ARGS+=("$1")
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
NEW_ARGS+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Normalize the path and add mount if provided
|
||||
if [ -n "$FRANKENPHP_APP_PATH" ]; then
|
||||
# expand ~ to $HOME
|
||||
if [ "${FRANKENPHP_APP_PATH#~}" != "$FRANKENPHP_APP_PATH" ]; then
|
||||
FRANKENPHP_APP_PATH="$HOME${FRANKENPHP_APP_PATH#~}"
|
||||
fi
|
||||
# make absolute if relative
|
||||
case "$FRANKENPHP_APP_PATH" in
|
||||
/*) ABS_APP_PATH="$FRANKENPHP_APP_PATH" ;;
|
||||
*) ABS_APP_PATH="$(pwd)/$FRANKENPHP_APP_PATH" ;;
|
||||
esac
|
||||
MOUNT_LIST="$MOUNT_LIST -v $ABS_APP_PATH:/app/app"
|
||||
fi
|
||||
|
||||
# Run docker
|
||||
# shellcheck disable=SC2068
|
||||
# shellcheck disable=SC2086
|
||||
@ -195,5 +232,5 @@ if [ "$SPC_DOCKER_DEBUG" = "yes" ]; then
|
||||
set -ex
|
||||
$DOCKER_EXECUTABLE run $PLATFORM_ARG --privileged --rm -it $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION /bin/bash
|
||||
else
|
||||
$DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc $@
|
||||
$DOCKER_EXECUTABLE run $PLATFORM_ARG --rm $INTERACT $ENV_LIST --env-file /tmp/spc-gnu-docker.env $MOUNT_LIST cwcc-spc-gnu-$SPC_USE_ARCH-$SPC_DOCKER_VERSION bin/spc "${NEW_ARGS[@]}"
|
||||
fi
|
||||
|
||||
679
composer.lock
generated
679
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,40 +1,41 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; static-php-cli (spc) env configuration
|
||||
;
|
||||
; This file is used to set default env vars for static-php-cli build.
|
||||
; As dynamic build process, some of these vars can be overwritten by CLI options.
|
||||
; And you can also overwrite these vars by setting them in your shell environment.
|
||||
; The value should be changed only if you know what you are doing. Otherwise, please leave them as default.
|
||||
;
|
||||
; We need to use some pre-defined internal env vars, like `BUILD_ROOT_PATH`, `DOWNLOAD_PATH`, etc.
|
||||
; Please note that these vars cannot be defined in this file, they are only be defined before static-php-cli running.
|
||||
; Please note that these vars cannot be defined in this file, they should only be defined before static-php-cli running.
|
||||
;
|
||||
; Here's a list of env vars, these value cannot be changed anywhere:
|
||||
; Here's a list of env vars, these variables will be defined if not defined:
|
||||
;
|
||||
; SPC_VERSION: the version of static-php-cli.
|
||||
; WORKING_DIR: the working directory of the build process. (default: `$(pwd)`)
|
||||
; ROOT_DIR: the root directory of static-php-cli. (default: `/path/to/static-php-cli`, when running in phar or micro mode: `phar://path/to/spc.phar`)
|
||||
; BUILD_ROOT_PATH: the root path of the build process. (default: `$(pwd)/buildroot`)
|
||||
; BUILD_INCLUDE_PATH: the path of the include files. (default: `$BUILD_ROOT_PATH/include`)
|
||||
; BUILD_LIB_PATH: the path of the lib files. (default: `$BUILD_ROOT_PATH/lib`)
|
||||
; BUILD_BIN_PATH: the path of the bin files. (default: `$BUILD_ROOT_PATH/bin`)
|
||||
; PKG_ROOT_PATH: the root path of the package files. (default: `$(pwd)/pkgroot`)
|
||||
; BUILD_MODULES_PATH: the path of the php modules (shared extensions) files. (default: `$BUILD_ROOT_PATH/modules`)
|
||||
; PKG_ROOT_PATH: the root path of the package files. (default: `$(pwd)/pkgroot/$GNU_ARCH-{darwin|linux|windows}`)
|
||||
; SOURCE_PATH: the path of the source files. (default: `$(pwd)/source`)
|
||||
; DOWNLOAD_PATH: the path of the download files. (default: `$(pwd)/downloads`)
|
||||
; CPU_COUNT: the count of the CPU cores. (default: `$(nproc)`)
|
||||
; SPC_ARCH: the arch of the current system, for some libraries needed `--host=XXX` args. (default: `$(uname -m)`, e.g. `x86_64`, `aarch64`, `arm64`)
|
||||
; GNU_ARCH: the GNU arch of the current system. (default: `$(uname -m)`, e.g. `x86_64`, `aarch64`)
|
||||
; MAC_ARCH: the MAC arch of the current system. (default: `$(uname -m)`, e.g. `x86_64`, `arm64`)
|
||||
; PATH: (*nix only) static-php-cli will add `$BUILD_BIN_PATH` to PATH.
|
||||
; PKG_CONFIG_PATH: (*nix only) static-php-cli will set `$BUILD_LIB_PATH/pkgconfig` to PKG_CONFIG_PATH.
|
||||
;
|
||||
; * These vars are only be defined in Unix (macOS, Linux, FreeBSD)Builder and cannot be changed anywhere:
|
||||
; PATH: static-php-cli will add `$BUILD_BIN_PATH` to PATH.
|
||||
; PKG_CONFIG: static-php-cli will set `$BUILD_BIN_PATH/pkg-config` to PKG_CONFIG.
|
||||
; PKG_CONFIG_PATH: static-php-cli will set `$BUILD_LIB_PATH/pkgconfig` to PKG_CONFIG_PATH.
|
||||
; Here's a list of env vars, these variables is defined in SPC and cannot be changed anywhere:
|
||||
;
|
||||
; * These vars are only be defined in LinuxBuilder and cannot be changed anywhere:
|
||||
; SPC_LINUX_DEFAULT_CC: the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`)
|
||||
; SPC_LINUX_DEFAULT_CXX: the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`)
|
||||
; SPC_LINUX_DEFAULT_AR: the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`)
|
||||
; SPC_EXTRA_PHP_VARS: the extra vars for building php, used in `configure` and `make` command.
|
||||
; SPC_VERSION: the version of static-php-cli.
|
||||
; WORKING_DIR: the working directory of the build process. (default: `$(pwd)`)
|
||||
; ROOT_DIR: the root directory of static-php-cli. (default: `/path/to/static-php-cli`, when running in phar or micro mode: `phar://path/to/spc.phar`)
|
||||
; CPU_COUNT: the count of the CPU cores. (default: `$(nproc)`)
|
||||
; SPC_ARCH: the arch of the current system, for some libraries needed `--host=XXX` args. (default: `$(uname -m)`, e.g. `x86_64`, `aarch64`, `arm64`)
|
||||
; GNU_ARCH: the GNU arch of the current system. (default: `$(uname -m)`, e.g. `x86_64`, `aarch64`)
|
||||
; MAC_ARCH: the MAC arch of the current system. (default: `$(uname -m)`, e.g. `x86_64`, `arm64`)
|
||||
; PKG_CONFIG: (*nix only) static-php-cli will set `$BUILD_BIN_PATH/pkg-config` to PKG_CONFIG.
|
||||
; SPC_LINUX_DEFAULT_CC: (linux only) the default compiler for linux. (For alpine linux: `gcc`, default: `$GNU_ARCH-linux-musl-gcc`)
|
||||
; SPC_LINUX_DEFAULT_CXX: (linux only) the default c++ compiler for linux. (For alpine linux: `g++`, default: `$GNU_ARCH-linux-musl-g++`)
|
||||
; SPC_LINUX_DEFAULT_AR: (linux only) the default archiver for linux. (For alpine linux: `ar`, default: `$GNU_ARCH-linux-musl-ar`)
|
||||
; SPC_EXTRA_PHP_VARS: (linux only) the extra vars for building php, used in `configure` and `make` command.
|
||||
|
||||
[global]
|
||||
; Build concurrency for make -jN, default is CPU_COUNT, this value are used in every libs.
|
||||
@ -44,7 +45,7 @@ SPC_SKIP_PHP_VERSION_CHECK="no"
|
||||
; Ignore some check item for bin/spc doctor command, comma separated (e.g. SPC_SKIP_DOCTOR_CHECK_ITEMS="if homebrew has installed")
|
||||
SPC_SKIP_DOCTOR_CHECK_ITEMS=""
|
||||
; extra modules that xcaddy will include in the FrankenPHP build
|
||||
SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES="--with github.com/dunglas/frankenphp/caddy --with github.com/dunglas/mercure/caddy --with github.com/dunglas/vulcain/caddy --with github.com/dunglas/caddy-cbrotli"
|
||||
SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES="--with github.com/dunglas/mercure/caddy --with github.com/dunglas/vulcain/caddy --with github.com/dunglas/caddy-cbrotli"
|
||||
; The display message for php version output (PHP >= 8.4 available)
|
||||
PHP_BUILD_PROVIDER="static-php-cli ${SPC_VERSION}"
|
||||
|
||||
@ -65,7 +66,7 @@ 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
|
||||
SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static,win32_api
|
||||
|
||||
[linux]
|
||||
; Linux can use different build toolchains.
|
||||
@ -74,8 +75,10 @@ SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime
|
||||
; - musl-native: used for alpine linux, can build `musl` and `musl -dynamic` target.
|
||||
; - gnu-native: used for general linux distros, can build gnu target for the installed glibc version only.
|
||||
|
||||
; LEGACY option to specify the target
|
||||
; option to specify the target, superceded by SPC_TARGET if set
|
||||
SPC_LIBC=musl
|
||||
; uncomment to link libc dynamically on musl
|
||||
; SPC_MUSL_DYNAMIC=true
|
||||
|
||||
; Recommended: specify your target here. Zig toolchain will be used.
|
||||
; examples:
|
||||
@ -105,19 +108,19 @@ SPC_MICRO_PATCHES=cli_checks,disable_huge_page
|
||||
SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force"
|
||||
; configure command
|
||||
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --disable-shared --enable-static --disable-all --disable-phpdbg --with-pic"
|
||||
; make command
|
||||
SPC_CMD_PREFIX_PHP_MAKE="make -j${SPC_CONCURRENCY}"
|
||||
|
||||
; *** default build vars for building php ***
|
||||
; embed type for php, static (libphp.a) or shared (libphp.so)
|
||||
SPC_CMD_VAR_PHP_EMBED_TYPE="static"
|
||||
; CFLAGS for configuring php
|
||||
SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS="${SPC_DEFAULT_C_FLAGS} -fPIE"
|
||||
; EXTRA_CFLAGS for `make` php
|
||||
; EXTRA_CFLAGS for `configure` and `make` php
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE ${SPC_DEFAULT_C_FLAGS}"
|
||||
; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=""
|
||||
|
||||
; optional, path to openssl conf. This affects where openssl will look for the default CA.
|
||||
; default on Debian/Alpine: /etc/ssl, default on RHEL: /etc/pki/tls
|
||||
OPENSSLDIR=""
|
||||
|
||||
[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.
|
||||
@ -139,16 +142,14 @@ SPC_MICRO_PATCHES=cli_checks,macos_iconv
|
||||
SPC_CMD_PREFIX_PHP_BUILDCONF="./buildconf --force"
|
||||
; configure command
|
||||
SPC_CMD_PREFIX_PHP_CONFIGURE="./configure --prefix= --with-valgrind=no --enable-shared=no --enable-static=yes --disable-all --disable-phpdbg"
|
||||
; make command
|
||||
SPC_CMD_PREFIX_PHP_MAKE="make -j${SPC_CONCURRENCY}"
|
||||
|
||||
; *** default build vars for building php ***
|
||||
; embed type for php, static (libphp.a) or shared (libphp.dylib)
|
||||
SPC_CMD_VAR_PHP_EMBED_TYPE="static"
|
||||
; CFLAGS for configuring php
|
||||
SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS="${SPC_DEFAULT_C_FLAGS} -Werror=unknown-warning-option"
|
||||
; EXTRA_CFLAGS for `make` php
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie ${SPC_DEFAULT_C_FLAGS}"
|
||||
; EXTRA_CFLAGS for `configure` and `make` php
|
||||
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie -Werror=unknown-warning-option ${SPC_DEFAULT_C_FLAGS}"
|
||||
; minimum compatible macOS version (LLVM vars, availability not guaranteed)
|
||||
MACOSX_DEPLOYMENT_TARGET=12.0
|
||||
|
||||
[freebsd]
|
||||
; compiler environments
|
||||
|
||||
140
config/ext.json
140
config/ext.json
@ -43,6 +43,14 @@
|
||||
"calendar": {
|
||||
"type": "builtin"
|
||||
},
|
||||
"com_dotnet": {
|
||||
"support": {
|
||||
"BSD": "no",
|
||||
"Linux": "no",
|
||||
"Darwin": "no"
|
||||
},
|
||||
"type": "builtin"
|
||||
},
|
||||
"ctype": {
|
||||
"type": "builtin"
|
||||
},
|
||||
@ -127,6 +135,14 @@
|
||||
"sockets"
|
||||
]
|
||||
},
|
||||
"excimer": {
|
||||
"support": {
|
||||
"Windows": "wip",
|
||||
"BSD": "wip"
|
||||
},
|
||||
"type": "external",
|
||||
"source": "ext-excimer"
|
||||
},
|
||||
"exif": {
|
||||
"type": "builtin"
|
||||
},
|
||||
@ -232,11 +248,14 @@
|
||||
"BSD": "wip"
|
||||
},
|
||||
"type": "external",
|
||||
"source": "grpc",
|
||||
"source": "ext-grpc",
|
||||
"arg-type-unix": "enable-path",
|
||||
"cpp-extension": true,
|
||||
"lib-depends": [
|
||||
"grpc"
|
||||
"grpc",
|
||||
"zlib",
|
||||
"openssl",
|
||||
"libcares"
|
||||
]
|
||||
},
|
||||
"iconv": {
|
||||
@ -341,6 +360,7 @@
|
||||
"ext-depends": [
|
||||
"xml"
|
||||
],
|
||||
"build-with-php": true,
|
||||
"target": [
|
||||
"static"
|
||||
]
|
||||
@ -357,6 +377,18 @@
|
||||
"liblz4"
|
||||
]
|
||||
},
|
||||
"maxminddb": {
|
||||
"support": {
|
||||
"BSD": "wip",
|
||||
"Windows": "wip"
|
||||
},
|
||||
"type": "external",
|
||||
"source": "ext-maxminddb",
|
||||
"arg-type": "with",
|
||||
"lib-depends": [
|
||||
"libmaxminddb"
|
||||
]
|
||||
},
|
||||
"mbregex": {
|
||||
"type": "builtin",
|
||||
"arg-type": "custom",
|
||||
@ -395,8 +427,7 @@
|
||||
"ext-depends": [
|
||||
"zlib",
|
||||
"session"
|
||||
],
|
||||
"build-with-php": true
|
||||
]
|
||||
},
|
||||
"memcached": {
|
||||
"support": {
|
||||
@ -453,7 +484,7 @@
|
||||
"type": "external",
|
||||
"source": "msgpack",
|
||||
"arg-type-unix": "with",
|
||||
"arg-type-win": "enable",
|
||||
"arg-type-windows": "enable",
|
||||
"ext-depends": [
|
||||
"session"
|
||||
]
|
||||
@ -461,6 +492,7 @@
|
||||
"mysqli": {
|
||||
"type": "builtin",
|
||||
"arg-type": "with",
|
||||
"build-with-php": true,
|
||||
"ext-depends": [
|
||||
"mysqlnd"
|
||||
]
|
||||
@ -468,10 +500,45 @@
|
||||
"mysqlnd": {
|
||||
"type": "builtin",
|
||||
"arg-type-windows": "with",
|
||||
"build-with-php": true,
|
||||
"lib-depends": [
|
||||
"zlib"
|
||||
]
|
||||
},
|
||||
"mysqlnd_ed25519": {
|
||||
"type": "external",
|
||||
"source": "mysqlnd_ed25519",
|
||||
"arg-type": "enable",
|
||||
"target": [
|
||||
"shared"
|
||||
],
|
||||
"ext-depends": [
|
||||
"mysqlnd"
|
||||
],
|
||||
"lib-depends": [
|
||||
"libsodium"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"openssl"
|
||||
]
|
||||
},
|
||||
"mysqlnd_parsec": {
|
||||
"type": "external",
|
||||
"source": "mysqlnd_parsec",
|
||||
"arg-type": "enable",
|
||||
"target": [
|
||||
"shared"
|
||||
],
|
||||
"ext-depends": [
|
||||
"mysqlnd"
|
||||
],
|
||||
"lib-depends": [
|
||||
"libsodium"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"openssl"
|
||||
]
|
||||
},
|
||||
"oci8": {
|
||||
"type": "wip",
|
||||
"support": {
|
||||
@ -552,6 +619,13 @@
|
||||
"type": "builtin",
|
||||
"unix-only": true
|
||||
},
|
||||
"pcov": {
|
||||
"type": "external",
|
||||
"source": "pcov",
|
||||
"target": [
|
||||
"shared"
|
||||
]
|
||||
},
|
||||
"pdo": {
|
||||
"type": "builtin"
|
||||
},
|
||||
@ -687,7 +761,7 @@
|
||||
"type": "builtin",
|
||||
"arg-type": "with-path",
|
||||
"lib-depends": [
|
||||
"readline"
|
||||
"libedit"
|
||||
],
|
||||
"target": [
|
||||
"static"
|
||||
@ -753,6 +827,18 @@
|
||||
"apcu"
|
||||
]
|
||||
},
|
||||
"snmp": {
|
||||
"support": {
|
||||
"Windows": "wip",
|
||||
"BSD": "wip"
|
||||
},
|
||||
"type": "builtin",
|
||||
"arg-type-unix": "with",
|
||||
"arg-type-windows": "with",
|
||||
"lib-depends": [
|
||||
"net-snmp"
|
||||
]
|
||||
},
|
||||
"soap": {
|
||||
"support": {
|
||||
"BSD": "wip"
|
||||
@ -797,6 +883,7 @@
|
||||
"type": "builtin",
|
||||
"arg-type": "with-path",
|
||||
"arg-type-windows": "with",
|
||||
"build-with-php": true,
|
||||
"lib-depends": [
|
||||
"sqlite"
|
||||
]
|
||||
@ -885,6 +972,22 @@
|
||||
"mysqli"
|
||||
]
|
||||
},
|
||||
"swoole-hook-odbc": {
|
||||
"support": {
|
||||
"Windows": "no",
|
||||
"BSD": "wip"
|
||||
},
|
||||
"notes": true,
|
||||
"type": "addon",
|
||||
"arg-type": "none",
|
||||
"ext-depends": [
|
||||
"pdo",
|
||||
"swoole"
|
||||
],
|
||||
"lib-depends": [
|
||||
"unixodbc"
|
||||
]
|
||||
},
|
||||
"swoole-hook-pgsql": {
|
||||
"support": {
|
||||
"Windows": "no",
|
||||
@ -914,22 +1017,6 @@
|
||||
"swoole"
|
||||
]
|
||||
},
|
||||
"swoole-hook-odbc": {
|
||||
"support": {
|
||||
"Windows": "no",
|
||||
"BSD": "wip"
|
||||
},
|
||||
"notes": true,
|
||||
"type": "addon",
|
||||
"arg-type": "none",
|
||||
"ext-depends": [
|
||||
"pdo",
|
||||
"swoole"
|
||||
],
|
||||
"lib-depends": [
|
||||
"unixodbc"
|
||||
]
|
||||
},
|
||||
"swow": {
|
||||
"support": {
|
||||
"BSD": "wip"
|
||||
@ -984,6 +1071,14 @@
|
||||
"type": "builtin",
|
||||
"build-with-php": true
|
||||
},
|
||||
"trader": {
|
||||
"support": {
|
||||
"BSD": "wip",
|
||||
"Windows": "wip"
|
||||
},
|
||||
"type": "external",
|
||||
"source": "ext-trader"
|
||||
},
|
||||
"uuid": {
|
||||
"support": {
|
||||
"Windows": "wip",
|
||||
@ -1177,6 +1272,7 @@
|
||||
"lib-depends": [
|
||||
"zlib"
|
||||
],
|
||||
"build-with-php": true,
|
||||
"target": [
|
||||
"static"
|
||||
]
|
||||
|
||||
166
config/lib.json
166
config/lib.json
@ -7,12 +7,14 @@
|
||||
"source": "php-src",
|
||||
"lib-depends": [
|
||||
"lib-base",
|
||||
"micro"
|
||||
"micro",
|
||||
"frankenphp"
|
||||
],
|
||||
"lib-depends-macos": [
|
||||
"lib-base",
|
||||
"micro",
|
||||
"libxml2"
|
||||
"libxml2",
|
||||
"frankenphp"
|
||||
],
|
||||
"lib-suggests-linux": [
|
||||
"libacl",
|
||||
@ -24,6 +26,10 @@
|
||||
"watcher"
|
||||
]
|
||||
},
|
||||
"frankenphp": {
|
||||
"source": "frankenphp",
|
||||
"type": "target"
|
||||
},
|
||||
"micro": {
|
||||
"type": "target",
|
||||
"source": "micro"
|
||||
@ -98,7 +104,9 @@
|
||||
"ngtcp2",
|
||||
"zstd",
|
||||
"libcares",
|
||||
"ldap"
|
||||
"ldap",
|
||||
"idn2",
|
||||
"krb5"
|
||||
],
|
||||
"lib-suggests-windows": [
|
||||
"brotli",
|
||||
@ -203,7 +211,6 @@
|
||||
"libcares"
|
||||
],
|
||||
"cpp-library": true,
|
||||
"provide-pre-built": true,
|
||||
"frameworks": [
|
||||
"CoreFoundation"
|
||||
]
|
||||
@ -229,6 +236,24 @@
|
||||
"unicode"
|
||||
]
|
||||
},
|
||||
"idn2": {
|
||||
"source": "libidn2",
|
||||
"pkg-configs": [
|
||||
"libidn2"
|
||||
],
|
||||
"headers": [
|
||||
"idn2.h"
|
||||
],
|
||||
"lib-suggests-unix": [
|
||||
"libiconv",
|
||||
"gettext",
|
||||
"libunistring"
|
||||
],
|
||||
"lib-depends-macos": [
|
||||
"libiconv",
|
||||
"gettext"
|
||||
]
|
||||
},
|
||||
"imagemagick": {
|
||||
"source": "imagemagick",
|
||||
"cpp-library": true,
|
||||
@ -276,6 +301,26 @@
|
||||
"jbig_ar.h"
|
||||
]
|
||||
},
|
||||
"krb5": {
|
||||
"source": "krb5",
|
||||
"pkg-configs": [
|
||||
"krb5-gssapi"
|
||||
],
|
||||
"headers": [
|
||||
"krb5.h",
|
||||
"gssapi/gssapi.h"
|
||||
],
|
||||
"lib-depends": [
|
||||
"openssl"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"ldap",
|
||||
"libedit"
|
||||
],
|
||||
"frameworks": [
|
||||
"Kerberos"
|
||||
]
|
||||
},
|
||||
"ldap": {
|
||||
"source": "ldap",
|
||||
"pkg-configs": [
|
||||
@ -316,6 +361,9 @@
|
||||
"source": "libargon2",
|
||||
"static-libs-unix": [
|
||||
"libargon2.a"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"libsodium"
|
||||
]
|
||||
},
|
||||
"libavif": {
|
||||
@ -325,6 +373,15 @@
|
||||
],
|
||||
"static-libs-windows": [
|
||||
"avif.lib"
|
||||
],
|
||||
"lib-depends": [
|
||||
"libaom"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"libwebp",
|
||||
"libjpeg",
|
||||
"libxml2",
|
||||
"libpng"
|
||||
]
|
||||
},
|
||||
"libcares": {
|
||||
@ -345,6 +402,15 @@
|
||||
],
|
||||
"cpp-library": true
|
||||
},
|
||||
"libedit": {
|
||||
"source": "libedit",
|
||||
"static-libs-unix": [
|
||||
"libedit.a"
|
||||
],
|
||||
"lib-depends": [
|
||||
"ncurses"
|
||||
]
|
||||
},
|
||||
"libevent": {
|
||||
"source": "libevent",
|
||||
"static-libs-unix": [
|
||||
@ -452,6 +518,16 @@
|
||||
"liblz4.a"
|
||||
]
|
||||
},
|
||||
"libmaxminddb": {
|
||||
"source": "libmaxminddb",
|
||||
"static-libs-unix": [
|
||||
"libmaxminddb.a"
|
||||
],
|
||||
"headers": [
|
||||
"maxminddb.h",
|
||||
"maxminddb_config.h"
|
||||
]
|
||||
},
|
||||
"libmemcached": {
|
||||
"source": "libmemcached",
|
||||
"cpp-library": true,
|
||||
@ -498,13 +574,16 @@
|
||||
},
|
||||
"librdkafka": {
|
||||
"source": "librdkafka",
|
||||
"static-libs-unix": [
|
||||
"librdkafka.a",
|
||||
"librdkafka++.a",
|
||||
"librdkafka-static.a"
|
||||
"pkg-configs": [
|
||||
"rdkafka++-static",
|
||||
"rdkafka-static"
|
||||
],
|
||||
"cpp-library": true,
|
||||
"lib-suggests": [
|
||||
"curl",
|
||||
"liblz4",
|
||||
"openssl",
|
||||
"zlib",
|
||||
"zstd"
|
||||
]
|
||||
},
|
||||
@ -551,6 +630,31 @@
|
||||
"zstd"
|
||||
]
|
||||
},
|
||||
"libunistring": {
|
||||
"source": "libunistring",
|
||||
"static-libs-unix": [
|
||||
"libunistring.a"
|
||||
],
|
||||
"headers": [
|
||||
"unistr.h",
|
||||
"unistring/"
|
||||
]
|
||||
},
|
||||
"liburing": {
|
||||
"source": "liburing",
|
||||
"pkg-configs": [
|
||||
"liburing",
|
||||
"liburing-ffi"
|
||||
],
|
||||
"static-libs-linux": [
|
||||
"liburing.a",
|
||||
"liburing-ffi.a"
|
||||
],
|
||||
"headers-linux": [
|
||||
"liburing/",
|
||||
"liburing.h"
|
||||
]
|
||||
},
|
||||
"libuuid": {
|
||||
"source": "libuuid",
|
||||
"static-libs-unix": [
|
||||
@ -584,8 +688,8 @@
|
||||
},
|
||||
"libxml2": {
|
||||
"source": "libxml2",
|
||||
"static-libs-unix": [
|
||||
"libxml2.a"
|
||||
"pkg-configs": [
|
||||
"libxml-2.0"
|
||||
],
|
||||
"static-libs-windows": [
|
||||
"libxml2s.lib",
|
||||
@ -674,6 +778,17 @@
|
||||
"libncurses.a"
|
||||
]
|
||||
},
|
||||
"net-snmp": {
|
||||
"source": "net-snmp",
|
||||
"pkg-configs": [
|
||||
"netsnmp",
|
||||
"netsnmp-agent"
|
||||
],
|
||||
"lib-depends": [
|
||||
"openssl",
|
||||
"zlib"
|
||||
]
|
||||
},
|
||||
"nghttp2": {
|
||||
"source": "nghttp2",
|
||||
"static-libs-unix": [
|
||||
@ -747,6 +862,9 @@
|
||||
},
|
||||
"openssl": {
|
||||
"source": "openssl",
|
||||
"pkg-configs": [
|
||||
"openssl"
|
||||
],
|
||||
"static-libs-unix": [
|
||||
"libssl.a",
|
||||
"libcrypto.a"
|
||||
@ -772,7 +890,7 @@
|
||||
"libxml2",
|
||||
"openssl",
|
||||
"zlib",
|
||||
"readline"
|
||||
"libedit"
|
||||
],
|
||||
"lib-suggests": [
|
||||
"icu",
|
||||
@ -859,6 +977,11 @@
|
||||
},
|
||||
"unixodbc": {
|
||||
"source": "unixodbc",
|
||||
"pkg-configs": [
|
||||
"odbc",
|
||||
"odbccr",
|
||||
"odbcinst"
|
||||
],
|
||||
"static-libs-unix": [
|
||||
"libodbc.a",
|
||||
"libodbccr.a",
|
||||
@ -900,6 +1023,9 @@
|
||||
},
|
||||
"zlib": {
|
||||
"source": "zlib",
|
||||
"pkg-configs": [
|
||||
"zlib"
|
||||
],
|
||||
"static-libs-unix": [
|
||||
"libz.a"
|
||||
],
|
||||
@ -913,6 +1039,9 @@
|
||||
},
|
||||
"zstd": {
|
||||
"source": "zstd",
|
||||
"pkg-configs": [
|
||||
"libzstd"
|
||||
],
|
||||
"static-libs-unix": [
|
||||
"libzstd.a"
|
||||
],
|
||||
@ -931,20 +1060,5 @@
|
||||
"zstd.h",
|
||||
"zstd_errors.h"
|
||||
]
|
||||
},
|
||||
"liburing": {
|
||||
"source": "liburing",
|
||||
"pkg-configs": [
|
||||
"liburing",
|
||||
"liburing-ffi"
|
||||
],
|
||||
"static-libs-linux": [
|
||||
"liburing.a",
|
||||
"liburing-ffi.a"
|
||||
],
|
||||
"headers-linux": [
|
||||
"liburing/",
|
||||
"liburing.h"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,8 +23,8 @@
|
||||
"type": "url",
|
||||
"url": "https://dl.static-php.dev/static-php-cli/deps/nasm/nasm-2.16.01-win64.zip",
|
||||
"extract-files": {
|
||||
"nasm-2.16.01/nasm.exe": "{php_sdk_path}/bin/nasm.exe",
|
||||
"nasm-2.16.01/ndisasm.exe": "{php_sdk_path}/bin/ndisasm.exe"
|
||||
"nasm.exe": "{php_sdk_path}/bin/nasm.exe",
|
||||
"ndisasm.exe": "{php_sdk_path}/bin/ndisasm.exe"
|
||||
}
|
||||
},
|
||||
"pkg-config-aarch64-linux": {
|
||||
@ -84,7 +84,7 @@
|
||||
"repo": "upx/upx",
|
||||
"match": "upx.+-win64\\.zip",
|
||||
"extract-files": {
|
||||
"upx-*-win64/upx.exe": "{pkg_root_path}/bin/upx.exe"
|
||||
"upx.exe": "{pkg_root_path}/bin/upx.exe"
|
||||
}
|
||||
},
|
||||
"zig-aarch64-linux": {
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "doc/COPYING"
|
||||
"path": "doc/COPYING.LGPL"
|
||||
}
|
||||
},
|
||||
"brotli": {
|
||||
@ -126,13 +126,23 @@
|
||||
},
|
||||
"ext-event": {
|
||||
"type": "url",
|
||||
"url": "https://bitbucket.org/osmanov/pecl-event/get/3.0.8.tar.gz",
|
||||
"url": "https://bitbucket.org/osmanov/pecl-event/get/3.1.4.tar.gz",
|
||||
"path": "php-src/ext/event",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"ext-excimer": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/excimer",
|
||||
"path": "php-src/ext/excimer",
|
||||
"filename": "excimer.tgz",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"ext-glfw": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mario-deluna/php-glfw",
|
||||
@ -151,6 +161,18 @@
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"ext-grpc": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/grpc",
|
||||
"path": "php-src/ext/grpc",
|
||||
"filename": "grpc.tgz",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": [
|
||||
"LICENSE"
|
||||
]
|
||||
}
|
||||
},
|
||||
"ext-imagick": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/imagick",
|
||||
@ -184,6 +206,15 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"ext-maxminddb": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/maxminddb",
|
||||
"filename": "ext-maxminddb.tgz",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"ext-memcache": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/memcache",
|
||||
@ -233,6 +264,16 @@
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"ext-trader": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/trader",
|
||||
"path": "php-src/ext/trader",
|
||||
"filename": "trader.tgz",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"ext-uuid": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/uuid",
|
||||
@ -291,10 +332,19 @@
|
||||
"path": "LICENSE.MIT"
|
||||
}
|
||||
},
|
||||
"frankenphp": {
|
||||
"type": "ghtar",
|
||||
"repo": "php/frankenphp",
|
||||
"prefer-stable": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"freetype": {
|
||||
"type": "git",
|
||||
"rev": "VER-2-13-2",
|
||||
"url": "https://github.com/freetype/freetype",
|
||||
"type": "ghtagtar",
|
||||
"repo": "freetype/freetype",
|
||||
"match": "VER-2-\\d+-\\d+",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE.TXT"
|
||||
@ -306,16 +356,17 @@
|
||||
"regex": "/href=\"(?<file>gettext-(?<version>[^\"]+)\\.tar\\.xz)\"/",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
"path": "gettext-runtime/intl/COPYING.LIB"
|
||||
}
|
||||
},
|
||||
"gmp": {
|
||||
"type": "url",
|
||||
"url": "https://dl.static-php.dev/static-php-cli/deps/gmp/gmp-6.3.0.tar.xz",
|
||||
"type": "filelist",
|
||||
"url": "https://ftp.gnu.org/gnu/gmp/",
|
||||
"regex": "/href=\"(?<file>gmp-(?<version>[^\"]+)\\.tar\\.xz)\"/",
|
||||
"provide-pre-built": true,
|
||||
"alt": {
|
||||
"type": "ghtagtar",
|
||||
"repo": "alisw/GMP"
|
||||
"type": "url",
|
||||
"url": "https://dl.static-php.dev/static-php-cli/deps/gmp/gmp-6.3.0.tar.xz"
|
||||
},
|
||||
"license": {
|
||||
"type": "text",
|
||||
@ -410,6 +461,16 @@
|
||||
"path": "COPYING"
|
||||
}
|
||||
},
|
||||
"krb5": {
|
||||
"type": "ghtagtar",
|
||||
"repo": "krb5/krb5",
|
||||
"match": "krb5.+-final",
|
||||
"prefer-stable": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "NOTICE"
|
||||
}
|
||||
},
|
||||
"ldap": {
|
||||
"type": "filelist",
|
||||
"url": "https://www.openldap.org/software/download/OpenLDAP/openldap-release/",
|
||||
@ -439,7 +500,7 @@
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "doc/COPYING"
|
||||
"path": "doc/COPYING.LGPL"
|
||||
}
|
||||
},
|
||||
"libaom": {
|
||||
@ -465,7 +526,7 @@
|
||||
"libavif": {
|
||||
"type": "ghtar",
|
||||
"repo": "AOMediaCodec/libavif",
|
||||
"provide-pre-built": true,
|
||||
"provide-pre-built": false,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
@ -498,6 +559,16 @@
|
||||
"path": "COPYING"
|
||||
}
|
||||
},
|
||||
"libedit": {
|
||||
"type": "filelist",
|
||||
"url": "https://thrysoee.dk/editline/",
|
||||
"regex": "/href=\"(?<file>libedit-(?<version>[^\"]+)\\.tar\\.gz)\"/",
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
}
|
||||
},
|
||||
"libevent": {
|
||||
"type": "ghrel",
|
||||
"repo": "libevent/libevent",
|
||||
@ -546,7 +617,7 @@
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
"path": "COPYING.LIB"
|
||||
}
|
||||
},
|
||||
"libiconv-win": {
|
||||
@ -558,6 +629,15 @@
|
||||
"path": "source/COPYING"
|
||||
}
|
||||
},
|
||||
"libidn2": {
|
||||
"type": "filelist",
|
||||
"url": "https://ftp.gnu.org/gnu/libidn/",
|
||||
"regex": "/href=\"(?<file>libidn2-(?<version>[^\"]+)\\.tar\\.gz)\"/",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING.LESSERv3"
|
||||
}
|
||||
},
|
||||
"libjpeg": {
|
||||
"type": "ghtar",
|
||||
"repo": "libjpeg-turbo/libjpeg-turbo",
|
||||
@ -592,6 +672,16 @@
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"libmaxminddb": {
|
||||
"type": "ghrel",
|
||||
"repo": "maxmind/libmaxminddb",
|
||||
"match": "libmaxminddb-.+\\.tar\\.gz",
|
||||
"prefer-stable": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"libmemcached": {
|
||||
"type": "ghtagtar",
|
||||
"repo": "awesomized/libmemcached",
|
||||
@ -602,9 +692,10 @@
|
||||
}
|
||||
},
|
||||
"libpng": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/glennrp/libpng.git",
|
||||
"rev": "libpng16",
|
||||
"type": "ghtagtar",
|
||||
"repo": "pnggroup/libpng",
|
||||
"match": "v1\\.6\\.\\d+",
|
||||
"query": "?per_page=150",
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
@ -612,9 +703,9 @@
|
||||
}
|
||||
},
|
||||
"librabbitmq": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/alanxz/rabbitmq-c.git",
|
||||
"rev": "master",
|
||||
"type": "ghtar",
|
||||
"repo": "alanxz/rabbitmq-c",
|
||||
"prefer-stable": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
@ -631,7 +722,7 @@
|
||||
"libsodium": {
|
||||
"type": "ghrel",
|
||||
"repo": "jedisct1/libsodium",
|
||||
"match": "libsodium-\\d+(\\.\\d+)*\\.tar\\.gz",
|
||||
"match": "libsodium-(?!1\\.0\\.21)\\d+(\\.\\d+)*\\.tar\\.gz",
|
||||
"prefer-stable": true,
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
@ -659,10 +750,30 @@
|
||||
"path": "LICENSE.md"
|
||||
}
|
||||
},
|
||||
"libunistring": {
|
||||
"type": "filelist",
|
||||
"url": "https://ftp.gnu.org/gnu/libunistring/",
|
||||
"regex": "/href=\"(?<file>libunistring-(?<version>[^\"]+)\\.tar\\.gz)\"/",
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING.LIB"
|
||||
}
|
||||
},
|
||||
"liburing": {
|
||||
"type": "ghtar",
|
||||
"repo": "axboe/liburing",
|
||||
"prefer-stable": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
}
|
||||
},
|
||||
"libuuid": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/static-php/libuuid.git",
|
||||
"rev": "master",
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
@ -683,8 +794,9 @@
|
||||
]
|
||||
},
|
||||
"libwebp": {
|
||||
"type": "url",
|
||||
"url": "https://github.com/webmproject/libwebp/archive/refs/tags/v1.3.2.tar.gz",
|
||||
"type": "ghtagtar",
|
||||
"repo": "webmproject/libwebp",
|
||||
"match": "v1\\.\\d+\\.\\d+$",
|
||||
"provide-pre-built": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
@ -692,8 +804,10 @@
|
||||
}
|
||||
},
|
||||
"libxml2": {
|
||||
"type": "url",
|
||||
"url": "https://github.com/GNOME/libxml2/archive/refs/tags/v2.12.5.tar.gz",
|
||||
"type": "ghtagtar",
|
||||
"repo": "GNOME/libxml2",
|
||||
"match": "v2\\.\\d+\\.\\d+$",
|
||||
"provide-pre-built": false,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "Copyright"
|
||||
@ -742,7 +856,7 @@
|
||||
"micro": {
|
||||
"type": "git",
|
||||
"path": "php-src/sapi/micro",
|
||||
"rev": "php-85-win",
|
||||
"rev": "master",
|
||||
"url": "https://github.com/static-php/phpmicro",
|
||||
"license": {
|
||||
"type": "file",
|
||||
@ -780,6 +894,24 @@
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"mysqlnd_ed25519": {
|
||||
"type": "pie",
|
||||
"repo": "mariadb/mysqlnd_ed25519",
|
||||
"path": "php-src/ext/mysqlnd_ed25519",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"mysqlnd_parsec": {
|
||||
"type": "pie",
|
||||
"repo": "mariadb/mysqlnd_parsec",
|
||||
"path": "php-src/ext/mysqlnd_parsec",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"ncurses": {
|
||||
"type": "filelist",
|
||||
"url": "https://ftp.gnu.org/pub/gnu/ncurses/",
|
||||
@ -790,6 +922,14 @@
|
||||
"path": "COPYING"
|
||||
}
|
||||
},
|
||||
"net-snmp": {
|
||||
"type": "ghtagtar",
|
||||
"repo": "net-snmp/net-snmp",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
}
|
||||
},
|
||||
"nghttp2": {
|
||||
"type": "ghrel",
|
||||
"repo": "nghttp2/nghttp2",
|
||||
@ -867,6 +1007,15 @@
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"pcov": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/pcov",
|
||||
"filename": "pcov.tgz",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"pdo_sqlsrv": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/pdo_sqlsrv",
|
||||
@ -980,7 +1129,6 @@
|
||||
},
|
||||
"snappy": {
|
||||
"type": "git",
|
||||
"repo": "google/snappy",
|
||||
"rev": "main",
|
||||
"url": "https://github.com/google/snappy",
|
||||
"license": {
|
||||
@ -989,9 +1137,8 @@
|
||||
}
|
||||
},
|
||||
"spx": {
|
||||
"type": "git",
|
||||
"rev": "master",
|
||||
"url": "https://github.com/static-php/php-spx.git",
|
||||
"type": "pie",
|
||||
"repo": "noisebynorthwest/php-spx",
|
||||
"path": "php-src/ext/spx",
|
||||
"license": {
|
||||
"type": "file",
|
||||
@ -1066,9 +1213,8 @@
|
||||
}
|
||||
},
|
||||
"xdebug": {
|
||||
"type": "url",
|
||||
"url": "https://pecl.php.net/get/xdebug",
|
||||
"filename": "xdebug.tgz",
|
||||
"type": "pie",
|
||||
"repo": "xdebug/xdebug",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
@ -1145,14 +1291,5 @@
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
},
|
||||
"liburing": {
|
||||
"type": "ghtar",
|
||||
"repo": "axboe/liburing",
|
||||
"prefer-stable": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "COPYING"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,10 +744,26 @@ h2 {
|
||||
}
|
||||
|
||||
select {
|
||||
border-radius: 4px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
padding: 0 4px;
|
||||
padding: 8px 12px;
|
||||
width: 300px;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
color: var(--vp-c-text-1);
|
||||
font-size: 14px;
|
||||
transition: all 0.2s ease;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
select:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
background-color: var(--vp-c-bg);
|
||||
}
|
||||
|
||||
select:focus {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
box-shadow: 0 0 0 3px var(--vp-c-brand-soft);
|
||||
}
|
||||
|
||||
.my-btn {
|
||||
@ -781,17 +797,160 @@ select {
|
||||
|
||||
.textarea {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 4px;
|
||||
width: calc(100% - 12px);
|
||||
padding: 4px 8px;
|
||||
border-radius: 8px;
|
||||
width: calc(100% - 24px);
|
||||
padding: 12px;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
color: var(--vp-c-text-1);
|
||||
font-size: 14px;
|
||||
font-family: var(--vp-font-family-mono);
|
||||
line-height: 1.5;
|
||||
transition: all 0.2s ease;
|
||||
outline: none;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.textarea:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
background-color: var(--vp-c-bg);
|
||||
}
|
||||
|
||||
.textarea:focus {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
box-shadow: 0 0 0 3px var(--vp-c-brand-soft);
|
||||
}
|
||||
|
||||
.input {
|
||||
display: block;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 4px;
|
||||
border-radius: 8px;
|
||||
width: 100%;
|
||||
padding: 4px 8px;
|
||||
padding: 10px 12px;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
color: var(--vp-c-text-1);
|
||||
font-size: 14px;
|
||||
transition: all 0.2s ease;
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.input:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
background-color: var(--vp-c-bg);
|
||||
}
|
||||
|
||||
.input:focus {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
box-shadow: 0 0 0 3px var(--vp-c-brand-soft);
|
||||
}
|
||||
|
||||
/* Radio button styles */
|
||||
input[type="radio"] {
|
||||
appearance: none;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 2px solid var(--vp-c-border);
|
||||
border-radius: 50%;
|
||||
background-color: var(--vp-c-bg);
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
margin-right: 6px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
input[type="radio"]:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
}
|
||||
|
||||
input[type="radio"]:checked {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
background-color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
input[type="radio"]:checked::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background-color: var(--vp-c-bg);
|
||||
}
|
||||
|
||||
input[type="radio"]:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Checkbox styles */
|
||||
input[type="checkbox"] {
|
||||
appearance: none;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 2px solid var(--vp-c-border);
|
||||
border-radius: 4px;
|
||||
background-color: var(--vp-c-bg);
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
margin-right: 6px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
background-color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 5px;
|
||||
width: 4px;
|
||||
height: 8px;
|
||||
border: solid var(--vp-c-bg);
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Label styles */
|
||||
label {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
color: var(--vp-c-text-1);
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
label:hover {
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
input[type="radio"]:disabled + label,
|
||||
input[type="checkbox"]:disabled + label {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
input[type="radio"]:disabled + label:hover,
|
||||
input[type="checkbox"]:disabled + label:hover {
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.command-container {
|
||||
|
||||
219
docs/.vitepress/components/Contributors.vue
Normal file
219
docs/.vitepress/components/Contributors.vue
Normal file
@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<div class="contributors-container">
|
||||
<div class="contributors-header">
|
||||
<h2>Contributors</h2>
|
||||
<p class="contributors-description">
|
||||
Thanks to all the amazing people who have contributed to this project!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div v-if="loading" class="loading-state">
|
||||
<div class="spinner"></div>
|
||||
<p>Loading contributors...</p>
|
||||
</div>
|
||||
|
||||
<div v-else-if="error" class="error-state">
|
||||
<p>{{ error }}</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="contributors-grid">
|
||||
<a
|
||||
v-for="contributor in contributors"
|
||||
:key="contributor.id"
|
||||
:href="contributor.html_url"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="contributor-card"
|
||||
:title="contributor.login"
|
||||
>
|
||||
<img
|
||||
:src="contributor.avatar_url"
|
||||
:alt="contributor.login"
|
||||
class="contributor-avatar"
|
||||
loading="lazy"
|
||||
/>
|
||||
<div class="contributor-name">{{ contributor.login }}</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
|
||||
interface Contributor {
|
||||
id: number;
|
||||
login: string;
|
||||
avatar_url: string;
|
||||
html_url: string;
|
||||
contributions: number;
|
||||
}
|
||||
|
||||
const contributors = ref<Contributor[]>([]);
|
||||
const loading = ref(true);
|
||||
const error = ref('');
|
||||
|
||||
const fetchContributors = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = '';
|
||||
|
||||
const response = await fetch(
|
||||
'https://api.github.com/repos/crazywhalecc/static-php-cli/contributors?per_page=24'
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch contributors');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
contributors.value = data;
|
||||
} catch (err) {
|
||||
error.value = 'Failed to load contributors. Please try again later.';
|
||||
console.error('Error fetching contributors:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchContributors();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.contributors-container {
|
||||
margin: 48px auto;
|
||||
padding: 32px 24px;
|
||||
max-width: 1152px;
|
||||
background: linear-gradient(135deg, var(--vp-c-bg-soft) 0%, var(--vp-c-bg) 100%);
|
||||
border-radius: 16px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.contributors-header {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.contributors-header h2 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 8px 0;
|
||||
background: linear-gradient(120deg, var(--vp-c-brand-1), var(--vp-c-brand-2));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.contributors-description {
|
||||
font-size: 0.95rem;
|
||||
color: var(--vp-c-text-2);
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.loading-state,
|
||||
.error-state {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: 0 auto 16px;
|
||||
border: 4px solid var(--vp-c-divider);
|
||||
border-top-color: var(--vp-c-brand-1);
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.contributors-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.contributor-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
background: var(--vp-c-bg);
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.contributor-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||||
border-color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.contributor-avatar {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
transition: all 0.3s ease;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.contributor-card:hover .contributor-avatar {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.contributor-name {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
word-break: break-word;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.contributors-container {
|
||||
margin: 32px 16px;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.contributors-header h2 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.contributors-description {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.contributors-grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(70px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.contributor-card {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.contributor-avatar {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.contributor-name {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -4,7 +4,7 @@ import sidebarZh from "./sidebar.zh";
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default {
|
||||
title: "static-php-cli",
|
||||
title: "Static PHP",
|
||||
description: "Build single static PHP binary, with PHP project together, with popular extensions included.",
|
||||
locales: {
|
||||
en: {
|
||||
@ -44,6 +44,7 @@ export default {
|
||||
},
|
||||
themeConfig: {
|
||||
// https://vitepress.dev/reference/default-theme-config
|
||||
logo: '/images/static-php_nobg.png',
|
||||
nav: [],
|
||||
socialLinks: [
|
||||
{icon: 'github', link: 'https://github.com/crazywhalecc/static-php-cli'}
|
||||
|
||||
@ -4,3 +4,21 @@
|
||||
max-width: 1000px !important;
|
||||
}
|
||||
|
||||
|
||||
.vp-doc .contributors-header h2 {
|
||||
padding-top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.vp-doc .sponsors-header h2 {
|
||||
padding-top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.dark .VPImage.logo {
|
||||
filter: contrast(0.7);
|
||||
}
|
||||
|
||||
.dark .VPImage.image-src {
|
||||
filter: contrast(0.7);
|
||||
}
|
||||
|
||||
@ -36,6 +36,7 @@ The following is the source download configuration corresponding to the `libeven
|
||||
The most important field here is `type`. Currently, the types it supports are:
|
||||
|
||||
- `url`: Directly use URL to download, for example: `https://download.libsodium.org/libsodium/releases/libsodium-1.0.18.tar.gz`.
|
||||
- `pie`: Download PHP extensions from Packagist using the PIE (PHP Installer for Extensions) standard.
|
||||
- `ghrel`: Use the GitHub Release API to download, download the artifacts uploaded from the latest version released by maintainers.
|
||||
- `ghtar`: Use the GitHub Release API to download.
|
||||
Different from `ghrel`, `ghtar` is downloaded from the `source code (tar.gz)` in the latest Release of the project.
|
||||
@ -89,6 +90,37 @@ Example (download the imagick extension and extract it to the extension storage
|
||||
}
|
||||
```
|
||||
|
||||
## Download type - pie
|
||||
|
||||
PIE (PHP Installer for Extensions) type sources refer to downloading PHP extensions from Packagist that follow the PIE standard.
|
||||
This method automatically fetches extension information from the Packagist repository and downloads the appropriate distribution file.
|
||||
|
||||
The parameters included are:
|
||||
|
||||
- `repo`: The Packagist vendor/package name, such as `vendor/package-name`
|
||||
|
||||
Example (download a PHP extension from Packagist using PIE):
|
||||
|
||||
```json
|
||||
{
|
||||
"ext-example": {
|
||||
"type": "pie",
|
||||
"repo": "vendor/example-extension",
|
||||
"path": "php-src/ext/example",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
The PIE download type will automatically detect the extension information from Packagist metadata,
|
||||
including the download URL, version, and distribution type.
|
||||
The extension must be marked as `type: php-ext` or contain `php-ext` metadata in its Packagist package definition.
|
||||
:::
|
||||
|
||||
## Download type - ghrel
|
||||
|
||||
ghrel will download files from Assets uploaded in GitHub Release.
|
||||
|
||||
@ -44,6 +44,11 @@ So on macOS, you can **directly** use SPC to build statically compiled PHP binar
|
||||
2. You will get `buildroot/modules/xdebug.so` and `buildroot/bin/php`.
|
||||
3. The `xdebug.so` file could be used for php that version and thread-safe are the same.
|
||||
|
||||
For the Windows platform, since officially built extensions (such as `php_yaml.dll`) force the use of the `php8.dll` dynamic library as a link, and statically built PHP does not include any dynamic libraries other than system libraries,
|
||||
php.exe built by static-php cannot load officially built dynamic extensions. Since static-php-cli does not yet support building dynamic extensions, there is currently no way to load dynamic extensions with static-php.
|
||||
|
||||
However, Windows can normally use the `FFI` extension to load other dll files and call them.
|
||||
|
||||
## Can it support Oracle database extension?
|
||||
|
||||
Some extensions that rely on closed source libraries, such as `oci8`, `sourceguardian`, etc.,
|
||||
|
||||
@ -549,22 +549,24 @@ otherwise it will be executed repeatedly in other events.
|
||||
|
||||
The following are the supported `patch_point` event names and corresponding locations:
|
||||
|
||||
| Event name | Event description |
|
||||
|------------------------------|----------------------------------------------------------------------------------------------------|
|
||||
| before-libs-extract | Triggered before the dependent libraries extracted |
|
||||
| after-libs-extract | Triggered after the compiled dependent libraries extracted |
|
||||
| before-php-extract | Triggered before PHP source code extracted |
|
||||
| after-php-extract | Triggered after PHP source code extracted |
|
||||
| before-micro-extract | Triggered before phpmicro extract |
|
||||
| after-micro-extract | Triggered after phpmicro extracted |
|
||||
| before-exts-extract | Triggered before the extension (to be compiled) extracted to the PHP source directory |
|
||||
| after-exts-extract | Triggered after the extension extracted to the PHP source directory |
|
||||
| before-library[*name*]-build | Triggered before the library named `name` is compiled (such as `before-library[postgresql]-build`) |
|
||||
| after-library[*name*]-build | Triggered after the library named `name` is compiled |
|
||||
| before-php-buildconf | Triggered before compiling PHP command `./buildconf` |
|
||||
| before-php-configure | Triggered before compiling PHP command `./configure` |
|
||||
| before-php-make | Triggered before compiling PHP command `make` |
|
||||
| before-sanity-check | Triggered after compiling PHP but before running extended checks |
|
||||
| Event name | Event description |
|
||||
|---------------------------------|----------------------------------------------------------------------------------------------------|
|
||||
| before-libs-extract | Triggered before the dependent libraries extracted |
|
||||
| after-libs-extract | Triggered after the compiled dependent libraries extracted |
|
||||
| before-php-extract | Triggered before PHP source code extracted |
|
||||
| after-php-extract | Triggered after PHP source code extracted |
|
||||
| before-micro-extract | Triggered before phpmicro extract |
|
||||
| after-micro-extract | Triggered after phpmicro extracted |
|
||||
| before-exts-extract | Triggered before the extension (to be compiled) extracted to the PHP source directory |
|
||||
| after-exts-extract | Triggered after the extension extracted to the PHP source directory |
|
||||
| before-library[*name*]-build | Triggered before the library named `name` is compiled (such as `before-library[postgresql]-build`) |
|
||||
| after-library[*name*]-build | Triggered after the library named `name` is compiled |
|
||||
| after-shared-ext[*name*]-build | Triggered after the shared extension named `name` is compiled |
|
||||
| before-shared-ext[*name*]-build | Triggered before the shared extension named `name` is compiled |
|
||||
| before-php-buildconf | Triggered before compiling PHP command `./buildconf` |
|
||||
| before-php-configure | Triggered before compiling PHP command `./configure` |
|
||||
| before-php-make | Triggered before compiling PHP command `make` |
|
||||
| before-sanity-check | Triggered after compiling PHP but before running extended checks |
|
||||
|
||||
The following is a simple example of temporarily modifying the PHP source code.
|
||||
Enable the CLI function to search for the `php.ini` configuration in the current working directory:
|
||||
|
||||
125
docs/en/index.md
125
docs/en/index.md
@ -3,11 +3,14 @@
|
||||
layout: home
|
||||
|
||||
hero:
|
||||
name: "static-php-cli"
|
||||
name: "Static PHP"
|
||||
tagline: "Build standalone PHP binary on Linux, macOS, FreeBSD, Windows, with PHP project together, with popular extensions included."
|
||||
image:
|
||||
src: /images/static-php_nobg.png
|
||||
alt: Static PHP CLI Logo
|
||||
actions:
|
||||
- theme: brand
|
||||
text: Guide
|
||||
text: Get Started
|
||||
link: ./guide/
|
||||
|
||||
features:
|
||||
@ -19,3 +22,121 @@ features:
|
||||
details: static-php-cli comes with dependency management and supports installation of different types of PHP extensions.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import {VPSponsors} from "vitepress/theme";
|
||||
import Contributors from '../.vitepress/components/Contributors.vue';
|
||||
|
||||
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>
|
||||
|
||||
<div class="sponsors-section">
|
||||
<div class="sponsors-header">
|
||||
<h2>Special Sponsors</h2>
|
||||
<p class="sponsors-description">
|
||||
Thank you to our amazing sponsors for supporting this project!
|
||||
</p>
|
||||
</div>
|
||||
<VPSponsors :data="sponsors"/>
|
||||
</div>
|
||||
|
||||
<style scoped>
|
||||
.sponsors-section {
|
||||
margin: 48px auto;
|
||||
padding: 32px 24px;
|
||||
max-width: 1152px;
|
||||
background: linear-gradient(135deg, var(--vp-c-bg-soft) 0%, var(--vp-c-bg) 100%);
|
||||
border-radius: 16px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.sponsors-section:hover {
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.sponsors-header {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.sponsors-header h2 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 8px 0;
|
||||
background: linear-gradient(120deg, var(--vp-c-brand-1), var(--vp-c-brand-2));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.sponsors-description {
|
||||
font-size: 0.95rem;
|
||||
color: var(--vp-c-text-2);
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.sponsors-section {
|
||||
margin: 32px 16px;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.sponsors-header h2 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.sponsors-description {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hero logo styling */
|
||||
:deep(.VPImage.image-src) {
|
||||
border-radius: 20px;
|
||||
background: linear-gradient(135deg, var(--vp-c-bg-soft) 0%, var(--vp-c-default-soft) 100%);
|
||||
padding: 40px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
:deep(.VPImage.image-src:hover) {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Dark mode adjustments for logo */
|
||||
.dark :deep(.VPImage.image-src) {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.02) 100%);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.dark :deep(.VPImage.image-src:hover) {
|
||||
opacity: 1;
|
||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
/* Additional styling for the logo image itself */
|
||||
:deep(.VPImage.image-src img) {
|
||||
max-height: 280px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
:deep(.VPImage.image-src) {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
:deep(.VPImage.image-src img) {
|
||||
max-height: 200px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<Contributors />
|
||||
|
||||
117
docs/index.md
117
docs/index.md
@ -3,8 +3,11 @@
|
||||
layout: home
|
||||
|
||||
hero:
|
||||
name: "static-php-cli"
|
||||
name: "Static PHP"
|
||||
tagline: "Build standalone PHP binary on Linux, macOS, FreeBSD, Windows, with PHP project together, with popular extensions included."
|
||||
image:
|
||||
src: /images/static-php_nobg.png
|
||||
alt: Static PHP CLI Logo
|
||||
actions:
|
||||
- theme: brand
|
||||
text: Get Started
|
||||
@ -24,13 +27,121 @@ features:
|
||||
|
||||
<script setup>
|
||||
import {VPSponsors} from "vitepress/theme";
|
||||
import Contributors from './.vitepress/components/Contributors.vue';
|
||||
|
||||
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
|
||||
<div class="sponsors-section">
|
||||
<div class="sponsors-header">
|
||||
<h2>Special Sponsors</h2>
|
||||
<p class="sponsors-description">
|
||||
Thank you to our amazing sponsors for supporting this project!
|
||||
</p>
|
||||
</div>
|
||||
<VPSponsors :data="sponsors"/>
|
||||
</div>
|
||||
|
||||
<VPSponsors :data="sponsors"/>
|
||||
<style scoped>
|
||||
.sponsors-section {
|
||||
margin: 48px auto;
|
||||
padding: 32px 24px;
|
||||
max-width: 1152px;
|
||||
background: linear-gradient(135deg, var(--vp-c-bg-soft) 0%, var(--vp-c-bg) 100%);
|
||||
border-radius: 16px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.sponsors-section:hover {
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.sponsors-header {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.sponsors-header h2 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 8px 0;
|
||||
background: linear-gradient(120deg, var(--vp-c-brand-1), var(--vp-c-brand-2));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.sponsors-description {
|
||||
font-size: 0.95rem;
|
||||
color: var(--vp-c-text-2);
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.sponsors-section {
|
||||
margin: 32px 16px;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.sponsors-header h2 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.sponsors-description {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hero logo styling */
|
||||
:deep(.VPImage.image-src) {
|
||||
border-radius: 20px;
|
||||
background: linear-gradient(135deg, var(--vp-c-bg-soft) 0%, var(--vp-c-default-soft) 100%);
|
||||
padding: 40px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
:deep(.VPImage.image-src:hover) {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Dark mode adjustments for logo */
|
||||
.dark :deep(.VPImage.image-src) {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.02) 100%);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.dark :deep(.VPImage.image-src:hover) {
|
||||
opacity: 1;
|
||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
/* Additional styling for the logo image itself */
|
||||
:deep(.VPImage.image-src img) {
|
||||
max-height: 280px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
:deep(.VPImage.image-src) {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
:deep(.VPImage.image-src img) {
|
||||
max-height: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<Contributors />
|
||||
|
||||
|
||||
BIN
docs/public/images/static-php_nobg.png
Normal file
BIN
docs/public/images/static-php_nobg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 965 KiB |
@ -30,6 +30,7 @@ static-php-cli 的下载资源模块是一个主要的功能,它包含了所
|
||||
这里最主要的字段是 `type`,目前它支持的类型有:
|
||||
|
||||
- `url`: 直接使用 URL 下载,例如:`https://download.libsodium.org/libsodium/releases/libsodium-1.0.18.tar.gz`。
|
||||
- `pie`: 使用 PIE(PHP Installer for Extensions)标准从 Packagist 下载 PHP 扩展。
|
||||
- `ghrel`: 使用 GitHub Release API 下载,即从 GitHub 项目发布的最新版本中上传的附件下载。
|
||||
- `ghtar`: 使用 GitHub Release API 下载,与 `ghrel` 不同的是,`ghtar` 是从项目的最新 Release 中找 `source code (tar.gz)` 下载的。
|
||||
- `ghtagtar`: 使用 GitHub Release API 下载,与 `ghtar` 相比,`ghtagtar` 可以从 `tags` 列表找最新的,并下载 `tar.gz` 格式的源码(因为有些项目只使用了 `tag` 发布版本)。
|
||||
@ -77,6 +78,36 @@ url 类型的资源指的是从 URL 直接下载文件。
|
||||
}
|
||||
```
|
||||
|
||||
## 下载类型 - pie
|
||||
|
||||
PIE(PHP Installer for Extensions)类型的资源是从 Packagist 下载遵循 PIE 标准的 PHP 扩展。
|
||||
该方法会自动从 Packagist 仓库获取扩展信息,并下载相应的分发文件。
|
||||
|
||||
包含的参数有:
|
||||
|
||||
- `repo`: Packagist 的 vendor/package 名称,如 `vendor/package-name`
|
||||
|
||||
例子(使用 PIE 从 Packagist 下载 PHP 扩展):
|
||||
|
||||
```json
|
||||
{
|
||||
"ext-example": {
|
||||
"type": "pie",
|
||||
"repo": "vendor/example-extension",
|
||||
"path": "php-src/ext/example",
|
||||
"license": {
|
||||
"type": "file",
|
||||
"path": "LICENSE"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
PIE 下载类型会自动从 Packagist 元数据中检测扩展信息,包括下载 URL、版本和分发类型。
|
||||
扩展必须在其 Packagist 包定义中标记为 `type: php-ext` 或包含 `php-ext` 元数据。
|
||||
:::
|
||||
|
||||
## 下载类型 - ghrel
|
||||
|
||||
ghrel 会从 GitHub Release 中上传的 Assets 下载文件。首先使用 GitHub Release API 获取最新版本,然后根据正则匹配方式下载相应的文件。
|
||||
|
||||
@ -41,6 +41,11 @@ buildroot/bin/php -d "zend_extension=/path/to/php{PHP_VER}-{ts/nts}/xdebug.so" -
|
||||
2. 你将获得 `buildroot/modules/xdebug.so` 和 `buildroot/bin/php`。
|
||||
3. `xdebug.so` 文件可用于版本和线程安全相同的 php。
|
||||
|
||||
对于 Windows 平台,由于官方构建的扩展(如 `php_yaml.dll`)强制使用了 `php8.dll` 动态库作为链接,静态构建的 PHP 不包含任何系统库以外的动态库,
|
||||
所以 Windows 下无法加载官方构建的动态扩展。 由于 static-php-cli 还暂未支持构建动态扩展,所以目前还没有让 static-php 加载动态扩展的方法。
|
||||
|
||||
不过,Windows 可以正常使用 `FFI` 扩展加载其他的 dll 文件并调用。
|
||||
|
||||
## 可以支持 Oracle 数据库扩展吗?
|
||||
|
||||
部分依赖库闭源的扩展,如 `oci8`、`sourceguardian` 等,它们没有提供纯静态编译的依赖库文件(`.a`),仅提供了动态依赖库文件(`.so`),
|
||||
|
||||
@ -500,6 +500,8 @@ bin/spc dev:sort-config ext
|
||||
| after-exts-extract | 在要编译的扩展解压到 PHP 源码目录后触发 |
|
||||
| before-library[*name*]-build | 在名称为 `name` 的库编译前触发(如 `before-library[postgresql]-build`) |
|
||||
| after-library[*name*]-build | 在名称为 `name` 的库编译后触发 |
|
||||
| after-shared-ext[*name*]-build | 在名称为 `name` 的共享扩展编译后触发(如 `after-shared-ext[redis]-build`) |
|
||||
| before-shared-ext[*name*]-build | 在名称为 `name` 的共享扩展编译前触发 |
|
||||
| before-php-buildconf | 在编译 PHP 命令 `./buildconf` 前触发 |
|
||||
| before-php-configure | 在编译 PHP 命令 `./configure` 前触发 |
|
||||
| before-php-make | 在编译 PHP 命令 `make` 前触发 |
|
||||
|
||||
138
docs/zh/index.md
138
docs/zh/index.md
@ -3,18 +3,140 @@
|
||||
layout: home
|
||||
|
||||
hero:
|
||||
name: "static-php-cli"
|
||||
name: "Static PHP"
|
||||
tagline: "在 Linux、macOS、FreeBSD、Windows 上与 PHP 项目一起构建独立的 PHP 二进制文件,并包含流行的扩展。"
|
||||
image:
|
||||
src: /images/static-php_nobg.png
|
||||
alt: Static PHP CLI Logo
|
||||
actions:
|
||||
- theme: brand
|
||||
text: 指南
|
||||
text: 开始使用
|
||||
link: ./guide/
|
||||
|
||||
features:
|
||||
- title: 静态二进制
|
||||
details: 您可以轻松地编译一个独立的 PHP 二进制文件以供嵌入程序使用。包括 cli、fpm、micro。
|
||||
- title: phpmicro 自执行二进制
|
||||
details: 您可以使用 micro SAPI 编译一个自解压的可执行文件,并将 PHP 代码与二进制文件打包为一个文件。
|
||||
- title: 依赖管理
|
||||
details: static-php-cli 附带依赖项管理,支持安装不同类型的 PHP 扩展和不同的依赖库。
|
||||
- title: 静态 CLI 二进制
|
||||
details: 您可以轻松地编译一个独立的 PHP 二进制文件以供通用使用,包括 CLI、FPM SAPI。
|
||||
- title: Micro 自解压可执行文件
|
||||
details: 您可以编译一个自解压的可执行文件,并将 PHP 源代码与二进制文件打包在一起。
|
||||
- title: 依赖管理
|
||||
details: static-php-cli 附带依赖项管理,支持安装不同类型的 PHP 扩展。
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import {VPSponsors} from "vitepress/theme";
|
||||
import Contributors from '../.vitepress/components/Contributors.vue';
|
||||
|
||||
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>
|
||||
|
||||
<div class="sponsors-section">
|
||||
<div class="sponsors-header">
|
||||
<h2>特别赞助商</h2>
|
||||
<p class="sponsors-description">
|
||||
感谢我们出色的赞助商对本项目的支持!
|
||||
</p>
|
||||
</div>
|
||||
<VPSponsors :data="sponsors"/>
|
||||
</div>
|
||||
|
||||
<style scoped>
|
||||
.sponsors-section {
|
||||
margin: 48px auto;
|
||||
padding: 32px 24px;
|
||||
max-width: 1152px;
|
||||
background: linear-gradient(135deg, var(--vp-c-bg-soft) 0%, var(--vp-c-bg) 100%);
|
||||
border-radius: 16px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.sponsors-section:hover {
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.sponsors-header {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.sponsors-header h2 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 8px 0;
|
||||
background: linear-gradient(120deg, var(--vp-c-brand-1), var(--vp-c-brand-2));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.sponsors-description {
|
||||
font-size: 0.95rem;
|
||||
color: var(--vp-c-text-2);
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.sponsors-section {
|
||||
margin: 32px 16px;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.sponsors-header h2 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.sponsors-description {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hero logo styling */
|
||||
:deep(.VPImage.image-src) {
|
||||
border-radius: 20px;
|
||||
background: linear-gradient(135deg, var(--vp-c-bg-soft) 0%, var(--vp-c-default-soft) 100%);
|
||||
padding: 40px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
:deep(.VPImage.image-src:hover) {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Dark mode adjustments for logo */
|
||||
.dark :deep(.VPImage.image-src) {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.02) 100%);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.dark :deep(.VPImage.image-src:hover) {
|
||||
opacity: 1;
|
||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
/* Additional styling for the logo image itself */
|
||||
:deep(.VPImage.image-src img) {
|
||||
max-height: 280px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
:deep(.VPImage.image-src) {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
:deep(.VPImage.image-src img) {
|
||||
max-height: 200px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<Contributors />
|
||||
|
||||
@ -34,7 +34,7 @@ use Symfony\Component\Console\Application;
|
||||
*/
|
||||
final class ConsoleApplication extends Application
|
||||
{
|
||||
public const string VERSION = '2.7.5';
|
||||
public const string VERSION = '2.8.3';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder;
|
||||
|
||||
use SPC\builder\unix\UnixBuilderBase;
|
||||
use SPC\exception\EnvironmentException;
|
||||
use SPC\exception\SPCException;
|
||||
use SPC\exception\ValidationException;
|
||||
@ -95,7 +96,8 @@ class Extension
|
||||
fn ($x) => $x->getStaticLibFiles(),
|
||||
$this->getLibraryDependencies(recursive: true)
|
||||
);
|
||||
return implode(' ', $ret);
|
||||
$libs = implode(' ', $ret);
|
||||
return deduplicate_flags($libs);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -220,7 +222,7 @@ class Extension
|
||||
*/
|
||||
public function patchBeforeSharedMake(): bool
|
||||
{
|
||||
$config = (new SPCConfigUtil($this->builder))->config([$this->getName()], array_map(fn ($l) => $l->getName(), $this->builder->getLibs()));
|
||||
$config = (new SPCConfigUtil($this->builder))->getExtensionConfig($this);
|
||||
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
|
||||
$lstdcpp = str_contains($sharedLibs, '-l:libstdc++.a') ? '-l:libstdc++.a' : null;
|
||||
$lstdcpp ??= str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : '';
|
||||
@ -305,7 +307,7 @@ class Extension
|
||||
// Run compile check if build target is cli
|
||||
// If you need to run some check, overwrite this or add your assert in src/globals/ext-tests/{extension_name}.php
|
||||
$sharedExtensions = $this->getSharedExtensionLoadString();
|
||||
[$ret, $out] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
|
||||
[$ret] = shell()->execWithResult(BUILD_BIN_PATH . '/php -n' . $sharedExtensions . ' --ri "' . $this->getDistName() . '"');
|
||||
if ($ret !== 0) {
|
||||
throw new ValidationException(
|
||||
"extension {$this->getName()} failed compile check: php-cli returned {$ret}",
|
||||
@ -335,7 +337,7 @@ class Extension
|
||||
{
|
||||
// Run compile check if build target is cli
|
||||
// If you need to run some check, overwrite this or add your assert in src/globals/ext-tests/{extension_name}.php
|
||||
[$ret] = cmd()->execWithResult(BUILD_ROOT_PATH . '/bin/php.exe -n --ri "' . $this->getDistName() . '"', false);
|
||||
[$ret] = cmd()->execWithResult(BUILD_BIN_PATH . '/php.exe -n --ri "' . $this->getDistName() . '"', false);
|
||||
if ($ret !== 0) {
|
||||
throw new ValidationException("extension {$this->getName()} failed compile check: php-cli returned {$ret}", validation_module: "Extension {$this->getName()} sanity check");
|
||||
}
|
||||
@ -384,6 +386,9 @@ class Extension
|
||||
logger()->info('Shared extension [' . $this->getName() . '] was already built, skipping (' . $this->getName() . '.so)');
|
||||
return;
|
||||
}
|
||||
if ((string) Config::getExt($this->getName(), 'type') === 'addon') {
|
||||
return;
|
||||
}
|
||||
logger()->info('Building extension [' . $this->getName() . '] as shared extension (' . $this->getName() . '.so)');
|
||||
foreach ($this->dependencies as $dependency) {
|
||||
if (!$dependency instanceof Extension) {
|
||||
@ -394,13 +399,12 @@ class Extension
|
||||
$dependency->buildShared([...$visited, $this->getName()]);
|
||||
}
|
||||
}
|
||||
if (Config::getExt($this->getName(), 'type') === 'addon') {
|
||||
return;
|
||||
}
|
||||
$this->builder->emitPatchPoint('before-shared-ext[' . $this->getName() . ']-build');
|
||||
match (PHP_OS_FAMILY) {
|
||||
'Darwin', 'Linux' => $this->buildUnixShared(),
|
||||
default => throw new WrongUsageException(PHP_OS_FAMILY . ' build shared extensions is not supported yet'),
|
||||
};
|
||||
$this->builder->emitPatchPoint('after-shared-ext[' . $this->getName() . ']-build');
|
||||
} catch (SPCException $e) {
|
||||
$e->bindExtensionInfo(['extension_name' => $this->getName()]);
|
||||
throw $e;
|
||||
@ -448,6 +452,20 @@ class Extension
|
||||
->exec('make clean')
|
||||
->exec('make -j' . $this->builder->concurrency)
|
||||
->exec('make install');
|
||||
|
||||
// process *.so file
|
||||
$soFile = BUILD_MODULES_PATH . '/' . $this->getName() . '.so';
|
||||
$soDest = $soFile;
|
||||
preg_match('/-release\s+(\S*)/', getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'), $matches);
|
||||
if (!empty($matches[1])) {
|
||||
$soDest = str_replace('.so', '-' . $matches[1] . '.so', $soFile);
|
||||
}
|
||||
if (!file_exists($soFile)) {
|
||||
throw new ValidationException("extension {$this->getName()} build failed: {$soFile} not found", validation_module: "Extension {$this->getName()} build");
|
||||
}
|
||||
/** @var UnixBuilderBase $builder */
|
||||
$builder = $this->builder;
|
||||
$builder->deployBinary($soFile, $soDest, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -486,18 +504,46 @@ class Extension
|
||||
return $this->build_static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the library dependencies that current extension depends on.
|
||||
*
|
||||
* @param bool $recursive Whether it includes dependencies recursively
|
||||
*/
|
||||
public function getLibraryDependencies(bool $recursive = false): array
|
||||
{
|
||||
$ret = array_filter($this->dependencies, fn ($x) => $x instanceof LibraryBase);
|
||||
if (!$recursive) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$deps = [];
|
||||
|
||||
$added = 1;
|
||||
while ($added !== 0) {
|
||||
$added = 0;
|
||||
foreach ($ret as $depName => $dep) {
|
||||
foreach ($dep->getDependencies(true) as $depdepName => $depdep) {
|
||||
if (!array_key_exists($depdepName, $deps)) {
|
||||
$deps[$depdepName] = $depdep;
|
||||
++$added;
|
||||
}
|
||||
}
|
||||
if (!array_key_exists($depName, $deps)) {
|
||||
$deps[$depName] = $dep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $deps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the environment variables a shared extension needs to be built.
|
||||
* CFLAGS, CXXFLAGS, LDFLAGS and so on.
|
||||
*/
|
||||
protected function getSharedExtensionEnv(): array
|
||||
{
|
||||
$config = (new SPCConfigUtil($this->builder))->config(
|
||||
[$this->getName()],
|
||||
array_map(fn ($l) => $l->getName(), $this->getLibraryDependencies(recursive: true)),
|
||||
$this->builder->getOption('with-suggested-exts'),
|
||||
$this->builder->getOption('with-suggested-libs'),
|
||||
);
|
||||
$config = (new SPCConfigUtil($this->builder, ['no_php' => true]))->getExtensionConfig($this);
|
||||
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
|
||||
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
|
||||
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
|
||||
@ -505,6 +551,7 @@ class Extension
|
||||
'CFLAGS' => $config['cflags'],
|
||||
'CXXFLAGS' => $config['cflags'],
|
||||
'LDFLAGS' => $config['ldflags'],
|
||||
'EXTRA_LDFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'),
|
||||
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
|
||||
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
|
||||
];
|
||||
@ -519,7 +566,7 @@ class Extension
|
||||
}
|
||||
logger()->info("enabling {$this->name} without library {$name}");
|
||||
} else {
|
||||
$this->dependencies[] = $depLib;
|
||||
$this->dependencies[$name] = $depLib;
|
||||
}
|
||||
}
|
||||
|
||||
@ -532,7 +579,7 @@ class Extension
|
||||
}
|
||||
logger()->info("enabling {$this->name} without extension {$name}");
|
||||
} else {
|
||||
$this->dependencies[] = $depExt;
|
||||
$this->dependencies[$name] = $depExt;
|
||||
}
|
||||
}
|
||||
|
||||
@ -567,37 +614,4 @@ class Extension
|
||||
}
|
||||
return [trim($staticLibString), trim($sharedLibString)];
|
||||
}
|
||||
|
||||
private function getLibraryDependencies(bool $recursive = false): array
|
||||
{
|
||||
$ret = array_filter($this->dependencies, fn ($x) => $x instanceof LibraryBase);
|
||||
if (!$recursive) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$deps = [];
|
||||
|
||||
$added = 1;
|
||||
while ($added !== 0) {
|
||||
$added = 0;
|
||||
foreach ($ret as $depName => $dep) {
|
||||
foreach ($dep->getDependencies(true) as $depdepName => $depdep) {
|
||||
if (!array_key_exists($depdepName, $deps)) {
|
||||
$deps[$depdepName] = $depdep;
|
||||
++$added;
|
||||
}
|
||||
}
|
||||
if (!array_key_exists($depName, $deps)) {
|
||||
$deps[$depName] = $dep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists(0, $deps)) {
|
||||
$zero = [0 => $deps[0]];
|
||||
unset($deps[0]);
|
||||
return $zero + $deps;
|
||||
}
|
||||
return $deps;
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,18 +184,18 @@ abstract class LibraryBase
|
||||
|
||||
// extract first if not exists
|
||||
if (!is_dir($this->source_dir)) {
|
||||
$this->getBuilder()->emitPatchPoint('before-library[ ' . static::NAME . ']-extract');
|
||||
$this->getBuilder()->emitPatchPoint('before-library[' . static::NAME . ']-extract');
|
||||
SourceManager::initSource(libs: [static::NAME], source_only: true);
|
||||
$this->getBuilder()->emitPatchPoint('after-library[ ' . static::NAME . ']-extract');
|
||||
$this->getBuilder()->emitPatchPoint('after-library[' . static::NAME . ']-extract');
|
||||
}
|
||||
|
||||
if (!$this->patched && $this->patchBeforeBuild()) {
|
||||
file_put_contents($this->source_dir . '/.spc.patched', 'PATCHED!!!');
|
||||
}
|
||||
$this->getBuilder()->emitPatchPoint('before-library[ ' . static::NAME . ']-build');
|
||||
$this->getBuilder()->emitPatchPoint('before-library[' . static::NAME . ']-build');
|
||||
$this->build();
|
||||
$this->installLicense();
|
||||
$this->getBuilder()->emitPatchPoint('after-library[ ' . static::NAME . ']-build');
|
||||
$this->getBuilder()->emitPatchPoint('after-library[' . static::NAME . ']-build');
|
||||
return LIB_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -346,25 +346,46 @@ abstract class LibraryBase
|
||||
*/
|
||||
protected function installLicense(): void
|
||||
{
|
||||
FileSystem::createDir(BUILD_ROOT_PATH . '/source-licenses/' . $this->getName());
|
||||
$source = Config::getLib($this->getName(), 'source');
|
||||
FileSystem::createDir(BUILD_ROOT_PATH . "/source-licenses/{$source}");
|
||||
$license_files = Config::getSource($source)['license'] ?? [];
|
||||
if (is_assoc_array($license_files)) {
|
||||
$license_files = [$license_files];
|
||||
}
|
||||
foreach ($license_files as $index => $license) {
|
||||
if ($license['type'] === 'text') {
|
||||
FileSystem::writeFile(BUILD_ROOT_PATH . '/source-licenses/' . $this->getName() . "/{$index}.txt", $license['text']);
|
||||
FileSystem::writeFile(BUILD_ROOT_PATH . "/source-licenses/{$source}/{$index}.txt", $license['text']);
|
||||
continue;
|
||||
}
|
||||
if ($license['type'] === 'file') {
|
||||
copy($this->source_dir . '/' . $license['path'], BUILD_ROOT_PATH . '/source-licenses/' . $this->getName() . "/{$index}.txt");
|
||||
copy($this->source_dir . '/' . $license['path'], BUILD_ROOT_PATH . "/source-licenses/{$source}/{$index}.txt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function isLibraryInstalled(): bool
|
||||
{
|
||||
if ($pkg_configs = Config::getLib(static::NAME, 'pkg-configs', [])) {
|
||||
$pkg_config_path = getenv('PKG_CONFIG_PATH') ?: '';
|
||||
$search_paths = array_unique(array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path)));
|
||||
|
||||
foreach ($pkg_configs as $name) {
|
||||
$found = false;
|
||||
foreach ($search_paths as $path) {
|
||||
if (file_exists($path . "/{$name}.pc")) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// allow using system dependencies if pkg_config_path is explicitly defined
|
||||
if (count($search_paths) > 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
foreach (Config::getLib(static::NAME, 'static-libs', []) as $name) {
|
||||
if (!file_exists(BUILD_LIB_PATH . "/{$name}")) {
|
||||
return false;
|
||||
@ -375,8 +396,17 @@ abstract class LibraryBase
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$pkg_config_path = getenv('PKG_CONFIG_PATH') ?: '';
|
||||
$search_paths = array_filter(explode(is_unix() ? ':' : ';', $pkg_config_path));
|
||||
foreach (Config::getLib(static::NAME, 'pkg-configs', []) as $name) {
|
||||
if (!file_exists(BUILD_LIB_PATH . "/pkgconfig/{$name}.pc")) {
|
||||
$found = false;
|
||||
foreach ($search_paths as $path) {
|
||||
if (file_exists($path . "/{$name}.pc")) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
17
src/SPC/builder/extension/com_dotnet.php
Normal file
17
src/SPC/builder/extension/com_dotnet.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('com_dotnet')]
|
||||
class com_dotnet extends Extension
|
||||
{
|
||||
public function getWindowsConfigureArg(bool $shared = false): string
|
||||
{
|
||||
return '--enable-com-dotnet=yes';
|
||||
}
|
||||
}
|
||||
@ -5,11 +5,21 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\store\SourcePatcher;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('ffi')]
|
||||
class ffi extends Extension
|
||||
{
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
if (PHP_OS_FAMILY === 'Linux' && SystemUtil::getOSRelease()['dist'] === 'centos') {
|
||||
return SourcePatcher::patchFfiCentos7FixO3strncmp();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getUnixConfigureArg(bool $shared = false): string
|
||||
{
|
||||
return '--with-ffi' . ($shared ? '=shared' : '') . ' --enable-zend-signals';
|
||||
|
||||
@ -15,7 +15,11 @@ class gettext extends Extension
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
if ($this->builder instanceof MacOSBuilder) {
|
||||
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/gettext/config.m4', 'AC_CHECK_LIB($GETTEXT_CHECK_IN_LIB', 'AC_CHECK_LIB(intl');
|
||||
FileSystem::replaceFileStr(
|
||||
SOURCE_PATH . '/php-src/ext/gettext/config.m4',
|
||||
['AC_CHECK_LIB($GETTEXT_CHECK_IN_LIB', 'AC_CHECK_LIB([$GETTEXT_CHECK_IN_LIB'],
|
||||
['AC_CHECK_LIB(intl', 'AC_CHECK_LIB([intl'] // new php versions use a bracket
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -11,7 +11,6 @@ use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
use SPC\util\SPCConfigUtil;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
#[CustomExt('grpc')]
|
||||
class grpc extends Extension
|
||||
@ -21,29 +20,57 @@ class grpc extends Extension
|
||||
if ($this->builder instanceof WindowsBuilder) {
|
||||
throw new ValidationException('grpc extension does not support windows yet');
|
||||
}
|
||||
if (file_exists(SOURCE_PATH . '/php-src/ext/grpc')) {
|
||||
return false;
|
||||
}
|
||||
// soft link to the grpc source code
|
||||
if (is_dir($this->source_dir . '/src/php/ext/grpc')) {
|
||||
shell()->exec('ln -s ' . $this->source_dir . '/src/php/ext/grpc ' . SOURCE_PATH . '/php-src/ext/grpc');
|
||||
} else {
|
||||
throw new ValidationException('Cannot find grpc source code in ' . $this->source_dir . '/src/php/ext/grpc');
|
||||
}
|
||||
if (SPCTarget::getTargetOS() === 'Darwin') {
|
||||
FileSystem::replaceFileRegex(
|
||||
SOURCE_PATH . '/php-src/ext/grpc/config.m4',
|
||||
'/GRPC_LIBDIR=.*$/m',
|
||||
'GRPC_LIBDIR=' . BUILD_LIB_PATH . "\n" . 'LDFLAGS="$LDFLAGS -framework CoreFoundation"'
|
||||
);
|
||||
}
|
||||
|
||||
// Fix deprecated PHP API usage in call.c
|
||||
FileSystem::replaceFileStr(
|
||||
"{$this->source_dir}/src/php/ext/grpc/call.c",
|
||||
'zend_exception_get_default(TSRMLS_C),',
|
||||
'zend_ce_exception,',
|
||||
);
|
||||
|
||||
$config_m4 = <<<'M4'
|
||||
PHP_ARG_ENABLE(grpc, [whether to enable grpc support], [AS_HELP_STRING([--enable-grpc], [Enable grpc support])])
|
||||
|
||||
if test "$PHP_GRPC" != "no"; then
|
||||
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
|
||||
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
|
||||
GRPC_LIBDIR=@@build_lib_path@@
|
||||
PHP_ADD_LIBPATH($GRPC_LIBDIR)
|
||||
PHP_ADD_LIBRARY(grpc,,GRPC_SHARED_LIBADD)
|
||||
LIBS="-lpthread $LIBS"
|
||||
PHP_ADD_LIBRARY(pthread)
|
||||
|
||||
case $host in
|
||||
*darwin*)
|
||||
PHP_ADD_LIBRARY(c++,1,GRPC_SHARED_LIBADD)
|
||||
;;
|
||||
*)
|
||||
PHP_ADD_LIBRARY(stdc++,1,GRPC_SHARED_LIBADD)
|
||||
PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD)
|
||||
PHP_ADD_LIBRARY(rt)
|
||||
;;
|
||||
esac
|
||||
|
||||
PHP_NEW_EXTENSION(grpc, @grpc_c_files@, $ext_shared, , -DGRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK=1)
|
||||
PHP_SUBST(GRPC_SHARED_LIBADD)
|
||||
PHP_INSTALL_HEADERS([ext/grpc], [php_grpc.h])
|
||||
fi
|
||||
M4;
|
||||
$replace = get_pack_replace();
|
||||
// load grpc c files from src/php/ext/grpc
|
||||
$c_files = glob($this->source_dir . '/src/php/ext/grpc/*.c');
|
||||
$replace['@grpc_c_files@'] = implode(" \\\n ", array_map(fn ($f) => 'src/php/ext/grpc/' . basename($f), $c_files));
|
||||
$config_m4 = str_replace(array_keys($replace), array_values($replace), $config_m4);
|
||||
file_put_contents($this->source_dir . '/config.m4', $config_m4);
|
||||
|
||||
copy($this->source_dir . '/src/php/ext/grpc/php_grpc.h', $this->source_dir . '/php_grpc.h');
|
||||
return true;
|
||||
}
|
||||
|
||||
public function patchBeforeConfigure(): bool
|
||||
{
|
||||
$util = new SPCConfigUtil($this->builder, ['libs_only_deps' => true]);
|
||||
$config = $util->config(['grpc']);
|
||||
$config = $util->getExtensionConfig($this);
|
||||
$libs = $config['libs'];
|
||||
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/configure', '-lgrpc', $libs);
|
||||
return true;
|
||||
@ -52,7 +79,6 @@ class grpc extends Extension
|
||||
public function patchBeforeMake(): bool
|
||||
{
|
||||
parent::patchBeforeMake();
|
||||
// add -Wno-strict-prototypes
|
||||
GlobalEnvManager::putenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS=' . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -Wno-strict-prototypes');
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\toolchain\ToolchainManager;
|
||||
use SPC\toolchain\ZigToolchain;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('imagick')]
|
||||
@ -19,7 +21,9 @@ class imagick extends Extension
|
||||
protected function splitLibsIntoStaticAndShared(string $allLibs): array
|
||||
{
|
||||
[$static, $shared] = parent::splitLibsIntoStaticAndShared($allLibs);
|
||||
if (str_contains(getenv('PATH'), 'rh/devtoolset') || str_contains(getenv('PATH'), 'rh/gcc-toolset')) {
|
||||
if (ToolchainManager::getToolchainClass() !== ZigToolchain::class &&
|
||||
(str_contains(getenv('PATH'), 'rh/devtoolset') || str_contains(getenv('PATH'), 'rh/gcc-toolset'))
|
||||
) {
|
||||
$static .= ' -l:libstdc++.a';
|
||||
$shared = str_replace('-lstdc++', '', $shared);
|
||||
}
|
||||
|
||||
25
src/SPC/builder/extension/maxminddb.php
Normal file
25
src/SPC/builder/extension/maxminddb.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('maxminddb')]
|
||||
class maxminddb extends Extension
|
||||
{
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
if (!is_dir(SOURCE_PATH . '/php-src/ext/maxminddb')) {
|
||||
$original = $this->source_dir;
|
||||
FileSystem::copyDir($original . '/ext', SOURCE_PATH . '/php-src/ext/maxminddb');
|
||||
$this->source_dir = SOURCE_PATH . '/php-src/ext/maxminddb';
|
||||
return true;
|
||||
}
|
||||
$this->source_dir = SOURCE_PATH . '/php-src/ext/maxminddb';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,9 @@ class memcache extends Extension
|
||||
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
if (!$this->isBuildStatic()) {
|
||||
return false;
|
||||
}
|
||||
FileSystem::replaceFileStr(
|
||||
SOURCE_PATH . '/php-src/ext/memcache/config9.m4',
|
||||
'if test -d $abs_srcdir/src ; then',
|
||||
@ -43,4 +46,27 @@ EOF
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function patchBeforeSharedConfigure(): bool
|
||||
{
|
||||
if (!$this->isBuildShared()) {
|
||||
return false;
|
||||
}
|
||||
FileSystem::replaceFileStr(
|
||||
SOURCE_PATH . '/php-src/ext/memcache/config9.m4',
|
||||
'if test -d $abs_srcdir/main ; then',
|
||||
'if test -d $abs_srcdir/src ; then',
|
||||
);
|
||||
FileSystem::replaceFileStr(
|
||||
SOURCE_PATH . '/php-src/ext/memcache/config9.m4',
|
||||
'export CPPFLAGS="$CPPFLAGS $INCLUDES -I$abs_srcdir/main"',
|
||||
'export CPPFLAGS="$CPPFLAGS $INCLUDES"',
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function getExtraEnv(): array
|
||||
{
|
||||
return ['CFLAGS' => '-std=c17'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,4 +24,9 @@ class mongodb extends Extension
|
||||
$arg .= $this->builder->getLib('zlib') ? ' --with-mongodb-zlib=yes ' : ' --with-mongodb-zlib=bundled ';
|
||||
return clean_spaces($arg);
|
||||
}
|
||||
|
||||
public function getExtraEnv(): array
|
||||
{
|
||||
return ['CFLAGS' => '-std=c17'];
|
||||
}
|
||||
}
|
||||
|
||||
22
src/SPC/builder/extension/mysqlnd_ed25519.php
Normal file
22
src/SPC/builder/extension/mysqlnd_ed25519.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('mysqlnd_ed25519')]
|
||||
class mysqlnd_ed25519 extends Extension
|
||||
{
|
||||
public function getConfigureArg(bool $shared = false): string
|
||||
{
|
||||
return '--with-mysqlnd_ed25519' . ($shared ? '=shared' : '');
|
||||
}
|
||||
|
||||
public function getUnixConfigureArg(bool $shared = false): string
|
||||
{
|
||||
return $this->getConfigureArg();
|
||||
}
|
||||
}
|
||||
22
src/SPC/builder/extension/mysqlnd_parsec.php
Normal file
22
src/SPC/builder/extension/mysqlnd_parsec.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('mysqlnd_parsec')]
|
||||
class mysqlnd_parsec extends Extension
|
||||
{
|
||||
public function getConfigureArg(bool $shared = false): string
|
||||
{
|
||||
return '--enable-mysqlnd_parsec' . ($shared ? '=shared' : '');
|
||||
}
|
||||
|
||||
public function getUnixConfigureArg(bool $shared = false): string
|
||||
{
|
||||
return $this->getConfigureArg();
|
||||
}
|
||||
}
|
||||
@ -24,25 +24,6 @@ class password_argon2 extends Extension
|
||||
}
|
||||
}
|
||||
|
||||
public function patchBeforeMake(): bool
|
||||
{
|
||||
$patched = parent::patchBeforeMake();
|
||||
if ($this->builder->getLib('libsodium') !== null) {
|
||||
$extraLibs = getenv('SPC_EXTRA_LIBS');
|
||||
if ($extraLibs !== false) {
|
||||
$extraLibs = str_replace(
|
||||
[BUILD_LIB_PATH . '/libargon2.a', BUILD_LIB_PATH . '/libsodium.a'],
|
||||
['', BUILD_LIB_PATH . '/libargon2.a ' . BUILD_LIB_PATH . '/libsodium.a'],
|
||||
$extraLibs,
|
||||
);
|
||||
$extraLibs = trim(preg_replace('/\s+/', ' ', $extraLibs)); // normalize spacing
|
||||
f_putenv('SPC_EXTRA_LIBS=' . $extraLibs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return $patched;
|
||||
}
|
||||
|
||||
public function getConfigureArg(bool $shared = false): string
|
||||
{
|
||||
if ($this->builder->getLib('openssl') !== null) {
|
||||
|
||||
@ -45,7 +45,7 @@ class pgsql extends Extension
|
||||
protected function getExtraEnv(): array
|
||||
{
|
||||
return [
|
||||
'CFLAGS' => '-Wno-int-conversion',
|
||||
'CFLAGS' => '-std=c17 -Wno-int-conversion',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ namespace SPC\builder\extension;
|
||||
use SPC\builder\Extension;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
use SPC\util\SPCConfigUtil;
|
||||
|
||||
#[CustomExt('rdkafka')]
|
||||
class rdkafka extends Extension
|
||||
@ -15,6 +16,7 @@ class rdkafka extends Extension
|
||||
{
|
||||
FileSystem::replaceFileStr("{$this->source_dir}/config.m4", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm\n", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm \$RDKAFKA_LIBS\n");
|
||||
FileSystem::replaceFileStr("{$this->source_dir}/config.m4", "-L\$RDKAFKA_DIR/\$PHP_LIBDIR -lm\"\n", '-L$RDKAFKA_DIR/$PHP_LIBDIR -lm $RDKAFKA_LIBS"');
|
||||
FileSystem::replaceFileStr("{$this->source_dir}/config.m4", 'PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,', 'AC_CHECK_LIB([$LIBNAME], [$LIBSYMBOL],');
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -37,8 +39,7 @@ class rdkafka extends Extension
|
||||
|
||||
public function getUnixConfigureArg(bool $shared = false): string
|
||||
{
|
||||
$pkgconf_libs = shell()->execWithResult('pkg-config --libs --static rdkafka')[1];
|
||||
$pkgconf_libs = trim(implode('', $pkgconf_libs));
|
||||
return '--with-rdkafka=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . ' RDKAFKA_LIBS="' . $pkgconf_libs . '"';
|
||||
$pkgconf_libs = (new SPCConfigUtil($this->builder, ['no_php' => true, 'libs_only_deps' => true]))->getExtensionConfig($this);
|
||||
return '--with-rdkafka=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . " RDKAFKA_LIBS=\"{$pkgconf_libs['libs']}\"";
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\exception\ValidationException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
@ -23,12 +24,7 @@ class readline extends Extension
|
||||
|
||||
public function getUnixConfigureArg(bool $shared = false): string
|
||||
{
|
||||
$enable = '--without-libedit --with-readline=' . BUILD_ROOT_PATH;
|
||||
if ($this->builder->getPHPVersionID() < 84000) {
|
||||
// the check uses `char rl_pending_input()` instead of `extern int rl_pending_input`, which makes LTO fail
|
||||
$enable .= ' ac_cv_lib_readline_rl_pending_input=yes';
|
||||
}
|
||||
return $enable;
|
||||
return '--with-libedit --without-readline';
|
||||
}
|
||||
|
||||
public function buildUnixShared(): void
|
||||
@ -39,4 +35,13 @@ class readline extends Extension
|
||||
}
|
||||
parent::buildUnixShared();
|
||||
}
|
||||
|
||||
public function runCliCheckUnix(): void
|
||||
{
|
||||
parent::runCliCheckUnix();
|
||||
[$ret, $out] = shell()->execWithResult('printf "exit\n" | ' . BUILD_BIN_PATH . '/php -a');
|
||||
if ($ret !== 0 || !str_contains(implode("\n", $out), 'Interactive shell')) {
|
||||
throw new ValidationException("readline extension failed sanity check. Code: {$ret}, output: " . implode("\n", $out));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
29
src/SPC/builder/extension/snmp.php
Normal file
29
src/SPC/builder/extension/snmp.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
use SPC\util\PkgConfigUtil;
|
||||
|
||||
#[CustomExt('snmp')]
|
||||
class snmp extends Extension
|
||||
{
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
// Overwrite m4 config using newer PHP version
|
||||
if ($this->builder->getPHPVersionID() < 80400) {
|
||||
FileSystem::copy(ROOT_DIR . '/src/globals/extra/snmp-ext-config-old.m4', "{$this->source_dir}/config.m4");
|
||||
}
|
||||
$libs = implode(' ', PkgConfigUtil::getLibsArray('netsnmp'));
|
||||
FileSystem::replaceFileStr(
|
||||
"{$this->source_dir}/config.m4",
|
||||
'PHP_EVAL_LIBLINE([$SNMP_LIBS], [SNMP_SHARED_LIBADD])',
|
||||
"SNMP_LIBS=\"{$libs}\"\nPHP_EVAL_LIBLINE([\$SNMP_LIBS], [SNMP_SHARED_LIBADD])"
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,7 @@ class spx extends Extension
|
||||
{
|
||||
public function getUnixConfigureArg(bool $shared = false): string
|
||||
{
|
||||
$arg = '--enable-spx' . ($shared ? '=shared' : '');
|
||||
$arg = '--enable-SPX' . ($shared ? '=shared' : '');
|
||||
if ($this->builder->getLib('zlib') !== null) {
|
||||
$arg .= ' --with-zlib-dir=' . BUILD_ROOT_PATH;
|
||||
}
|
||||
@ -29,4 +29,27 @@ class spx extends Extension
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
FileSystem::replaceFileStr(
|
||||
$this->source_dir . '/config.m4',
|
||||
'CFLAGS="$CFLAGS -Werror -Wall -O3 -pthread -std=gnu90"',
|
||||
'CFLAGS="$CFLAGS -pthread"'
|
||||
);
|
||||
FileSystem::replaceFileStr(
|
||||
$this->source_dir . '/src/php_spx.h',
|
||||
"extern zend_module_entry spx_module_entry;\n",
|
||||
"extern zend_module_entry spx_module_entry;;\n#define phpext_spx_ptr &spx_module_entry\n"
|
||||
);
|
||||
FileSystem::copy($this->source_dir . '/src/php_spx.h', $this->source_dir . '/php_spx.h');
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getSharedExtensionEnv(): array
|
||||
{
|
||||
$env = parent::getSharedExtensionEnv();
|
||||
$env['SPX_SHARED_LIBADD'] = $env['LIBS'];
|
||||
return $env;
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ class swoole extends Extension
|
||||
public function patchBeforeMake(): bool
|
||||
{
|
||||
$patched = parent::patchBeforeMake();
|
||||
FileSystem::replaceFileStr($this->source_dir . '/ext-src/php_swoole_private.h', 'PHP_VERSION_ID > 80500', 'PHP_VERSION_ID >= 80600');
|
||||
if ($this->builder instanceof MacOSBuilder) {
|
||||
// Fix swoole with event extension <util.h> conflict bug
|
||||
$util_path = shell()->execWithResult('xcrun --show-sdk-path', false)[1][0] . '/usr/include/util.h';
|
||||
@ -49,19 +50,16 @@ class swoole extends Extension
|
||||
|
||||
// commonly used feature: coroutine-time
|
||||
$arg .= ' --enable-swoole-coro-time --with-pic';
|
||||
$arg .= ' --enable-swoole-ssh --enable-swoole-curl';
|
||||
|
||||
$arg .= $this->builder->getOption('enable-zts') ? ' --enable-swoole-thread --disable-thread-context' : ' --disable-swoole-thread --enable-thread-context';
|
||||
|
||||
// required features: curl, openssl (but curl hook is buggy for php 8.0)
|
||||
$arg .= $this->builder->getPHPVersionID() >= 80100 ? ' --enable-swoole-curl' : ' --disable-swoole-curl';
|
||||
$arg .= ' --enable-openssl';
|
||||
|
||||
// additional features that only require libraries
|
||||
$arg .= $this->builder->getLib('libcares') ? ' --enable-cares' : '';
|
||||
$arg .= $this->builder->getLib('brotli') ? (' --enable-brotli --with-brotli-dir=' . BUILD_ROOT_PATH) : '';
|
||||
$arg .= $this->builder->getLib('nghttp2') ? (' --with-nghttp2-dir=' . BUILD_ROOT_PATH) : '';
|
||||
$arg .= $this->builder->getLib('zstd') ? ' --enable-zstd' : '';
|
||||
$arg .= $this->builder->getLib('liburing') ? ' --enable-iouring' : '';
|
||||
$arg .= $this->builder->getLib('liburing') ? ' --enable-iouring --enable-uring-socket' : '';
|
||||
$arg .= $this->builder->getExt('sockets') ? ' --enable-sockets' : '';
|
||||
|
||||
// enable additional features that require the pdo extension, but conflict with pdo_* extensions
|
||||
@ -69,11 +67,15 @@ class swoole extends Extension
|
||||
$arg .= $this->builder->getExt('swoole-hook-pgsql') ? ' --enable-swoole-pgsql' : ' --disable-swoole-pgsql';
|
||||
$arg .= $this->builder->getExt('swoole-hook-mysql') ? ' --enable-mysqlnd' : ' --disable-mysqlnd';
|
||||
$arg .= $this->builder->getExt('swoole-hook-sqlite') ? ' --enable-swoole-sqlite' : ' --disable-swoole-sqlite';
|
||||
|
||||
if ($this->builder->getExt('swoole-hook-odbc')) {
|
||||
$config = (new SPCConfigUtil($this->builder, ['libs_only_deps' => true]))->config([], ['unixodbc']);
|
||||
$config = (new SPCConfigUtil($this->builder))->getLibraryConfig($this->builder->getLib('unixodbc'));
|
||||
$arg .= ' --with-swoole-odbc=unixODBC,' . BUILD_ROOT_PATH . ' SWOOLE_ODBC_LIBS="' . $config['libs'] . '"';
|
||||
}
|
||||
$arg .= $this->builder->getExt('ftp')?->isBuildStatic() ? ' --disable-swoole-ftp' : ' --enable-swoole-ftp';
|
||||
|
||||
if ($this->getExtVersion() >= '6.1.0') {
|
||||
$arg .= ' --enable-swoole-stdext';
|
||||
}
|
||||
|
||||
if (SPCTarget::getTargetOS() === 'Darwin') {
|
||||
$arg .= ' ac_cv_lib_pthread_pthread_barrier_init=no';
|
||||
|
||||
19
src/SPC/builder/extension/trader.php
Normal file
19
src/SPC/builder/extension/trader.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('trader')]
|
||||
class trader extends Extension
|
||||
{
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/ext/trader/config.m4', 'PHP_TA', 'PHP_TRADER');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -153,7 +153,7 @@ class BSDBuilder extends UnixBuilderBase
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
$shell->exec('strip sapi/cli/php');
|
||||
}
|
||||
$this->deployBinary(BUILD_TARGET_CLI);
|
||||
$this->deploySAPIBinary(BUILD_TARGET_CLI);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -184,7 +184,7 @@ class BSDBuilder extends UnixBuilderBase
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/micro')->exec('strip --strip-unneeded micro.sfx');
|
||||
}
|
||||
$this->deployBinary(BUILD_TARGET_MICRO);
|
||||
$this->deploySAPIBinary(BUILD_TARGET_MICRO);
|
||||
|
||||
if ($this->phar_patched) {
|
||||
SourcePatcher::unpatchMicroPhar();
|
||||
@ -206,7 +206,7 @@ class BSDBuilder extends UnixBuilderBase
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
$shell->exec('strip sapi/fpm/php-fpm');
|
||||
}
|
||||
$this->deployBinary(BUILD_TARGET_FPM);
|
||||
$this->deploySAPIBinary(BUILD_TARGET_FPM);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -7,6 +7,8 @@ namespace SPC\builder\linux;
|
||||
use SPC\builder\unix\UnixBuilderBase;
|
||||
use SPC\exception\PatchException;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\DirDiff;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\SourcePatcher;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
@ -89,7 +91,7 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
// prepare build php envs
|
||||
// $musl_flag = SPCTarget::getLibc() === 'musl' ? ' -D__MUSL__' : ' -U__MUSL__';
|
||||
$php_configure_env = SystemUtil::makeEnvVarString([
|
||||
'CFLAGS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS'),
|
||||
'CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'),
|
||||
'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, // . ' -Dsomethinghere', // . $musl_flag,
|
||||
'LDFLAGS' => '-L' . BUILD_LIB_PATH,
|
||||
// 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions!
|
||||
@ -107,19 +109,19 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
|
||||
$this->seekPhpSrcLogFileOnException(fn () => shell()->cd(SOURCE_PATH . '/php-src')->exec(
|
||||
$php_configure_env . ' ' .
|
||||
getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' .
|
||||
($enableCli ? '--enable-cli ' : '--disable-cli ') .
|
||||
($enableFpm ? '--enable-fpm ' . ($this->getLib('libacl') !== null ? '--with-fpm-acl ' : '') : '--disable-fpm ') .
|
||||
($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') .
|
||||
($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') .
|
||||
($enableCgi ? '--enable-cgi ' : '--disable-cgi ') .
|
||||
$config_file_path .
|
||||
$config_file_scan_dir .
|
||||
$json_74 .
|
||||
$zts .
|
||||
$maxExecutionTimers .
|
||||
"{$phpvars} " .
|
||||
$this->makeStaticExtensionArgs() . ' '
|
||||
getenv('SPC_CMD_PREFIX_PHP_CONFIGURE') . ' ' .
|
||||
($enableCli ? '--enable-cli ' : '--disable-cli ') .
|
||||
($enableFpm ? '--enable-fpm ' . ($this->getLib('libacl') !== null ? '--with-fpm-acl ' : '') : '--disable-fpm ') .
|
||||
($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') .
|
||||
($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') .
|
||||
($enableCgi ? '--enable-cgi ' : '--disable-cgi ') .
|
||||
$config_file_path .
|
||||
$config_file_scan_dir .
|
||||
$json_74 .
|
||||
$zts .
|
||||
$maxExecutionTimers .
|
||||
$phpvars . ' ' .
|
||||
$this->makeStaticExtensionArgs() . ' '
|
||||
));
|
||||
|
||||
$this->emitPatchPoint('before-php-make');
|
||||
@ -179,47 +181,32 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
*/
|
||||
protected function buildCli(): void
|
||||
{
|
||||
if ($this->getExt('readline')) {
|
||||
if ($this->getExt('readline') && SPCTarget::isStatic()) {
|
||||
SourcePatcher::patchFile('musl_static_readline.patch', SOURCE_PATH . '/php-src');
|
||||
}
|
||||
|
||||
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
|
||||
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
|
||||
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cli");
|
||||
->exec("make {$concurrency} {$vars} cli");
|
||||
|
||||
if ($this->getExt('readline')) {
|
||||
if ($this->getExt('readline') && SPCTarget::isStatic()) {
|
||||
SourcePatcher::patchFile('musl_static_readline.patch', SOURCE_PATH . '/php-src', true);
|
||||
}
|
||||
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')->exec('strip --strip-unneeded php');
|
||||
}
|
||||
if ($this->getOption('with-upx-pack')) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/cli')
|
||||
->exec(getenv('UPX_EXEC') . ' --best php');
|
||||
}
|
||||
|
||||
$this->deployBinary(BUILD_TARGET_CLI);
|
||||
$this->deploySAPIBinary(BUILD_TARGET_CLI);
|
||||
}
|
||||
|
||||
protected function buildCgi(): void
|
||||
{
|
||||
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
|
||||
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
|
||||
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cgi");
|
||||
->exec("make {$concurrency} {$vars} cgi");
|
||||
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/cgi')->exec('strip --strip-unneeded php-cgi');
|
||||
}
|
||||
if ($this->getOption('with-upx-pack')) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/cgi')
|
||||
->exec(getenv('UPX_EXEC') . ' --best php-cgi');
|
||||
}
|
||||
|
||||
$this->deployBinary(BUILD_TARGET_CGI);
|
||||
$this->deploySAPIBinary(BUILD_TARGET_CGI);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -230,29 +217,33 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
if ($this->getPHPVersionID() < 80000) {
|
||||
throw new WrongUsageException('phpmicro only support PHP >= 8.0!');
|
||||
}
|
||||
if ($this->getExt('phar')) {
|
||||
$this->phar_patched = true;
|
||||
SourcePatcher::patchMicroPhar($this->getPHPVersionID());
|
||||
}
|
||||
try {
|
||||
if ($this->getExt('phar')) {
|
||||
$this->phar_patched = true;
|
||||
SourcePatcher::patchMicroPhar($this->getPHPVersionID());
|
||||
}
|
||||
|
||||
$enable_fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' -DPHP_MICRO_FAKE_CLI' : '';
|
||||
$vars = $this->getMakeExtraVars();
|
||||
$enable_fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' -DPHP_MICRO_FAKE_CLI' : '';
|
||||
$vars = $this->getMakeExtraVars();
|
||||
|
||||
// patch fake cli for micro
|
||||
$vars['EXTRA_CFLAGS'] .= $enable_fake_cli;
|
||||
$vars = SystemUtil::makeEnvVarString($vars);
|
||||
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
|
||||
// patch fake cli for micro
|
||||
$vars['EXTRA_CFLAGS'] .= $enable_fake_cli;
|
||||
$vars = SystemUtil::makeEnvVarString($vars);
|
||||
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} micro");
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||
->exec("make {$concurrency} {$vars} micro");
|
||||
|
||||
$this->processMicroUPX();
|
||||
// deploy micro.sfx
|
||||
$dst = $this->deploySAPIBinary(BUILD_TARGET_MICRO);
|
||||
|
||||
$this->deployBinary(BUILD_TARGET_MICRO);
|
||||
|
||||
if ($this->phar_patched) {
|
||||
SourcePatcher::unpatchMicroPhar();
|
||||
// patch after UPX-ed micro.sfx
|
||||
$this->processUpxedMicroSfx($dst);
|
||||
} finally {
|
||||
if ($this->phar_patched) {
|
||||
SourcePatcher::unpatchMicroPhar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,19 +253,12 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
protected function buildFpm(): void
|
||||
{
|
||||
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
|
||||
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
|
||||
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||
->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} fpm");
|
||||
->exec("make {$concurrency} {$vars} fpm");
|
||||
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')->exec('strip --strip-unneeded php-fpm');
|
||||
}
|
||||
if ($this->getOption('with-upx-pack')) {
|
||||
shell()->cd(SOURCE_PATH . '/php-src/sapi/fpm')
|
||||
->exec(getenv('UPX_EXEC') . ' --best php-fpm');
|
||||
}
|
||||
$this->deployBinary(BUILD_TARGET_FPM);
|
||||
$this->deploySAPIBinary(BUILD_TARGET_FPM);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -282,79 +266,40 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
*/
|
||||
protected function buildEmbed(): void
|
||||
{
|
||||
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
|
||||
$sharedExts = array_filter($this->exts, static fn ($ext) => $ext->isBuildShared());
|
||||
$sharedExts = array_filter($sharedExts, static function ($ext) {
|
||||
return Config::getExt($ext->getName(), 'build-with-php') === true;
|
||||
});
|
||||
$install_modules = $sharedExts ? 'install-modules' : '';
|
||||
|
||||
// detect changes in module path
|
||||
$diff = new DirDiff(BUILD_MODULES_PATH, true);
|
||||
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
|
||||
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec('sed -i "s|//lib|/lib|g" Makefile')
|
||||
->exec('sed -i "s|^EXTENSION_DIR = .*|EXTENSION_DIR = /' . basename(BUILD_MODULES_PATH) . '|" Makefile')
|
||||
->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install");
|
||||
->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi {$install_modules} install-build install-headers install-programs");
|
||||
|
||||
$ldflags = getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS') ?: '';
|
||||
$libDir = BUILD_LIB_PATH;
|
||||
$modulesDir = BUILD_MODULES_PATH;
|
||||
$libphpSo = "{$libDir}/libphp.so";
|
||||
$realLibName = 'libphp.so';
|
||||
$cwd = getcwd();
|
||||
|
||||
if (preg_match('/-release\s+(\S+)/', $ldflags, $matches)) {
|
||||
$release = $matches[1];
|
||||
$realLibName = "libphp-{$release}.so";
|
||||
$libphpRelease = "{$libDir}/{$realLibName}";
|
||||
if (!file_exists($libphpRelease) && file_exists($libphpSo)) {
|
||||
rename($libphpSo, $libphpRelease);
|
||||
// process libphp.so for shared embed
|
||||
$libphpSo = BUILD_LIB_PATH . '/libphp.so';
|
||||
$libphpSoDest = BUILD_LIB_PATH . '/libphp.so';
|
||||
if (file_exists($libphpSo)) {
|
||||
// deploy libphp.so
|
||||
preg_match('/-release\s+(\S*)/', getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'), $matches);
|
||||
if (!empty($matches[1])) {
|
||||
$libphpSoDest = str_replace('.so', '-' . $matches[1] . '.so', $libphpSo);
|
||||
}
|
||||
if (file_exists($libphpRelease)) {
|
||||
chdir($libDir);
|
||||
if (file_exists($libphpSo)) {
|
||||
unlink($libphpSo);
|
||||
}
|
||||
symlink($realLibName, 'libphp.so');
|
||||
shell()->exec(sprintf(
|
||||
'patchelf --set-soname %s %s',
|
||||
escapeshellarg($realLibName),
|
||||
escapeshellarg($libphpRelease)
|
||||
));
|
||||
}
|
||||
if (is_dir($modulesDir)) {
|
||||
chdir($modulesDir);
|
||||
foreach ($this->getExts() as $ext) {
|
||||
if (!$ext->isBuildShared()) {
|
||||
continue;
|
||||
}
|
||||
$name = $ext->getName();
|
||||
$versioned = "{$name}-{$release}.so";
|
||||
$unversioned = "{$name}.so";
|
||||
$src = "{$modulesDir}/{$versioned}";
|
||||
$dst = "{$modulesDir}/{$unversioned}";
|
||||
if (is_file($src)) {
|
||||
rename($src, $dst);
|
||||
shell()->exec(sprintf(
|
||||
'patchelf --set-soname %s %s',
|
||||
escapeshellarg($unversioned),
|
||||
escapeshellarg($dst)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
chdir($cwd);
|
||||
$this->deployBinary($libphpSo, $libphpSoDest, false);
|
||||
}
|
||||
|
||||
$target = "{$libDir}/{$realLibName}";
|
||||
if (file_exists($target)) {
|
||||
[, $output] = shell()->execWithResult('readelf -d ' . escapeshellarg($target));
|
||||
$output = implode("\n", $output);
|
||||
if (preg_match('/SONAME.*\[(.+)]/', $output, $sonameMatch)) {
|
||||
$currentSoname = $sonameMatch[1];
|
||||
if ($currentSoname !== basename($target)) {
|
||||
shell()->exec(sprintf(
|
||||
'patchelf --set-soname %s %s',
|
||||
escapeshellarg(basename($target)),
|
||||
escapeshellarg($target)
|
||||
));
|
||||
}
|
||||
}
|
||||
// process shared extensions build-with-php
|
||||
$increment_files = $diff->getChangedFiles();
|
||||
foreach ($increment_files as $increment_file) {
|
||||
$this->deployBinary($increment_file, $increment_file, false);
|
||||
}
|
||||
|
||||
// process libphp.a for static embed
|
||||
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') {
|
||||
$AR = getenv('AR') ?: 'ar';
|
||||
f_passthru("{$AR} -t " . BUILD_LIB_PATH . "/libphp.a | grep '\\.a$' | xargs -n1 {$AR} d " . BUILD_LIB_PATH . '/libphp.a');
|
||||
@ -362,9 +307,7 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
SystemUtil::exportDynamicSymbols(BUILD_LIB_PATH . '/libphp.a');
|
||||
}
|
||||
|
||||
if (!$this->getOption('no-strip', false) && file_exists(BUILD_LIB_PATH . '/' . $realLibName)) {
|
||||
shell()->cd(BUILD_LIB_PATH)->exec("strip --strip-unneeded {$realLibName}");
|
||||
}
|
||||
// patch embed php scripts
|
||||
$this->patchPhpScripts();
|
||||
}
|
||||
|
||||
@ -376,38 +319,35 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
$config = (new SPCConfigUtil($this, ['libs_only_deps' => true, 'absolute_libs' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
|
||||
$static = SPCTarget::isStatic() ? '-all-static' : '';
|
||||
$lib = BUILD_LIB_PATH;
|
||||
return [
|
||||
return array_filter([
|
||||
'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'),
|
||||
'EXTRA_LIBS' => $config['libs'],
|
||||
'EXTRA_LDFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS'),
|
||||
'EXTRA_LDFLAGS_PROGRAM' => "-L{$lib} {$static} -pie",
|
||||
];
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip micro.sfx for Linux.
|
||||
* The micro.sfx does not support UPX directly, but we can remove UPX-info segment to adapt.
|
||||
* This will also make micro.sfx with upx-packed more like a malware fore antivirus :(
|
||||
* Patch micro.sfx after UPX compression.
|
||||
* micro needs special section handling in LinuxBuilder.
|
||||
* The micro.sfx does not support UPX directly, but we can remove UPX
|
||||
* info segment to adapt.
|
||||
* This will also make micro.sfx with upx-packed more like a malware fore antivirus
|
||||
*/
|
||||
private function processMicroUPX(): void
|
||||
private function processUpxedMicroSfx(string $dst): void
|
||||
{
|
||||
if (version_compare($this->getMicroVersion(), '0.2.0') >= 0 && !$this->getOption('no-strip', false)) {
|
||||
shell()->exec('strip --strip-unneeded ' . SOURCE_PATH . '/php-src/sapi/micro/micro.sfx');
|
||||
|
||||
if ($this->getOption('with-upx-pack')) {
|
||||
// strip first
|
||||
shell()->exec(getenv('UPX_EXEC') . ' --best ' . SOURCE_PATH . '/php-src/sapi/micro/micro.sfx');
|
||||
// cut binary with readelf
|
||||
[$ret, $out] = shell()->execWithResult('readelf -l ' . SOURCE_PATH . '/php-src/sapi/micro/micro.sfx | awk \'/LOAD|GNU_STACK/ {getline; print $1, $2, $3, $4, $6, $7}\'');
|
||||
$out[1] = explode(' ', $out[1]);
|
||||
$offset = $out[1][0];
|
||||
if ($ret !== 0 || !str_starts_with($offset, '0x')) {
|
||||
throw new PatchException('phpmicro UPX patcher', 'Cannot find offset in readelf output');
|
||||
}
|
||||
$offset = hexdec($offset);
|
||||
// remove upx extra wastes
|
||||
file_put_contents(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx', substr(file_get_contents(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx'), 0, $offset));
|
||||
if ($this->getOption('with-upx-pack') && version_compare($this->getMicroVersion(), '0.2.0') >= 0) {
|
||||
// strip first
|
||||
// cut binary with readelf
|
||||
[$ret, $out] = shell()->execWithResult("readelf -l {$dst} | awk '/LOAD|GNU_STACK/ {getline; print \$1, \$2, \$3, \$4, \$6, \$7}'");
|
||||
$out[1] = explode(' ', $out[1]);
|
||||
$offset = $out[1][0];
|
||||
if ($ret !== 0 || !str_starts_with($offset, '0x')) {
|
||||
throw new PatchException('phpmicro UPX patcher', 'Cannot find offset in readelf output');
|
||||
}
|
||||
$offset = hexdec($offset);
|
||||
// remove upx extra wastes
|
||||
file_put_contents($dst, substr(file_get_contents($dst), 0, $offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
12
src/SPC/builder/linux/library/idn2.php
Normal file
12
src/SPC/builder/linux/library/idn2.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class idn2 extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\idn2;
|
||||
|
||||
public const NAME = 'idn2';
|
||||
}
|
||||
12
src/SPC/builder/linux/library/krb5.php
Normal file
12
src/SPC/builder/linux/library/krb5.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class krb5 extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\krb5;
|
||||
|
||||
public const NAME = 'krb5';
|
||||
}
|
||||
12
src/SPC/builder/linux/library/libedit.php
Normal file
12
src/SPC/builder/linux/library/libedit.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class libedit extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\libedit;
|
||||
|
||||
public const NAME = 'libedit';
|
||||
}
|
||||
12
src/SPC/builder/linux/library/libmaxminddb.php
Normal file
12
src/SPC/builder/linux/library/libmaxminddb.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class libmaxminddb extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\libmaxminddb;
|
||||
|
||||
public const NAME = 'libmaxminddb';
|
||||
}
|
||||
12
src/SPC/builder/linux/library/libunistring.php
Normal file
12
src/SPC/builder/linux/library/libunistring.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class libunistring extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\libunistring;
|
||||
|
||||
public const NAME = 'libunistring';
|
||||
}
|
||||
@ -6,6 +6,8 @@ namespace SPC\builder\linux\library;
|
||||
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\toolchain\GccNativeToolchain;
|
||||
use SPC\toolchain\ToolchainManager;
|
||||
use SPC\util\executor\UnixAutoconfExecutor;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
@ -15,26 +17,19 @@ class liburing extends LinuxLibraryBase
|
||||
|
||||
public function patchBeforeBuild(): bool
|
||||
{
|
||||
if (!SystemUtil::isMuslDist()) {
|
||||
return false;
|
||||
if (SystemUtil::isMuslDist()) {
|
||||
FileSystem::replaceFileStr($this->source_dir . '/configure', 'realpath -s', 'realpath');
|
||||
return true;
|
||||
}
|
||||
FileSystem::replaceFileStr($this->source_dir . '/configure', 'realpath -s', 'realpath');
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
$use_libc = SPCTarget::getLibc() !== 'glibc' || version_compare(SPCTarget::getLibcVersion(), '2.30', '>=');
|
||||
$use_libc = ToolchainManager::getToolchainClass() !== GccNativeToolchain::class || version_compare(SPCTarget::getLibcVersion(), '2.30', '>=');
|
||||
$make = UnixAutoconfExecutor::create($this);
|
||||
|
||||
if (!$use_libc) {
|
||||
$make->appendEnv([
|
||||
'CC' => 'gcc', // libc-less version fails to compile with clang or zig
|
||||
'CXX' => 'g++',
|
||||
'AR' => 'ar',
|
||||
'LD' => 'ld',
|
||||
]);
|
||||
} else {
|
||||
if ($use_libc) {
|
||||
$make->appendEnv([
|
||||
'CFLAGS' => '-D_GNU_SOURCE',
|
||||
]);
|
||||
@ -51,7 +46,7 @@ class liburing extends LinuxLibraryBase
|
||||
$use_libc ? '--use-libc' : '',
|
||||
)
|
||||
->configure()
|
||||
->make('library', 'install ENABLE_SHARED=0', with_clean: false);
|
||||
->make('library ENABLE_SHARED=0', 'install ENABLE_SHARED=0', with_clean: false);
|
||||
|
||||
$this->patchPkgconfPrefix();
|
||||
}
|
||||
|
||||
12
src/SPC/builder/linux/library/net_snmp.php
Normal file
12
src/SPC/builder/linux/library/net_snmp.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
class net_snmp extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\net_snmp;
|
||||
|
||||
public const NAME = 'net-snmp';
|
||||
}
|
||||
@ -21,6 +21,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\store\FileSystem;
|
||||
|
||||
class openssl extends LinuxLibraryBase
|
||||
@ -51,6 +52,9 @@ class openssl extends LinuxLibraryBase
|
||||
$zlib_extra = '';
|
||||
}
|
||||
|
||||
$openssl_dir = getenv('OPENSSLDIR') ?: null;
|
||||
// TODO: in v3 use the following: $openssl_dir ??= SystemUtil::getOSRelease()['dist'] === 'redhat' ? '/etc/pki/tls' : '/etc/ssl';
|
||||
$openssl_dir ??= '/etc/ssl';
|
||||
$ex_lib = trim($ex_lib);
|
||||
|
||||
shell()->cd($this->source_dir)->initializeEnv($this)
|
||||
@ -58,10 +62,11 @@ class openssl extends LinuxLibraryBase
|
||||
"{$env} ./Configure no-shared {$extra} " .
|
||||
'--prefix=' . BUILD_ROOT_PATH . ' ' .
|
||||
'--libdir=' . BUILD_LIB_PATH . ' ' .
|
||||
'--openssldir=/etc/ssl ' .
|
||||
"--openssldir={$openssl_dir} " .
|
||||
"{$zlib_extra}" .
|
||||
'enable-pie ' .
|
||||
'no-legacy ' .
|
||||
'no-tests ' .
|
||||
"linux-{$arch}"
|
||||
)
|
||||
->exec('make clean')
|
||||
@ -78,7 +83,7 @@ class openssl extends LinuxLibraryBase
|
||||
if (!str_contains($file = FileSystem::readFile(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc'), 'prefix=')) {
|
||||
FileSystem::writeFile(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc', 'prefix=' . BUILD_ROOT_PATH . "\n" . $file);
|
||||
}
|
||||
FileSystem::replaceFileRegex(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc', '/Libs.private:.*/m', 'Libs.private: ${libdir}/libz.a');
|
||||
FileSystem::replaceFileRegex(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc', '/Libs.private:.*/m', 'Requires.private: zlib');
|
||||
FileSystem::replaceFileRegex(BUILD_LIB_PATH . '/cmake/OpenSSL/OpenSSLConfig.cmake', '/set\(OPENSSL_LIBCRYPTO_DEPENDENCIES .*\)/m', 'set(OPENSSL_LIBCRYPTO_DEPENDENCIES "${OPENSSL_LIBRARY_DIR}/libz.a")');
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,9 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\linux\library;
|
||||
|
||||
/**
|
||||
* gmp is a template library class for unix
|
||||
*/
|
||||
class readline extends LinuxLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\readline;
|
||||
|
||||
@ -7,6 +7,8 @@ namespace SPC\builder\macos;
|
||||
use SPC\builder\macos\library\MacOSLibraryBase;
|
||||
use SPC\builder\unix\UnixBuilderBase;
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\DirDiff;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\SourcePatcher;
|
||||
use SPC\util\GlobalEnvManager;
|
||||
@ -104,7 +106,7 @@ class MacOSBuilder extends UnixBuilderBase
|
||||
|
||||
// prepare build php envs
|
||||
$envs_build_php = SystemUtil::makeEnvVarString([
|
||||
'CFLAGS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS'),
|
||||
'CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'),
|
||||
'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH,
|
||||
'LDFLAGS' => '-L' . BUILD_LIB_PATH,
|
||||
]);
|
||||
@ -186,12 +188,9 @@ class MacOSBuilder extends UnixBuilderBase
|
||||
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
|
||||
|
||||
$shell = shell()->cd(SOURCE_PATH . '/php-src');
|
||||
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
|
||||
$shell->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cli");
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
$shell->exec('dsymutil -f sapi/cli/php')->exec('strip -S sapi/cli/php');
|
||||
}
|
||||
$this->deployBinary(BUILD_TARGET_CLI);
|
||||
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
|
||||
$shell->exec("make {$concurrency} {$vars} cli");
|
||||
$this->deploySAPIBinary(BUILD_TARGET_CLI);
|
||||
}
|
||||
|
||||
protected function buildCgi(): void
|
||||
@ -199,12 +198,9 @@ class MacOSBuilder extends UnixBuilderBase
|
||||
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
|
||||
|
||||
$shell = shell()->cd(SOURCE_PATH . '/php-src');
|
||||
$SPC_CMD_PREFIX_PHP_MAKE = getenv('SPC_CMD_PREFIX_PHP_MAKE') ?: 'make';
|
||||
$shell->exec("{$SPC_CMD_PREFIX_PHP_MAKE} {$vars} cgi");
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
$shell->exec('dsymutil -f sapi/cgi/php-cgi')->exec('strip -S sapi/cgi/php-cgi');
|
||||
}
|
||||
$this->deployBinary(BUILD_TARGET_CGI);
|
||||
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
|
||||
$shell->exec("make {$concurrency} {$vars} cgi");
|
||||
$this->deploySAPIBinary(BUILD_TARGET_CGI);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -215,30 +211,30 @@ class MacOSBuilder extends UnixBuilderBase
|
||||
if ($this->getPHPVersionID() < 80000) {
|
||||
throw new WrongUsageException('phpmicro only support PHP >= 8.0!');
|
||||
}
|
||||
if ($this->getExt('phar')) {
|
||||
$this->phar_patched = true;
|
||||
SourcePatcher::patchMicroPhar($this->getPHPVersionID());
|
||||
}
|
||||
|
||||
$enable_fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' -DPHP_MICRO_FAKE_CLI' : '';
|
||||
$vars = $this->getMakeExtraVars();
|
||||
try {
|
||||
if ($this->getExt('phar')) {
|
||||
$this->phar_patched = true;
|
||||
SourcePatcher::patchMicroPhar($this->getPHPVersionID());
|
||||
}
|
||||
|
||||
// patch fake cli for micro
|
||||
$vars['EXTRA_CFLAGS'] .= $enable_fake_cli;
|
||||
$vars = SystemUtil::makeEnvVarString($vars);
|
||||
$enable_fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' -DPHP_MICRO_FAKE_CLI' : '';
|
||||
$vars = $this->getMakeExtraVars();
|
||||
|
||||
$shell = shell()->cd(SOURCE_PATH . '/php-src');
|
||||
// build
|
||||
$shell->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . " {$vars} micro");
|
||||
// strip
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
$shell->exec('dsymutil -f sapi/micro/micro.sfx')->exec('strip -S sapi/micro/micro.sfx');
|
||||
}
|
||||
// patch fake cli for micro
|
||||
$vars['EXTRA_CFLAGS'] .= $enable_fake_cli;
|
||||
$vars = SystemUtil::makeEnvVarString($vars);
|
||||
|
||||
$this->deployBinary(BUILD_TARGET_MICRO);
|
||||
$shell = shell()->cd(SOURCE_PATH . '/php-src');
|
||||
// build
|
||||
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
|
||||
$shell->exec("make {$concurrency} {$vars} micro");
|
||||
|
||||
if ($this->phar_patched) {
|
||||
SourcePatcher::unpatchMicroPhar();
|
||||
$this->deploySAPIBinary(BUILD_TARGET_MICRO);
|
||||
} finally {
|
||||
if ($this->phar_patched) {
|
||||
SourcePatcher::unpatchMicroPhar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,11 +246,9 @@ class MacOSBuilder extends UnixBuilderBase
|
||||
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
|
||||
|
||||
$shell = shell()->cd(SOURCE_PATH . '/php-src');
|
||||
$shell->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . " {$vars} fpm");
|
||||
if (!$this->getOption('no-strip', false)) {
|
||||
$shell->exec('dsymutil -f sapi/fpm/php-fpm')->exec('strip -S sapi/fpm/php-fpm');
|
||||
}
|
||||
$this->deployBinary(BUILD_TARGET_FPM);
|
||||
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
|
||||
$shell->exec("make {$concurrency} {$vars} fpm");
|
||||
$this->deploySAPIBinary(BUILD_TARGET_FPM);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -262,10 +256,31 @@ class MacOSBuilder extends UnixBuilderBase
|
||||
*/
|
||||
protected function buildEmbed(): void
|
||||
{
|
||||
$sharedExts = array_filter($this->exts, static fn ($ext) => $ext->isBuildShared());
|
||||
$sharedExts = array_filter($sharedExts, static function ($ext) {
|
||||
return Config::getExt($ext->getName(), 'build-with-php') === true;
|
||||
});
|
||||
$install_modules = $sharedExts ? 'install-modules' : '';
|
||||
$vars = SystemUtil::makeEnvVarString($this->getMakeExtraVars());
|
||||
$concurrency = getenv('SPC_CONCURRENCY') ? '-j' . getenv('SPC_CONCURRENCY') : '';
|
||||
|
||||
$diff = new DirDiff(BUILD_MODULES_PATH, true);
|
||||
|
||||
shell()->cd(SOURCE_PATH . '/php-src')
|
||||
->exec(getenv('SPC_CMD_PREFIX_PHP_MAKE') . ' INSTALL_ROOT=' . BUILD_ROOT_PATH . " {$vars} install");
|
||||
->exec('sed -i "" "s|^EXTENSION_DIR = .*|EXTENSION_DIR = /' . basename(BUILD_MODULES_PATH) . '|" Makefile')
|
||||
->exec("make {$concurrency} INSTALL_ROOT=" . BUILD_ROOT_PATH . " {$vars} install-sapi {$install_modules} install-build install-headers install-programs");
|
||||
|
||||
$libphp = BUILD_LIB_PATH . '/libphp.dylib';
|
||||
if (file_exists($libphp)) {
|
||||
$this->deployBinary($libphp, $libphp, false);
|
||||
// macOS currently have no -release option for dylib, so we just rename it here
|
||||
}
|
||||
|
||||
// process shared extensions build-with-php
|
||||
$increment_files = $diff->getChangedFiles();
|
||||
foreach ($increment_files as $increment_file) {
|
||||
$this->deployBinary($increment_file, $increment_file, false);
|
||||
}
|
||||
|
||||
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'static') {
|
||||
$AR = getenv('AR') ?: 'ar';
|
||||
@ -279,10 +294,10 @@ class MacOSBuilder extends UnixBuilderBase
|
||||
private function getMakeExtraVars(): array
|
||||
{
|
||||
$config = (new SPCConfigUtil($this, ['libs_only_deps' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
|
||||
return [
|
||||
return array_filter([
|
||||
'EXTRA_CFLAGS' => getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS'),
|
||||
'EXTRA_LDFLAGS_PROGRAM' => '-L' . BUILD_LIB_PATH,
|
||||
'EXTRA_LIBS' => $config['libs'],
|
||||
];
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
12
src/SPC/builder/macos/library/idn2.php
Normal file
12
src/SPC/builder/macos/library/idn2.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class idn2 extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\idn2;
|
||||
|
||||
public const NAME = 'idn2';
|
||||
}
|
||||
12
src/SPC/builder/macos/library/krb5.php
Normal file
12
src/SPC/builder/macos/library/krb5.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class krb5 extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\krb5;
|
||||
|
||||
public const NAME = 'krb5';
|
||||
}
|
||||
12
src/SPC/builder/macos/library/libedit.php
Normal file
12
src/SPC/builder/macos/library/libedit.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class libedit extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\libedit;
|
||||
|
||||
public const NAME = 'libedit';
|
||||
}
|
||||
12
src/SPC/builder/macos/library/libmaxminddb.php
Normal file
12
src/SPC/builder/macos/library/libmaxminddb.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class libmaxminddb extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\libmaxminddb;
|
||||
|
||||
public const NAME = 'libmaxminddb';
|
||||
}
|
||||
12
src/SPC/builder/macos/library/libunistring.php
Normal file
12
src/SPC/builder/macos/library/libunistring.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class libunistring extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\libunistring;
|
||||
|
||||
public const NAME = 'libunistring';
|
||||
}
|
||||
12
src/SPC/builder/macos/library/net_snmp.php
Normal file
12
src/SPC/builder/macos/library/net_snmp.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
class net_snmp extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\net_snmp;
|
||||
|
||||
public const NAME = 'net-snmp';
|
||||
}
|
||||
@ -63,7 +63,7 @@ class openssl extends MacOSLibraryBase
|
||||
if (!str_contains($file = FileSystem::readFile(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc'), 'prefix=')) {
|
||||
FileSystem::writeFile(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc', 'prefix=' . BUILD_ROOT_PATH . "\n" . $file);
|
||||
}
|
||||
FileSystem::replaceFileRegex(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc', '/Libs.private:.*/m', 'Libs.private: ${libdir}/libz.a');
|
||||
FileSystem::replaceFileRegex(BUILD_LIB_PATH . '/pkgconfig/libcrypto.pc', '/Libs.private:.*/m', 'Requires.private: zlib');
|
||||
FileSystem::replaceFileRegex(BUILD_LIB_PATH . '/cmake/OpenSSL/OpenSSLConfig.cmake', '/set\(OPENSSL_LIBCRYPTO_DEPENDENCIES .*\)/m', 'set(OPENSSL_LIBCRYPTO_DEPENDENCIES "${OPENSSL_LIBRARY_DIR}/libz.a")');
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,9 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\macos\library;
|
||||
|
||||
/**
|
||||
* gmp is a template library class for unix
|
||||
*/
|
||||
class readline extends MacOSLibraryBase
|
||||
{
|
||||
use \SPC\builder\unix\library\readline;
|
||||
|
||||
@ -34,7 +34,7 @@ trait UnixLibraryTrait
|
||||
$files = array_map(fn ($x) => "{$x}.pc", $conf_pc);
|
||||
}
|
||||
foreach ($files as $name) {
|
||||
$realpath = realpath(BUILD_ROOT_PATH . '/lib/pkgconfig/' . $name);
|
||||
$realpath = realpath(BUILD_LIB_PATH . '/pkgconfig/' . $name);
|
||||
if ($realpath === false) {
|
||||
throw new PatchException('pkg-config prefix patcher', 'Cannot find library [' . static::NAME . '] pkgconfig file [' . $name . '] in ' . BUILD_LIB_PATH . '/pkgconfig/ !');
|
||||
}
|
||||
|
||||
@ -74,10 +74,10 @@ trait UnixSystemUtilTrait
|
||||
}
|
||||
// https://github.com/ziglang/zig/issues/24662
|
||||
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
|
||||
return '-Wl,--export-dynamic';
|
||||
return '-Wl,--export-dynamic'; // needs release 0.16, can be removed then
|
||||
}
|
||||
// macOS
|
||||
if (SPCTarget::getTargetOS() !== 'Linux') {
|
||||
// macOS/zig
|
||||
if (SPCTarget::getTargetOS() !== 'Linux' || ToolchainManager::getToolchainClass() === ZigToolchain::class) {
|
||||
return "-Wl,-exported_symbols_list,{$symbol_file}";
|
||||
}
|
||||
return "-Wl,--dynamic-list={$symbol_file}";
|
||||
|
||||
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\unix;
|
||||
|
||||
use SPC\builder\BuilderBase;
|
||||
use SPC\builder\linux\SystemUtil;
|
||||
use SPC\builder\linux\SystemUtil as LinuxSystemUtil;
|
||||
use SPC\exception\SPCException;
|
||||
use SPC\exception\SPCInternalException;
|
||||
@ -13,6 +14,7 @@ use SPC\exception\WrongUsageException;
|
||||
use SPC\store\Config;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\store\pkg\GoXcaddy;
|
||||
use SPC\store\SourceManager;
|
||||
use SPC\toolchain\GccNativeToolchain;
|
||||
use SPC\toolchain\ToolchainManager;
|
||||
use SPC\util\DependencyUtil;
|
||||
@ -78,6 +80,91 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
$this->lib_list = $sorted_libraries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip unneeded symbols from binary file.
|
||||
*/
|
||||
public function stripBinary(string $binary_path): void
|
||||
{
|
||||
shell()->exec(match (PHP_OS_FAMILY) {
|
||||
'Darwin' => "strip -S {$binary_path}",
|
||||
'Linux' => "strip --strip-unneeded {$binary_path}",
|
||||
default => throw new SPCInternalException('stripBinary is only supported on Linux and macOS'),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract debug information from binary file.
|
||||
*
|
||||
* @param string $binary_path the path to the binary file, including executables, shared libraries, etc
|
||||
*/
|
||||
public function extractDebugInfo(string $binary_path): string
|
||||
{
|
||||
$target_dir = BUILD_ROOT_PATH . '/debug';
|
||||
FileSystem::createDir($target_dir);
|
||||
$basename = basename($binary_path);
|
||||
$debug_file = "{$target_dir}/{$basename}" . (PHP_OS_FAMILY === 'Darwin' ? '.dwarf' : '.debug');
|
||||
if (PHP_OS_FAMILY === 'Darwin') {
|
||||
shell()->exec("dsymutil -f {$binary_path} -o {$debug_file}");
|
||||
} elseif (PHP_OS_FAMILY === 'Linux') {
|
||||
if ($eu_strip = SystemUtil::findCommand('eu-strip')) {
|
||||
shell()
|
||||
->exec("{$eu_strip} -f {$debug_file} {$binary_path}")
|
||||
->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}");
|
||||
} else {
|
||||
shell()
|
||||
->exec("objcopy --only-keep-debug {$binary_path} {$debug_file}")
|
||||
->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}");
|
||||
}
|
||||
} else {
|
||||
throw new SPCInternalException('extractDebugInfo is only supported on Linux and macOS');
|
||||
}
|
||||
return $debug_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploy the binary file from src to dst.
|
||||
*/
|
||||
public function deployBinary(string $src, string $dst, bool $executable = true): string
|
||||
{
|
||||
logger()->debug('Deploying binary from ' . $src . ' to ' . $dst);
|
||||
|
||||
// file must exists
|
||||
if (!file_exists($src)) {
|
||||
throw new SPCInternalException("Deploy failed. Cannot find file: {$src}");
|
||||
}
|
||||
// dst dir must exists
|
||||
FileSystem::createDir(dirname($dst));
|
||||
|
||||
// ignore copy to self
|
||||
if (realpath($src) !== realpath($dst)) {
|
||||
shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg($dst));
|
||||
}
|
||||
|
||||
// file exist
|
||||
if (!file_exists($dst)) {
|
||||
throw new SPCInternalException("Deploy failed. Cannot find file after copy: {$dst}");
|
||||
}
|
||||
|
||||
if (!$this->getOption('no-strip')) {
|
||||
// extract debug info
|
||||
$this->extractDebugInfo($dst);
|
||||
// extra strip
|
||||
$this->stripBinary($dst);
|
||||
}
|
||||
|
||||
// UPX for linux
|
||||
$upx_option = $this->getOption('with-upx-pack');
|
||||
if ($upx_option && PHP_OS_FAMILY === 'Linux' && $executable) {
|
||||
if ($this->getOption('no-strip')) {
|
||||
logger()->warning('UPX compression is not recommended when --no-strip is enabled.');
|
||||
}
|
||||
logger()->info("Compressing {$dst} with UPX");
|
||||
shell()->exec(getenv('UPX_EXEC') . " --best {$dst}");
|
||||
}
|
||||
|
||||
return $dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanity check after build complete.
|
||||
*/
|
||||
@ -148,8 +235,10 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
$lens .= ' -static';
|
||||
}
|
||||
$dynamic_exports = '';
|
||||
$embedType = 'static';
|
||||
// if someone changed to EMBED_TYPE=shared, we need to add LD_LIBRARY_PATH
|
||||
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
|
||||
$embedType = 'shared';
|
||||
if (PHP_OS_FAMILY === 'Darwin') {
|
||||
$ext_path = 'DYLD_LIBRARY_PATH=' . BUILD_LIB_PATH . ':$DYLD_LIBRARY_PATH ';
|
||||
} else {
|
||||
@ -168,18 +257,19 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
}
|
||||
}
|
||||
$cc = getenv('CC');
|
||||
|
||||
[$ret, $out] = shell()->cd($sample_file_path)->execWithResult("{$cc} -o embed embed.c {$lens} {$dynamic_exports}");
|
||||
if ($ret !== 0) {
|
||||
throw new ValidationException(
|
||||
'embed failed sanity check: build failed. Error message: ' . implode("\n", $out),
|
||||
validation_module: 'static libphp.a sanity check'
|
||||
'embed failed to build. Error message: ' . implode("\n", $out),
|
||||
validation_module: $embedType . ' libphp embed build sanity check'
|
||||
);
|
||||
}
|
||||
[$ret, $output] = shell()->cd($sample_file_path)->execWithResult($ext_path . './embed');
|
||||
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
|
||||
throw new ValidationException(
|
||||
'embed failed sanity check: run failed. Error message: ' . implode("\n", $output),
|
||||
validation_module: 'static libphp.a sanity check'
|
||||
'embed failed to run. Error message: ' . implode("\n", $output),
|
||||
validation_module: $embedType . ' libphp embed run sanity check'
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -208,23 +298,20 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploy the binary file to the build bin path.
|
||||
*
|
||||
* @param int $type Type integer, one of BUILD_TARGET_CLI, BUILD_TARGET_MICRO, BUILD_TARGET_FPM
|
||||
* Deploy binaries that produces executable SAPI
|
||||
*/
|
||||
protected function deployBinary(int $type): bool
|
||||
protected function deploySAPIBinary(int $type): string
|
||||
{
|
||||
$src = match ($type) {
|
||||
BUILD_TARGET_CLI => SOURCE_PATH . '/php-src/sapi/cli/php',
|
||||
BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx',
|
||||
BUILD_TARGET_FPM => SOURCE_PATH . '/php-src/sapi/fpm/php-fpm',
|
||||
BUILD_TARGET_CGI => SOURCE_PATH . '/php-src/sapi/cgi/php-cgi',
|
||||
BUILD_TARGET_FRANKENPHP => BUILD_BIN_PATH . '/frankenphp',
|
||||
default => throw new SPCInternalException("Deployment does not accept type {$type}"),
|
||||
};
|
||||
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
|
||||
FileSystem::createDir(BUILD_BIN_PATH);
|
||||
shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_BIN_PATH));
|
||||
return true;
|
||||
$dst = BUILD_BIN_PATH . '/' . basename($src);
|
||||
return $this->deployBinary($src, $dst);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,22 +352,76 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the --with-frankenphp-app option
|
||||
* Creates app.tar and app.checksum in source/frankenphp directory
|
||||
*/
|
||||
protected function processFrankenphpApp(): void
|
||||
{
|
||||
$frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp';
|
||||
if (!is_dir($frankenphpSourceDir)) {
|
||||
SourceManager::initSource(['frankenphp'], ['frankenphp']);
|
||||
}
|
||||
$frankenphpAppPath = $this->getOption('with-frankenphp-app');
|
||||
|
||||
if ($frankenphpAppPath) {
|
||||
$frankenphpAppPath = trim($frankenphpAppPath, "\"'");
|
||||
if (!is_dir($frankenphpAppPath)) {
|
||||
throw new WrongUsageException("The path provided to --with-frankenphp-app is not a valid directory: {$frankenphpAppPath}");
|
||||
}
|
||||
$appTarPath = $frankenphpSourceDir . '/app.tar';
|
||||
logger()->info("Creating app.tar from {$frankenphpAppPath}");
|
||||
|
||||
shell()->exec('tar -cf ' . escapeshellarg($appTarPath) . ' -C ' . escapeshellarg($frankenphpAppPath) . ' .');
|
||||
|
||||
$checksum = hash_file('md5', $appTarPath);
|
||||
file_put_contents($frankenphpSourceDir . '/app_checksum.txt', $checksum);
|
||||
} else {
|
||||
FileSystem::removeFileIfExists($frankenphpSourceDir . '/app.tar');
|
||||
FileSystem::removeFileIfExists($frankenphpSourceDir . '/app_checksum.txt');
|
||||
file_put_contents($frankenphpSourceDir . '/app.tar', '');
|
||||
file_put_contents($frankenphpSourceDir . '/app_checksum.txt', '');
|
||||
}
|
||||
}
|
||||
|
||||
protected function getFrankenPHPVersion(): string
|
||||
{
|
||||
if ($version = getenv('FRANKENPHP_VERSION')) {
|
||||
return $version;
|
||||
}
|
||||
$frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp';
|
||||
$goModPath = $frankenphpSourceDir . '/caddy/go.mod';
|
||||
|
||||
if (!file_exists($goModPath)) {
|
||||
throw new SPCInternalException("FrankenPHP caddy/go.mod file not found at {$goModPath}, why did we not download FrankenPHP?");
|
||||
}
|
||||
|
||||
$content = file_get_contents($goModPath);
|
||||
if (preg_match('/github\.com\/dunglas\/frankenphp\s+v?(\d+\.\d+\.\d+)/', $content, $matches)) {
|
||||
return $matches[1];
|
||||
}
|
||||
|
||||
throw new SPCInternalException('Could not find FrankenPHP version in caddy/go.mod');
|
||||
}
|
||||
|
||||
protected function buildFrankenphp(): void
|
||||
{
|
||||
GlobalEnvManager::addPathIfNotExists(GoXcaddy::getPath());
|
||||
$this->processFrankenphpApp();
|
||||
$nobrotli = $this->getLib('brotli') === null ? ',nobrotli' : '';
|
||||
$nowatcher = $this->getLib('watcher') === null ? ',nowatcher' : '';
|
||||
$xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES');
|
||||
// make it possible to build from a different frankenphp directory!
|
||||
if (!str_contains($xcaddyModules, '--with github.com/dunglas/frankenphp')) {
|
||||
$xcaddyModules = '--with github.com/dunglas/frankenphp ' . $xcaddyModules;
|
||||
}
|
||||
$frankenphpSourceDir = getenv('FRANKENPHP_SOURCE_PATH') ?: SOURCE_PATH . '/frankenphp';
|
||||
|
||||
$xcaddyModules = preg_replace('#--with github.com/dunglas/frankenphp\S*#', '', $xcaddyModules);
|
||||
$xcaddyModules = "--with github.com/dunglas/frankenphp={$frankenphpSourceDir} " .
|
||||
"--with github.com/dunglas/frankenphp/caddy={$frankenphpSourceDir}/caddy {$xcaddyModules}";
|
||||
if ($this->getLib('brotli') === null && str_contains($xcaddyModules, '--with github.com/dunglas/caddy-cbrotli')) {
|
||||
logger()->warning('caddy-cbrotli module is enabled, but brotli library is not built. Disabling caddy-cbrotli.');
|
||||
$xcaddyModules = str_replace('--with github.com/dunglas/caddy-cbrotli', '', $xcaddyModules);
|
||||
}
|
||||
[, $out] = shell()->execWithResult('go list -m github.com/dunglas/frankenphp@latest');
|
||||
$frankenPhpVersion = str_replace('github.com/dunglas/frankenphp v', '', $out[0]);
|
||||
|
||||
$frankenPhpVersion = $this->getFrankenPHPVersion();
|
||||
$libphpVersion = $this->getPHPVersion();
|
||||
$dynamic_exports = '';
|
||||
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
|
||||
@ -290,7 +431,6 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
$dynamic_exports = ' ' . $dynamicSymbolsArgument;
|
||||
}
|
||||
}
|
||||
$debugFlags = $this->getOption('no-strip') ? '-w -s ' : '';
|
||||
$extLdFlags = "-extldflags '-pie{$dynamic_exports} {$this->arch_ld_flags}'";
|
||||
$muslTags = '';
|
||||
$staticFlags = '';
|
||||
@ -301,7 +441,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
}
|
||||
|
||||
$config = (new SPCConfigUtil($this))->config($this->ext_list, $this->lib_list);
|
||||
$cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS');
|
||||
$cflags = "{$this->arch_c_flags} {$config['cflags']} " . getenv('SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS') . ' -DFRANKENPHP_VERSION=' . $frankenPhpVersion;
|
||||
$libs = $config['libs'];
|
||||
// Go's gcc driver doesn't automatically link against -lgcov or -lrt. Ugly, but necessary fix.
|
||||
if ((str_contains((string) getenv('SPC_DEFAULT_C_FLAGS'), '-fprofile') ||
|
||||
@ -315,7 +455,9 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
'CGO_CFLAGS' => clean_spaces($cflags),
|
||||
'CGO_LDFLAGS' => "{$this->arch_ld_flags} {$staticFlags} {$config['ldflags']} {$libs}",
|
||||
'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' .
|
||||
'-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . $debugFlags .
|
||||
'-ldflags \"-linkmode=external ' . $extLdFlags . ' ' .
|
||||
'-X \'github.com/caddyserver/caddy/v2/modules/caddyhttp.ServerHeader=FrankenPHP Caddy\' ' .
|
||||
'-X \'github.com/caddyserver/caddy/v2.CustomBinaryName=frankenphp\' ' .
|
||||
'-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' .
|
||||
"v{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " .
|
||||
"-tags={$muslTags}nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}",
|
||||
@ -325,13 +467,7 @@ abstract class UnixBuilderBase extends BuilderBase
|
||||
->setEnv($env)
|
||||
->exec("xcaddy build --output frankenphp {$xcaddyModules}");
|
||||
|
||||
if (!$this->getOption('no-strip', false) && file_exists(BUILD_BIN_PATH . '/frankenphp')) {
|
||||
if (PHP_OS_FAMILY === 'Linux') {
|
||||
shell()->cd(BUILD_BIN_PATH)->exec('strip --strip-unneeded frankenphp');
|
||||
} else { // macOS doesn't understand strip-unneeded
|
||||
shell()->cd(BUILD_BIN_PATH)->exec('strip -S frankenphp');
|
||||
}
|
||||
}
|
||||
$this->deploySAPIBinary(BUILD_TARGET_FRANKENPHP);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -17,7 +17,7 @@ trait attr
|
||||
->exec('libtoolize --force --copy')
|
||||
->exec('./autogen.sh || autoreconf -if')
|
||||
->configure('--disable-nls')
|
||||
->make();
|
||||
->make('install-attributes_h install-data install-libattr_h install-libLTLIBRARIES install-pkgincludeHEADERS install-pkgconfDATA', with_install: false);
|
||||
$this->patchPkgconfPrefix(['libattr.pc'], PKGCONF_PATCH_PREFIX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,8 @@ trait curl
|
||||
->optionalLib('zstd', ...cmake_boolean_args('CURL_ZSTD'))
|
||||
->optionalLib('idn2', ...cmake_boolean_args('USE_LIBIDN2'))
|
||||
->optionalLib('psl', ...cmake_boolean_args('CURL_USE_LIBPSL'))
|
||||
->optionalLib('krb5', ...cmake_boolean_args('CURL_USE_GSSAPI'))
|
||||
->optionalLib('idn2', ...cmake_boolean_args('CURL_USE_IDN2'))
|
||||
->optionalLib('libcares', '-DENABLE_ARES=ON')
|
||||
->addConfigureArgs(
|
||||
'-DBUILD_CURL_EXE=OFF',
|
||||
|
||||
@ -16,7 +16,11 @@ trait gettext
|
||||
->addConfigureArgs(
|
||||
'--disable-java',
|
||||
'--disable-c++',
|
||||
'--with-included-gettext',
|
||||
'--disable-d',
|
||||
'--disable-rpath',
|
||||
'--disable-modula2',
|
||||
'--disable-libasprintf',
|
||||
'--with-included-libintl',
|
||||
"--with-iconv-prefix={$this->getBuildRootPath()}",
|
||||
);
|
||||
|
||||
@ -31,7 +35,7 @@ trait gettext
|
||||
$autoconf->addConfigureArgs('--disable-threads');
|
||||
}
|
||||
|
||||
$autoconf->configure()->make();
|
||||
$autoconf->configure()->make(dir: $this->getSourceDir() . '/gettext-runtime/intl');
|
||||
$this->patchLaDependencyPrefix();
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,14 @@ trait gmp
|
||||
{
|
||||
protected function build(): void
|
||||
{
|
||||
UnixAutoconfExecutor::create($this)->configure()->make();
|
||||
UnixAutoconfExecutor::create($this)
|
||||
->appendEnv([
|
||||
'CFLAGS' => '-std=c17',
|
||||
])
|
||||
->configure(
|
||||
'--enable-fat'
|
||||
)
|
||||
->make();
|
||||
$this->patchPkgconfPrefix(['gmp.pc']);
|
||||
}
|
||||
}
|
||||
|
||||
27
src/SPC/builder/unix/library/idn2.php
Normal file
27
src/SPC/builder/unix/library/idn2.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\util\executor\UnixAutoconfExecutor;
|
||||
|
||||
trait idn2
|
||||
{
|
||||
protected function build(): void
|
||||
{
|
||||
UnixAutoconfExecutor::create($this)
|
||||
->configure(
|
||||
'--disable-nls',
|
||||
'--disable-doc',
|
||||
'--enable-year2038',
|
||||
'--disable-rpath'
|
||||
)
|
||||
->optionalLib('libiconv', "--with-libiconv-prefix={$this->getBuildRootPath()}")
|
||||
->optionalLib('libunistring', "--with-libunistring-prefix={$this->getBuildRootPath()}")
|
||||
->optionalLib('gettext', "--with-libnintl-prefix={$this->getBuildRootPath()}")
|
||||
->make();
|
||||
$this->patchPkgconfPrefix(['libidn2.pc']);
|
||||
$this->patchLaDependencyPrefix();
|
||||
}
|
||||
}
|
||||
57
src/SPC/builder/unix/library/krb5.php
Normal file
57
src/SPC/builder/unix/library/krb5.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\util\executor\UnixAutoconfExecutor;
|
||||
use SPC\util\SPCConfigUtil;
|
||||
|
||||
trait krb5
|
||||
{
|
||||
protected function build(): void
|
||||
{
|
||||
$origin_source_dir = $this->source_dir;
|
||||
$this->source_dir .= '/src';
|
||||
shell()->cd($this->source_dir)->exec('autoreconf -if');
|
||||
$libs = array_map(fn ($x) => $x->getName(), $this->getDependencies(true));
|
||||
$spc = new SPCConfigUtil($this->builder, ['no_php' => true, 'libs_only_deps' => true]);
|
||||
$config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs', false));
|
||||
$extraEnv = [
|
||||
'CFLAGS' => '-fcommon',
|
||||
'LIBS' => $config['libs'],
|
||||
];
|
||||
if (getenv('SPC_LD_LIBRARY_PATH') && getenv('SPC_LIBRARY_PATH')) {
|
||||
$extraEnv = [...$extraEnv, ...[
|
||||
'LD_LIBRARY_PATH' => getenv('SPC_LD_LIBRARY_PATH'),
|
||||
'LIBRARY_PATH' => getenv('SPC_LIBRARY_PATH'),
|
||||
]];
|
||||
}
|
||||
$args = [
|
||||
'--disable-nls',
|
||||
'--disable-rpath',
|
||||
'--without-system-verto',
|
||||
];
|
||||
if (PHP_OS_FAMILY === 'Darwin') {
|
||||
$extraEnv['LDFLAGS'] = '-framework Kerberos';
|
||||
$args[] = 'ac_cv_func_secure_getenv=no';
|
||||
}
|
||||
UnixAutoconfExecutor::create($this)
|
||||
->appendEnv($extraEnv)
|
||||
->optionalLib('ldap', '--with-ldap', '--without-ldap')
|
||||
->optionalLib('libedit', '--with-libedit', '--without-libedit')
|
||||
->configure(...$args)
|
||||
->make();
|
||||
$this->patchPkgconfPrefix([
|
||||
'krb5-gssapi.pc',
|
||||
'krb5.pc',
|
||||
'kadm-server.pc',
|
||||
'kadm-client.pc',
|
||||
'kdb.pc',
|
||||
'mit-krb5-gssapi.pc',
|
||||
'mit-krb5.pc',
|
||||
'gssrpc.pc',
|
||||
]);
|
||||
$this->source_dir = $origin_source_dir;
|
||||
}
|
||||
}
|
||||
@ -26,7 +26,7 @@ trait libacl
|
||||
->exec('libtoolize --force --copy')
|
||||
->exec('./autogen.sh || autoreconf -if')
|
||||
->configure('--disable-nls', '--disable-tests')
|
||||
->make();
|
||||
->make('install-acl_h install-libacl_h install-data install-libLTLIBRARIES install-pkgincludeHEADERS install-sysincludeHEADERS install-pkgconfDATA', with_install: false);
|
||||
$this->patchPkgconfPrefix(['libacl.pc'], PKGCONF_PATCH_PREFIX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,11 @@ trait libavif
|
||||
protected function build(): void
|
||||
{
|
||||
UnixCMakeExecutor::create($this)
|
||||
->optionalLib('libaom', '-DAVIF_CODEC_AOM=SYSTEM', '-DAVIF_CODEC_AOM=OFF')
|
||||
->optionalLib('libsharpyuv', '-DAVIF_LIBSHARPYUV=SYSTEM', '-DAVIF_LIBSHARPYUV=OFF')
|
||||
->optionalLib('libjpeg', '-DAVIF_JPEG=SYSTEM', '-DAVIF_JPEG=OFF')
|
||||
->optionalLib('libxml2', '-DAVIF_LIBXML2=SYSTEM', '-DAVIF_LIBXML2=OFF')
|
||||
->optionalLib('libpng', '-DAVIF_LIBPNG=SYSTEM', '-DAVIF_LIBPNG=OFF')
|
||||
->addConfigureArgs('-DAVIF_LIBYUV=OFF')
|
||||
->build();
|
||||
// patch pkgconfig
|
||||
|
||||
30
src/SPC/builder/unix/library/libedit.php
Normal file
30
src/SPC/builder/unix/library/libedit.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\executor\UnixAutoconfExecutor;
|
||||
|
||||
trait libedit
|
||||
{
|
||||
public function patchBeforeBuild(): bool
|
||||
{
|
||||
FileSystem::replaceFileRegex(
|
||||
$this->source_dir . '/src/sys.h',
|
||||
'|//#define\s+strl|',
|
||||
'#define strl'
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
UnixAutoconfExecutor::create($this)
|
||||
->appendEnv(['CFLAGS' => '-D__STDC_ISO_10646__=201103L'])
|
||||
->configure()
|
||||
->make();
|
||||
$this->patchPkgconfPrefix(['libedit.pc']);
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,13 @@ trait libiconv
|
||||
{
|
||||
protected function build(): void
|
||||
{
|
||||
UnixAutoconfExecutor::create($this)->configure('--enable-extra-encodings')->make();
|
||||
UnixAutoconfExecutor::create($this)
|
||||
->configure(
|
||||
'--enable-extra-encodings',
|
||||
'--enable-year2038',
|
||||
)
|
||||
->make('install-lib', with_install: false)
|
||||
->make('install-lib', with_install: false, dir: $this->getSourceDir() . '/libcharset');
|
||||
$this->patchLaDependencyPrefix();
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,13 +29,17 @@ trait libjxl
|
||||
);
|
||||
|
||||
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
|
||||
$cmake->addConfigureArgs(
|
||||
'-DCXX_MAVX512F_SUPPORTED:BOOL=FALSE',
|
||||
'-DCXX_MAVX512DQ_SUPPORTED:BOOL=FALSE',
|
||||
'-DCXX_MAVX512CD_SUPPORTED:BOOL=FALSE',
|
||||
'-DCXX_MAVX512BW_SUPPORTED:BOOL=FALSE',
|
||||
'-DCXX_MAVX512VL_SUPPORTED:BOOL=FALSE'
|
||||
);
|
||||
$cflags = getenv('SPC_DEFAULT_C_FLAGS') ?: getenv('CFLAGS') ?: '';
|
||||
$has_avx512 = str_contains($cflags, '-mavx512') || str_contains($cflags, '-march=x86-64-v4');
|
||||
if (!$has_avx512) {
|
||||
$cmake->addConfigureArgs(
|
||||
'-DCXX_MAVX512F_SUPPORTED:BOOL=FALSE',
|
||||
'-DCXX_MAVX512DQ_SUPPORTED:BOOL=FALSE',
|
||||
'-DCXX_MAVX512CD_SUPPORTED:BOOL=FALSE',
|
||||
'-DCXX_MAVX512BW_SUPPORTED:BOOL=FALSE',
|
||||
'-DCXX_MAVX512VL_SUPPORTED:BOOL=FALSE'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$cmake->build();
|
||||
|
||||
20
src/SPC/builder/unix/library/libmaxminddb.php
Normal file
20
src/SPC/builder/unix/library/libmaxminddb.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\util\executor\UnixCMakeExecutor;
|
||||
|
||||
trait libmaxminddb
|
||||
{
|
||||
protected function build(): void
|
||||
{
|
||||
UnixCMakeExecutor::create($this)
|
||||
->addConfigureArgs(
|
||||
'-DBUILD_TESTING=OFF',
|
||||
'-DMAXMINDDB_BUILD_BINARIES=OFF',
|
||||
)
|
||||
->build();
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\executor\UnixAutoconfExecutor;
|
||||
use SPC\util\executor\UnixCMakeExecutor;
|
||||
|
||||
trait librdkafka
|
||||
{
|
||||
@ -26,34 +26,18 @@ trait librdkafka
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
UnixAutoconfExecutor::create($this)
|
||||
->appendEnv(['CFLAGS' => '-Wno-int-conversion -Wno-unused-but-set-variable -Wno-unused-variable'])
|
||||
->optionalLib(
|
||||
'zstd',
|
||||
function ($lib) {
|
||||
putenv("STATIC_LIB_libzstd={$lib->getLibDir()}/libzstd.a");
|
||||
return '';
|
||||
},
|
||||
'--disable-zstd'
|
||||
UnixCMakeExecutor::create($this)
|
||||
->optionalLib('zstd', ...cmake_boolean_args('WITH_ZSTD'))
|
||||
->optionalLib('curl', ...cmake_boolean_args('WITH_CURL'))
|
||||
->optionalLib('openssl', ...cmake_boolean_args('WITH_SSL'))
|
||||
->optionalLib('zlib', ...cmake_boolean_args('WITH_ZLIB'))
|
||||
->optionalLib('liblz4', ...cmake_boolean_args('ENABLE_LZ4_EXT'))
|
||||
->addConfigureArgs(
|
||||
'-DWITH_SASL=OFF',
|
||||
'-DRDKAFKA_BUILD_STATIC=ON',
|
||||
'-DRDKAFKA_BUILD_EXAMPLES=OFF',
|
||||
'-DRDKAFKA_BUILD_TESTS=OFF',
|
||||
)
|
||||
->removeConfigureArgs(
|
||||
'--with-pic',
|
||||
'--enable-pic',
|
||||
)
|
||||
->configure(
|
||||
'--disable-curl',
|
||||
'--disable-sasl',
|
||||
'--disable-valgrind',
|
||||
'--disable-zlib',
|
||||
'--disable-ssl',
|
||||
)
|
||||
->make();
|
||||
|
||||
$this->patchPkgconfPrefix(['rdkafka.pc', 'rdkafka-static.pc', 'rdkafka++.pc', 'rdkafka++-static.pc']);
|
||||
// remove dynamic libs
|
||||
shell()
|
||||
->exec("rm -rf {$this->getLibDir()}/*.so.*")
|
||||
->exec("rm -rf {$this->getLibDir()}/*.so")
|
||||
->exec("rm -rf {$this->getLibDir()}/*.dylib");
|
||||
->build();
|
||||
}
|
||||
}
|
||||
|
||||
18
src/SPC/builder/unix/library/libunistring.php
Normal file
18
src/SPC/builder/unix/library/libunistring.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\util\executor\UnixAutoconfExecutor;
|
||||
|
||||
trait libunistring
|
||||
{
|
||||
protected function build(): void
|
||||
{
|
||||
UnixAutoconfExecutor::create($this)
|
||||
->configure('--disable-nls')
|
||||
->make();
|
||||
$this->patchLaDependencyPrefix();
|
||||
}
|
||||
}
|
||||
@ -10,8 +10,26 @@ trait libwebp
|
||||
{
|
||||
protected function build(): void
|
||||
{
|
||||
$code = '#include <immintrin.h>
|
||||
int main() { return _mm256_cvtsi256_si32(_mm256_setzero_si256()); }';
|
||||
$cc = getenv('CC') ?: 'gcc';
|
||||
[$ret] = shell()->execWithResult("printf '%s' '{$code}' | {$cc} -x c -mavx2 -o /dev/null - 2>&1");
|
||||
$disableAvx2 = $ret !== 0 && GNU_ARCH === 'x86_64' && PHP_OS_FAMILY === 'Linux';
|
||||
|
||||
UnixCMakeExecutor::create($this)
|
||||
->addConfigureArgs('-DWEBP_BUILD_EXTRAS=ON')
|
||||
->addConfigureArgs(
|
||||
'-DWEBP_BUILD_EXTRAS=OFF',
|
||||
'-DWEBP_BUILD_ANIM_UTILS=OFF',
|
||||
'-DWEBP_BUILD_CWEBP=OFF',
|
||||
'-DWEBP_BUILD_DWEBP=OFF',
|
||||
'-DWEBP_BUILD_GIF2WEBP=OFF',
|
||||
'-DWEBP_BUILD_IMG2WEBP=OFF',
|
||||
'-DWEBP_BUILD_VWEBP=OFF',
|
||||
'-DWEBP_BUILD_WEBPINFO=OFF',
|
||||
'-DWEBP_BUILD_WEBPMUX=OFF',
|
||||
'-DWEBP_BUILD_FUZZTEST=OFF',
|
||||
$disableAvx2 ? '-DWEBP_ENABLE_SIMD=OFF' : ''
|
||||
)
|
||||
->build();
|
||||
// patch pkgconfig
|
||||
$this->patchPkgconfPrefix(patch_option: PKGCONF_PATCH_PREFIX | PKGCONF_PATCH_LIBDIR);
|
||||
|
||||
@ -22,6 +22,7 @@ trait libzip
|
||||
'-DBUILD_EXAMPLES=OFF',
|
||||
'-DBUILD_REGRESS=OFF',
|
||||
'-DBUILD_TOOLS=OFF',
|
||||
'-DBUILD_OSSFUZZ=OFF',
|
||||
)
|
||||
->build();
|
||||
$this->patchPkgconfPrefix(['libzip.pc'], PKGCONF_PATCH_PREFIX);
|
||||
|
||||
@ -16,6 +16,7 @@ trait ncurses
|
||||
|
||||
UnixAutoconfExecutor::create($this)
|
||||
->appendEnv([
|
||||
'CFLAGS' => '-std=c17',
|
||||
'LDFLAGS' => SPCTarget::isStatic() ? '-static' : '',
|
||||
])
|
||||
->configure(
|
||||
@ -29,7 +30,7 @@ trait ncurses
|
||||
'--without-tests',
|
||||
'--without-dlsym',
|
||||
'--without-debug',
|
||||
'-enable-symlinks',
|
||||
'--enable-symlinks',
|
||||
"--bindir={$this->getBinDir()}",
|
||||
"--includedir={$this->getIncludeDir()}",
|
||||
"--libdir={$this->getLibDir()}",
|
||||
|
||||
49
src/SPC/builder/unix/library/net_snmp.php
Normal file
49
src/SPC/builder/unix/library/net_snmp.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\executor\UnixAutoconfExecutor;
|
||||
|
||||
trait net_snmp
|
||||
{
|
||||
public function patchBeforeBuild(): bool
|
||||
{
|
||||
if (PHP_OS_FAMILY === 'Linux') {
|
||||
FileSystem::replaceFileStr("{$this->source_dir}/configure", 'LIBS="-lssl ${OPENSSL_LIBS}"', 'LIBS="-lssl ${OPENSSL_LIBS} -lpthread -ldl"');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
// use --static for PKG_CONFIG
|
||||
UnixAutoconfExecutor::create($this)
|
||||
->setEnv(['PKG_CONFIG' => getenv('PKG_CONFIG') . ' --static'])
|
||||
->configure(
|
||||
'--disable-mibs',
|
||||
'--without-nl',
|
||||
'--disable-agent',
|
||||
'--disable-applications',
|
||||
'--disable-manuals',
|
||||
'--disable-scripts',
|
||||
'--disable-embedded-perl',
|
||||
'--without-perl-modules',
|
||||
'--with-out-mib-modules="if-mib host disman/event-mib ucd-snmp/diskio mibII"',
|
||||
'--with-out-transports="Unix"',
|
||||
'--with-mib-modules=""',
|
||||
'--enable-mini-agent',
|
||||
'--with-default-snmp-version="3"',
|
||||
'--with-sys-contact="@@no.where"',
|
||||
'--with-sys-location="Unknown"',
|
||||
'--with-logfile="/var/log/snmpd.log"',
|
||||
'--with-persistent-directory="/var/lib/net-snmp"',
|
||||
'--with-openssl=' . BUILD_ROOT_PATH,
|
||||
'--with-zlib=' . BUILD_ROOT_PATH,
|
||||
)->make(with_install: 'installheaders installlibs install_pkgconfig');
|
||||
$this->patchPkgconfPrefix();
|
||||
}
|
||||
}
|
||||
@ -4,29 +4,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\exception\FileSystemException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\PkgConfigUtil;
|
||||
use SPC\util\SPCConfigUtil;
|
||||
use SPC\util\SPCTarget;
|
||||
|
||||
trait postgresql
|
||||
{
|
||||
public function patchBeforeBuild(): bool
|
||||
{
|
||||
// fix aarch64 build on glibc 2.17 (e.g. CentOS 7)
|
||||
if (SPCTarget::getLibcVersion() === '2.17' && GNU_ARCH === 'aarch64') {
|
||||
try {
|
||||
FileSystem::replaceFileStr("{$this->source_dir}/src/port/pg_popcount_aarch64.c", 'HWCAP_SVE', '0');
|
||||
FileSystem::replaceFileStr(
|
||||
"{$this->source_dir}/src/port/pg_crc32c_armv8_choose.c",
|
||||
'#if defined(__linux__) && !defined(__aarch64__) && !defined(HWCAP2_CRC32)',
|
||||
'#if defined(__linux__) && !defined(HWCAP_CRC32)'
|
||||
);
|
||||
} catch (FileSystemException) {
|
||||
// allow file not-existence to make it compatible with old and new version
|
||||
}
|
||||
}
|
||||
// skip the test on platforms where libpq infrastructure may be provided by statically-linked libraries
|
||||
FileSystem::replaceFileStr("{$this->source_dir}/src/interfaces/libpq/Makefile", 'invokes exit\'; exit 1;', 'invokes exit\';');
|
||||
// disable shared libs build
|
||||
@ -45,12 +30,12 @@ trait postgresql
|
||||
|
||||
protected function build(): void
|
||||
{
|
||||
$libs = array_map(fn ($x) => $x->getName(), $this->getDependencies());
|
||||
$spc = new SPCConfigUtil($this->getBuilder(), ['no_php' => true, 'libs_only_deps' => true]);
|
||||
$config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs'));
|
||||
$libs = array_map(fn ($x) => $x->getName(), $this->getDependencies(true));
|
||||
$spc = new SPCConfigUtil($this->builder, ['no_php' => true, 'libs_only_deps' => true]);
|
||||
$config = $spc->config(libraries: $libs, include_suggest_lib: $this->builder->getOption('with-suggested-libs', false));
|
||||
|
||||
$env_vars = [
|
||||
'CFLAGS' => $config['cflags'],
|
||||
'CFLAGS' => $config['cflags'] . ' -std=c17',
|
||||
'CPPFLAGS' => '-DPIC',
|
||||
'LDFLAGS' => $config['ldflags'],
|
||||
'LIBS' => $config['libs'],
|
||||
@ -108,8 +93,7 @@ trait postgresql
|
||||
|
||||
// remove dynamic libs
|
||||
shell()->cd($this->source_dir . '/build')
|
||||
->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so.*")
|
||||
->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so")
|
||||
->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so*")
|
||||
->exec("rm -rf {$this->getBuildRootPath()}/lib/*.dylib");
|
||||
|
||||
FileSystem::replaceFileStr("{$this->getLibDir()}/pkgconfig/libpq.pc", '-lldap', '-lldap -llber');
|
||||
|
||||
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\unix\library;
|
||||
|
||||
use SPC\exception\WrongUsageException;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\executor\UnixAutoconfExecutor;
|
||||
|
||||
trait unixodbc
|
||||
@ -30,7 +31,15 @@ trait unixodbc
|
||||
'--enable-gui=no',
|
||||
)
|
||||
->make();
|
||||
$this->patchPkgconfPrefix(['odbc.pc', 'odbccr.pc', 'odbcinst.pc']);
|
||||
$pkgConfigs = ['odbc.pc', 'odbccr.pc', 'odbcinst.pc'];
|
||||
$this->patchPkgconfPrefix($pkgConfigs);
|
||||
foreach ($pkgConfigs as $file) {
|
||||
FileSystem::replaceFileStr(
|
||||
BUILD_LIB_PATH . "/pkgconfig/{$file}",
|
||||
'$(top_build_prefix)libltdl/libltdlc.la',
|
||||
''
|
||||
);
|
||||
}
|
||||
$this->patchLaDependencyPrefix();
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,6 +57,7 @@ class WindowsBuilder extends BuilderBase
|
||||
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
|
||||
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
|
||||
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
|
||||
$enableCgi = ($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI;
|
||||
|
||||
SourcePatcher::patchBeforeBuildconf($this);
|
||||
|
||||
@ -66,21 +67,6 @@ class WindowsBuilder extends BuilderBase
|
||||
|
||||
$zts = $this->zts ? '--enable-zts=yes ' : '--enable-zts=no ';
|
||||
|
||||
// with-upx-pack for phpmicro
|
||||
if ($enableMicro && version_compare($this->getMicroVersion(), '0.2.0') < 0) {
|
||||
$makefile = FileSystem::convertPath(SOURCE_PATH . '/php-src/sapi/micro/Makefile.frag.w32');
|
||||
if ($this->getOption('with-upx-pack', false)) {
|
||||
if (!file_exists($makefile . '.originfile')) {
|
||||
copy($makefile, $makefile . '.originfile');
|
||||
FileSystem::replaceFileStr($makefile, '$(MICRO_SFX):', '_MICRO_UPX = ' . getenv('UPX_EXEC') . " --best $(MICRO_SFX)\n$(MICRO_SFX):");
|
||||
FileSystem::replaceFileStr($makefile, '@$(_MICRO_MT)', "@$(_MICRO_MT)\n\t@$(_MICRO_UPX)");
|
||||
}
|
||||
} elseif (file_exists($makefile . '.originfile')) {
|
||||
copy($makefile . '.originfile', $makefile);
|
||||
unlink($makefile . '.originfile');
|
||||
}
|
||||
}
|
||||
|
||||
$opcache_jit = !$this->getOption('disable-opcache-jit', false);
|
||||
$opcache_jit_arg = $opcache_jit ? '--enable-opcache-jit=yes ' : '--enable-opcache-jit=no ';
|
||||
|
||||
@ -102,13 +88,13 @@ class WindowsBuilder extends BuilderBase
|
||||
->exec(
|
||||
"{$this->sdk_prefix} configure.bat --task-args \"" .
|
||||
'--disable-all ' .
|
||||
'--disable-cgi ' .
|
||||
'--with-php-build=' . BUILD_ROOT_PATH . ' ' .
|
||||
'--with-extra-includes=' . BUILD_INCLUDE_PATH . ' ' .
|
||||
'--with-extra-libs=' . BUILD_LIB_PATH . ' ' .
|
||||
($enableCli ? '--enable-cli=yes ' : '--enable-cli=no ') .
|
||||
($enableMicro ? ('--enable-micro=yes ' . $micro_logo . $micro_w32) : '--enable-micro=no ') .
|
||||
($enableEmbed ? '--enable-embed=yes ' : '--enable-embed=no ') .
|
||||
($enableCli ? '--enable-cli ' : '--disable-cli ') .
|
||||
($enableMicro ? ('--enable-micro ' . $micro_logo . $micro_w32) : '--disable-micro ') .
|
||||
($enableEmbed ? '--enable-embed ' : '--disable-embed ') .
|
||||
($enableCgi ? '--enable-cgi ' : '--disable-cgi ') .
|
||||
$config_file_scan_dir .
|
||||
$opcache_jit_arg .
|
||||
"{$this->makeStaticExtensionArgs()} " .
|
||||
@ -127,6 +113,10 @@ class WindowsBuilder extends BuilderBase
|
||||
if ($enableFpm) {
|
||||
logger()->warning('Windows does not support fpm SAPI, I will skip it.');
|
||||
}
|
||||
if ($enableCgi) {
|
||||
logger()->info('building cgi');
|
||||
$this->buildCgi();
|
||||
}
|
||||
if ($enableMicro) {
|
||||
logger()->info('building micro');
|
||||
$this->buildMicro();
|
||||
@ -140,7 +130,7 @@ class WindowsBuilder extends BuilderBase
|
||||
}
|
||||
}
|
||||
|
||||
public function testPHP(int $build_target = BUILD_TARGET_NONE)
|
||||
public function testPHP(int $build_target = BUILD_TARGET_NONE): void
|
||||
{
|
||||
$this->sanityCheck($build_target);
|
||||
}
|
||||
@ -151,12 +141,52 @@ class WindowsBuilder extends BuilderBase
|
||||
|
||||
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
|
||||
|
||||
// Add debug symbols for release build if --no-strip is specified
|
||||
// We need to modify CFLAGS to replace /Ox with /Zi and add /DEBUG to LDFLAGS
|
||||
$debug_overrides = '';
|
||||
if ($this->getOption('no-strip', false)) {
|
||||
// Read current CFLAGS from Makefile and replace optimization flags
|
||||
$makefile_content = file_get_contents(SOURCE_PATH . '\php-src\Makefile');
|
||||
if (preg_match('/^CFLAGS=(.+?)$/m', $makefile_content, $matches)) {
|
||||
$cflags = $matches[1];
|
||||
// Replace /Ox (full optimization) with /Zi (debug info) and /Od (disable optimization)
|
||||
// Keep optimization for speed: /O2 /Zi instead of /Od /Zi
|
||||
$cflags = str_replace('/Ox ', '/O2 /Zi ', $cflags);
|
||||
$debug_overrides = '"CFLAGS=' . $cflags . '" "LDFLAGS=/DEBUG /LTCG /INCREMENTAL:NO" "LDFLAGS_CLI=/DEBUG" ';
|
||||
}
|
||||
}
|
||||
|
||||
// add nmake wrapper
|
||||
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= %*");
|
||||
FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_cli_wrapper.bat', "nmake /nologo {$debug_overrides}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");
|
||||
|
||||
$this->deployBinary(BUILD_TARGET_CLI);
|
||||
$this->deploySAPIBinary(BUILD_TARGET_CLI);
|
||||
}
|
||||
|
||||
public function buildCgi(): void
|
||||
{
|
||||
SourcePatcher::patchWindowsCGITarget();
|
||||
|
||||
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
|
||||
|
||||
// Add debug symbols for release build if --no-strip is specified
|
||||
$debug_overrides = '';
|
||||
if ($this->getOption('no-strip', false)) {
|
||||
$makefile_content = file_get_contents(SOURCE_PATH . '\php-src\Makefile');
|
||||
if (preg_match('/^CFLAGS=(.+?)$/m', $makefile_content, $matches)) {
|
||||
$cflags = $matches[1];
|
||||
$cflags = str_replace('/Ox ', '/O2 /Zi ', $cflags);
|
||||
$debug_overrides = '"CFLAGS=' . $cflags . '" "LDFLAGS=/DEBUG /LTCG /INCREMENTAL:NO" "LDFLAGS_CGI=/DEBUG" ';
|
||||
}
|
||||
}
|
||||
|
||||
// add nmake wrapper
|
||||
FileSystem::writeFile(SOURCE_PATH . '\php-src\nmake_cgi_wrapper.bat', "nmake /nologo {$debug_overrides}LIBS_CGI=\"ws2_32.lib kernel32.lib advapi32.lib {$extra_libs}\" EXTRA_LD_FLAGS_PROGRAM= %*");
|
||||
|
||||
cmd()->cd(SOURCE_PATH . '\php-src')->exec("{$this->sdk_prefix} nmake_cgi_wrapper.bat --task-args php-cgi.exe");
|
||||
|
||||
$this->deploySAPIBinary(BUILD_TARGET_CGI);
|
||||
}
|
||||
|
||||
public function buildEmbed(): void
|
||||
@ -183,9 +213,20 @@ class WindowsBuilder extends BuilderBase
|
||||
|
||||
$extra_libs = getenv('SPC_EXTRA_LIBS') ?: '';
|
||||
|
||||
// Add debug symbols for release build if --no-strip is specified
|
||||
$debug_overrides = '';
|
||||
if ($this->getOption('no-strip', false) && !$this->getOption('debug', false)) {
|
||||
$makefile_content = file_get_contents(SOURCE_PATH . '\php-src\Makefile');
|
||||
if (preg_match('/^CFLAGS=(.+?)$/m', $makefile_content, $matches)) {
|
||||
$cflags = $matches[1];
|
||||
$cflags = str_replace('/Ox ', '/O2 /Zi ', $cflags);
|
||||
$debug_overrides = '"CFLAGS=' . $cflags . '" "LDFLAGS=/DEBUG /LTCG /INCREMENTAL:NO" "LDFLAGS_MICRO=/DEBUG" ';
|
||||
}
|
||||
}
|
||||
|
||||
// add nmake wrapper
|
||||
$fake_cli = $this->getOption('with-micro-fake-cli', false) ? ' /DPHP_MICRO_FAKE_CLI" ' : '';
|
||||
$wrapper = "nmake /nologo LIBS_MICRO=\"ws2_32.lib shell32.lib {$extra_libs}\" CFLAGS_MICRO=\"/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1{$fake_cli}\" %*";
|
||||
$wrapper = "nmake /nologo {$debug_overrides}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
|
||||
@ -202,7 +243,7 @@ class WindowsBuilder extends BuilderBase
|
||||
}
|
||||
}
|
||||
|
||||
$this->deployBinary(BUILD_TARGET_MICRO);
|
||||
$this->deploySAPIBinary(BUILD_TARGET_MICRO);
|
||||
}
|
||||
|
||||
public function proveLibs(array $sorted_libraries): void
|
||||
@ -265,7 +306,7 @@ class WindowsBuilder extends BuilderBase
|
||||
// sanity check for php-cli
|
||||
if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
|
||||
logger()->info('running cli sanity check');
|
||||
[$ret, $output] = cmd()->execWithResult(BUILD_ROOT_PATH . '\bin\php.exe -n -r "echo \"hello\";"');
|
||||
[$ret, $output] = cmd()->execWithResult(BUILD_BIN_PATH . '\php.exe -n -r "echo \"hello\";"');
|
||||
if ($ret !== 0 || trim(implode('', $output)) !== 'hello') {
|
||||
throw new ValidationException('cli failed sanity check', validation_module: 'php-cli function check');
|
||||
}
|
||||
@ -284,7 +325,7 @@ class WindowsBuilder extends BuilderBase
|
||||
if (file_exists($test_file)) {
|
||||
@unlink($test_file);
|
||||
}
|
||||
file_put_contents($test_file, file_get_contents(BUILD_ROOT_PATH . '\bin\micro.sfx') . $task['content']);
|
||||
file_put_contents($test_file, file_get_contents(BUILD_BIN_PATH . '\micro.sfx') . $task['content']);
|
||||
chmod($test_file, 0755);
|
||||
[$ret, $out] = cmd()->execWithResult($test_file);
|
||||
foreach ($task['conditions'] as $condition => $closure) {
|
||||
@ -298,6 +339,17 @@ class WindowsBuilder extends BuilderBase
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sanity check for php-cgi
|
||||
if (($build_target & BUILD_TARGET_CGI) === BUILD_TARGET_CGI) {
|
||||
logger()->info('running cgi sanity check');
|
||||
FileSystem::writeFile(SOURCE_PATH . '\php-cgi-test.php', '<?php echo "<h1>Hello, World!</h1>"; ?>');
|
||||
[$ret, $output] = cmd()->execWithResult(BUILD_BIN_PATH . '\php-cgi.exe -n -f ' . SOURCE_PATH . '\php-cgi-test.php');
|
||||
$raw_output = implode("\n", $output);
|
||||
if ($ret !== 0 || !str_contains($raw_output, 'Hello, World!')) {
|
||||
throw new ValidationException("cgi failed sanity check. code: {$ret}, output: {$raw_output}", validation_module: 'php-cgi sanity check');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -305,27 +357,53 @@ class WindowsBuilder extends BuilderBase
|
||||
*
|
||||
* @param int $type Deploy type
|
||||
*/
|
||||
public function deployBinary(int $type): bool
|
||||
public function deploySAPIBinary(int $type): void
|
||||
{
|
||||
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
|
||||
|
||||
$debug_dir = BUILD_ROOT_PATH . '\debug';
|
||||
$bin_path = BUILD_BIN_PATH;
|
||||
|
||||
// create dirs
|
||||
FileSystem::createDir($debug_dir);
|
||||
FileSystem::createDir($bin_path);
|
||||
|
||||
// determine source path for different SAPI
|
||||
$rel_type = 'Release'; // TODO: Debug build support
|
||||
$ts = $this->zts ? '_TS' : '';
|
||||
$src = match ($type) {
|
||||
BUILD_TARGET_CLI => SOURCE_PATH . "\\php-src\\x64\\Release{$ts}\\php.exe",
|
||||
BUILD_TARGET_MICRO => SOURCE_PATH . "\\php-src\\x64\\Release{$ts}\\micro.sfx",
|
||||
BUILD_TARGET_CLI => [SOURCE_PATH . "\\php-src\\x64\\{$rel_type}{$ts}", 'php.exe', 'php.pdb'],
|
||||
BUILD_TARGET_MICRO => [SOURCE_PATH . "\\php-src\\x64\\{$rel_type}{$ts}", 'micro.sfx', 'micro.pdb'],
|
||||
BUILD_TARGET_CGI => [SOURCE_PATH . "\\php-src\\x64\\{$rel_type}{$ts}", 'php-cgi.exe', 'php-cgi.pdb'],
|
||||
default => throw new SPCInternalException("Deployment does not accept type {$type}"),
|
||||
};
|
||||
|
||||
// with-upx-pack for cli and micro
|
||||
if ($this->getOption('with-upx-pack', false)) {
|
||||
if ($type === BUILD_TARGET_CLI || ($type === BUILD_TARGET_MICRO && version_compare($this->getMicroVersion(), '0.2.0') >= 0)) {
|
||||
cmd()->exec(getenv('UPX_EXEC') . ' --best ' . escapeshellarg($src));
|
||||
}
|
||||
$src = "{$src[0]}\\{$src[1]}";
|
||||
$dst = BUILD_BIN_PATH . '\\' . basename($src);
|
||||
|
||||
// file must exists
|
||||
if (!file_exists($src)) {
|
||||
throw new SPCInternalException("Deploy failed. Cannot find file: {$src}");
|
||||
}
|
||||
// dst dir must exists
|
||||
FileSystem::createDir(dirname($dst));
|
||||
|
||||
// copy file
|
||||
if (realpath($src) !== realpath($dst)) {
|
||||
cmd()->exec('copy ' . escapeshellarg($src) . ' ' . escapeshellarg($dst));
|
||||
}
|
||||
|
||||
logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file');
|
||||
FileSystem::createDir(BUILD_ROOT_PATH . '\bin');
|
||||
// extract debug info in buildroot/debug
|
||||
if ($this->getOption('no-strip', false) && file_exists("{$src[0]}\\{$src[2]}")) {
|
||||
cmd()->exec('copy ' . escapeshellarg("{$src[0]}\\{$src[2]}") . ' ' . escapeshellarg($debug_dir));
|
||||
}
|
||||
|
||||
cmd()->exec('copy ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_ROOT_PATH . '\bin\\'));
|
||||
return true;
|
||||
// with-upx-pack for cli and micro
|
||||
if ($this->getOption('with-upx-pack', false)) {
|
||||
if ($type === BUILD_TARGET_CLI || $type === BUILD_TARGET_CGI || ($type === BUILD_TARGET_MICRO && version_compare($this->getMicroVersion(), '0.2.0') >= 0)) {
|
||||
cmd()->exec(getenv('UPX_EXEC') . ' --best ' . escapeshellarg($dst));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -30,7 +30,6 @@ class curl extends WindowsLibraryBase
|
||||
'-DCMAKE_BUILD_TYPE=Release ' .
|
||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||
'-DBUILD_STATIC_LIBS=ON ' .
|
||||
'-DCURL_STATICLIB=ON ' .
|
||||
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' .
|
||||
'-DBUILD_CURL_EXE=OFF ' . // disable curl.exe
|
||||
'-DBUILD_TESTING=OFF ' . // disable tests
|
||||
@ -42,9 +41,9 @@ class curl extends WindowsLibraryBase
|
||||
'-DCURL_USE_OPENSSL=OFF ' . // disable openssl due to certificate issue
|
||||
'-DCURL_ENABLE_SSL=ON ' .
|
||||
'-DUSE_NGHTTP2=ON ' . // enable nghttp2
|
||||
'-DSHARE_LIB_OBJECT=OFF ' . // disable shared lib object
|
||||
'-DCURL_USE_LIBSSH2=ON ' . // enable libssh2
|
||||
'-DENABLE_IPV6=ON ' . // enable ipv6
|
||||
'-DNGHTTP2_CFLAGS="/DNGHTTP2_STATICLIB" ' .
|
||||
$alt
|
||||
)
|
||||
->execWithWrapper(
|
||||
@ -53,5 +52,7 @@ class curl extends WindowsLibraryBase
|
||||
);
|
||||
// move libcurl.lib to libcurl_a.lib
|
||||
rename(BUILD_LIB_PATH . '\libcurl.lib', BUILD_LIB_PATH . '\libcurl_a.lib');
|
||||
|
||||
FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '\curl\curl.h', '#ifdef CURL_STATICLIB', '#if 1');
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,11 +29,16 @@ class nghttp2 extends WindowsLibraryBase
|
||||
'-DBUILD_SHARED_LIBS=OFF ' .
|
||||
'-DENABLE_STATIC_CRT=ON ' .
|
||||
'-DENABLE_LIB_ONLY=ON ' .
|
||||
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' '
|
||||
'-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' .
|
||||
'-DENABLE_STATIC_CRT=ON ' .
|
||||
'-DENABLE_DOC=OFF ' .
|
||||
'-DBUILD_TESTING=OFF '
|
||||
)
|
||||
->execWithWrapper(
|
||||
$this->builder->makeSimpleWrapper('cmake'),
|
||||
"--build build --config Release --target install -j{$this->builder->concurrency}"
|
||||
);
|
||||
|
||||
FileSystem::replaceFileStr(BUILD_INCLUDE_PATH . '\nghttp2\nghttp2.h', '#ifdef NGHTTP2_STATICLIB', '#if 1');
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ class BuildPHPCommand extends BuildCommand
|
||||
$this->addOption('build-fpm', null, null, 'Build fpm SAPI (not available on Windows)');
|
||||
$this->addOption('build-embed', null, null, 'Build embed SAPI (not available on Windows)');
|
||||
$this->addOption('build-frankenphp', null, null, 'Build FrankenPHP SAPI (not available on Windows)');
|
||||
$this->addOption('build-cgi', null, null, 'Build cgi SAPI (not available on Windows)');
|
||||
$this->addOption('build-cgi', null, null, 'Build cgi SAPI');
|
||||
$this->addOption('build-all', null, null, 'Build all SAPI');
|
||||
$this->addOption('no-strip', null, null, 'build without strip, keep symbols to debug');
|
||||
$this->addOption('disable-opcache-jit', null, null, 'disable opcache jit');
|
||||
@ -48,6 +48,7 @@ class BuildPHPCommand extends BuildCommand
|
||||
$this->addOption('with-upx-pack', null, null, 'Compress / pack binary using UPX tool (linux/windows only)');
|
||||
$this->addOption('with-micro-logo', null, InputOption::VALUE_REQUIRED, 'Use custom .ico for micro.sfx (windows only)');
|
||||
$this->addOption('enable-micro-win32', null, null, 'Enable win32 mode for phpmicro (Windows only)');
|
||||
$this->addOption('with-frankenphp-app', null, InputOption::VALUE_REQUIRED, 'Path to a folder to be embedded in FrankenPHP');
|
||||
}
|
||||
|
||||
public function handle(): int
|
||||
@ -222,11 +223,9 @@ class BuildPHPCommand extends BuildCommand
|
||||
|
||||
// ---------- When using bin/spc-alpine-docker, the build root path is different from the host system ----------
|
||||
$build_root_path = BUILD_ROOT_PATH;
|
||||
$cwd = getcwd();
|
||||
$fixed = '';
|
||||
$build_root_path = get_display_path($build_root_path);
|
||||
if (!empty(getenv('SPC_FIX_DEPLOY_ROOT'))) {
|
||||
str_replace($cwd, '', $build_root_path);
|
||||
$build_root_path = getenv('SPC_FIX_DEPLOY_ROOT') . '/' . basename($build_root_path);
|
||||
$fixed = ' (host system)';
|
||||
}
|
||||
if (($rule & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) {
|
||||
|
||||
@ -30,7 +30,7 @@ class DownloadCommand extends BaseCommand
|
||||
$this->addArgument('sources', InputArgument::REQUIRED, 'The sources will be compiled, comma separated');
|
||||
$this->addOption('shallow-clone', null, null, 'Clone shallow');
|
||||
$this->addOption('with-openssl11', null, null, 'Use openssl 1.1');
|
||||
$this->addOption('with-php', null, InputOption::VALUE_REQUIRED, 'version in major.minor format (default 8.4)', '8.4');
|
||||
$this->addOption('with-php', null, InputOption::VALUE_REQUIRED, 'version in major.minor format (default 8.5)', '8.5');
|
||||
$this->addOption('clean', null, null, 'Clean old download cache and source before fetch');
|
||||
$this->addOption('all', 'A', null, 'Fetch all sources that static-php-cli needed');
|
||||
$this->addOption('custom-url', 'U', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Specify custom source download url, e.g "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"');
|
||||
|
||||
@ -20,9 +20,9 @@ class SwitchPhpVersionCommand extends BaseCommand
|
||||
$this->addArgument(
|
||||
'php-major-version',
|
||||
InputArgument::REQUIRED,
|
||||
'PHP major version (supported: 7.4, 8.0, 8.1, 8.2, 8.3, 8.4)',
|
||||
'PHP major version (supported: 7.4, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5)',
|
||||
null,
|
||||
fn () => ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
|
||||
fn () => ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']
|
||||
);
|
||||
$this->no_motd = true;
|
||||
|
||||
@ -32,7 +32,7 @@ class SwitchPhpVersionCommand extends BaseCommand
|
||||
public function handle(): int
|
||||
{
|
||||
$php_ver = $this->input->getArgument('php-major-version');
|
||||
if (!in_array($php_ver, ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4'])) {
|
||||
if (!in_array($php_ver, ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'])) {
|
||||
// match x.y.z
|
||||
preg_match('/^\d+\.\d+\.\d+$/', $php_ver, $matches);
|
||||
if (!$matches) {
|
||||
|
||||
@ -22,7 +22,7 @@ class LinuxMuslCheck
|
||||
public static function optionalCheck(): bool
|
||||
{
|
||||
return getenv('SPC_TOOLCHAIN') === MuslToolchain::class ||
|
||||
(getenv('SPC_TOOLCHAIN') === ZigToolchain::class && !SystemUtil::isMuslDist());
|
||||
(getenv('SPC_TOOLCHAIN') === ZigToolchain::class && !SystemUtil::isMuslDist() && !str_contains((string) getenv('SPC_TARGET'), 'gnu'));
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
|
||||
@ -22,7 +22,6 @@ class LinuxToolCheckList
|
||||
'bzip2', 'cmake', 'gcc',
|
||||
'g++', 'patch', 'binutils-gold',
|
||||
'libtoolize', 'which',
|
||||
'patchelf',
|
||||
];
|
||||
|
||||
public const TOOLS_DEBIAN = [
|
||||
@ -31,7 +30,6 @@ class LinuxToolCheckList
|
||||
'tar', 'unzip', 'gzip', 'gcc', 'g++',
|
||||
'bzip2', 'cmake', 'patch',
|
||||
'xz', 'libtoolize', 'which',
|
||||
'patchelf',
|
||||
];
|
||||
|
||||
public const TOOLS_RHEL = [
|
||||
@ -39,8 +37,7 @@ class LinuxToolCheckList
|
||||
'git', 'autoconf', 'automake',
|
||||
'tar', 'unzip', 'gzip', 'gcc', 'g++',
|
||||
'bzip2', 'cmake', 'patch', 'which',
|
||||
'xz', 'libtool', 'gettext-devel',
|
||||
'patchelf',
|
||||
'xz', 'libtool', 'gettext-devel', 'file',
|
||||
];
|
||||
|
||||
public const TOOLS_ARCH = [
|
||||
@ -82,14 +79,14 @@ class LinuxToolCheckList
|
||||
return CheckResult::ok();
|
||||
}
|
||||
|
||||
#[AsCheckItem('if cmake version >= 3.18', limit_os: 'Linux')]
|
||||
#[AsCheckItem('if cmake version >= 3.22', limit_os: 'Linux')]
|
||||
public function checkCMakeVersion(): ?CheckResult
|
||||
{
|
||||
$ver = get_cmake_version();
|
||||
if ($ver === null) {
|
||||
return CheckResult::fail('Failed to get cmake version');
|
||||
}
|
||||
if (version_compare($ver, '3.18.0') < 0) {
|
||||
if (version_compare($ver, '3.22.0') < 0) {
|
||||
return CheckResult::fail('cmake version is too low (' . $ver . '), please update it manually!');
|
||||
}
|
||||
return CheckResult::ok($ver);
|
||||
|
||||
@ -137,13 +137,18 @@ class ExceptionHandler
|
||||
|
||||
self::logError("\n----------------------------------------\n");
|
||||
|
||||
self::logError('⚠ The ' . ConsoleColor::cyan('console output log') . ConsoleColor::red(' is saved in ') . ConsoleColor::none(SPC_OUTPUT_LOG));
|
||||
// convert log file path if in docker
|
||||
$spc_log_convert = get_display_path(SPC_OUTPUT_LOG);
|
||||
$shell_log_convert = get_display_path(SPC_SHELL_LOG);
|
||||
$spc_logs_dir_convert = get_display_path(SPC_LOGS_DIR);
|
||||
|
||||
self::logError('⚠ The ' . ConsoleColor::cyan('console output log') . ConsoleColor::red(' is saved in ') . ConsoleColor::none($spc_log_convert));
|
||||
if (file_exists(SPC_SHELL_LOG)) {
|
||||
self::logError('⚠ The ' . ConsoleColor::cyan('shell output log') . ConsoleColor::red(' is saved in ') . ConsoleColor::none(SPC_SHELL_LOG));
|
||||
self::logError('⚠ The ' . ConsoleColor::cyan('shell output log') . ConsoleColor::red(' is saved in ') . ConsoleColor::none($shell_log_convert));
|
||||
}
|
||||
if ($e->getExtraLogFiles() !== []) {
|
||||
foreach ($e->getExtraLogFiles() as $key => $file) {
|
||||
self::logError("⚠ Log file [{$key}] is saved in: " . ConsoleColor::none(SPC_LOGS_DIR . "/{$file}"));
|
||||
self::logError("⚠ Log file [{$key}] is saved in: " . ConsoleColor::none("{$spc_logs_dir_convert}/{$file}"));
|
||||
}
|
||||
}
|
||||
if (!defined('DEBUG_MODE')) {
|
||||
@ -154,7 +159,9 @@ class ExceptionHandler
|
||||
public static function handleDefaultException(\Throwable $e): void
|
||||
{
|
||||
$class = get_class($e);
|
||||
self::logError("✗ Unhandled exception {$class}:\n\t{$e->getMessage()}\n");
|
||||
$file = $e->getFile();
|
||||
$line = $e->getLine();
|
||||
self::logError("✗ Unhandled exception {$class} on {$file} line {$line}:\n\t{$e->getMessage()}\n");
|
||||
self::logError('Stack trace:');
|
||||
self::logError(ConsoleColor::gray($e->getTraceAsString()) . PHP_EOL, 4);
|
||||
self::logError('⚠ Please report this exception to: https://github.com/crazywhalecc/static-php-cli/issues');
|
||||
|
||||
95
src/SPC/store/DirDiff.php
Normal file
95
src/SPC/store/DirDiff.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace SPC\store;
|
||||
|
||||
/**
|
||||
* A util class to diff directory file increments.
|
||||
*/
|
||||
class DirDiff
|
||||
{
|
||||
protected array $before = [];
|
||||
|
||||
protected array $before_file_hashes = [];
|
||||
|
||||
public function __construct(protected string $dir, protected bool $track_content_changes = false)
|
||||
{
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the baseline to current state.
|
||||
*/
|
||||
public function reset(): void
|
||||
{
|
||||
$this->before = FileSystem::scanDirFiles($this->dir, relative: true) ?: [];
|
||||
|
||||
if ($this->track_content_changes) {
|
||||
$this->before_file_hashes = [];
|
||||
foreach ($this->before as $file) {
|
||||
$this->before_file_hashes[$file] = md5_file($this->dir . DIRECTORY_SEPARATOR . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of incremented files.
|
||||
*
|
||||
* @param bool $relative Return relative paths or absolute paths
|
||||
* @return array<string> List of incremented files
|
||||
*/
|
||||
public function getIncrementFiles(bool $relative = false): array
|
||||
{
|
||||
$after = FileSystem::scanDirFiles($this->dir, relative: true) ?: [];
|
||||
$diff = array_diff($after, $this->before);
|
||||
if ($relative) {
|
||||
return $diff;
|
||||
}
|
||||
return array_map(fn ($f) => $this->dir . DIRECTORY_SEPARATOR . $f, $diff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of changed files (including new files).
|
||||
*
|
||||
* @param bool $relative Return relative paths or absolute paths
|
||||
* @param bool $include_new_files Include new files as changed files
|
||||
* @return array<string> List of changed files
|
||||
*/
|
||||
public function getChangedFiles(bool $relative = false, bool $include_new_files = true): array
|
||||
{
|
||||
$after = FileSystem::scanDirFiles($this->dir, relative: true) ?: [];
|
||||
$changed = [];
|
||||
foreach ($after as $file) {
|
||||
if (isset($this->before_file_hashes[$file])) {
|
||||
$after_hash = md5_file($this->dir . DIRECTORY_SEPARATOR . $file);
|
||||
if ($after_hash !== $this->before_file_hashes[$file]) {
|
||||
$changed[] = $file;
|
||||
}
|
||||
} elseif ($include_new_files) {
|
||||
// New file, consider as changed
|
||||
$changed[] = $file;
|
||||
}
|
||||
}
|
||||
if ($relative) {
|
||||
return $changed;
|
||||
}
|
||||
return array_map(fn ($f) => $this->dir . DIRECTORY_SEPARATOR . $f, $changed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of removed files.
|
||||
*
|
||||
* @param bool $relative Return relative paths or absolute paths
|
||||
* @return array<string> List of removed files
|
||||
*/
|
||||
public function getRemovedFiles(bool $relative = false): array
|
||||
{
|
||||
$after = FileSystem::scanDirFiles($this->dir, relative: true) ?: [];
|
||||
$removed = array_diff($this->before, $after);
|
||||
if ($relative) {
|
||||
return $removed;
|
||||
}
|
||||
return array_map(fn ($f) => $this->dir . DIRECTORY_SEPARATOR . $f, $removed);
|
||||
}
|
||||
}
|
||||
@ -16,6 +16,42 @@ use SPC\util\SPCTarget;
|
||||
*/
|
||||
class Downloader
|
||||
{
|
||||
/**
|
||||
* Get latest version from PIE config (Packagist)
|
||||
*
|
||||
* @param string $name Source name
|
||||
* @param array $source Source meta info: [repo]
|
||||
* @return array<int, string> [url, filename]
|
||||
*/
|
||||
public static function getPIEInfo(string $name, array $source): array
|
||||
{
|
||||
$packagist_url = "https://repo.packagist.org/p2/{$source['repo']}.json";
|
||||
logger()->debug("Fetching {$name} source from packagist index: {$packagist_url}");
|
||||
$data = json_decode(self::curlExec(
|
||||
url: $packagist_url,
|
||||
retries: self::getRetryAttempts()
|
||||
), true);
|
||||
if (!isset($data['packages'][$source['repo']]) || !is_array($data['packages'][$source['repo']])) {
|
||||
throw new DownloaderException("failed to find {$name} repo info from packagist");
|
||||
}
|
||||
// get the first version
|
||||
$first = $data['packages'][$source['repo']][0] ?? [];
|
||||
// check 'type' => 'php-ext' or contains 'php-ext' key
|
||||
if (!isset($first['php-ext'])) {
|
||||
throw new DownloaderException("failed to find {$name} php-ext info from packagist, maybe not a php extension package");
|
||||
}
|
||||
// get download link from dist
|
||||
$dist_url = $first['dist']['url'] ?? null;
|
||||
$dist_type = $first['dist']['type'] ?? null;
|
||||
if (!$dist_url || !$dist_type) {
|
||||
throw new DownloaderException("failed to find {$name} dist info from packagist");
|
||||
}
|
||||
$name = str_replace('/', '_', $source['repo']);
|
||||
$version = $first['version'] ?? 'unknown';
|
||||
// file name use: $name-$version.$dist_type
|
||||
return [$dist_url, "{$name}-{$version}.{$dist_type}"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest version from BitBucket tag
|
||||
*
|
||||
@ -61,8 +97,9 @@ class Downloader
|
||||
public static function getLatestGithubTarball(string $name, array $source, string $type = 'releases'): array
|
||||
{
|
||||
logger()->debug("finding {$name} source from github {$type} tarball");
|
||||
$source['query'] ??= '';
|
||||
$data = json_decode(self::curlExec(
|
||||
url: "https://api.github.com/repos/{$source['repo']}/{$type}",
|
||||
url: "https://api.github.com/repos/{$source['repo']}/{$type}{$source['query']}",
|
||||
hooks: [[CurlHook::class, 'setupGithubToken']],
|
||||
retries: self::getRetryAttempts()
|
||||
), true, 512, JSON_THROW_ON_ERROR);
|
||||
@ -72,6 +109,9 @@ class Downloader
|
||||
if (($rel['prerelease'] ?? false) === true && ($source['prefer-stable'] ?? false)) {
|
||||
continue;
|
||||
}
|
||||
if (($rel['draft'] ?? false) === true && (($source['prefer-stable'] ?? false) || !$rel['tarball_url'])) {
|
||||
continue;
|
||||
}
|
||||
if (!($source['match'] ?? null)) {
|
||||
$url = $rel['tarball_url'] ?? null;
|
||||
break;
|
||||
@ -317,84 +357,7 @@ class Downloader
|
||||
if (self::isAlreadyDownloaded($name, $force, SPC_DOWNLOAD_PACKAGE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
switch ($pkg['type']) {
|
||||
case 'bitbuckettag': // BitBucket Tag
|
||||
[$url, $filename] = self::getLatestBitbucketTag($name, $pkg);
|
||||
self::downloadFile($name, $url, $filename, $pkg['extract'] ?? null, SPC_DOWNLOAD_PACKAGE);
|
||||
break;
|
||||
case 'ghtar': // GitHub Release (tar)
|
||||
[$url, $filename] = self::getLatestGithubTarball($name, $pkg);
|
||||
self::downloadFile($name, $url, $filename, $pkg['extract'] ?? null, SPC_DOWNLOAD_PACKAGE, hooks: [[CurlHook::class, 'setupGithubToken']]);
|
||||
break;
|
||||
case 'ghtagtar': // GitHub Tag (tar)
|
||||
[$url, $filename] = self::getLatestGithubTarball($name, $pkg, 'tags');
|
||||
self::downloadFile($name, $url, $filename, $pkg['extract'] ?? null, SPC_DOWNLOAD_PACKAGE, hooks: [[CurlHook::class, 'setupGithubToken']]);
|
||||
break;
|
||||
case 'ghrel': // GitHub Release (uploaded)
|
||||
[$url, $filename] = self::getLatestGithubRelease($name, $pkg);
|
||||
self::downloadFile($name, $url, $filename, $pkg['extract'] ?? null, SPC_DOWNLOAD_PACKAGE, ['Accept: application/octet-stream'], [[CurlHook::class, 'setupGithubToken']]);
|
||||
break;
|
||||
case 'filelist': // Basic File List (regex based crawler)
|
||||
[$url, $filename] = self::getFromFileList($name, $pkg);
|
||||
self::downloadFile($name, $url, $filename, $pkg['extract'] ?? null, SPC_DOWNLOAD_PACKAGE);
|
||||
break;
|
||||
case 'url': // Direct download URL
|
||||
$url = $pkg['url'];
|
||||
$filename = $pkg['filename'] ?? basename($pkg['url']);
|
||||
self::downloadFile($name, $url, $filename, $pkg['extract'] ?? null, SPC_DOWNLOAD_PACKAGE);
|
||||
break;
|
||||
case 'git': // Git repo
|
||||
self::downloadGit(
|
||||
$name,
|
||||
$pkg['url'],
|
||||
$pkg['rev'],
|
||||
$pkg['submodules'] ?? null,
|
||||
$pkg['extract'] ?? null,
|
||||
self::getRetryAttempts(),
|
||||
SPC_DOWNLOAD_PRE_BUILT
|
||||
);
|
||||
break;
|
||||
case 'local':
|
||||
// Local directory, do nothing, just lock it
|
||||
logger()->debug("Locking local source {$name}");
|
||||
LockFile::lockSource($name, [
|
||||
'source_type' => SPC_SOURCE_LOCAL,
|
||||
'dirname' => $pkg['dirname'],
|
||||
'move_path' => $pkg['extract'] ?? null,
|
||||
'lock_as' => SPC_DOWNLOAD_PACKAGE,
|
||||
]);
|
||||
break;
|
||||
case 'custom': // Custom download method, like API-based download or other
|
||||
$classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/pkg', 'SPC\store\pkg');
|
||||
if (isset($pkg['func']) && is_callable($pkg['func'])) {
|
||||
$pkg['name'] = $name;
|
||||
$pkg['func']($force, $pkg, SPC_DOWNLOAD_PACKAGE);
|
||||
break;
|
||||
}
|
||||
foreach ($classes as $class) {
|
||||
if (is_a($class, CustomPackage::class, true) && $class !== CustomPackage::class) {
|
||||
$cls = new $class();
|
||||
if (in_array($name, $cls->getSupportName())) {
|
||||
(new $class())->fetch($name, $force, $pkg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new DownloaderException('unknown source type: ' . $pkg['type']);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// Because sometimes files downloaded through the command line are not automatically deleted after a failure.
|
||||
// Here we need to manually delete the file if it is detected to exist.
|
||||
if (isset($filename) && file_exists(DOWNLOAD_PATH . '/' . $filename)) {
|
||||
logger()->warning('Deleting download file: ' . $filename);
|
||||
unlink(DOWNLOAD_PATH . '/' . $filename);
|
||||
}
|
||||
throw new DownloaderException('Download failed! ' . $e->getMessage());
|
||||
}
|
||||
self::downloadByType($pkg['type'], $name, $pkg, $force, SPC_DOWNLOAD_PACKAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -439,80 +402,7 @@ class Downloader
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
switch ($source['type']) {
|
||||
case 'bitbuckettag': // BitBucket Tag
|
||||
[$url, $filename] = self::getLatestBitbucketTag($name, $source);
|
||||
self::downloadFile($name, $url, $filename, $source['path'] ?? null, $download_as);
|
||||
break;
|
||||
case 'ghtar': // GitHub Release (tar)
|
||||
[$url, $filename] = self::getLatestGithubTarball($name, $source);
|
||||
self::downloadFile($name, $url, $filename, $source['path'] ?? null, $download_as, hooks: [[CurlHook::class, 'setupGithubToken']]);
|
||||
break;
|
||||
case 'ghtagtar': // GitHub Tag (tar)
|
||||
[$url, $filename] = self::getLatestGithubTarball($name, $source, 'tags');
|
||||
self::downloadFile($name, $url, $filename, $source['path'] ?? null, $download_as, hooks: [[CurlHook::class, 'setupGithubToken']]);
|
||||
break;
|
||||
case 'ghrel': // GitHub Release (uploaded)
|
||||
[$url, $filename] = self::getLatestGithubRelease($name, $source);
|
||||
self::downloadFile($name, $url, $filename, $source['path'] ?? null, $download_as, ['Accept: application/octet-stream'], [[CurlHook::class, 'setupGithubToken']]);
|
||||
break;
|
||||
case 'filelist': // Basic File List (regex based crawler)
|
||||
[$url, $filename] = self::getFromFileList($name, $source);
|
||||
self::downloadFile($name, $url, $filename, $source['path'] ?? null, $download_as);
|
||||
break;
|
||||
case 'url': // Direct download URL
|
||||
$url = $source['url'];
|
||||
$filename = $source['filename'] ?? basename($source['url']);
|
||||
self::downloadFile($name, $url, $filename, $source['path'] ?? null, $download_as);
|
||||
break;
|
||||
case 'git': // Git repo
|
||||
self::downloadGit(
|
||||
$name,
|
||||
$source['url'],
|
||||
$source['rev'],
|
||||
$source['submodules'] ?? null,
|
||||
$source['path'] ?? null,
|
||||
self::getRetryAttempts(),
|
||||
$download_as
|
||||
);
|
||||
break;
|
||||
case 'local':
|
||||
// Local directory, do nothing, just lock it
|
||||
logger()->debug("Locking local source {$name}");
|
||||
LockFile::lockSource($name, [
|
||||
'source_type' => SPC_SOURCE_LOCAL,
|
||||
'dirname' => $source['dirname'],
|
||||
'move_path' => $source['extract'] ?? null,
|
||||
'lock_as' => $download_as,
|
||||
]);
|
||||
break;
|
||||
case 'custom': // Custom download method, like API-based download or other
|
||||
if (isset($source['func']) && is_callable($source['func'])) {
|
||||
$source['name'] = $name;
|
||||
$source['func']($force, $source, $download_as);
|
||||
break;
|
||||
}
|
||||
$classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/source', 'SPC\store\source');
|
||||
foreach ($classes as $class) {
|
||||
if (is_a($class, CustomSourceBase::class, true) && $class::NAME === $name) {
|
||||
(new $class())->fetch($force, $source, $download_as);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new DownloaderException('unknown source type: ' . $source['type']);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// Because sometimes files downloaded through the command line are not automatically deleted after a failure.
|
||||
// Here we need to manually delete the file if it is detected to exist.
|
||||
if (isset($filename) && file_exists(DOWNLOAD_PATH . '/' . $filename)) {
|
||||
logger()->warning('Deleting download file: ' . $filename);
|
||||
unlink(DOWNLOAD_PATH . '/' . $filename);
|
||||
}
|
||||
throw new DownloaderException('Download failed! ' . $e->getMessage());
|
||||
}
|
||||
self::downloadByType($source['type'], $name, $source, $force, $download_as);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -713,4 +603,109 @@ class Downloader
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download by type.
|
||||
*
|
||||
* @param string $type Types
|
||||
* @param string $name Download item name
|
||||
* @param array{
|
||||
* url?: string,
|
||||
* repo?: string,
|
||||
* rev?: string,
|
||||
* path?: string,
|
||||
* filename?: string,
|
||||
* dirname?: string,
|
||||
* match?: string,
|
||||
* prefer-stable?: bool,
|
||||
* extract?: string,
|
||||
* submodules?: array<string>,
|
||||
* provide-pre-built?: bool,
|
||||
* func?: ?callable,
|
||||
* license?: array
|
||||
* } $conf Download item config
|
||||
* @param bool $force Force download
|
||||
* @param int $download_as Lock source type
|
||||
*/
|
||||
private static function downloadByType(string $type, string $name, array $conf, bool $force, int $download_as): void
|
||||
{
|
||||
try {
|
||||
switch ($type) {
|
||||
case 'pie': // Packagist
|
||||
[$url, $filename] = self::getPIEInfo($name, $conf);
|
||||
self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as, hooks: [[CurlHook::class, 'setupGithubToken']]);
|
||||
break;
|
||||
case 'bitbuckettag': // BitBucket Tag
|
||||
[$url, $filename] = self::getLatestBitbucketTag($name, $conf);
|
||||
self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as);
|
||||
break;
|
||||
case 'ghtar': // GitHub Release (tar)
|
||||
[$url, $filename] = self::getLatestGithubTarball($name, $conf);
|
||||
self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as, hooks: [[CurlHook::class, 'setupGithubToken']]);
|
||||
break;
|
||||
case 'ghtagtar': // GitHub Tag (tar)
|
||||
[$url, $filename] = self::getLatestGithubTarball($name, $conf, 'tags');
|
||||
self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as, hooks: [[CurlHook::class, 'setupGithubToken']]);
|
||||
break;
|
||||
case 'ghrel': // GitHub Release (uploaded)
|
||||
[$url, $filename] = self::getLatestGithubRelease($name, $conf);
|
||||
self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as, ['Accept: application/octet-stream'], [[CurlHook::class, 'setupGithubToken']]);
|
||||
break;
|
||||
case 'filelist': // Basic File List (regex based crawler)
|
||||
[$url, $filename] = self::getFromFileList($name, $conf);
|
||||
self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as);
|
||||
break;
|
||||
case 'url': // Direct download URL
|
||||
$url = $conf['url'];
|
||||
$filename = $conf['filename'] ?? basename($conf['url']);
|
||||
self::downloadFile($name, $url, $filename, $conf['path'] ?? $conf['extract'] ?? null, $download_as);
|
||||
break;
|
||||
case 'git': // Git repo
|
||||
self::downloadGit($name, $conf['url'], $conf['rev'], $conf['submodules'] ?? null, $conf['path'] ?? $conf['extract'] ?? null, self::getRetryAttempts(), $download_as);
|
||||
break;
|
||||
case 'local': // Local directory, do nothing, just lock it
|
||||
LockFile::lockSource($name, [
|
||||
'source_type' => SPC_SOURCE_LOCAL,
|
||||
'dirname' => $conf['dirname'],
|
||||
'move_path' => $conf['path'] ?? $conf['extract'] ?? null,
|
||||
'lock_as' => $download_as,
|
||||
]);
|
||||
break;
|
||||
case 'custom': // Custom download method, like API-based download or other
|
||||
if (isset($conf['func'])) {
|
||||
$conf['name'] = $name;
|
||||
$conf['func']($force, $conf, $download_as);
|
||||
break;
|
||||
}
|
||||
$classes = [
|
||||
...FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/source', 'SPC\store\source'),
|
||||
...FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/store/pkg', 'SPC\store\pkg'),
|
||||
];
|
||||
foreach ($classes as $class) {
|
||||
if (is_a($class, CustomSourceBase::class, true) && $class::NAME === $name) {
|
||||
(new $class())->fetch($force, $conf, $download_as);
|
||||
break;
|
||||
}
|
||||
if (is_a($class, CustomPackage::class, true) && $class !== CustomPackage::class) {
|
||||
$cls = new $class();
|
||||
if (in_array($name, $cls->getSupportName())) {
|
||||
(new $class())->fetch($name, $force, $conf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new DownloaderException("Unknown download type: {$type}");
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// Because sometimes files downloaded through the command line are not automatically deleted after a failure.
|
||||
// Here we need to manually delete the file if it is detected to exist.
|
||||
if (isset($filename) && file_exists(DOWNLOAD_PATH . '/' . $filename)) {
|
||||
logger()->warning("Deleting download file: {$filename}");
|
||||
unlink(DOWNLOAD_PATH . '/' . $filename);
|
||||
}
|
||||
throw new DownloaderException("Download failed: {$e->getMessage()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user