mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-02 14:25:41 +08:00
[v3] docs update: guide part (#1112)
This commit is contained in:
12
.github/workflows/vitepress-deploy.yml
vendored
12
.github/workflows/vitepress-deploy.yml
vendored
@@ -55,11 +55,13 @@ jobs:
|
|||||||
- name: "Install Locked Dependencies"
|
- name: "Install Locked Dependencies"
|
||||||
run: "composer install --no-interaction --no-progress"
|
run: "composer install --no-interaction --no-progress"
|
||||||
|
|
||||||
- name: "Generate Extension Support List"
|
# TODO: Uncomment when v3 gen commands are implemented
|
||||||
run: |
|
# - name: "Generate Extension Support List"
|
||||||
bin/spc dev:gen-ext-docs > docs/extensions.md
|
# run: |
|
||||||
bin/spc dev:gen-ext-dep-docs > docs/deps-map-ext.md
|
# bin/spc dev:gen-ext-docs > docs/en/guide/extensions.md
|
||||||
bin/spc dev:gen-lib-dep-docs > docs/deps-map-lib.md
|
# bin/spc dev:gen-ext-docs > docs/zh/guide/extensions.md
|
||||||
|
# bin/spc dev:gen-ext-dep-docs > docs/en/guide/deps-map.md
|
||||||
|
# bin/spc dev:gen-ext-dep-docs > docs/zh/guide/deps-map.md
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: yarn docs:build
|
run: yarn docs:build
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -52,6 +52,8 @@ packlib_files.txt
|
|||||||
/node_modules/
|
/node_modules/
|
||||||
/docs/.vitepress/dist/
|
/docs/.vitepress/dist/
|
||||||
/docs/.vitepress/cache/
|
/docs/.vitepress/cache/
|
||||||
|
/docs/.vitepress/ext-data.json
|
||||||
|
/docs/.vitepress/deps-data.json
|
||||||
package-lock.json
|
package-lock.json
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<div v-if="missing" class="warning custom-block" style="margin-bottom: 16px">
|
||||||
|
<p class="custom-block-title">WARNING</p>
|
||||||
|
<p>Extension list is not generated yet. Run <code>bin/spc dev:gen-ext-docs</code> to generate it.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>{{ I18N[lang].selectedSystem }}</h2>
|
<h2>{{ I18N[lang].selectedSystem }}</h2>
|
||||||
<div class="option-line">
|
<div class="option-line">
|
||||||
<span v-for="(item, index) in osList" :key="index" style="margin-right: 8px">
|
<span v-for="(item, index) in osList" :key="index" style="margin-right: 8px">
|
||||||
<input type="radio" :id="'os-' + item.os" :value="item.os" :disabled="item.disabled === true" v-model="selectedSystem" />
|
<input type="radio" :id="'os-' + item.os" :value="item.os" v-model="selectedSystem" />
|
||||||
<label :for="'os-' + item.os">{{ item.label }}</label>
|
<label :for="'os-' + item.os">{{ item.label }}</label>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -13,13 +18,14 @@
|
|||||||
<option value="aarch64" :disabled="selectedSystem === 'windows'">aarch64</option>
|
<option value="aarch64" :disabled="selectedSystem === 'windows'">aarch64</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>{{ I18N[lang].selectExt }}{{ checkedExts.length > 0 ? (' (' + checkedExts.length + ')') : '' }}</h2>
|
<h2>{{ I18N[lang].selectExt }}{{ checkedExts.length > 0 ? (' (' + checkedExts.length + ')') : '' }}</h2>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<input class="input" v-model="filterText" :placeholder="I18N[lang].searchPlaceholder" />
|
<input class="input" v-model="filterText" :placeholder="I18N[lang].searchPlaceholder" />
|
||||||
<br>
|
<br>
|
||||||
<div v-for="item in extFilter" :key="item" class="ext-item">
|
<div v-for="item in extByOS" :key="item" class="ext-item">
|
||||||
<span>
|
<span>
|
||||||
<input type="checkbox" :id="item" :value="item" v-model="checkedExts" :disabled="extDisableList.indexOf(item) !== -1">
|
<input type="checkbox" :id="item" :value="item" v-model="checkedExts" />
|
||||||
<label :for="item">
|
<label :for="item">
|
||||||
<span>{{ highlightItem(item, 0) }}</span>
|
<span>{{ highlightItem(item, 0) }}</span>
|
||||||
<span style="color: orangered; font-weight: bolder">{{ highlightItem(item, 1) }}</span>
|
<span style="color: orangered; font-weight: bolder">{{ highlightItem(item, 1) }}</span>
|
||||||
@@ -32,50 +38,31 @@
|
|||||||
<div class="my-btn" v-if="selectedSystem !== 'windows'" @click="selectAll">{{ I18N[lang].selectAll }}</div>
|
<div class="my-btn" v-if="selectedSystem !== 'windows'" @click="selectAll">{{ I18N[lang].selectAll }}</div>
|
||||||
<div class="my-btn" @click="checkedExts = []">{{ I18N[lang].selectNone }}</div>
|
<div class="my-btn" @click="checkedExts = []">{{ I18N[lang].selectNone }}</div>
|
||||||
|
|
||||||
<details class="details custom-block" open>
|
|
||||||
<summary>{{ I18N[lang].buildLibs }}{{ checkedLibs.length > 0 ? (' (' + checkedLibs.length + ')') : '' }}</summary>
|
|
||||||
<div class="box">
|
|
||||||
<div v-for="(item, index) in libContain" :key="index" class="ext-item">
|
|
||||||
<input type="checkbox" :id="index" :value="item" v-model="checkedLibs" :disabled="libDisableList.indexOf(item) !== -1">
|
|
||||||
<label :for="index">{{ item }}</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
<div class="tip custom-block">
|
|
||||||
<p class="custom-block-title">TIP</p>
|
|
||||||
<p>{{ I18N[lang].depTips }}</p>
|
|
||||||
<p>{{ I18N[lang].depTips2 }}</p>
|
|
||||||
</div>
|
|
||||||
<h2>{{ I18N[lang].buildTarget }}</h2>
|
<h2>{{ I18N[lang].buildTarget }}</h2>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div v-for="item in TARGET" :key="item" class="ext-item">
|
<div v-for="item in TARGET" :key="item" class="ext-item">
|
||||||
<input type="checkbox" :id="'build_' + item" :value="item" v-model="checkedTargets" @change="onTargetChange">
|
<input type="checkbox" :id="'build_' + item" :value="item" v-model="checkedTargets" />
|
||||||
<label :for="'build_' + item">{{ item }}</label>
|
<label :for="'build_' + item">{{ item }}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="selectedPhpVersion === '7.4' && (checkedTargets.indexOf('micro') !== -1 || checkedTargets.indexOf('all') !== -1)" class="warning custom-block">
|
<div v-if="selectedSystem === 'windows' && (checkedTargets.includes('fpm') || checkedTargets.includes('embed') || checkedTargets.includes('frankenphp'))" class="warning custom-block">
|
||||||
<p class="custom-block-title">WARNING</p>
|
|
||||||
<p>{{ I18N[lang].microUnavailable }}</p>
|
|
||||||
</div>
|
|
||||||
<div v-if="selectedSystem === 'windows' && (checkedTargets.indexOf('fpm') !== -1 || checkedTargets.indexOf('embed') !== -1 || checkedTargets.indexOf('frankenphp') !== -1)" class="warning custom-block">
|
|
||||||
<p class="custom-block-title">WARNING</p>
|
<p class="custom-block-title">WARNING</p>
|
||||||
<p>{{ I18N[lang].windowsSAPIUnavailable }}</p>
|
<p>{{ I18N[lang].windowsSAPIUnavailable }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>{{ I18N[lang].buildOptions }}</h2>
|
<h2>{{ I18N[lang].buildOptions }}</h2>
|
||||||
<!-- Refactor all build options in table -->
|
|
||||||
<table>
|
<table>
|
||||||
<!-- buildEnvironment -->
|
<!-- Build Environment -->
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ I18N[lang].buildEnvironment }}</td>
|
<td>{{ I18N[lang].buildEnvironment }}</td>
|
||||||
<td>
|
<td>
|
||||||
<select v-model="selectedEnv">
|
<select v-model="selectedEnv">
|
||||||
<option value="native">{{ I18N[lang].buildEnvNative }}</option>
|
|
||||||
<option value="spc">{{ I18N[lang].buildEnvSpc }}</option>
|
<option value="spc">{{ I18N[lang].buildEnvSpc }}</option>
|
||||||
<option value="docker" v-if="selectedSystem !== 'windows'">{{ I18N[lang].buildEnvDocker }}</option>
|
<option value="native">{{ I18N[lang].buildEnvNative }}</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- Download PHP version -->
|
<!-- PHP Version -->
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ I18N[lang].downloadPhpVersion }}</td>
|
<td>{{ I18N[lang].downloadPhpVersion }}</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -84,70 +71,85 @@
|
|||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- Enable debug message -->
|
<!-- Verbose log -->
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ I18N[lang].useDebug }}</td>
|
<td>{{ I18N[lang].useVerbose }}</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="radio" id="debug-yes" :value="1" v-model="debug" />
|
<select v-model="verbosity">
|
||||||
<label for="debug-yes">{{ I18N[lang].yes }}</label>
|
<option value="">{{ I18N[lang].verboseNone }}</option>
|
||||||
<input type="radio" id="debug-no" :value="0" v-model="debug" />
|
<option value="-v">-v</option>
|
||||||
<label for="debug-no">{{ I18N[lang].no }}</label>
|
<option value="-vv">-vv</option>
|
||||||
|
<option value="-vvv">-vvv</option>
|
||||||
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- Enable ZTS -->
|
<!-- Enable ZTS -->
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ I18N[lang].useZTS }}</td>
|
<td>{{ I18N[lang].useZTS }}</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="radio" id="zts-yes" :value="1" v-model="zts" />
|
<input type="radio" id="zts-yes" :value="true" v-model="zts" />
|
||||||
<label for="zts-yes">{{ I18N[lang].yes }}</label>
|
<label for="zts-yes">{{ I18N[lang].yes }}</label>
|
||||||
<input type="radio" id="zts-no" :value="0" v-model="zts" />
|
<input type="radio" id="zts-no" :value="false" v-model="zts" />
|
||||||
<label for="zts-no">{{ I18N[lang].no }}</label>
|
<label for="zts-no">{{ I18N[lang].no }}</label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- download corresponding extensions -->
|
<!-- Parallel downloads -->
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ I18N[lang].resultShowDownload }}</td>
|
<td>{{ I18N[lang].dlParallel }}</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="radio" id="show-download-yes" :value="1" v-model="downloadByExt" />
|
<input class="number-input" type="number" v-model.number="dlParallel" min="1" max="50" />
|
||||||
<label for="show-download-yes">{{ I18N[lang].yes }}</label>
|
|
||||||
<input type="radio" id="show-download-no" :value="0" v-model="downloadByExt" />
|
|
||||||
<label for="show-download-no">{{ I18N[lang].no }}</label>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- Download pre-built -->
|
<!-- Retry count -->
|
||||||
|
<tr>
|
||||||
|
<td>{{ I18N[lang].dlRetry }}</td>
|
||||||
|
<td>
|
||||||
|
<input class="number-input" type="number" v-model.number="dlRetry" min="0" max="100" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- Prefer binary (pre-built) -->
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ I18N[lang].usePreBuilt }}</td>
|
<td>{{ I18N[lang].usePreBuilt }}</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="radio" id="pre-built-yes" :value="1" v-model="preBuilt" />
|
<input type="radio" id="pre-built-yes" :value="true" v-model="preBuilt" />
|
||||||
<label for="pre-built-yes">{{ I18N[lang].yes }}</label>
|
<label for="pre-built-yes">{{ I18N[lang].yes }}</label>
|
||||||
<input type="radio" id="pre-built-no" :value="0" v-model="preBuilt" />
|
<input type="radio" id="pre-built-no" :value="false" v-model="preBuilt" />
|
||||||
<label for="pre-built-no">{{ I18N[lang].no }}</label>
|
<label for="pre-built-no">{{ I18N[lang].no }}</label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- Enable UPX -->
|
<!-- Enable UPX (linux/windows only) -->
|
||||||
<tr v-if="selectedSystem !== 'macos'">
|
<tr v-if="selectedSystem !== 'macos'">
|
||||||
<td>{{ I18N[lang].useUPX }}</td>
|
<td>{{ I18N[lang].useUPX }}</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="radio" id="upx-yes" :value="1" v-model="enableUPX" />
|
<input type="radio" id="upx-yes" :value="true" v-model="enableUPX" />
|
||||||
<label for="upx-yes">{{ I18N[lang].yes }}</label>
|
<label for="upx-yes">{{ I18N[lang].yes }}</label>
|
||||||
<input type="radio" id="upx-no" :value="0" v-model="enableUPX" />
|
<input type="radio" id="upx-no" :value="false" v-model="enableUPX" />
|
||||||
<label for="upx-no">{{ I18N[lang].no }}</label>
|
<label for="upx-no">{{ I18N[lang].no }}</label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<!-- Keep debug symbols (--no-strip) -->
|
||||||
|
<tr>
|
||||||
|
<td>{{ I18N[lang].noStrip }}</td>
|
||||||
|
<td>
|
||||||
|
<input type="radio" id="nostrip-yes" :value="true" v-model="noStrip" />
|
||||||
|
<label for="nostrip-yes">{{ I18N[lang].yes }}</label>
|
||||||
|
<input type="radio" id="nostrip-no" :value="false" v-model="noStrip" />
|
||||||
|
<label for="nostrip-no">{{ I18N[lang].no }}</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h2>{{ I18N[lang].hardcodedINI }}</h2>
|
<h2>{{ I18N[lang].hardcodedINI }}</h2>
|
||||||
<textarea class="textarea" :placeholder="I18N[lang].hardcodedINIPlacehoder" v-model="hardcodedINIData" rows="5" />
|
<textarea class="textarea" :placeholder="I18N[lang].hardcodedINIPlaceholder" v-model="hardcodedINIData" rows="5" />
|
||||||
|
|
||||||
<h2>{{ I18N[lang].resultShow }}</h2>
|
<h2>{{ I18N[lang].resultShow }}</h2>
|
||||||
|
|
||||||
<!-- SPC Binary Download Command -->
|
<!-- SPC Binary Download Command (spc env only) -->
|
||||||
<div v-if="selectedEnv === 'spc'" class="command-container">
|
<div v-if="selectedEnv === 'spc'" class="command-container">
|
||||||
<b>{{ I18N[lang].downloadSPCBinaryCommand }}</b>
|
<b>{{ I18N[lang].downloadSPCBinaryCommand }}</b>
|
||||||
<div v-if="selectedSystem !== 'windows'" class="command-preview">
|
<div v-if="selectedSystem !== 'windows'" class="command-preview">
|
||||||
<div class="command-content">
|
<div class="command-content">{{ spcDownloadCommand }}</div>
|
||||||
{{ spcDownloadCommand }}
|
<button class="copy-btn" @click="copyToClipboard(spcDownloadCommand, 'spcDownload')" :class="{ 'copied': copiedStates.spcDownload }">
|
||||||
</div>
|
|
||||||
<button class="copy-btn" @click="copyToClipboard(spcDownloadCommand)" :class="{ 'copied': copiedStates.spcDownload }">
|
|
||||||
{{ copiedStates.spcDownload ? I18N[lang].copied : I18N[lang].copy }}
|
{{ copiedStates.spcDownload ? I18N[lang].copied : I18N[lang].copy }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -155,56 +157,17 @@
|
|||||||
<div class="warning custom-block">
|
<div class="warning custom-block">
|
||||||
<p class="custom-block-title">WARNING</p>
|
<p class="custom-block-title">WARNING</p>
|
||||||
<p>{{ I18N[lang].windowsDownSPCWarning }}</p>
|
<p>{{ I18N[lang].windowsDownSPCWarning }}</p>
|
||||||
<a href="https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe" target="_blank">https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe</a>
|
<a href="https://dl.static-php.dev/v3/spc-bin/latest/spc-windows-x86_64.exe" target="_blank">https://dl.static-php.dev/v3/spc-bin/latest/spc-windows-x86_64.exe</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Download Commands -->
|
|
||||||
<div v-if="downloadByExt" class="command-container">
|
|
||||||
<b>{{ I18N[lang].downloadExtOnlyCommand }}</b>
|
|
||||||
<div class="command-preview">
|
|
||||||
<div class="command-content">
|
|
||||||
{{ downloadExtCommand }}
|
|
||||||
</div>
|
|
||||||
<button class="copy-btn" @click="copyToClipboard(downloadExtCommand)" :class="{ 'copied': copiedStates.downloadExt }">
|
|
||||||
{{ copiedStates.downloadExt ? I18N[lang].copied : I18N[lang].copy }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="command-container">
|
|
||||||
<b>{{ I18N[lang].downloadAllCommand }}</b>
|
|
||||||
<div class="command-preview">
|
|
||||||
<div class="command-content">
|
|
||||||
{{ downloadAllCommand }}
|
|
||||||
</div>
|
|
||||||
<button class="copy-btn" @click="copyToClipboard(downloadAllCommand)" :class="{ 'copied': copiedStates.downloadAll }">
|
|
||||||
{{ copiedStates.downloadAll ? I18N[lang].copied : I18N[lang].copy }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- UPX Download Command -->
|
|
||||||
<div class="command-container" v-if="enableUPX">
|
|
||||||
<b>{{ I18N[lang].downloadUPXCommand }}</b>
|
|
||||||
<div class="command-preview">
|
|
||||||
<div class="command-content">
|
|
||||||
{{ downloadPkgCommand }}
|
|
||||||
</div>
|
|
||||||
<button class="copy-btn" @click="copyToClipboard(downloadPkgCommand)" :class="{ 'copied': copiedStates.downloadPkg }">
|
|
||||||
{{ copiedStates.downloadPkg ? I18N[lang].copied : I18N[lang].copy }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Doctor Command -->
|
<!-- Doctor Command -->
|
||||||
<div class="command-container">
|
<div class="command-container">
|
||||||
<b>{{ I18N[lang].doctorCommand }}</b>
|
<b>{{ I18N[lang].doctorCommand }}</b>
|
||||||
<div class="command-preview">
|
<div class="command-preview">
|
||||||
<div class="command-content">
|
<div class="command-content">{{ doctorCommandString }}</div>
|
||||||
{{ doctorCommandString }}
|
<button class="copy-btn" @click="copyToClipboard(doctorCommandString, 'doctor')" :class="{ 'copied': copiedStates.doctor }">
|
||||||
</div>
|
|
||||||
<button class="copy-btn" @click="copyToClipboard(doctorCommandString)" :class="{ 'copied': copiedStates.doctor }">
|
|
||||||
{{ copiedStates.doctor ? I18N[lang].copied : I18N[lang].copy }}
|
{{ copiedStates.doctor ? I18N[lang].copied : I18N[lang].copy }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -214,23 +177,19 @@
|
|||||||
<div class="command-container">
|
<div class="command-container">
|
||||||
<b>{{ I18N[lang].compileCommand }}</b>
|
<b>{{ I18N[lang].compileCommand }}</b>
|
||||||
<div class="command-preview">
|
<div class="command-preview">
|
||||||
<div class="command-content">
|
<div class="command-content">{{ buildCommandString }}</div>
|
||||||
{{ buildCommandString }}
|
<button class="copy-btn" @click="copyToClipboard(buildCommandString, 'build')" :class="{ 'copied': copiedStates.build }">
|
||||||
</div>
|
|
||||||
<button class="copy-btn" @click="copyToClipboard(buildCommandString)" :class="{ 'copied': copiedStates.build }">
|
|
||||||
{{ copiedStates.build ? I18N[lang].copied : I18N[lang].copy }}
|
{{ copiedStates.build ? I18N[lang].copied : I18N[lang].copy }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Craft.yml -->
|
<!-- craft.yml -->
|
||||||
<div class="command-container">
|
<div class="command-container">
|
||||||
<b>craft.yml</b>
|
<b>craft.yml</b>
|
||||||
<div class="command-preview pre">
|
<div class="command-preview pre">
|
||||||
<div class="command-content">
|
<div class="command-content">{{ craftCommandString }}</div>
|
||||||
{{ craftCommandString }}
|
<button class="copy-btn" @click="copyToClipboard(craftCommandString, 'craft')" :class="{ 'copied': copiedStates.craft }">
|
||||||
</div>
|
|
||||||
<button class="copy-btn" @click="copyToClipboard(craftCommandString)" :class="{ 'copied': copiedStates.craft }">
|
|
||||||
{{ copiedStates.craft ? I18N[lang].copied : I18N[lang].copy }}
|
{{ copiedStates.craft ? I18N[lang].copied : I18N[lang].copy }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -245,14 +204,12 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, ref, watch} from "vue";
|
import { computed, ref, watch } from 'vue';
|
||||||
import extData from '../config/ext.json';
|
// @ts-ignore VitePress data loader — transformed at build time
|
||||||
import libData from '../config/lib.json';
|
import { data as extDataRaw } from '../extensions.data.js';
|
||||||
import { getAllExtLibsByDeps } from './DependencyUtil.js';
|
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const OS_MAP = new Map([['linux', 'Linux'], ['macos', 'Darwin'], ['windows', 'Windows']]);
|
const TARGET = ['cli', 'fpm', 'micro', 'embed', 'frankenphp', 'cgi'];
|
||||||
const TARGET = ['cli', 'fpm', 'micro', 'embed', 'frankenphp', 'all'];
|
|
||||||
const availablePhpVersions = ['8.0', '8.1', '8.2', '8.3', '8.4', '8.5'];
|
const availablePhpVersions = ['8.0', '8.1', '8.2', '8.3', '8.4', '8.5'];
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
@@ -263,154 +220,135 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reactive data
|
// Extension data
|
||||||
const ext = ref(extData);
|
const missing = extDataRaw.missing ?? false;
|
||||||
const lib = ref(libData);
|
const allExtensions: Array<{ name: string; linux: boolean; macos: boolean; windows: boolean }> = extDataRaw.extensions ?? [];
|
||||||
const libContain = ref([]);
|
|
||||||
|
// Reactive state
|
||||||
const filterText = ref('');
|
const filterText = ref('');
|
||||||
const checkedExts = ref([]);
|
const checkedExts = ref<string[]>([]);
|
||||||
const checkedLibs = ref([]);
|
const checkedTargets = ref<string[]>(['cli']);
|
||||||
const extDisableList = ref([]);
|
const selectedEnv = ref<'spc' | 'native'>('spc');
|
||||||
const libDisableList = ref([]);
|
|
||||||
const checkedTargets = ref(['cli']);
|
|
||||||
const selectedEnv = ref('spc');
|
|
||||||
const selectedPhpVersion = ref('8.4');
|
const selectedPhpVersion = ref('8.4');
|
||||||
const selectedSystem = ref('linux');
|
const selectedSystem = ref<'linux' | 'macos' | 'windows'>('linux');
|
||||||
const selectedArch = ref('x86_64');
|
const selectedArch = ref<'x86_64' | 'aarch64'>('x86_64');
|
||||||
const debug = ref(0);
|
const verbosity = ref('');
|
||||||
const zts = ref(0);
|
const zts = ref(false);
|
||||||
const downloadByExt = ref(1);
|
const preBuilt = ref(true);
|
||||||
const preBuilt = ref(1);
|
const enableUPX = ref(false);
|
||||||
const enableUPX = ref(0);
|
const noStrip = ref(false);
|
||||||
|
const dlParallel = ref(10);
|
||||||
|
const dlRetry = ref(5);
|
||||||
const hardcodedINIData = ref('');
|
const hardcodedINIData = ref('');
|
||||||
const buildCommand = ref('--build-cli');
|
|
||||||
|
|
||||||
// Copy states
|
// Copy states
|
||||||
const copiedStates = ref({
|
const copiedStates = ref<Record<string, boolean>>({
|
||||||
spcDownload: false,
|
spcDownload: false,
|
||||||
downloadExt: false,
|
doctor: false,
|
||||||
downloadAll: false,
|
|
||||||
downloadPkg: false,
|
|
||||||
build: false,
|
build: false,
|
||||||
craft: false,
|
craft: false,
|
||||||
doctor: false
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// OS list
|
// OS list
|
||||||
const osList = [
|
const osList = [
|
||||||
{ os: 'linux', label: 'Linux', disabled: false },
|
{ os: 'linux', label: 'Linux' },
|
||||||
{ os: 'macos', label: 'macOS', disabled: false },
|
{ os: 'macos', label: 'macOS' },
|
||||||
{ os: 'windows', label: 'Windows', disabled: false },
|
{ os: 'windows', label: 'Windows' },
|
||||||
];
|
];
|
||||||
|
|
||||||
// Computed properties
|
// Computed: extensions filtered by selected OS
|
||||||
const extFilter = computed(() => {
|
const extByOS = computed(() => {
|
||||||
return Object.entries(ext.value)
|
return allExtensions
|
||||||
.filter(([name]) => isSupported(name, selectedSystem.value))
|
.filter(item => {
|
||||||
.map(([name]) => name);
|
if (selectedSystem.value === 'linux') return item.linux;
|
||||||
|
if (selectedSystem.value === 'macos') return item.macos;
|
||||||
|
if (selectedSystem.value === 'windows') return item.windows;
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.map(item => item.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
const extList = computed(() => checkedExts.value.join(','));
|
const extList = computed(() => [...checkedExts.value].sort().join(','));
|
||||||
|
|
||||||
const additionalLibs = computed(() => {
|
|
||||||
const ls = checkedLibs.value.filter(item => libDisableList.value.indexOf(item) === -1);
|
|
||||||
return ls.length > 0 ? ` --with-libs="${ls.join(',')}"` : '';
|
|
||||||
});
|
|
||||||
|
|
||||||
const spcCommand = computed(() => {
|
const spcCommand = computed(() => {
|
||||||
switch (selectedEnv.value) {
|
if (selectedEnv.value === 'native') return 'bin/spc';
|
||||||
case 'native':
|
return selectedSystem.value === 'windows' ? '.\\spc.exe' : './spc';
|
||||||
return 'bin/spc';
|
|
||||||
case 'spc':
|
|
||||||
return selectedSystem.value === 'windows' ? '.\\spc.exe' : './spc';
|
|
||||||
case 'docker':
|
|
||||||
return 'bin/spc-alpine-docker';
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const spcDownloadCommand = computed(() => {
|
const spcDownloadCommand = computed(() => {
|
||||||
if (selectedSystem.value === 'windows') return '';
|
const os = selectedSystem.value === 'macos' ? 'macos' : 'linux';
|
||||||
return `curl -fsSL -o spc.tgz https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-${selectedSystem.value}-${selectedArch.value}.tar.gz && tar -zxvf spc.tgz && rm spc.tgz`;
|
const arch = selectedArch.value;
|
||||||
|
return `curl -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-${os}-${arch} -o spc && chmod +x spc`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const doctorCommandString = computed(() => `${spcCommand.value} doctor --auto-fix`);
|
||||||
|
|
||||||
const displayINI = computed(() => {
|
const displayINI = computed(() => {
|
||||||
const split = hardcodedINIData.value.split('\n');
|
const lines = hardcodedINIData.value.split('\n').filter(x => x.indexOf('=') >= 1);
|
||||||
const validLines = split.filter(x => x.indexOf('=') >= 1);
|
return lines.length > 0 ? ' ' + lines.map(x => `-I "${x}"`).join(' ') : '';
|
||||||
return validLines.length > 0 ? ' ' + validLines.map(x => `-I "${x}"`).join(' ') : '';
|
|
||||||
});
|
|
||||||
|
|
||||||
const downloadAllCommand = computed(() => {
|
|
||||||
return `${spcCommand.value} download --all --with-php=${selectedPhpVersion.value}${preBuilt.value ? ' --prefer-pre-built' : ''}${debug.value ? ' --debug' : ''}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const downloadExtCommand = computed(() => {
|
|
||||||
return `${spcCommand.value} download --with-php=${selectedPhpVersion.value} --for-extensions "${extList.value}"${preBuilt.value ? ' --prefer-pre-built' : ''}${debug.value ? ' --debug' : ''}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const downloadPkgCommand = computed(() => {
|
|
||||||
return `${spcCommand.value} install-pkg upx${debug.value ? ' --debug' : ''}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const doctorCommandString = computed(() => {
|
|
||||||
return `${spcCommand.value} doctor --auto-fix${debug.value ? ' --debug' : ''}`;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const buildCommandString = computed(() => {
|
const buildCommandString = computed(() => {
|
||||||
return `${spcCommand.value} build ${buildCommand.value} "${extList.value}"${additionalLibs.value}${debug.value ? ' --debug' : ''}${zts.value ? ' --enable-zts' : ''}${enableUPX.value ? ' --with-upx-pack' : ''}${displayINI.value}`;
|
const sapi = checkedTargets.value.map(x => `--build-${x}`).join(' ');
|
||||||
|
const php = ` --dl-with-php=${selectedPhpVersion.value}`;
|
||||||
|
const parallel = ` --dl-parallel=${dlParallel.value}`;
|
||||||
|
const retry = ` --dl-retry=${dlRetry.value}`;
|
||||||
|
const ignoreCache = ' --dl-ignore-cache=php-src';
|
||||||
|
const binary = preBuilt.value ? ' --dl-prefer-binary' : '';
|
||||||
|
const strip = noStrip.value ? ' --no-strip' : '';
|
||||||
|
const upx = enableUPX.value ? ' --with-upx-pack' : '';
|
||||||
|
const ztsFlag = zts.value ? ' --enable-zts' : '';
|
||||||
|
const verbose = verbosity.value ? ` ${verbosity.value}` : '';
|
||||||
|
return `${spcCommand.value} build:php "${extList.value}" ${sapi}${php}${parallel}${retry}${ignoreCache}${binary}${strip}${upx}${ztsFlag}${displayINI.value}${verbose}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const craftCommandString = computed(() => {
|
const craftCommandString = computed(() => {
|
||||||
let str = `php-version: ${selectedPhpVersion.value}\n`;
|
let str = `php-version: ${selectedPhpVersion.value}\n`;
|
||||||
str += `extensions: "${extList.value}"\n`;
|
str += `extensions: "${extList.value}"\n`;
|
||||||
|
|
||||||
if (checkedTargets.value.join(',') === 'all') {
|
// sapi
|
||||||
str += 'sapi: ' + ['cli', 'fpm', 'micro', 'embed', 'frankenphp'].join(',') + '\n';
|
if (checkedTargets.value.length === 1) {
|
||||||
|
str += `sapi:\n - ${checkedTargets.value[0]}\n`;
|
||||||
} else {
|
} else {
|
||||||
str += `sapi: ${checkedTargets.value.join(',')}\n`;
|
str += `sapi:\n`;
|
||||||
|
checkedTargets.value.forEach(s => { str += ` - ${s}\n`; });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (additionalLibs.value) {
|
// verbosity (Symfony OutputInterface constants: 64=-v, 128=-vv, 256=-vvv)
|
||||||
str += `libs: ${additionalLibs.value.replace('--with-libs="', '').replace('"', '').trim()}\n`;
|
const verbosityMap: Record<string, number> = { '-v': 64, '-vv': 128, '-vvv': 256 };
|
||||||
|
if (verbosity.value && verbosityMap[verbosity.value]) {
|
||||||
|
str += `verbosity: ${verbosityMap[verbosity.value]}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug.value) {
|
// download-options
|
||||||
str += 'debug: true\n';
|
str += `download-options:\n`;
|
||||||
|
str += ` parallel: ${dlParallel.value}\n`;
|
||||||
|
str += ` retry: ${dlRetry.value}\n`;
|
||||||
|
str += ` ignore-cache: php-src\n`;
|
||||||
|
if (preBuilt.value) str += ` prefer-binary: true\n`;
|
||||||
|
|
||||||
|
// build-options (only when needed)
|
||||||
|
const buildOpts: string[] = [];
|
||||||
|
if (noStrip.value) buildOpts.push(` no-strip: true`);
|
||||||
|
if (enableUPX.value) buildOpts.push(` with-upx-pack: true`);
|
||||||
|
if (zts.value) buildOpts.push(` enable-zts: true`);
|
||||||
|
|
||||||
|
const iniLines = hardcodedINIData.value.split('\n').filter(x => x.indexOf('=') >= 1);
|
||||||
|
if (iniLines.length > 0) {
|
||||||
|
buildOpts.push(` with-hardcoded-ini:`);
|
||||||
|
iniLines.forEach(line => buildOpts.push(` - "${line}"`));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preBuilt.value) {
|
if (buildOpts.length > 0) {
|
||||||
str += 'download-options:\n';
|
str += `build-options:\n${buildOpts.join('\n')}\n`;
|
||||||
str += ' prefer-pre-built: true\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
str += '{{position_hold}}';
|
|
||||||
|
|
||||||
if (enableUPX.value) {
|
|
||||||
str += ' with-upx-pack: true\n';
|
|
||||||
}
|
|
||||||
if (zts.value) {
|
|
||||||
str += ' enable-zts: true\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!str.endsWith('{{position_hold}}')) {
|
|
||||||
str = str.replace('{{position_hold}}', 'build-options:\n');
|
|
||||||
} else {
|
|
||||||
str = str.replace('{{position_hold}}', '');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
const isSupported = (extName: string, os: string) => {
|
|
||||||
const osName = OS_MAP.get(os);
|
|
||||||
const osSupport = ext.value[extName]?.support?.[osName] ?? 'yes';
|
|
||||||
return osSupport === 'yes' || osSupport === 'partial';
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectCommon = () => {
|
const selectCommon = () => {
|
||||||
checkedExts.value = [
|
const common = [
|
||||||
'apcu', 'bcmath', 'calendar', 'ctype', 'curl', 'dba', 'dom', 'exif',
|
'apcu', 'bcmath', 'calendar', 'ctype', 'curl', 'dba', 'dom', 'exif',
|
||||||
'filter', 'fileinfo', 'gd', 'iconv', 'intl', 'mbstring', 'mbregex',
|
'filter', 'fileinfo', 'gd', 'iconv', 'intl', 'mbstring', 'mbregex',
|
||||||
'mysqli', 'mysqlnd', 'openssl', 'opcache', 'pcntl', 'pdo', 'pdo_mysql',
|
'mysqli', 'mysqlnd', 'openssl', 'opcache', 'pcntl', 'pdo', 'pdo_mysql',
|
||||||
@@ -418,30 +356,18 @@ const selectCommon = () => {
|
|||||||
'session', 'simplexml', 'sockets', 'sodium', 'sqlite3', 'tokenizer',
|
'session', 'simplexml', 'sockets', 'sodium', 'sqlite3', 'tokenizer',
|
||||||
'xml', 'xmlreader', 'xmlwriter', 'xsl', 'zip', 'zlib',
|
'xml', 'xmlreader', 'xmlwriter', 'xsl', 'zip', 'zlib',
|
||||||
];
|
];
|
||||||
|
const supported = new Set(extByOS.value);
|
||||||
|
checkedExts.value = common.filter(e => supported.has(e));
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectAll = () => {
|
const selectAll = () => {
|
||||||
checkedExts.value = [...extFilter.value];
|
checkedExts.value = [...extByOS.value];
|
||||||
};
|
|
||||||
|
|
||||||
const onTargetChange = (event: Event) => {
|
|
||||||
const target = (event.target as HTMLInputElement).value;
|
|
||||||
if (target === 'all') {
|
|
||||||
checkedTargets.value = ['all'];
|
|
||||||
} else {
|
|
||||||
const allIndex = checkedTargets.value.indexOf('all');
|
|
||||||
if (allIndex !== -1) {
|
|
||||||
checkedTargets.value.splice(allIndex, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buildCommand.value = checkedTargets.value.map(x => `--build-${x}`).join(' ');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const highlightItem = (item: string, step: number) => {
|
const highlightItem = (item: string, step: number) => {
|
||||||
if (!filterText.value || !item.includes(filterText.value)) {
|
if (!filterText.value || !item.includes(filterText.value)) {
|
||||||
return step === 0 ? item : '';
|
return step === 0 ? item : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = item.indexOf(filterText.value);
|
const index = item.indexOf(filterText.value);
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case 0: return item.substring(0, index);
|
case 0: return item.substring(0, index);
|
||||||
@@ -451,30 +377,12 @@ const highlightItem = (item: string, step: number) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const copyToClipboard = async (text: string) => {
|
const copyToClipboard = async (text: string, key: string) => {
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(text);
|
await navigator.clipboard.writeText(text);
|
||||||
// Find which command was copied and update its state
|
copiedStates.value[key] = true;
|
||||||
const commandMap = {
|
setTimeout(() => { copiedStates.value[key] = false; }, 2000);
|
||||||
[spcDownloadCommand.value]: 'spcDownload',
|
} catch {
|
||||||
[downloadExtCommand.value]: 'downloadExt',
|
|
||||||
[downloadAllCommand.value]: 'downloadAll',
|
|
||||||
[downloadPkgCommand.value]: 'downloadPkg',
|
|
||||||
[doctorCommandString.value]: 'doctor',
|
|
||||||
[buildCommandString.value]: 'build',
|
|
||||||
[craftCommandString.value]: 'craft'
|
|
||||||
};
|
|
||||||
|
|
||||||
const key = commandMap[text];
|
|
||||||
if (key) {
|
|
||||||
copiedStates.value[key] = true;
|
|
||||||
setTimeout(() => {
|
|
||||||
copiedStates.value[key] = false;
|
|
||||||
}, 2000);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Failed to copy text: ', err);
|
|
||||||
// Fallback for older browsers
|
|
||||||
const textArea = document.createElement('textarea');
|
const textArea = document.createElement('textarea');
|
||||||
textArea.value = text;
|
textArea.value = text;
|
||||||
document.body.appendChild(textArea);
|
document.body.appendChild(textArea);
|
||||||
@@ -484,113 +392,17 @@ const copyToClipboard = async (text: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const calculateExtDepends = (input: string[]) => {
|
|
||||||
const result = new Set<string>();
|
|
||||||
|
|
||||||
const dfs = (node: string) => {
|
|
||||||
let depends: string[] = [];
|
|
||||||
|
|
||||||
if (selectedSystem.value === 'linux') {
|
|
||||||
depends = ext.value[node]?.['ext-depends-linux'] ?? ext.value[node]?.['ext-depends-unix'] ?? ext.value[node]?.['ext-depends'] ?? [];
|
|
||||||
} else if (selectedSystem.value === 'macos') {
|
|
||||||
depends = ext.value[node]?.['ext-depends-macos'] ?? ext.value[node]?.['ext-depends-unix'] ?? ext.value[node]?.['ext-depends'] ?? [];
|
|
||||||
} else if (selectedSystem.value === 'windows') {
|
|
||||||
depends = ext.value[node]?.['ext-depends-windows'] ?? ext.value[node]?.['ext-depends'] ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depends.length === 0) return;
|
|
||||||
|
|
||||||
depends.forEach(dep => {
|
|
||||||
result.add(dep);
|
|
||||||
dfs(dep);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
input.forEach(dfs);
|
|
||||||
return Array.from(result);
|
|
||||||
};
|
|
||||||
|
|
||||||
const calculateExtLibDepends = (input: string[]) => {
|
|
||||||
const result = new Set<string>();
|
|
||||||
|
|
||||||
const dfsLib = (node: string) => {
|
|
||||||
let depends: string[] = [];
|
|
||||||
|
|
||||||
if (selectedSystem.value === 'linux') {
|
|
||||||
depends = lib.value[node]?.['lib-depends-linux'] ?? lib.value[node]?.['lib-depends-unix'] ?? lib.value[node]?.['lib-depends'] ?? [];
|
|
||||||
} else if (selectedSystem.value === 'macos') {
|
|
||||||
depends = lib.value[node]?.['lib-depends-macos'] ?? lib.value[node]?.['lib-depends-unix'] ?? lib.value[node]?.['lib-depends'] ?? [];
|
|
||||||
} else if (selectedSystem.value === 'windows') {
|
|
||||||
depends = lib.value[node]?.['lib-depends-windows'] ?? lib.value[node]?.['lib-depends'] ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depends.length === 0) return;
|
|
||||||
|
|
||||||
depends.forEach(dep => {
|
|
||||||
result.add(dep);
|
|
||||||
dfsLib(dep);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const dfsExt = (node: string) => {
|
|
||||||
let depends: string[] = [];
|
|
||||||
|
|
||||||
if (selectedSystem.value === 'linux') {
|
|
||||||
depends = ext.value[node]?.['lib-depends-linux'] ?? ext.value[node]?.['lib-depends-unix'] ?? ext.value[node]?.['lib-depends'] ?? [];
|
|
||||||
} else if (selectedSystem.value === 'macos') {
|
|
||||||
depends = ext.value[node]?.['lib-depends-macos'] ?? ext.value[node]?.['lib-depends-unix'] ?? ext.value[node]?.['lib-depends'] ?? [];
|
|
||||||
} else if (selectedSystem.value === 'windows') {
|
|
||||||
depends = ext.value[node]?.['lib-depends-windows'] ?? ext.value[node]?.['lib-depends'] ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depends.length === 0) return;
|
|
||||||
|
|
||||||
depends.forEach(dep => {
|
|
||||||
result.add(dep);
|
|
||||||
dfsLib(dep);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
input.forEach(dfsExt);
|
|
||||||
return Array.from(result);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Watchers
|
// Watchers
|
||||||
watch(selectedSystem, () => {
|
watch(selectedSystem, () => {
|
||||||
if (selectedSystem.value === 'windows') {
|
if (selectedSystem.value === 'windows') {
|
||||||
selectedArch.value = 'x86_64';
|
selectedArch.value = 'x86_64';
|
||||||
|
enableUPX.value = false;
|
||||||
}
|
}
|
||||||
// Reset related values when OS changes
|
|
||||||
checkedExts.value = [];
|
checkedExts.value = [];
|
||||||
enableUPX.value = 0;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(checkedExts, (newValue) => {
|
|
||||||
// Apply ext-depends
|
|
||||||
extDisableList.value = calculateExtDepends(newValue);
|
|
||||||
extDisableList.value.forEach(x => {
|
|
||||||
if (checkedExts.value.indexOf(x) === -1) {
|
|
||||||
checkedExts.value.push(x);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
checkedExts.value.sort();
|
|
||||||
|
|
||||||
const calculated = getAllExtLibsByDeps({ ext: ext.value, lib: lib.value, os: selectedSystem.value }, checkedExts.value);
|
|
||||||
libContain.value = calculated.libs.sort();
|
|
||||||
|
|
||||||
// Apply lib-depends
|
|
||||||
checkedLibs.value = [];
|
|
||||||
libDisableList.value = calculateExtLibDepends(calculated.exts);
|
|
||||||
libDisableList.value.forEach(x => {
|
|
||||||
if (checkedLibs.value.indexOf(x) === -1) {
|
|
||||||
checkedLibs.value.push(x);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, { deep: true });
|
|
||||||
|
|
||||||
// I18N
|
// I18N
|
||||||
const I18N = {
|
const I18N: Record<string, Record<string, string>> = {
|
||||||
zh: {
|
zh: {
|
||||||
selectExt: '选择扩展',
|
selectExt: '选择扩展',
|
||||||
buildTarget: '选择编译目标',
|
buildTarget: '选择编译目标',
|
||||||
@@ -598,8 +410,8 @@ const I18N = {
|
|||||||
buildEnvironment: '编译环境',
|
buildEnvironment: '编译环境',
|
||||||
buildEnvNative: '本地构建(Git 源码)',
|
buildEnvNative: '本地构建(Git 源码)',
|
||||||
buildEnvSpc: '本地构建(独立 spc 二进制)',
|
buildEnvSpc: '本地构建(独立 spc 二进制)',
|
||||||
buildEnvDocker: 'Alpine Docker 构建',
|
useVerbose: '是否输出详细日志',
|
||||||
useDebug: '是否开启调试输出',
|
verboseNone: '不输出(默认)',
|
||||||
yes: '是',
|
yes: '是',
|
||||||
no: '否',
|
no: '否',
|
||||||
resultShow: '结果展示',
|
resultShow: '结果展示',
|
||||||
@@ -608,28 +420,22 @@ const I18N = {
|
|||||||
selectNone: '全部取消选择',
|
selectNone: '全部取消选择',
|
||||||
useZTS: '是否编译线程安全版',
|
useZTS: '是否编译线程安全版',
|
||||||
hardcodedINI: '硬编码 INI 选项',
|
hardcodedINI: '硬编码 INI 选项',
|
||||||
hardcodedINIPlacehoder: '如需要硬编码 ini,每行写一个,例如:memory_limit=2G',
|
hardcodedINIPlaceholder: '如需要硬编码 ini,每行写一个,例如:memory_limit=2G',
|
||||||
resultShowDownload: '是否展示仅下载对应扩展依赖的命令',
|
|
||||||
downloadExtOnlyCommand: '只下载对应扩展的依赖包命令',
|
|
||||||
downloadAllCommand: '下载所有依赖包命令',
|
|
||||||
downloadUPXCommand: '下载 UPX 命令',
|
|
||||||
compileCommand: '编译命令',
|
compileCommand: '编译命令',
|
||||||
downloadPhpVersion: '下载 PHP 版本',
|
downloadPhpVersion: '下载 PHP 版本',
|
||||||
downloadSPCBinaryCommand: '下载 spc 二进制命令',
|
downloadSPCBinaryCommand: '下载 spc 二进制命令',
|
||||||
selectedArch: '选择系统架构',
|
|
||||||
selectedSystem: '选择操作系统',
|
selectedSystem: '选择操作系统',
|
||||||
buildLibs: '要构建的库',
|
|
||||||
depTips: '选择扩展后,不可选中的项目为必需的依赖,编译的依赖库列表中可选的为现有扩展和依赖库的可选依赖。选择可选依赖后,将生成 --with-libs 参数。',
|
|
||||||
depTips2: '无法同时构建所有扩展,因为有些扩展之间相互冲突。请根据需要选择扩展。',
|
|
||||||
microUnavailable: 'micro 不支持 PHP 7.4 及更早版本!',
|
|
||||||
windowsSAPIUnavailable: 'Windows 目前不支持 fpm、embed、frankenphp 构建!',
|
windowsSAPIUnavailable: 'Windows 目前不支持 fpm、embed、frankenphp 构建!',
|
||||||
useUPX: '是否开启 UPX 压缩(减小二进制体积)',
|
useUPX: '是否开启 UPX 压缩(减小二进制体积)',
|
||||||
windowsDownSPCWarning: 'Windows 下请手动下载 spc.exe 二进制文件,解压到当前目录并重命名为 spc.exe!',
|
windowsDownSPCWarning: 'Windows 下请手动下载 spc.exe 二进制文件!',
|
||||||
usePreBuilt: '如果可能,下载预编译的依赖库(减少编译时间)',
|
usePreBuilt: '如果可能,使用预编译的依赖库(减少编译时间)',
|
||||||
searchPlaceholder: '搜索扩展...',
|
searchPlaceholder: '搜索扩展...',
|
||||||
copy: '复制',
|
copy: '复制',
|
||||||
copied: '已复制',
|
copied: '已复制',
|
||||||
doctorCommand: '自动检查和准备构建环境命令',
|
doctorCommand: '自动检查和准备构建环境命令',
|
||||||
|
dlParallel: '并行下载数(1-50)',
|
||||||
|
dlRetry: '失败重试次数',
|
||||||
|
noStrip: '保留调试符号(--no-strip)',
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
selectExt: 'Select Extensions',
|
selectExt: 'Select Extensions',
|
||||||
@@ -638,43 +444,58 @@ const I18N = {
|
|||||||
buildEnvironment: 'Build Environment',
|
buildEnvironment: 'Build Environment',
|
||||||
buildEnvNative: 'Native build (Git source code)',
|
buildEnvNative: 'Native build (Git source code)',
|
||||||
buildEnvSpc: 'Native build (standalone spc binary)',
|
buildEnvSpc: 'Native build (standalone spc binary)',
|
||||||
buildEnvDocker: 'Alpine docker build',
|
useVerbose: 'Verbose log output',
|
||||||
useDebug: 'Enable debug message',
|
verboseNone: 'None (default)',
|
||||||
yes: 'Yes',
|
yes: 'Yes',
|
||||||
no: 'No',
|
no: 'No',
|
||||||
resultShow: 'Result',
|
resultShow: 'Result',
|
||||||
selectCommon: 'Select common extensions',
|
selectCommon: 'Select common extensions',
|
||||||
selectAll: 'Select all',
|
selectAll: 'Select all',
|
||||||
selectNone: 'Unselect all',
|
selectNone: 'Unselect all',
|
||||||
useZTS: 'Enable ZTS',
|
useZTS: 'Enable ZTS (thread-safe)',
|
||||||
hardcodedINI: 'Hardcoded INI options',
|
hardcodedINI: 'Hardcoded INI options',
|
||||||
hardcodedINIPlacehoder: 'If you need to hardcode ini, write one per line, for example: memory_limit=2G',
|
hardcodedINIPlaceholder: 'If you need to hardcode ini, write one per line, for example: memory_limit=2G',
|
||||||
resultShowDownload: 'Download with corresponding extension dependencies',
|
compileCommand: 'Build command',
|
||||||
downloadExtOnlyCommand: 'Download sources by extensions command',
|
downloadPhpVersion: 'PHP version',
|
||||||
downloadAllCommand: 'Download all sources command',
|
downloadSPCBinaryCommand: 'Download spc binary',
|
||||||
downloadUPXCommand: 'Download UPX command',
|
selectedSystem: 'Select OS',
|
||||||
compileCommand: 'Compile command',
|
|
||||||
downloadPhpVersion: 'Download PHP version',
|
|
||||||
downloadSPCBinaryCommand: 'Download spc binary command',
|
|
||||||
selectedArch: 'Select build architecture',
|
|
||||||
selectedSystem: 'Select Build OS',
|
|
||||||
buildLibs: 'Select Dependencies',
|
|
||||||
depTips: 'After selecting the extensions, the unselectable items are essential dependencies. In the compiled dependencies list, optional dependencies consist of existing extensions and optional dependencies of libraries. Optional dependencies will be added in --with-libs parameter.',
|
|
||||||
depTips2: 'It is not possible to build all extensions at the same time, as some extensions conflict with each other. Please select the extensions you need.',
|
|
||||||
microUnavailable: 'Micro does not support PHP 7.4 and earlier versions!',
|
|
||||||
windowsSAPIUnavailable: 'Windows does not support fpm, embed and frankenphp build!',
|
windowsSAPIUnavailable: 'Windows does not support fpm, embed and frankenphp build!',
|
||||||
useUPX: 'Enable UPX compression (reduce binary size)',
|
useUPX: 'Enable UPX compression (reduce binary size)',
|
||||||
windowsDownSPCWarning: 'Please download the binary file manually, extract it to the current directory and rename to spc.exe on Windows!',
|
windowsDownSPCWarning: 'Please download the spc.exe binary manually on Windows!',
|
||||||
usePreBuilt: 'Download pre-built dependencies if possible (reduce compile time)',
|
usePreBuilt: 'Use pre-built dependencies where available (reduce compile time)',
|
||||||
searchPlaceholder: 'Search extensions...',
|
searchPlaceholder: 'Search extensions...',
|
||||||
copy: 'Copy',
|
copy: 'Copy',
|
||||||
copied: 'Copied',
|
copied: 'Copied',
|
||||||
doctorCommand: 'Auto-check and prepare build environment command',
|
doctorCommand: 'Auto-check and prepare build environment',
|
||||||
|
dlParallel: 'Parallel downloads (1-50)',
|
||||||
|
dlRetry: 'Retry count on failure',
|
||||||
|
noStrip: 'Keep debug symbols (--no-strip)',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.number-input {
|
||||||
|
border: 1px solid var(--vp-c-divider);
|
||||||
|
border-radius: 8px;
|
||||||
|
width: 80px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
background-color: var(--vp-c-bg-soft);
|
||||||
|
color: var(--vp-c-text-1);
|
||||||
|
font-size: 14px;
|
||||||
|
outline: none;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-input:hover {
|
||||||
|
border-color: var(--vp-c-brand-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-input:focus {
|
||||||
|
border-color: var(--vp-c-brand-1);
|
||||||
|
box-shadow: 0 0 0 3px var(--vp-c-brand-soft);
|
||||||
|
}
|
||||||
|
|
||||||
.box {
|
.box {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|||||||
589
docs/.vitepress/components/DepsMap.vue
Normal file
589
docs/.vitepress/components/DepsMap.vue
Normal file
@@ -0,0 +1,589 @@
|
|||||||
|
<template>
|
||||||
|
<div class="deps-map">
|
||||||
|
<!-- Warning if data missing -->
|
||||||
|
<div v-if="missing" class="warning custom-block" style="margin-bottom: 16px">
|
||||||
|
<p class="custom-block-title">WARNING</p>
|
||||||
|
<p>Dependency data not generated yet. Run <code>bin/spc dev:gen-deps-data</code> to generate it.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-else>
|
||||||
|
<!-- Toolbar -->
|
||||||
|
<div class="deps-toolbar">
|
||||||
|
<input
|
||||||
|
class="deps-search"
|
||||||
|
v-model="searchText"
|
||||||
|
:placeholder="i18n.searchPlaceholder"
|
||||||
|
@input="selectedPkg = null"
|
||||||
|
/>
|
||||||
|
<div class="deps-filters">
|
||||||
|
<div class="filter-group">
|
||||||
|
<button
|
||||||
|
v-for="t in typeOptions"
|
||||||
|
:key="t.value"
|
||||||
|
:class="['filter-btn', { active: selectedType === t.value }]"
|
||||||
|
@click="selectedType = t.value; selectedPkg = null"
|
||||||
|
>{{ t.label }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="filter-group">
|
||||||
|
<button
|
||||||
|
v-for="p in platformOptions"
|
||||||
|
:key="p.value"
|
||||||
|
:class="['filter-btn', { active: selectedPlatform === p.value }]"
|
||||||
|
@click="selectedPlatform = p.value"
|
||||||
|
>{{ p.label }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="deps-layout">
|
||||||
|
<!-- Package list -->
|
||||||
|
<div class="deps-list">
|
||||||
|
<div v-if="filteredPackages.length === 0" class="no-results">{{ i18n.noResults }}</div>
|
||||||
|
<div
|
||||||
|
v-for="pkg in filteredPackages"
|
||||||
|
:key="pkg.name"
|
||||||
|
:class="['pkg-item', { selected: selectedPkg === pkg.name }]"
|
||||||
|
@click="selectPkg(pkg.name)"
|
||||||
|
>
|
||||||
|
<span class="pkg-name">{{ pkg.name }}</span>
|
||||||
|
<span :class="['pkg-badge', pkg.type === 'php-extension' ? 'badge-ext' : 'badge-lib']">
|
||||||
|
{{ typeLabel(pkg.type) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Detail panel -->
|
||||||
|
<div class="deps-detail" v-if="selectedPkg && selectedPkgData">
|
||||||
|
<h3 class="detail-title">{{ selectedPkg }}</h3>
|
||||||
|
<span :class="['detail-type-badge', selectedPkgData.type === 'php-extension' ? 'badge-ext' : 'badge-lib']">
|
||||||
|
{{ typeLabel(selectedPkgData.type) }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- OS support for extensions -->
|
||||||
|
<div v-if="selectedPkgData.type === 'php-extension' && selectedPkgData.os" class="detail-section">
|
||||||
|
<div class="detail-label">{{ i18n.supportedPlatforms }}</div>
|
||||||
|
<div class="detail-chips">
|
||||||
|
<span v-for="os in selectedPkgData.os" :key="os" class="chip chip-os">{{ os }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Required deps -->
|
||||||
|
<div class="detail-section">
|
||||||
|
<div class="detail-label">{{ i18n.requiredDeps }}</div>
|
||||||
|
<div class="detail-chips" v-if="currentDepends.length > 0">
|
||||||
|
<span
|
||||||
|
v-for="dep in currentDepends"
|
||||||
|
:key="dep"
|
||||||
|
:class="['chip', 'chip-required', { clickable: packages[dep] }]"
|
||||||
|
@click="packages[dep] && selectPkg(dep)"
|
||||||
|
>{{ dep }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-else class="no-deps">{{ i18n.none }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Suggested deps -->
|
||||||
|
<div class="detail-section">
|
||||||
|
<div class="detail-label">{{ i18n.suggestedDeps }}</div>
|
||||||
|
<div class="detail-chips" v-if="currentSuggests.length > 0">
|
||||||
|
<span
|
||||||
|
v-for="dep in currentSuggests"
|
||||||
|
:key="dep"
|
||||||
|
:class="['chip', 'chip-suggested', { clickable: packages[dep] }]"
|
||||||
|
@click="packages[dep] && selectPkg(dep)"
|
||||||
|
>{{ dep }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-else class="no-deps">{{ i18n.none }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Required by -->
|
||||||
|
<div class="detail-section">
|
||||||
|
<div class="detail-label">{{ i18n.requiredBy }}</div>
|
||||||
|
<div class="detail-chips" v-if="requiredBy.length > 0">
|
||||||
|
<span
|
||||||
|
v-for="dep in requiredBy"
|
||||||
|
:key="dep"
|
||||||
|
class="chip chip-rev clickable"
|
||||||
|
@click="selectPkg(dep)"
|
||||||
|
>{{ dep }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-else class="no-deps">{{ i18n.none }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Suggested by -->
|
||||||
|
<div class="detail-section">
|
||||||
|
<div class="detail-label">{{ i18n.suggestedBy }}</div>
|
||||||
|
<div class="detail-chips" v-if="suggestedBy.length > 0">
|
||||||
|
<span
|
||||||
|
v-for="dep in suggestedBy"
|
||||||
|
:key="dep"
|
||||||
|
class="chip chip-rev-sug clickable"
|
||||||
|
@click="selectPkg(dep)"
|
||||||
|
>{{ dep }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-else class="no-deps">{{ i18n.none }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mermaid graph -->
|
||||||
|
<div class="detail-section" v-if="hasMermaid">
|
||||||
|
<div class="detail-label">{{ i18n.depGraph }}</div>
|
||||||
|
<div ref="mermaidEl" class="mermaid-wrap"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Empty state -->
|
||||||
|
<div class="deps-detail deps-detail-empty" v-else>
|
||||||
|
<p>{{ i18n.selectHint }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch, onMounted, nextTick } from 'vue'
|
||||||
|
import { useData } from 'vitepress'
|
||||||
|
import { data as depsData } from '../deps-map.data.js'
|
||||||
|
|
||||||
|
const { lang, isDark } = useData()
|
||||||
|
|
||||||
|
const missing = depsData.missing
|
||||||
|
const packages = depsData.packages ?? {}
|
||||||
|
|
||||||
|
// --- i18n ---
|
||||||
|
const I18N = {
|
||||||
|
zh: {
|
||||||
|
searchPlaceholder: '搜索包名...',
|
||||||
|
noResults: '未找到包。',
|
||||||
|
selectHint: '← 选择一个包以查看其依赖关系。',
|
||||||
|
supportedPlatforms: '支持的平台',
|
||||||
|
requiredDeps: '必需依赖',
|
||||||
|
suggestedDeps: '可选依赖',
|
||||||
|
requiredBy: '被哪些包依赖',
|
||||||
|
suggestedBy: '被哪些包建议',
|
||||||
|
depGraph: '依赖关系图',
|
||||||
|
none: '无',
|
||||||
|
},
|
||||||
|
en: {
|
||||||
|
searchPlaceholder: 'Search package...',
|
||||||
|
noResults: 'No packages found.',
|
||||||
|
selectHint: '← Select a package to view its dependency details.',
|
||||||
|
supportedPlatforms: 'Supported Platforms',
|
||||||
|
requiredDeps: 'Required Dependencies',
|
||||||
|
suggestedDeps: 'Suggested Dependencies',
|
||||||
|
requiredBy: 'Required By',
|
||||||
|
suggestedBy: 'Suggested By',
|
||||||
|
depGraph: 'Dependency Graph',
|
||||||
|
none: 'None',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const i18n = computed(() => I18N[lang.value] ?? I18N.en)
|
||||||
|
|
||||||
|
// --- State ---
|
||||||
|
const searchText = ref('')
|
||||||
|
const selectedType = ref('all')
|
||||||
|
const selectedPlatform = ref('linux')
|
||||||
|
const selectedPkg = ref(null)
|
||||||
|
const mermaidEl = ref(null)
|
||||||
|
|
||||||
|
// --- Options ---
|
||||||
|
const typeOptions = computed(() => [
|
||||||
|
{ value: 'all', label: lang.value === 'zh' ? '全部' : 'All' },
|
||||||
|
{ value: 'php-extension', label: lang.value === 'zh' ? '扩展' : 'Extensions' },
|
||||||
|
{ value: 'library', label: lang.value === 'zh' ? '库' : 'Libraries' },
|
||||||
|
])
|
||||||
|
const platformOptions = [
|
||||||
|
{ value: 'linux', label: 'Linux' },
|
||||||
|
{ value: 'macos', label: 'macOS' },
|
||||||
|
{ value: 'windows', label: 'Windows' },
|
||||||
|
]
|
||||||
|
|
||||||
|
function typeLabel(type) {
|
||||||
|
if (type === 'php-extension') return 'ext'
|
||||||
|
if (type === 'library') return 'lib'
|
||||||
|
return type
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Package list ---
|
||||||
|
const allPackages = computed(() =>
|
||||||
|
Object.entries(packages).map(([name, data]) => ({ name, ...data }))
|
||||||
|
)
|
||||||
|
|
||||||
|
const filteredPackages = computed(() => {
|
||||||
|
let list = allPackages.value
|
||||||
|
if (selectedType.value !== 'all') {
|
||||||
|
list = list.filter(p => p.type === selectedType.value)
|
||||||
|
}
|
||||||
|
if (searchText.value.trim()) {
|
||||||
|
const q = searchText.value.trim().toLowerCase()
|
||||||
|
list = list.filter(p => p.name.toLowerCase().includes(q))
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
})
|
||||||
|
|
||||||
|
// --- Selected package ---
|
||||||
|
const selectedPkgData = computed(() =>
|
||||||
|
selectedPkg.value ? (packages[selectedPkg.value] ?? null) : null
|
||||||
|
)
|
||||||
|
|
||||||
|
const currentDepends = computed(() =>
|
||||||
|
selectedPkgData.value?.platforms?.[selectedPlatform.value]?.depends ?? []
|
||||||
|
)
|
||||||
|
const currentSuggests = computed(() =>
|
||||||
|
selectedPkgData.value?.platforms?.[selectedPlatform.value]?.suggests ?? []
|
||||||
|
)
|
||||||
|
|
||||||
|
const requiredBy = computed(() => {
|
||||||
|
if (!selectedPkg.value) return []
|
||||||
|
const name = selectedPkg.value
|
||||||
|
const plat = selectedPlatform.value
|
||||||
|
return Object.entries(packages)
|
||||||
|
.filter(([, d]) => (d.platforms?.[plat]?.depends ?? []).includes(name))
|
||||||
|
.map(([n]) => n)
|
||||||
|
})
|
||||||
|
|
||||||
|
const suggestedBy = computed(() => {
|
||||||
|
if (!selectedPkg.value) return []
|
||||||
|
const name = selectedPkg.value
|
||||||
|
const plat = selectedPlatform.value
|
||||||
|
return Object.entries(packages)
|
||||||
|
.filter(([, d]) => (d.platforms?.[plat]?.suggests ?? []).includes(name))
|
||||||
|
.map(([n]) => n)
|
||||||
|
})
|
||||||
|
|
||||||
|
// --- Mermaid ---
|
||||||
|
const hasMermaid = computed(
|
||||||
|
() => currentDepends.value.length > 0 || currentSuggests.value.length > 0
|
||||||
|
)
|
||||||
|
|
||||||
|
function buildMermaidCode() {
|
||||||
|
const deps = currentDepends.value
|
||||||
|
const sugs = currentSuggests.value
|
||||||
|
if (deps.length === 0 && sugs.length === 0) return ''
|
||||||
|
|
||||||
|
const safe = s => s.replace(/[^a-zA-Z0-9_]/g, '_')
|
||||||
|
const root = safe(selectedPkg.value)
|
||||||
|
const lines = ['graph LR', ` ${root}["${selectedPkg.value}"]`]
|
||||||
|
|
||||||
|
const MAX_DEPTH = 6 // max hops from root
|
||||||
|
const MAX_CHILDREN = 6 // per-node child limit for levels 2+
|
||||||
|
|
||||||
|
const visitedNodes = new Set([selectedPkg.value])
|
||||||
|
const visitedEdges = new Set()
|
||||||
|
const queue = []
|
||||||
|
|
||||||
|
// Level 1: direct required deps — solid arrows, no child limit
|
||||||
|
for (const dep of deps) {
|
||||||
|
const ek = `${selectedPkg.value}\0${dep}`
|
||||||
|
if (!visitedEdges.has(ek)) {
|
||||||
|
visitedEdges.add(ek)
|
||||||
|
lines.push(` ${root} --> ${safe(dep)}["${dep}"]`)
|
||||||
|
}
|
||||||
|
if (!visitedNodes.has(dep)) {
|
||||||
|
visitedNodes.add(dep)
|
||||||
|
queue.push({ name: dep, depth: 1 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BFS: levels 2–MAX_DEPTH — dotted arrows, capped children per node
|
||||||
|
while (queue.length > 0) {
|
||||||
|
const { name, depth } = queue.shift()
|
||||||
|
if (depth >= MAX_DEPTH) continue
|
||||||
|
const children = packages[name]?.platforms?.[selectedPlatform.value]?.depends ?? []
|
||||||
|
for (const child of children.slice(0, MAX_CHILDREN)) {
|
||||||
|
const ek = `${name}\0${child}`
|
||||||
|
if (!visitedEdges.has(ek)) {
|
||||||
|
visitedEdges.add(ek)
|
||||||
|
lines.push(` ${safe(name)} -.-> ${safe(child)}["${child}"]`)
|
||||||
|
}
|
||||||
|
if (!visitedNodes.has(child)) {
|
||||||
|
visitedNodes.add(child)
|
||||||
|
queue.push({ name: child, depth: depth + 1 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suggested deps from root (single level, optional dotted)
|
||||||
|
for (const sug of sugs) {
|
||||||
|
lines.push(` ${root} -. optional .-> ${safe(sug)}["${sug}"]`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines.join('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
let mermaidLib = null
|
||||||
|
|
||||||
|
async function renderMermaid() {
|
||||||
|
if (!mermaidEl.value || !hasMermaid.value) return
|
||||||
|
const code = buildMermaidCode()
|
||||||
|
if (!code) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!mermaidLib) {
|
||||||
|
const m = await import('mermaid')
|
||||||
|
mermaidLib = m.default
|
||||||
|
}
|
||||||
|
mermaidLib.initialize({
|
||||||
|
startOnLoad: false,
|
||||||
|
theme: isDark.value ? 'dark' : 'default',
|
||||||
|
securityLevel: 'loose',
|
||||||
|
})
|
||||||
|
const id = 'deps-graph-' + Date.now()
|
||||||
|
const { svg } = await mermaidLib.render(id, code)
|
||||||
|
if (mermaidEl.value) {
|
||||||
|
mermaidEl.value.innerHTML = svg
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
if (mermaidEl.value) {
|
||||||
|
mermaidEl.value.innerHTML = `<pre class="mermaid-fallback">${code}</pre>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectPkg(name) {
|
||||||
|
selectedPkg.value = name
|
||||||
|
}
|
||||||
|
|
||||||
|
watch([selectedPkg, selectedPlatform, isDark], async () => {
|
||||||
|
await nextTick()
|
||||||
|
await renderMermaid()
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await nextTick()
|
||||||
|
await renderMermaid()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.deps-map {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toolbar */
|
||||||
|
.deps-toolbar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deps-search {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border: 1px solid var(--vp-c-divider);
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
background: var(--vp-c-bg);
|
||||||
|
color: var(--vp-c-text-1);
|
||||||
|
outline: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.deps-search:focus {
|
||||||
|
border-color: var(--vp-c-brand);
|
||||||
|
}
|
||||||
|
|
||||||
|
.deps-filters {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-btn {
|
||||||
|
padding: 4px 12px;
|
||||||
|
border: 1px solid var(--vp-c-divider);
|
||||||
|
border-radius: 20px;
|
||||||
|
background: var(--vp-c-bg);
|
||||||
|
color: var(--vp-c-text-2);
|
||||||
|
font-size: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s;
|
||||||
|
}
|
||||||
|
.filter-btn:hover {
|
||||||
|
border-color: var(--vp-c-brand);
|
||||||
|
color: var(--vp-c-brand);
|
||||||
|
}
|
||||||
|
.filter-btn.active {
|
||||||
|
background: var(--vp-c-brand);
|
||||||
|
border-color: var(--vp-c-brand);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Layout */
|
||||||
|
.deps-layout {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Package list */
|
||||||
|
.deps-list {
|
||||||
|
width: 260px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
border: 1px solid var(--vp-c-divider);
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-results {
|
||||||
|
padding: 16px;
|
||||||
|
color: var(--vp-c-text-3);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pkg-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 8px 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 1px solid var(--vp-c-divider);
|
||||||
|
transition: background 0.1s;
|
||||||
|
}
|
||||||
|
.pkg-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.pkg-item:hover {
|
||||||
|
background: var(--vp-c-bg-soft);
|
||||||
|
}
|
||||||
|
.pkg-item.selected {
|
||||||
|
background: var(--vp-c-brand-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pkg-name {
|
||||||
|
font-family: var(--vp-font-family-mono);
|
||||||
|
font-size: 13px;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pkg-badge {
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 1px 6px;
|
||||||
|
border-radius: 10px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detail panel */
|
||||||
|
.deps-detail {
|
||||||
|
flex: 1;
|
||||||
|
border: 1px solid var(--vp-c-divider);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deps-detail-empty {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: var(--vp-c-text-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-title {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: var(--vp-font-family-mono);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-type-badge {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-section {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-label {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--vp-c-text-2);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-chips {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-deps {
|
||||||
|
color: var(--vp-c-text-3);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chips */
|
||||||
|
.chip {
|
||||||
|
font-family: var(--vp-font-family-mono);
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.chip.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: opacity 0.15s;
|
||||||
|
}
|
||||||
|
.chip.clickable:hover {
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-required {
|
||||||
|
background: var(--vp-c-danger-soft);
|
||||||
|
border-color: var(--vp-c-danger-1);
|
||||||
|
color: var(--vp-c-danger-1);
|
||||||
|
}
|
||||||
|
.chip-suggested {
|
||||||
|
background: var(--vp-c-warning-soft);
|
||||||
|
border-color: var(--vp-c-warning-1);
|
||||||
|
color: var(--vp-c-warning-1);
|
||||||
|
}
|
||||||
|
.chip-rev {
|
||||||
|
background: var(--vp-c-brand-soft);
|
||||||
|
border-color: var(--vp-c-brand-1);
|
||||||
|
color: var(--vp-c-brand-1);
|
||||||
|
}
|
||||||
|
.chip-rev-sug {
|
||||||
|
background: var(--vp-c-bg-soft);
|
||||||
|
border-color: var(--vp-c-divider);
|
||||||
|
color: var(--vp-c-text-2);
|
||||||
|
}
|
||||||
|
.chip-os {
|
||||||
|
background: var(--vp-c-bg-soft);
|
||||||
|
border-color: var(--vp-c-divider);
|
||||||
|
color: var(--vp-c-text-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Badges */
|
||||||
|
.badge-ext {
|
||||||
|
background: var(--vp-c-brand-soft);
|
||||||
|
color: var(--vp-c-brand-1);
|
||||||
|
}
|
||||||
|
.badge-lib {
|
||||||
|
background: var(--vp-c-tip-soft);
|
||||||
|
color: var(--vp-c-tip-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mermaid */
|
||||||
|
.mermaid-wrap {
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
.mermaid-fallback {
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,36 +1,46 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<header class="DocSearch-SearchBar" style="padding: 0">
|
<div v-if="missing" class="warning custom-block" style="margin-bottom: 16px">
|
||||||
<form class="DocSearch-Form searchinput">
|
<p class="custom-block-title">WARNING</p>
|
||||||
<input class="DocSearch-Input" v-model="filterText" placeholder="Filter name..." @input="doFilter" />
|
<p>Extension list is not generated yet. Run <code>bin/spc dev:gen-ext-docs</code> to generate it.</p>
|
||||||
</form>
|
|
||||||
</header>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Extension Name</th>
|
|
||||||
<th>Linux</th>
|
|
||||||
<th>macOS</th>
|
|
||||||
<th>FreeBSD</th>
|
|
||||||
<th>Windows</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr v-for="item in filterData">
|
|
||||||
<td v-if="!item.notes">{{ item.name }}</td>
|
|
||||||
<td v-else>
|
|
||||||
<a :href="'./extension-notes.html#' + item.name">{{ item.name }}</a>
|
|
||||||
</td>
|
|
||||||
<td>{{ item.linux }}</td>
|
|
||||||
<td>{{ item.macos }}</td>
|
|
||||||
<td>{{ item.freebsd }}</td>
|
|
||||||
<td>{{ item.windows }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div v-if="filterData.length === 0" style="margin: 0 4px 20px 4px; color: var(--vp-c-text-2); font-size: 14px">
|
|
||||||
No result, please try another keyword.
|
|
||||||
</div>
|
</div>
|
||||||
|
<template v-else>
|
||||||
|
<header class="DocSearch-SearchBar" style="padding: 0">
|
||||||
|
<form class="DocSearch-Form searchinput">
|
||||||
|
<input class="DocSearch-Input" v-model="filterText" placeholder="Filter name..." @input="doFilter" />
|
||||||
|
</form>
|
||||||
|
</header>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Extension Name</th>
|
||||||
|
<th>Linux</th>
|
||||||
|
<th>macOS</th>
|
||||||
|
<th>Windows</th>
|
||||||
|
<th>Website</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="item in filterData" :key="item.name">
|
||||||
|
<td>
|
||||||
|
<span v-if="!item.hasNotes">{{ item.name }}</span>
|
||||||
|
<a v-else :href="'./extension-notes.html#' + item.name">{{ item.name }}</a>
|
||||||
|
</td>
|
||||||
|
<td>{{ item.linux ? '✅' : '' }}</td>
|
||||||
|
<td>{{ item.macos ? '✅' : '' }}</td>
|
||||||
|
<td>{{ item.windows ? '✅' : '' }}</td>
|
||||||
|
<td>
|
||||||
|
<a v-if="item.url" :href="item.url" target="_blank" rel="noopener noreferrer" class="ext-source-link">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="12" height="12" fill="currentColor"><path d="M10 6v2H5v11h11v-5h2v6a1 1 0 01-1 1H4a1 1 0 01-1-1V7a1 1 0 011-1h6zm11-3v8h-2V6.413l-7.793 7.794-1.414-1.414L17.585 5H13V3h8z"/></svg>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div v-if="filterData.length === 0" style="margin: 0 4px 20px 4px; color: var(--vp-c-text-2); font-size: 14px">
|
||||||
|
No result, please try another keyword.
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -41,34 +51,22 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {ref} from "vue";
|
import { ref } from 'vue'
|
||||||
import ext from '../../../config/ext.json';
|
import { data as extData } from '../extensions.data.js'
|
||||||
|
|
||||||
// 将 ext 转换为列表,方便后续操作
|
const missing = extData.missing
|
||||||
const data = ref([]);
|
const data = ref(extData.extensions)
|
||||||
for (const [name, item] of Object.entries(ext)) {
|
const filterData = ref(extData.extensions)
|
||||||
data.value.push({
|
const filterText = ref('')
|
||||||
name,
|
|
||||||
linux: item.support?.Linux === undefined ? 'yes' : (item.support?.Linux === 'wip' ? '' : item.support?.Linux),
|
|
||||||
macos: item.support?.Darwin === undefined ? 'yes' : (item.support?.Darwin === 'wip' ? '' : item.support?.Darwin),
|
|
||||||
freebsd: item.support?.BSD === undefined ? 'yes' : (item.support?.BSD === 'wip' ? '' : item.support?.BSD),
|
|
||||||
windows: item.support?.Windows === undefined ? 'yes' : (item.support?.Windows === 'wip' ? '' : item.support?.Windows),
|
|
||||||
notes: item.notes === true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const filterData = ref(data.value);
|
|
||||||
const filterText = ref('');
|
|
||||||
|
|
||||||
const doFilter = () => {
|
const doFilter = () => {
|
||||||
if (filterText.value === '') {
|
if (filterText.value === '') {
|
||||||
filterData.value = data.value;
|
filterData.value = data.value
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
filterData.value = data.value.filter(item => {
|
filterData.value = data.value.filter(item =>
|
||||||
return item.name.toLowerCase().includes(filterText.value.toLowerCase());
|
item.name.toLowerCase().includes(filterText.value.toLowerCase())
|
||||||
});
|
)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -76,4 +74,14 @@ const doFilter = () => {
|
|||||||
.searchinput {
|
.searchinput {
|
||||||
border: 1px solid var(--vp-c-divider);
|
border: 1px solid var(--vp-c-divider);
|
||||||
}
|
}
|
||||||
</style>
|
.ext-source-link {
|
||||||
|
color: var(--vp-c-text-3);
|
||||||
|
vertical-align: middle;
|
||||||
|
opacity: 0.6;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
.ext-source-link:hover {
|
||||||
|
opacity: 1;
|
||||||
|
color: var(--vp-c-brand-1);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,65 +1,84 @@
|
|||||||
import sidebarEn from "./sidebar.en";
|
import sidebarEn from "./sidebar.en";
|
||||||
import sidebarZh from "./sidebar.zh";
|
import sidebarZh from "./sidebar.zh";
|
||||||
|
|
||||||
|
|
||||||
// https://vitepress.dev/reference/site-config
|
// https://vitepress.dev/reference/site-config
|
||||||
export default {
|
export default {
|
||||||
title: "Static PHP",
|
title: "StaticPHP",
|
||||||
description: "Build single static PHP binary, with PHP project together, with popular extensions included.",
|
description: "A powerful tool designed for building portable executables including PHP, extensions, and more.",
|
||||||
locales: {
|
locales: {
|
||||||
en: {
|
en: {
|
||||||
label: 'English',
|
label: 'English',
|
||||||
lang: 'en',
|
lang: 'en',
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
nav: [
|
nav: [
|
||||||
{text: 'Guide', link: '/en/guide/',},
|
{ text: 'Guide', link: '/en/guide/' },
|
||||||
{text: 'Advanced', link: '/en/develop/'},
|
{ text: 'Develop', link: '/en/develop/' },
|
||||||
{text: 'Contributing', link: '/en/contributing/'},
|
{ text: 'Contributing', link: '/en/contributing/' },
|
||||||
{text: 'FAQ', link: '/en/faq/'},
|
{ text: 'FAQ', link: '/en/faq/' },
|
||||||
|
{
|
||||||
|
text: 'v3 (alpha)',
|
||||||
|
items: [
|
||||||
|
{ text: 'v3 (alpha)', link: '/en/' },
|
||||||
|
{ text: 'v2', link: 'https://static-php.github.io/v2-docs/' },
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
sidebar: sidebarEn,
|
sidebar: sidebarEn,
|
||||||
footer: {
|
footer: {
|
||||||
message: 'Released under the MIT License.',
|
message: 'Released under the MIT License.',
|
||||||
copyright: 'Copyright © 2023-present crazywhalecc'
|
copyright: 'Copyright © 2023-present crazywhalecc',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
label: '简体中文',
|
label: '简体中文',
|
||||||
lang: 'zh', // optional, will be added as `lang` attribute on `html` tag
|
lang: 'zh',
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
nav: [
|
nav: [
|
||||||
{text: '构建指南', link: '/zh/guide/'},
|
{ text: '构建指南', link: '/zh/guide/' },
|
||||||
{text: '进阶', link: '/zh/develop/'},
|
{ text: '开发者', link: '/zh/develop/' },
|
||||||
{text: '贡献', link: '/zh/contributing/'},
|
{ text: '贡献', link: '/zh/contributing/' },
|
||||||
{text: 'FAQ', link: '/zh/faq/'},
|
{ text: 'FAQ', link: '/zh/faq/' },
|
||||||
|
{
|
||||||
|
text: 'v3 (alpha)',
|
||||||
|
items: [
|
||||||
|
{ text: 'v3 (alpha)', link: '/zh/' },
|
||||||
|
{ text: 'v2', link: 'https://static-php.github.io/v2-docs/' },
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
sidebar: sidebarZh,
|
sidebar: sidebarZh,
|
||||||
footer: {
|
footer: {
|
||||||
message: 'Released under the MIT License.',
|
message: 'Released under the MIT License.',
|
||||||
copyright: 'Copyright © 2023-present crazywhalecc'
|
copyright: 'Copyright © 2023-present crazywhalecc',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
// https://vitepress.dev/reference/default-theme-config
|
|
||||||
logo: '/images/static-php_nobg.png',
|
logo: '/images/static-php_nobg.png',
|
||||||
nav: [],
|
nav: [],
|
||||||
socialLinks: [
|
socialLinks: [
|
||||||
{icon: 'github', link: 'https://github.com/crazywhalecc/static-php-cli'}
|
{ icon: 'github', link: 'https://github.com/crazywhalecc/static-php-cli' },
|
||||||
],
|
],
|
||||||
footer: {
|
footer: {
|
||||||
message: 'Released under the MIT License.',
|
message: 'Released under the MIT License.',
|
||||||
copyright: 'Copyright © 2023-present crazywhalecc'
|
copyright: 'Copyright © 2023-present crazywhalecc',
|
||||||
},
|
},
|
||||||
|
externalLinkIcon: true,
|
||||||
search: {
|
search: {
|
||||||
provider: 'algolia',
|
provider: 'algolia',
|
||||||
options: {
|
options: {
|
||||||
appId: 'IHJHUB1SF1',
|
appId: 'IHJHUB1SF1',
|
||||||
apiKey: '8266d31cc2ffbd0e059f1c6e5bdaf8fc',
|
apiKey: '8266d31cc2ffbd0e059f1c6e5bdaf8fc',
|
||||||
indexName: 'static-php docs',
|
indexName: 'static-php docs',
|
||||||
|
askAi: {
|
||||||
|
assistantId: 'b72369b2-60a5-461d-902c-5c18d8c05902',
|
||||||
|
agentStudio: true,
|
||||||
|
sidePanel: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
23
docs/.vitepress/deps-map.data.js
Normal file
23
docs/.vitepress/deps-map.data.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { readFileSync, existsSync } from 'node:fs'
|
||||||
|
import { resolve, dirname } from 'node:path'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||||
|
const DATA_PATH = resolve(__dirname, 'deps-data.json')
|
||||||
|
|
||||||
|
export default {
|
||||||
|
watch: [DATA_PATH],
|
||||||
|
|
||||||
|
load() {
|
||||||
|
if (!existsSync(DATA_PATH)) {
|
||||||
|
console.warn(
|
||||||
|
'[deps-map.data.js] deps-data.json not found. ' +
|
||||||
|
'Run `bin/spc dev:gen-deps-data` to generate it.'
|
||||||
|
)
|
||||||
|
return { packages: {}, missing: true }
|
||||||
|
}
|
||||||
|
|
||||||
|
const raw = JSON.parse(readFileSync(DATA_PATH, 'utf-8'))
|
||||||
|
return { packages: raw.packages ?? {}, missing: false }
|
||||||
|
},
|
||||||
|
}
|
||||||
40
docs/.vitepress/extensions.data.js
Normal file
40
docs/.vitepress/extensions.data.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { readFileSync, existsSync } from 'node:fs'
|
||||||
|
import { resolve, dirname } from 'node:path'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||||
|
const DATA_PATH = resolve(__dirname, 'ext-data.json')
|
||||||
|
const NOTES_PATH = resolve(__dirname, '../en/guide/extension-notes.md')
|
||||||
|
|
||||||
|
export default {
|
||||||
|
watch: [DATA_PATH, NOTES_PATH],
|
||||||
|
|
||||||
|
load() {
|
||||||
|
if (!existsSync(DATA_PATH)) {
|
||||||
|
console.warn(
|
||||||
|
'[extensions.data.js] ext-data.json not found. ' +
|
||||||
|
'Run `bin/spc dev:gen-ext-docs` to generate it.'
|
||||||
|
)
|
||||||
|
return { extensions: [], missing: true }
|
||||||
|
}
|
||||||
|
|
||||||
|
const raw = JSON.parse(readFileSync(DATA_PATH, 'utf-8'))
|
||||||
|
|
||||||
|
// Build the set of extension names that have a section in extension-notes.md.
|
||||||
|
// Headings at level 2 or 3 are matched; leading/trailing whitespace is stripped.
|
||||||
|
const notesSet = new Set()
|
||||||
|
if (existsSync(NOTES_PATH)) {
|
||||||
|
const notesContent = readFileSync(NOTES_PATH, 'utf-8')
|
||||||
|
for (const match of notesContent.matchAll(/^#{2,3}\s+(\S+)/gm)) {
|
||||||
|
notesSet.add(match[1].toLowerCase())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const extensions = raw.extensions.map(ext => ({
|
||||||
|
...ext,
|
||||||
|
hasNotes: notesSet.has(ext.name.toLowerCase()),
|
||||||
|
}))
|
||||||
|
|
||||||
|
return { extensions, missing: false }
|
||||||
|
},
|
||||||
|
}
|
||||||
118
docs/.vitepress/gen-meta.js
Normal file
118
docs/.vitepress/gen-meta.js
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* docs:gen-meta — Pre-build metadata generator for VitePress docs.
|
||||||
|
*
|
||||||
|
* Checks that the environment is ready (PHP installed, composer dependencies
|
||||||
|
* present, bin/spc executable), then runs:
|
||||||
|
* bin/spc dev:gen-deps-data → docs/.vitepress/deps-data.json
|
||||||
|
* bin/spc dev:gen-ext-docs → docs/.vitepress/ext-data.json
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const { execSync, spawnSync } = require('child_process')
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
// __dirname is docs/.vitepress/, so two levels up is the project root
|
||||||
|
const ROOT = path.resolve(__dirname, '../..')
|
||||||
|
|
||||||
|
function fail(msg) {
|
||||||
|
console.error(`\x1b[31m[gen-meta] ERROR: ${msg}\x1b[0m`)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
function info(msg) {
|
||||||
|
console.log(`\x1b[36m[gen-meta] ${msg}\x1b[0m`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ok(msg) {
|
||||||
|
console.log(`\x1b[32m[gen-meta] ${msg}\x1b[0m`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 1. Check PHP ------------------------------------------------------------
|
||||||
|
info('Checking PHP installation...')
|
||||||
|
const phpResult = spawnSync('php', ['--version'], { encoding: 'utf8' })
|
||||||
|
if (phpResult.status !== 0 || phpResult.error) {
|
||||||
|
fail(
|
||||||
|
'PHP is not installed or not in PATH.\n' +
|
||||||
|
' Please install PHP 8.1+ and ensure it is available in your PATH.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const phpVersion = phpResult.stdout.split('\n')[0].trim()
|
||||||
|
ok(`Found: ${phpVersion}`)
|
||||||
|
|
||||||
|
// --- 2. Check composer CLI ---------------------------------------------------
|
||||||
|
info('Checking composer...')
|
||||||
|
const composerCheck = spawnSync('composer', ['--version'], { encoding: 'utf8' })
|
||||||
|
if (composerCheck.status !== 0 || composerCheck.error) {
|
||||||
|
fail(
|
||||||
|
'composer is not installed or not in PATH.\n' +
|
||||||
|
' Please install Composer: https://getcomposer.org/download/'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ok(`Found: ${composerCheck.stdout.split('\n')[0].trim()}`)
|
||||||
|
|
||||||
|
// --- 3. Install composer dependencies if missing ----------------------------
|
||||||
|
info('Checking composer dependencies...')
|
||||||
|
const autoload = path.join(ROOT, 'vendor', 'autoload.php')
|
||||||
|
if (!fs.existsSync(autoload)) {
|
||||||
|
info('vendor/autoload.php not found — running composer install --no-dev ...')
|
||||||
|
const installResult = spawnSync('composer', ['install', '--no-dev'], {
|
||||||
|
cwd: ROOT,
|
||||||
|
stdio: 'inherit',
|
||||||
|
})
|
||||||
|
if (installResult.status !== 0) {
|
||||||
|
fail('composer install --no-dev failed (exit code ' + installResult.status + ').')
|
||||||
|
}
|
||||||
|
ok('Composer dependencies installed.')
|
||||||
|
} else {
|
||||||
|
ok('Composer vendor directory found.')
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 4. Check bin/spc --------------------------------------------------------
|
||||||
|
info('Checking bin/spc...')
|
||||||
|
const spc = path.join(ROOT, 'bin', 'spc')
|
||||||
|
if (!fs.existsSync(spc)) {
|
||||||
|
fail('bin/spc not found. Make sure you are in the project root.')
|
||||||
|
}
|
||||||
|
// Quick sanity check — list commands
|
||||||
|
const spcCheck = spawnSync('php', [spc, 'list', '--format=txt'], {
|
||||||
|
cwd: ROOT,
|
||||||
|
encoding: 'utf8',
|
||||||
|
env: { ...process.env, SPC_EXECUTION_SOURCE: '1' },
|
||||||
|
})
|
||||||
|
if (spcCheck.status !== 0) {
|
||||||
|
fail(
|
||||||
|
'bin/spc failed to run.\n' +
|
||||||
|
(spcCheck.stderr ?? '') +
|
||||||
|
'\n Make sure PHP extensions required by static-php-cli are available.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ok('bin/spc is operational.')
|
||||||
|
|
||||||
|
// --- 5. Run dev:gen-deps-data ------------------------------------------------
|
||||||
|
info('Running bin/spc dev:gen-deps-data ...')
|
||||||
|
const depsResult = spawnSync('php', [spc, 'dev:gen-deps-data'], {
|
||||||
|
cwd: ROOT,
|
||||||
|
stdio: 'inherit',
|
||||||
|
env: { ...process.env, SPC_EXECUTION_SOURCE: '1' },
|
||||||
|
})
|
||||||
|
if (depsResult.status !== 0) {
|
||||||
|
fail('dev:gen-deps-data failed (exit code ' + depsResult.status + ').')
|
||||||
|
}
|
||||||
|
ok('deps-data.json generated.')
|
||||||
|
|
||||||
|
// --- 6. Run dev:gen-ext-docs -------------------------------------------------
|
||||||
|
info('Running bin/spc dev:gen-ext-docs ...')
|
||||||
|
const extResult = spawnSync('php', [spc, 'dev:gen-ext-docs'], {
|
||||||
|
cwd: ROOT,
|
||||||
|
stdio: 'inherit',
|
||||||
|
env: { ...process.env, SPC_EXECUTION_SOURCE: '1' },
|
||||||
|
})
|
||||||
|
if (extResult.status !== 0) {
|
||||||
|
fail('dev:gen-ext-docs failed (exit code ' + extResult.status + ').')
|
||||||
|
}
|
||||||
|
ok('ext-data.json generated.')
|
||||||
|
|
||||||
|
ok('Metadata generation complete. Proceeding to VitePress build...')
|
||||||
@@ -1,57 +1,83 @@
|
|||||||
export default {
|
export default {
|
||||||
'/en/guide/': [
|
'/en/guide/': [
|
||||||
{
|
{
|
||||||
text: 'Basic Build Guides',
|
text: 'Getting Started',
|
||||||
items: [
|
items: [
|
||||||
{text: 'Guide', link: '/en/guide/'},
|
{ text: 'Overview', link: '/en/guide/' },
|
||||||
{text: 'Build (Local)', link: '/en/guide/manual-build'},
|
{ text: 'Installation', link: '/en/guide/installation' },
|
||||||
{text: 'Build (CI)', link: '/en/guide/action-build'},
|
{ text: 'First Build', link: '/en/guide/first-build' },
|
||||||
{text: 'Supported Extensions', link: '/en/guide/extensions'},
|
{ text: 'PHP SAPI Reference', link: '/en/guide/sapi-reference' },
|
||||||
{text: 'Extension Notes', link: '/en/guide/extension-notes'},
|
{ text: 'CLI Reference', link: '/en/guide/cli-reference' },
|
||||||
{text: 'Build Command Generator', link: '/en/guide/cli-generator'},
|
],
|
||||||
{text: 'Environment Variables', link: '/en/guide/env-vars', collapsed: true,},
|
},
|
||||||
{text: 'Dependency Table', link: '/en/guide/deps-map'},
|
{
|
||||||
]
|
text: 'Extensions',
|
||||||
},
|
items: [
|
||||||
{
|
{ text: 'Supported Extensions', link: '/en/guide/extensions' },
|
||||||
text: 'Extended Build Guides',
|
{ text: 'Extension Notes', link: '/en/guide/extension-notes' },
|
||||||
items: [
|
{ text: 'Build Command Generator', link: '/en/guide/cli-generator' },
|
||||||
{text: 'Troubleshooting', link: '/en/guide/troubleshooting'},
|
],
|
||||||
{text: 'Build on Windows', link: '/en/guide/build-on-windows'},
|
},
|
||||||
{text: 'Build with GNU libc', link: '/en/guide/build-with-glibc'},
|
{
|
||||||
],
|
text: 'Reference',
|
||||||
}
|
items: [
|
||||||
],
|
{ text: 'Environment Variables', link: '/en/guide/env-vars' },
|
||||||
'/en/develop/': [
|
{ text: 'Dependency Table', link: '/en/guide/deps-map' },
|
||||||
{
|
{ text: 'Troubleshooting', link: '/en/guide/troubleshooting' },
|
||||||
text: 'Development',
|
],
|
||||||
items: [
|
},
|
||||||
{text: 'Get Started', link: '/en/develop/'},
|
],
|
||||||
{text: 'Project Structure', link: '/en/develop/structure'},
|
'/en/develop/': [
|
||||||
{text: 'PHP Source Modification', link: '/en/develop/php-src-changes'},
|
{
|
||||||
],
|
text: 'Developer Guide',
|
||||||
},
|
items: [
|
||||||
{
|
{ text: 'Get Started', link: '/en/develop/' },
|
||||||
text: 'Module',
|
{ text: 'Project Structure', link: '/en/develop/structure' },
|
||||||
items: [
|
{ text: 'PHP Source Modifications', link: '/en/develop/php-src-changes' },
|
||||||
{text: 'Doctor ', link: '/en/develop/doctor-module'},
|
],
|
||||||
{text: 'Source', link: '/en/develop/source-module'},
|
},
|
||||||
]
|
{
|
||||||
},
|
text: 'Concepts',
|
||||||
{
|
items: [
|
||||||
text: 'Extra',
|
{ text: 'Package Model', link: '/en/develop/package-model' },
|
||||||
items: [
|
{ text: 'Registry & Plugin System', link: '/en/develop/registry' },
|
||||||
{text: 'Compilation Tools', link: '/en/develop/system-build-tools'},
|
{ text: 'Build Lifecycle', link: '/en/develop/build-lifecycle' },
|
||||||
{text: 'craft.yml Configuration', link: '/zh/develop/craft-yml'},
|
],
|
||||||
]
|
},
|
||||||
}
|
{
|
||||||
],
|
text: 'Modules',
|
||||||
'/en/contributing/': [
|
items: [
|
||||||
{
|
{ text: 'Doctor', link: '/en/develop/doctor-module' },
|
||||||
text: 'Contributing',
|
{ text: 'Source', link: '/en/develop/source-module' },
|
||||||
items: [
|
{ text: 'craft.yml', link: '/en/develop/craft-yml' },
|
||||||
{text: 'Contributing', link: '/en/contributing/'},
|
{ text: 'Compilation Tools', link: '/en/develop/system-build-tools' },
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
],
|
{
|
||||||
|
text: 'Vendor Mode',
|
||||||
|
items: [
|
||||||
|
{ text: 'Introduction', link: '/en/develop/vendor-mode/' },
|
||||||
|
{ text: 'Writing Package Classes', link: '/en/develop/vendor-mode/package-classes' },
|
||||||
|
{ text: 'Annotations Reference', link: '/en/develop/vendor-mode/annotations' },
|
||||||
|
{ text: 'Dependency Injection', link: '/en/develop/vendor-mode/dependency-injection' },
|
||||||
|
{ text: 'Lifecycle Hooks', link: '/en/develop/vendor-mode/lifecycle-hooks' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'/en/contributing/': [
|
||||||
|
{
|
||||||
|
text: 'Contributing',
|
||||||
|
items: [
|
||||||
|
{ text: 'Contributing Guide', link: '/en/contributing/' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'/en/faq/': [
|
||||||
|
{
|
||||||
|
text: 'FAQ',
|
||||||
|
items: [
|
||||||
|
{ text: 'Frequently Asked Questions', link: '/en/faq/' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,57 +1,83 @@
|
|||||||
export default {
|
export default {
|
||||||
'/zh/guide/': [
|
'/zh/guide/': [
|
||||||
{
|
{
|
||||||
text: '构建指南',
|
text: '快速上手',
|
||||||
items: [
|
items: [
|
||||||
{text: '指南', link: '/zh/guide/'},
|
{ text: '概览', link: '/zh/guide/' },
|
||||||
{text: '本地构建', link: '/zh/guide/manual-build'},
|
{ text: '安装', link: '/zh/guide/installation' },
|
||||||
{text: 'Actions 构建', link: '/zh/guide/action-build'},
|
{ text: '第一次构建', link: '/zh/guide/first-build' },
|
||||||
{text: '扩展列表', link: '/zh/guide/extensions'},
|
{ text: 'PHP SAPI 构建参考', link: '/zh/guide/sapi-reference' },
|
||||||
{text: '扩展注意事项', link: '/zh/guide/extension-notes'},
|
{ text: '命令行参考', link: '/zh/guide/cli-reference' },
|
||||||
{text: '编译命令生成器', link: '/zh/guide/cli-generator'},
|
],
|
||||||
{text: '环境变量列表', link: '/zh/guide/env-vars'},
|
},
|
||||||
{text: '依赖关系图表', link: '/zh/guide/deps-map'},
|
{
|
||||||
]
|
text: '扩展',
|
||||||
},
|
items: [
|
||||||
{
|
{ text: '支持的扩展列表', link: '/zh/guide/extensions' },
|
||||||
text: '扩展构建指南',
|
{ text: '扩展注意事项', link: '/zh/guide/extension-notes' },
|
||||||
items: [
|
{ text: '命令生成器', link: '/zh/guide/cli-generator' },
|
||||||
{text: '故障排除', link: '/zh/guide/troubleshooting'},
|
],
|
||||||
{text: '在 Windows 上构建', link: '/zh/guide/build-on-windows'},
|
},
|
||||||
{text: '构建 GNU libc 兼容的二进制', link: '/zh/guide/build-with-glibc'},
|
{
|
||||||
],
|
text: '参考',
|
||||||
}
|
items: [
|
||||||
],
|
{ text: '环境变量', link: '/zh/guide/env-vars' },
|
||||||
'/zh/develop/': [
|
{ text: '依赖关系图', link: '/zh/guide/deps-map' },
|
||||||
{
|
{ text: '故障排除', link: '/zh/guide/troubleshooting' },
|
||||||
text: '开发指南',
|
],
|
||||||
items: [
|
},
|
||||||
{text: '开发简介', link: '/zh/develop/'},
|
],
|
||||||
{text: '项目结构简介', link: '/zh/develop/structure'},
|
'/zh/develop/': [
|
||||||
{text: '对 PHP 源码的修改', link: '/zh/develop/php-src-changes'},
|
{
|
||||||
],
|
text: '开发者指南',
|
||||||
},
|
items: [
|
||||||
{
|
{ text: '开发简介', link: '/zh/develop/' },
|
||||||
text: '模块',
|
{ text: '项目结构', link: '/zh/develop/structure' },
|
||||||
items: [
|
{ text: '对 PHP 源码的修改', link: '/zh/develop/php-src-changes' },
|
||||||
{text: 'Doctor 环境检查工具', link: '/zh/develop/doctor-module'},
|
],
|
||||||
{text: '资源模块', link: '/zh/develop/source-module'},
|
},
|
||||||
]
|
{
|
||||||
},
|
text: '核心概念',
|
||||||
{
|
items: [
|
||||||
text: '其他',
|
{ text: 'Package 模型', link: '/zh/develop/package-model' },
|
||||||
items: [
|
{ text: 'Registry 与插件系统', link: '/zh/develop/registry' },
|
||||||
{text: '系统编译工具', link: '/zh/develop/system-build-tools'},
|
{ text: '构建生命周期', link: '/zh/develop/build-lifecycle' },
|
||||||
{text: 'craft.yml 配置详解', link: '/zh/develop/craft-yml'},
|
],
|
||||||
]
|
},
|
||||||
}
|
{
|
||||||
],
|
text: '模块',
|
||||||
'/zh/contributing/': [
|
items: [
|
||||||
{
|
{ text: 'Doctor 环境检查', link: '/zh/develop/doctor-module' },
|
||||||
text: '贡献指南',
|
{ text: '资源模块', link: '/zh/develop/source-module' },
|
||||||
items: [
|
{ text: 'craft.yml 配置', link: '/zh/develop/craft-yml' },
|
||||||
{text: '贡献指南', link: '/zh/contributing/'},
|
{ text: '编译工具', link: '/zh/develop/system-build-tools' },
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
],
|
{
|
||||||
|
text: 'Vendor 模式',
|
||||||
|
items: [
|
||||||
|
{ text: '简介', link: '/zh/develop/vendor-mode/' },
|
||||||
|
{ text: '编写 Package 类', link: '/zh/develop/vendor-mode/package-classes' },
|
||||||
|
{ text: '注解参考', link: '/zh/develop/vendor-mode/annotations' },
|
||||||
|
{ text: '依赖注入', link: '/zh/develop/vendor-mode/dependency-injection' },
|
||||||
|
{ text: '生命周期 Hook', link: '/zh/develop/vendor-mode/lifecycle-hooks' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'/zh/contributing/': [
|
||||||
|
{
|
||||||
|
text: '贡献指南',
|
||||||
|
items: [
|
||||||
|
{ text: '贡献指南', link: '/zh/contributing/' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'/zh/faq/': [
|
||||||
|
{
|
||||||
|
text: 'FAQ',
|
||||||
|
items: [
|
||||||
|
{ text: '常见问题', link: '/zh/faq/' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,9 +3,13 @@ import DefaultTheme from 'vitepress/theme'
|
|||||||
import {inBrowser, useData} from "vitepress";
|
import {inBrowser, useData} from "vitepress";
|
||||||
import {watchEffect} from "vue";
|
import {watchEffect} from "vue";
|
||||||
import './style.css';
|
import './style.css';
|
||||||
|
import DepsMap from '../components/DepsMap.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...DefaultTheme,
|
...DefaultTheme,
|
||||||
|
enhanceApp({ app }) {
|
||||||
|
app.component('DepsMap', DepsMap)
|
||||||
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const { lang } = useData()
|
const { lang } = useData()
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
```yaml
|
|
||||||
# PHP version to build (default: 8.4)
|
|
||||||
php-version: 8.4
|
|
||||||
# [REQUIRED] Static PHP extensions to build (list or comma-separated are both accepted)
|
|
||||||
extensions: bcmath,fileinfo,phar,zlib,sodium,posix,pcntl
|
|
||||||
# Extra libraries to build (list or comma-separated are both accepted)
|
|
||||||
libs: [ ]
|
|
||||||
# [REQUIRED] Build SAPIs (list or comma-separated are both accepted)
|
|
||||||
sapi: cli,micro,fpm
|
|
||||||
# Show full console output (default: false)
|
|
||||||
debug: false
|
|
||||||
# Build options (same as `build` command options, all options are optional)
|
|
||||||
build-options:
|
|
||||||
# Before build, remove all old build files and sources (default: false)
|
|
||||||
with-clean: false
|
|
||||||
# Build with all suggested libraries (default: false)
|
|
||||||
with-suggested-libs: false
|
|
||||||
# Build with all suggested extensions (default: false)
|
|
||||||
with-suggested-exts: false
|
|
||||||
# Build extra shared extensions (list or comma-separated are both accepted)
|
|
||||||
build-shared: [ ]
|
|
||||||
# Build without stripping the binary (default: false)
|
|
||||||
no-strip: false
|
|
||||||
# Disable Opcache JIT (default: false)
|
|
||||||
disable-opcache-jit: false
|
|
||||||
# PHP configuration options (same as --with-config-file-path)
|
|
||||||
with-config-file-path: ""
|
|
||||||
# PHP configuration options (same as --with-config-file-scan-dir)
|
|
||||||
with-config-file-scan-dir: ""
|
|
||||||
# Hardcoded INI options for cli and micro SAPI (e.g. "memory_limit=4G", list accepted)
|
|
||||||
with-hardcoded-ini: [ ]
|
|
||||||
# Pretend micro SAPI as cli SAPI to avoid some frameworks to limit the usage of micro SAPI
|
|
||||||
with-micro-fake-cli: false
|
|
||||||
# Additional patch point injection files (e.g. "path/to/patch.php", list accepted)
|
|
||||||
with-added-patch: [ ]
|
|
||||||
# Ignore micro extension tests (if you are using micro SAPI, default: false)
|
|
||||||
without-micro-ext-test: false
|
|
||||||
# UPX pack the binary (default: false)
|
|
||||||
with-upx-pack: false
|
|
||||||
# Set the micro.exe program icon (only for Windows, default: "")
|
|
||||||
with-micro-logo: ""
|
|
||||||
# Set micro SAPI as win32 mode, without this, micro SAPI will be compiled as a console application (only for Windows, default: false)
|
|
||||||
enable-micro-win32: false
|
|
||||||
|
|
||||||
# Build options for shared extensions (list or comma-separated are both accepted)
|
|
||||||
shared-extensions: [ ]
|
|
||||||
|
|
||||||
# Download options
|
|
||||||
download-options:
|
|
||||||
# Use custom url for specified sources, format: "{source-name}:{url}" (e.g. "php-src:https://example.com/php-8.4.0.tar.gz")
|
|
||||||
custom-url: [ ]
|
|
||||||
# Use custom git repo for specified sources, format: "{source-name}:{branch}:{url}" (e.g. "php-src:master:https://github.com/php/php-src.git")
|
|
||||||
custom-git: [ ]
|
|
||||||
# Retries count for downloading sources (default: 5)
|
|
||||||
retry: 5
|
|
||||||
# Use pre-built libraries if available (default: false)
|
|
||||||
prefer-pre-built: true
|
|
||||||
# Do not download from alternative sources (default: false)
|
|
||||||
no-alt: false
|
|
||||||
|
|
||||||
craft-options:
|
|
||||||
doctor: true
|
|
||||||
download: true
|
|
||||||
build: true
|
|
||||||
|
|
||||||
# Extra environment variables
|
|
||||||
extra-env:
|
|
||||||
# e.g. Use github token to avoid rate limit
|
|
||||||
GITHUB_TOKEN: your-github-token
|
|
||||||
```
|
|
||||||
@@ -1,63 +1,5 @@
|
|||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
Thank you for being here, this project welcomes your contributions!
|
<!-- TODO: v3 contribution guide.
|
||||||
|
Sections: code style (php-cs-fixer, phpstan), adding a new library/extension,
|
||||||
## Contribution Guide
|
adding a doctor check, submitting PRs, security disclosures. -->
|
||||||
|
|
||||||
If you have code or documentation to contribute, here's what you need to know first.
|
|
||||||
|
|
||||||
1. What type of code are you contributing? (new extensions, bug fixes, security issues, project framework optimizations, documentation)
|
|
||||||
2. If you contribute new files or new snippets, is your code checked by `php-cs-fixer` and `phpstan`?
|
|
||||||
3. Have you fully read the [Developer Guide](../develop/) before contributing code?
|
|
||||||
|
|
||||||
If you can answer the above questions and have made changes to the code,
|
|
||||||
you can initiate a Pull Request in the project GitHub repository in time.
|
|
||||||
After the code review is completed, the code can be modified according to the suggestion, or directly merged into the main branch.
|
|
||||||
|
|
||||||
## Contribution Type
|
|
||||||
|
|
||||||
The main purpose of this project is to compile statically linked PHP binaries,
|
|
||||||
and the command line processing function is written based on `symfony/console`.
|
|
||||||
Before development, if you are not familiar with it,
|
|
||||||
Check out the [symfony/console documentation](https://symfony.com/doc/current/components/console.html) first.
|
|
||||||
|
|
||||||
### Security Update
|
|
||||||
|
|
||||||
Because this project is basically a PHP project running locally, generally speaking, there will be no remote attacks.
|
|
||||||
But if you find such a problem, please **DO NOT submit a PR or Issue in the GitHub repository,
|
|
||||||
You need to contact the project maintainer (crazywhalecc) via [mail](mailto:admin@zhamao.me).
|
|
||||||
|
|
||||||
### Fix Bugs
|
|
||||||
|
|
||||||
Fixing bugs generally does not involve modification of the project structure and framework,
|
|
||||||
so if you can locate the wrong code and fix it directly, please submit a PR directly.
|
|
||||||
|
|
||||||
### New Extensions
|
|
||||||
|
|
||||||
For adding a new extension,
|
|
||||||
you need to understand some basic structure of the project and how to add a new extension according to the existing logic.
|
|
||||||
It will be covered in detail in the next section on this page.
|
|
||||||
In general, you will need:
|
|
||||||
|
|
||||||
1. Evaluate whether the extension can be compiled inline into PHP.
|
|
||||||
2. Evaluate whether the extension's dependent libraries (if any) can be compiled statically.
|
|
||||||
3. Write library compile commands on different platforms.
|
|
||||||
4. Verify that the extension and its dependencies are compatible with existing extensions and dependencies.
|
|
||||||
5. Verify that the extension works normally in `cli`, `micro`, `fpm`, `embed` SAPIs.
|
|
||||||
6. Write documentation and add your extension.
|
|
||||||
|
|
||||||
### Project Framework Optimization
|
|
||||||
|
|
||||||
If you are already familiar with the working principle of `symfony/console`,
|
|
||||||
and at the same time want to make some modifications or optimizations to the framework of the project,
|
|
||||||
please understand the following things first:
|
|
||||||
|
|
||||||
1. Adding extensions does not belong to project framework optimization,
|
|
||||||
but if you find that you have to optimize the framework when adding new extensions,
|
|
||||||
you need to modify the framework itself before adding extensions.
|
|
||||||
2. For some large-scale logical modifications (such as those involving LibraryBase, Extension objects, etc.),
|
|
||||||
it is recommended to submit an Issue or Draft PR for discussion first.
|
|
||||||
3. In the early stage of the project, it was a pure private development project, and there were some Chinese comments in the code.
|
|
||||||
After internationalizing your project you can submit a PR to translate these comments into English.
|
|
||||||
4. Please do not submit more useless code fragments in the code,
|
|
||||||
such as a large number of unused variables, methods, classes, and code that has been rewritten many times.
|
|
||||||
|
|||||||
6
docs/en/develop/build-lifecycle.md
Normal file
6
docs/en/develop/build-lifecycle.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Build Lifecycle
|
||||||
|
|
||||||
|
<!-- TODO: Describe the full build pipeline stage sequence.
|
||||||
|
When each hook fires: #[BeforeStage], #[AfterStage], #[PatchBeforeBuild].
|
||||||
|
How platform selection (#[BuildFor]) works at runtime.
|
||||||
|
Diagram of stage order for a typical library and extension build. -->
|
||||||
@@ -4,4 +4,4 @@ aside: false
|
|||||||
|
|
||||||
# craft.yml Configuration
|
# craft.yml Configuration
|
||||||
|
|
||||||
<!--@include: ../../deps-craft-yml.md-->
|
<!-- TODO: Full reference for craft.yml fields. -->
|
||||||
|
|||||||
@@ -1,70 +1,4 @@
|
|||||||
# Doctor module
|
# Doctor Module
|
||||||
|
|
||||||
The Doctor module is a relatively independent module used to check the system environment, which can be entered with the command `bin/spc doctor`, and the entry command class is in `DoctorCommand.php`.
|
<!-- TODO: Migrate and update from v2 doctor-module.md.
|
||||||
|
Cover v3 changes: --auto-fix, .spc-doctor.lock, new check items for v3 toolchain. -->
|
||||||
The Doctor module is a checklist with a series of check items and automatic repair items.
|
|
||||||
These items are stored in the `src/SPC/doctor/item/` directory,
|
|
||||||
And two Attributes are used as check item tags and auto-fix item tags: `#[AsCheckItem]` and `#[AsFixItem]`.
|
|
||||||
|
|
||||||
Take the existing check item `if necessary tools are installed`,
|
|
||||||
which is used to check whether the packages necessary for compilation are installed in the macOS system.
|
|
||||||
The following is its source code:
|
|
||||||
|
|
||||||
```php
|
|
||||||
use SPC\doctor\AsCheckItem;
|
|
||||||
use SPC\doctor\AsFixItem;
|
|
||||||
use SPC\doctor\CheckResult;
|
|
||||||
|
|
||||||
#[AsCheckItem('if necessary tools are installed', limit_os: 'Darwin', level: 997)]
|
|
||||||
public function checkCliTools(): ?CheckResult
|
|
||||||
{
|
|
||||||
$missing = [];
|
|
||||||
foreach (self::REQUIRED_COMMANDS as $cmd) {
|
|
||||||
if ($this->findCommand($cmd) === null) {
|
|
||||||
$missing[] = $cmd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!empty($missing)) {
|
|
||||||
return CheckResult::fail('missing system commands: ' . implode(', ', $missing), 'build-tools', [$missing]);
|
|
||||||
}
|
|
||||||
return CheckResult::ok();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The first parameter of the attribute is the name of the check item,
|
|
||||||
and the following `limit_os` parameter restricts the check item to be triggered only under the specified system,
|
|
||||||
and `level` is the priority of executing the check item, the larger the number, the higher the priority higher.
|
|
||||||
|
|
||||||
The `$this->findCommand()` method used in it is the method of `SPC\builder\traits\UnixSystemUtilTrait`,
|
|
||||||
the purpose is to find the location of the system command, and return NULL if it cannot be found.
|
|
||||||
|
|
||||||
Each check item method should return a `SPC\doctor\CheckResult`:
|
|
||||||
|
|
||||||
- When returning `CheckResult::fail()`, the first parameter is used to output the error prompt of the terminal,
|
|
||||||
and the second parameter is the name of the repair item when this check item can be automatically repaired.
|
|
||||||
- When `CheckResult::ok()` is returned, the check passed. You can also pass a parameter to return the check result, for example: `CheckResult::ok('OS supported')`.
|
|
||||||
- When returning `CheckResult::fail()`, if the third parameter is included, the array of the third parameter will be used as the parameter of `AsFixItem`.
|
|
||||||
|
|
||||||
The following is the method for automatically repairing items corresponding to this check item:
|
|
||||||
|
|
||||||
```php
|
|
||||||
#[AsFixItem('build-tools')]
|
|
||||||
public function fixBuildTools(array $missing): bool
|
|
||||||
{
|
|
||||||
foreach ($missing as $cmd) {
|
|
||||||
try {
|
|
||||||
shell(true)->exec('brew install ' . escapeshellarg($cmd));
|
|
||||||
} catch (RuntimeException) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`#[AsFixItem()]` first parameter is the name of the fix item, and this method must return True or False.
|
|
||||||
When False is returned, the automatic repair failed and manual handling is required.
|
|
||||||
|
|
||||||
In the code here, `shell()->exec()` is the method of executing commands of the project,
|
|
||||||
which is used to replace `exec()` and `system()`, and also provides debugging, obtaining execution status,
|
|
||||||
entering directories, etc. characteristic.
|
|
||||||
|
|||||||
@@ -1,35 +1,4 @@
|
|||||||
# Start Developing
|
# Start Developing
|
||||||
|
|
||||||
Developing this project requires the installation and deployment of a PHP environment,
|
<!-- TODO: Developer introduction, environment setup, required PHP extensions.
|
||||||
as well as some extensions and Composer commonly used in PHP projects.
|
Link to Vendor Mode for library authors, and Contributing for code contributors. -->
|
||||||
|
|
||||||
The development environment and running environment of the project are almost exactly the same.
|
|
||||||
You can refer to the **Manual Build** section to install system PHP or use the pre-built static PHP of this project as the environment.
|
|
||||||
I will not go into details here.
|
|
||||||
|
|
||||||
Regardless of its purpose, this project itself is actually a `php-cli` program. You can edit and develop it as a normal PHP project.
|
|
||||||
At the same time, you need to understand the Shell languages of different systems.
|
|
||||||
|
|
||||||
The current purpose of this project is to compile statically compiled independent PHP,
|
|
||||||
but the main part also includes compiling static versions of many dependent libraries,
|
|
||||||
so you can reuse this set of compilation logic to build independent binary versions of other programs, such as Nginx, etc.
|
|
||||||
|
|
||||||
## Environment preparation
|
|
||||||
|
|
||||||
A PHP environment is required to develop this project. You can use the PHP that comes with the system,
|
|
||||||
or you can use the static PHP built by this project.
|
|
||||||
|
|
||||||
Regardless of which PHP you use, in your development environment you need to install these extensions:
|
|
||||||
|
|
||||||
```
|
|
||||||
curl,dom,filter,mbstring,openssl,pcntl,phar,posix,sodium,tokenizer,xml,xmlwriter
|
|
||||||
```
|
|
||||||
|
|
||||||
The static-php-cli project itself does not require so many extensions, but during the development process,
|
|
||||||
you will use tools such as Composer and PHPUnit, which require these extensions.
|
|
||||||
|
|
||||||
> For micro self-executing binaries built by static-php-cli itself, only `pcntl,posix,mbstring,tokenizer,phar` is required.
|
|
||||||
|
|
||||||
## Start development
|
|
||||||
|
|
||||||
Continuing down to see the project structure documentation, you can learn how `static-php-cli` works.
|
|
||||||
|
|||||||
6
docs/en/develop/package-model.md
Normal file
6
docs/en/develop/package-model.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Package Model
|
||||||
|
|
||||||
|
<!-- TODO: Explain the unified package model: library / php-extension / target types.
|
||||||
|
Cover the per-package YAML format (config/pkg/), the `depends` field,
|
||||||
|
platform overrides (@windows / @unix notation), artifact.source and artifact.binary.
|
||||||
|
Show annotated example YAML for a library and an extension. -->
|
||||||
@@ -1,59 +1,4 @@
|
|||||||
# Modifications to PHP source code
|
# PHP Source Modifications
|
||||||
|
|
||||||
During the static compilation process, static-php-cli made some modifications to the PHP source code
|
<!-- TODO: Migrate and update from v2 php-src-changes.md.
|
||||||
in order to achieve good compatibility, performance, and security.
|
Add v3-specific patches (FrankenPHP embed, Windows fiber fix, etc.). -->
|
||||||
The following is a description of the current modifications to the PHP source code.
|
|
||||||
|
|
||||||
## Micro related patches
|
|
||||||
|
|
||||||
Based on the patches provided by the phpmicro project,
|
|
||||||
static-php-cli has made some modifications to the PHP source code to meet the needs of static compilation.
|
|
||||||
The patches currently used by static-php-cli during compilation in the [patch list](https://github.com/easysoft/phpmicro/tree/master/patches) are:
|
|
||||||
|
|
||||||
- static_opcache
|
|
||||||
- static_extensions_win32
|
|
||||||
- cli_checks
|
|
||||||
- disable_huge_page
|
|
||||||
- vcruntime140
|
|
||||||
- win32
|
|
||||||
- zend_stream
|
|
||||||
- cli_static
|
|
||||||
- macos_iconv
|
|
||||||
- phar
|
|
||||||
|
|
||||||
## PHP <= 8.1 libxml patch
|
|
||||||
|
|
||||||
Because PHP only provides security updates for 8.1 and stops updating older versions,
|
|
||||||
static-php-cli applies the libxml compilation patch that has been applied in newer versions of PHP to PHP 8.1 and below.
|
|
||||||
|
|
||||||
## gd extension Windows patch
|
|
||||||
|
|
||||||
Compiling the gd extension under Windows requires major changes to the `config.w32` file.
|
|
||||||
static-php-cli has made some changes to the gd extension to make it easier to compile under Windows.
|
|
||||||
|
|
||||||
## YAML extension Windows patch
|
|
||||||
|
|
||||||
YAML extension needs to modify the `config.w32` file to compile under Windows.
|
|
||||||
static-php-cli has made some modifications to the YAML extension to make it easier to compile under Windows.
|
|
||||||
|
|
||||||
## static-php-cli version information insertion
|
|
||||||
|
|
||||||
When compiling, static-php-cli will insert the static-php-cli version information into the PHP version information for easy identification.
|
|
||||||
|
|
||||||
## Add option to hardcode INI
|
|
||||||
|
|
||||||
When using the `-I` parameter to hardcode INI into static PHP functionality,
|
|
||||||
static-php-cli will modify the PHP source code to insert the hardcoded content.
|
|
||||||
|
|
||||||
## Linux system repair patch
|
|
||||||
|
|
||||||
Some compilation environments may lack some system header files or libraries.
|
|
||||||
static-php-cli will automatically fix these problems during compilation, such as:
|
|
||||||
|
|
||||||
- HAVE_STRLCAT missing problem
|
|
||||||
- HAVE_STRLCPY missing problem
|
|
||||||
|
|
||||||
## Fiber issue fix patch for Windows
|
|
||||||
|
|
||||||
When compiling PHP on Windows, there will be some issues with the Fiber extension.
|
|
||||||
static-php-cli will automatically fix these issues during compilation (modify `config.w32` in php-src).
|
|
||||||
|
|||||||
6
docs/en/develop/registry.md
Normal file
6
docs/en/develop/registry.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Registry & Plugin System
|
||||||
|
|
||||||
|
<!-- TODO: Explain spc.registry.yml structure.
|
||||||
|
How to add an external registry via SPC_REGISTRIES env var.
|
||||||
|
Vendor-specific configurations, overriding core packages.
|
||||||
|
Registry resolution order and conflict rules. -->
|
||||||
@@ -1,372 +1,5 @@
|
|||||||
# Source module
|
# Source Module
|
||||||
|
|
||||||
The download source module of static-php-cli is a major module.
|
<!-- TODO: Migrate and update from v2 source-module.md.
|
||||||
It includes dependent libraries, external extensions, PHP source code download methods and file decompression methods.
|
Document v3 source types: url, ghrel, ghtar, ghtagtar, git, pecl (new), filelist, custom.
|
||||||
The download configuration file mainly involves the `source.json` and `pkg.json` file, which records the download method of all downloadable sources.
|
Per-package YAML source block format. Parallel download (--parallel N). -->
|
||||||
|
|
||||||
The main commands involved in the download function are `bin/spc download` and `bin/spc extract`.
|
|
||||||
The `download` command is a downloader that downloads sources according to the configuration file,
|
|
||||||
and the `extract` command is an extractor that extract sources from downloaded files.
|
|
||||||
|
|
||||||
Generally speaking, downloading sources may be slow because these sources come from various official websites, GitHub,
|
|
||||||
and other different locations.
|
|
||||||
At the same time, they also occupy a large space, so you can download the sources once and reuse them.
|
|
||||||
|
|
||||||
The configuration file of the downloader is `source.json`, which contains the download methods of all sources.
|
|
||||||
You can add the source download methods you need, or modify the existing source download methods.
|
|
||||||
|
|
||||||
The download configuration structure of each source is as follows.
|
|
||||||
The following is the source download configuration corresponding to the `libevent` extension:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"libevent": {
|
|
||||||
"type": "ghrel",
|
|
||||||
"repo": "libevent/libevent",
|
|
||||||
"match": "libevent.+\\.tar\\.gz",
|
|
||||||
"provide-pre-built": true,
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
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.
|
|
||||||
- `ghtagtar`: Use GitHub Release API to download.
|
|
||||||
Compared with `ghtar`, `ghtagtar` can find the latest one from the `tags` list and download the source code in `tar.gz` format
|
|
||||||
(because some projects only use `tag` release version).
|
|
||||||
- `bitbuckettag`: Download using BitBucket API, basically the same as `ghtagtar`, except this one applies to BitBucket.
|
|
||||||
- `git`: Clone the project directly from a Git address to download sources, applicable to any public Git repository.
|
|
||||||
- `filelist`: Use a crawler to crawl the Web download site that provides file index,
|
|
||||||
and get the latest version of the file name and download it.
|
|
||||||
- `custom`: If none of the above download methods are satisfactory, you can write `custom`,
|
|
||||||
create a new class under `src/SPC/store/source/`, extends `CustomSourceBase`, and write the download script yourself.
|
|
||||||
|
|
||||||
## source.json Common parameters
|
|
||||||
|
|
||||||
Each source file in source.json has the following params:
|
|
||||||
|
|
||||||
- `license`: the open source license of the source code, see **Open Source License** section below
|
|
||||||
- `type`: must be one of the types mentioned above
|
|
||||||
- `path` (optional): release the source code to the specified directory instead of `source/{name}`
|
|
||||||
- `provide-pre-built` (optional): whether to provide precompiled binary files.
|
|
||||||
If `true`, it will automatically try to download precompiled binary files when running `bin/spc download`
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
The `path` parameter in `source.json` can specify a relative or absolute path. When specified as a relative path, the path is based on `source/`.
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Download type - url
|
|
||||||
|
|
||||||
URL type sources refer to downloading files directly from the URL.
|
|
||||||
|
|
||||||
The parameters included are:
|
|
||||||
|
|
||||||
- `url`: The download address of the file, such as `https://example.com/file.tgz`
|
|
||||||
- `filename` (optional): The file name saved to the local area. If not specified, the file name of the url will be used.
|
|
||||||
|
|
||||||
Example (download the imagick extension and extract it to the extension storage path of the php source code):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"ext-imagick": {
|
|
||||||
"type": "url",
|
|
||||||
"url": "https://pecl.php.net/get/imagick",
|
|
||||||
"path": "php-src/ext/imagick",
|
|
||||||
"filename": "imagick.tgz",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
First use the GitHub Release API to get the latest version, and then download the corresponding files according to the regular matching method.
|
|
||||||
|
|
||||||
The parameters included are:
|
|
||||||
|
|
||||||
- `repo`: GitHub repository name
|
|
||||||
- `match`: regular expression matching Assets files
|
|
||||||
- `prefer-stable`: Whether to download stable versions first (default is `false`)
|
|
||||||
|
|
||||||
Example (download the libsodium library, matching the libsodium-x.y.tar.gz file in Release):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"libsodium": {
|
|
||||||
"type": "ghrel",
|
|
||||||
"repo": "jedisct1/libsodium",
|
|
||||||
"match": "libsodium-\\d+(\\.\\d+)*\\.tar\\.gz",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Download type - ghtar
|
|
||||||
|
|
||||||
ghtar will download the file from the GitHub Release Tag.
|
|
||||||
Unlike `ghrel`, `ghtar` will download the `source code (tar.gz)` from the latest Release of the project.
|
|
||||||
|
|
||||||
The parameters included are:
|
|
||||||
|
|
||||||
- `repo`: GitHub repository name
|
|
||||||
- `prefer-stable`: Whether to download stable versions first (default is `false`)
|
|
||||||
|
|
||||||
Example (brotli library):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"brotli": {
|
|
||||||
"type": "ghtar",
|
|
||||||
"repo": "google/brotli",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Download type - ghtagtar
|
|
||||||
|
|
||||||
Use the GitHub Release API to download.
|
|
||||||
Compared with `ghtar`, `ghtagtar` can find the latest one from the `tags` list and download the source code in `tar.gz` format
|
|
||||||
(because some projects only use the `tag` version).
|
|
||||||
|
|
||||||
The parameters included are:
|
|
||||||
|
|
||||||
- `repo`: GitHub repository name
|
|
||||||
- `prefer-stable`: Whether to download stable versions first (default is `false`)
|
|
||||||
|
|
||||||
Example (gmp library):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"gmp": {
|
|
||||||
"type": "ghtagtar",
|
|
||||||
"repo": "alisw/GMP",
|
|
||||||
"license": {
|
|
||||||
"type": "text",
|
|
||||||
"text": "EXAMPLE LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Download Type - bitbuckettag
|
|
||||||
|
|
||||||
Download using BitBucket API, basically the same as `ghtagtar`, except this one works with BitBucket.
|
|
||||||
|
|
||||||
The parameters included are:
|
|
||||||
|
|
||||||
- `repo`: BitBucket repository name
|
|
||||||
|
|
||||||
## Download type - git
|
|
||||||
|
|
||||||
Clone the project directly from a Git address to download sources, applicable to any public Git repository.
|
|
||||||
|
|
||||||
The parameters included are:
|
|
||||||
|
|
||||||
- `url`: Git link (HTTPS only)
|
|
||||||
- `rev`: branch name
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"imap": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/static-php/imap.git",
|
|
||||||
"rev": "master",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Download type - filelist
|
|
||||||
|
|
||||||
Use a crawler to crawl a web download site that provides a file index and get the latest version of the file name and download it.
|
|
||||||
|
|
||||||
Note that this method is only applicable to static sites with page index functions such as mirror sites and GNU official websites.
|
|
||||||
|
|
||||||
The parameters included are:
|
|
||||||
|
|
||||||
- `url`: The URL of the page to crawl the latest version of the file
|
|
||||||
- `regex`: regular expression matching file names and download links
|
|
||||||
|
|
||||||
Example (download the libiconv library from the GNU official website):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"libiconv": {
|
|
||||||
"type": "filelist",
|
|
||||||
"url": "https://ftp.gnu.org/gnu/libiconv/",
|
|
||||||
"regex": "/href=\"(?<file>libiconv-(?<version>[^\"]+)\\.tar\\.gz)\"/",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "COPYING"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Download type - custom
|
|
||||||
|
|
||||||
If the above downloading methods are not satisfactory, you can write `custom`,
|
|
||||||
create a new class under `src/SPC/store/source/`, extends `CustomSourceBase`, and write the download script yourself.
|
|
||||||
|
|
||||||
I won’t go into details here, you can look at `src/SPC/store/source/PhpSource.php` or `src/SPC/store/source/PostgreSQLSource.php` as examples.
|
|
||||||
|
|
||||||
## pkg.json General parameters
|
|
||||||
|
|
||||||
pkg.json stores non-source-code files, such as precompiled tools musl-toolchain and UPX. It includes:
|
|
||||||
|
|
||||||
- `type`: The same type as `source.json` and different kinds of parameters.
|
|
||||||
- `extract` (optional): The path to decompress after downloading, the default is `pkgroot/{pkg_name}`.
|
|
||||||
- `extract-files` (optional): Extract only the specified files to the specified location after downloading.
|
|
||||||
|
|
||||||
It should be noted that `pkg.json` does not involve compilation, modification and distribution of source code,
|
|
||||||
so there is no `license` open source license field.
|
|
||||||
And you cannot use the `extract` and `extract-files` parameters at the same time.
|
|
||||||
|
|
||||||
Example (download nasm locally and extract only program files to PHP SDK):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nasm-x86_64-win": {
|
|
||||||
"type": "url",
|
|
||||||
"url": "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The key name in `extract-files` is the file in the source folder, and the key value is the storage path. The storage path can use the following variables:
|
|
||||||
|
|
||||||
- `{php_sdk_path}`: (Windows only) PHP SDK path
|
|
||||||
- `{pkg_root_path}`: `pkgroot/`
|
|
||||||
- `{working_dir}`: current working directory
|
|
||||||
- `{download_path}`: download directory
|
|
||||||
- `{source_path}`: source code decompression directory
|
|
||||||
|
|
||||||
When `extract-files` does not use variables and is a relative path, the directory of the relative path is `{working_dir}`.
|
|
||||||
|
|
||||||
## Open source license
|
|
||||||
|
|
||||||
For `source.json`, each source file should contain an open source license.
|
|
||||||
The `license` field stores the open source license information.
|
|
||||||
|
|
||||||
Each `license` contains the following parameters:
|
|
||||||
|
|
||||||
- `type`: `file` or `text`
|
|
||||||
- `path`: the license file in the source code directory (required when `type` is `file`)
|
|
||||||
- `text`: License text (required when `type` is `text`)
|
|
||||||
|
|
||||||
Example (yaml extension source code with LICENSE file):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"yaml": {
|
|
||||||
"type": "git",
|
|
||||||
"path": "php-src/ext/yaml",
|
|
||||||
"rev": "php7",
|
|
||||||
"url": "https://github.com/php/pecl-file_formats-yaml",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
When an open source project has multiple licenses, multiple files can be specified:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"libuv": {
|
|
||||||
"type": "ghtar",
|
|
||||||
"repo": "libuv/libuv",
|
|
||||||
"license": [
|
|
||||||
{
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE-extra"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
When the license of an open source project uses different files between versions,
|
|
||||||
`path` can be used as an array to list the possible license files:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"redis": {
|
|
||||||
"type": "git",
|
|
||||||
"path": "php-src/ext/redis",
|
|
||||||
"rev": "release/6.0.2",
|
|
||||||
"url": "https://github.com/phpredis/phpredis",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": [
|
|
||||||
"LICENSE",
|
|
||||||
"COPYING"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,180 +1,5 @@
|
|||||||
# Introduction to project structure
|
# Project Structure
|
||||||
|
|
||||||
static-php-cli mainly contains three logical components: sources, dependent libraries, and extensions.
|
<!-- TODO: v3 directory layout (bin/, config/pkg/, src/StaticPHP/, src/Package/, etc.).
|
||||||
These components contains 4 configuration files: `source.json`, `pkg.json`, `lib.json`, and `ext.json`.
|
Explain the role of each top-level directory. Internal class structure kept brief;
|
||||||
|
deep dives belong in the Concepts pages. -->
|
||||||
A complete process for building standalone static PHP is:
|
|
||||||
|
|
||||||
1. Use the source download module `Downloader` to download specified or all source codes.
|
|
||||||
These sources include PHP source code, dependent library source code, and extension source code.
|
|
||||||
2. Use the source decompression module `SourceExtractor` to decompress the downloaded sources to the compilation directory.
|
|
||||||
3. Use the dependency tool to calculate the dependent extensions and dependent libraries of the currently added extension,
|
|
||||||
and then compile each library that needs to be compiled in the order of dependencies.
|
|
||||||
4. After building each dependent library using `Builder` under the corresponding operating system, install it to the `buildroot` directory.
|
|
||||||
5. If external extensions are included (the source code does not contain extensions within PHP),
|
|
||||||
copy the external extensions to the `source/php-src/ext/` directory.
|
|
||||||
6. Use `Builder` to build the PHP source code and build target to the `buildroot` directory.
|
|
||||||
|
|
||||||
The project is mainly divided into several folders:
|
|
||||||
|
|
||||||
- `bin/`: used to store program entry files, including `bin/spc`, `bin/spc-alpine-docker`, `bin/setup-runtime`.
|
|
||||||
- `config/`: Contains all the extensions and dependent libraries supported by the project,
|
|
||||||
as well as the download link and download methods of these sources. It is divided into files: `lib.json`, `ext.json`, `source.json`, `pkg.json`, `pre-built.json` .
|
|
||||||
- `src/`: The core code of the project, including the entire framework and commands for compiling various extensions and libraries.
|
|
||||||
- `vendor/`: The directory that Composer depends on, you do not need to make any modifications to it.
|
|
||||||
|
|
||||||
The operating principle is to start a `ConsoleApplication` of `symfony/console`, and then parse the commands entered by the user in the terminal.
|
|
||||||
|
|
||||||
## Basic command line structure
|
|
||||||
|
|
||||||
`bin/spc` is an entry file, including the Unix common `#!/usr/bin/env php`,
|
|
||||||
which is used to allow the system to automatically execute with the PHP interpreter installed on the system.
|
|
||||||
After the project executes `new ConsoleApplication()`, the framework will automatically register them as commands.
|
|
||||||
|
|
||||||
The project does not directly use the Command registration method and command execution method recommended by Symfony. Here are small changes:
|
|
||||||
|
|
||||||
1. Each command uses the `#[AsCommand()]` Attribute to register the name and description.
|
|
||||||
2. Abstract `execute()` so that all commands are based on `BaseCommand` (which is based on `Symfony\Component\Console\Command\Command`),
|
|
||||||
and the execution code of each command itself is written in the `handle()` method .
|
|
||||||
3. Added variable `$no_motd` to `BaseCommand`, which is used to display the Figlet greeting when the command is executed.
|
|
||||||
4. `BaseCommand` saves `InputInterface` and `OutputInterface` as member variables. You can use `$this->input` and `$this->output` within the command class.
|
|
||||||
|
|
||||||
## Basic source code structure
|
|
||||||
|
|
||||||
The source code of the project is located in the `src/SPC` directory,
|
|
||||||
supports automatic loading of the PSR-4 standard, and contains the following subdirectories and classes:
|
|
||||||
|
|
||||||
- `src/SPC/builder/`: The core compilation command code used to build libraries,
|
|
||||||
PHP and related extensions under different operating systems, and also includes some compilation system tool methods.
|
|
||||||
- `src/SPC/command/`: All commands of the project are here.
|
|
||||||
- `src/SPC/doctor/`: Doctor module, which is a relatively independent module used to check the system environment.
|
|
||||||
It can be entered using the command `bin/spc doctor`.
|
|
||||||
- `src/SPC/exception/`: exception class.
|
|
||||||
- `src/SPC/store/`: Classes related to storage, files and sources are all here.
|
|
||||||
- `src/SPC/util/`: Some reusable tool methods are here.
|
|
||||||
- `src/SPC/ConsoleApplication.php`: command line program entry file.
|
|
||||||
|
|
||||||
If you have read the source code, you may find that there is also a `src/globals/` directory,
|
|
||||||
which is used to store some global variables, global methods,
|
|
||||||
and non-PSR-4 standard PHP source code that is relied upon during the build process, such as extension sanity check code etc.
|
|
||||||
|
|
||||||
## Phar application directory issue
|
|
||||||
|
|
||||||
Like other php-cli projects, spc itself has additional considerations for paths.
|
|
||||||
Because spc can run in multiple modes such as `php-cli directly`, `micro SAPI`, `php-cli with Phar`, `vendor with Phar`, etc.,
|
|
||||||
there are ambiguities in various root directories. A complete explanation is given here.
|
|
||||||
This problem is generally common in the base class path selection problem of accessing files in PHP projects, especially when used with `micro.sfx`.
|
|
||||||
|
|
||||||
Note that this may only be useful for you when developing Phar projects or PHP frameworks.
|
|
||||||
|
|
||||||
> Next, we will treat `static-php-cli` (that is, spc) as a normal `php` command line program. You can understand spc as any of your own php-cli applications for reference.
|
|
||||||
|
|
||||||
There are three basic constant theoretical values below. We recommend that you introduce these three constants when writing PHP projects:
|
|
||||||
|
|
||||||
- `WORKING_DIR`: the working directory when executing PHP scripts
|
|
||||||
|
|
||||||
- `SOURCE_ROOT_DIR` or `ROOT_DIR`: the root directory of the project folder, generally the directory where `composer.json` is located
|
|
||||||
|
|
||||||
- `FRAMEWORK_ROOT_DIR`: the root directory of the framework used, which may be used by self-developed frameworks. Generally, the framework directory is read-only
|
|
||||||
|
|
||||||
You can define these constants in your framework entry or cli applications to facilitate the use of paths in your project.
|
|
||||||
|
|
||||||
The following are PHP built-in constant values, which have been defined inside the PHP interpreter:
|
|
||||||
|
|
||||||
- `__DIR__`: the directory where the file of the currently executed script is located
|
|
||||||
|
|
||||||
- `__FILE__`: the file path of the currently executed script
|
|
||||||
|
|
||||||
### Git project mode (source)
|
|
||||||
|
|
||||||
Git project mode refers to a framework or program itself stored in plain text in the current folder, and running through `php path/to/entry.php`.
|
|
||||||
|
|
||||||
Assume that your project is stored in the `/home/example/static-php-cli/` directory, or your project is the framework itself,
|
|
||||||
which contains project files such as `composer.json`:
|
|
||||||
|
|
||||||
```
|
|
||||||
composer.json
|
|
||||||
src/App/MyCommand.app
|
|
||||||
vendor/*
|
|
||||||
bin/entry.php
|
|
||||||
```
|
|
||||||
|
|
||||||
We assume that the above constants are obtained from `src/App/MyCommand.php`:
|
|
||||||
|
|
||||||
| Constant | Value |
|
|
||||||
|----------------------|------------------------------------------------------|
|
|
||||||
| `WORKING_DIR` | `/home/example/static-php-cli` |
|
|
||||||
| `SOURCE_ROOT_DIR` | `/home/example/static-php-cli` |
|
|
||||||
| `FRAMEWORK_ROOT_DIR` | `/home/example/static-php-cli` |
|
|
||||||
| `__DIR__` | `/home/example/static-php-cli/src/App` |
|
|
||||||
| `__FILE__` | `/home/example/static-php-cli/src/App/MyCommand.php` |
|
|
||||||
|
|
||||||
In this case, the values of `WORKING_DIR`, `SOURCE_ROOT_DIR`, and `FRAMEWORK_ROOT_DIR` are exactly the same: `/home/example/static-php-cli`.
|
|
||||||
|
|
||||||
The source code of the framework and the source code of the application are both in the current path.
|
|
||||||
|
|
||||||
### Vendor library mode (vendor)
|
|
||||||
|
|
||||||
The vendor library mode generally means that your project is a framework or is installed into the project as a composer dependency by other applications,
|
|
||||||
and the storage location is in the `vendor/author/XXX` directory.
|
|
||||||
|
|
||||||
Suppose your project is `crazywhalecc/static-php-cli`, and you or others install this project in another project using `composer require`.
|
|
||||||
|
|
||||||
We assume that static-php-cli contains all files except the `vendor` directory with the same `Git mode`, and get the constant value from `src/App/MyCommand`,
|
|
||||||
Directory constant should be:
|
|
||||||
|
|
||||||
| Constant | Value |
|
|
||||||
|----------------------|--------------------------------------------------------------------------------------|
|
|
||||||
| `WORKING_DIR` | `/home/example/another-app` |
|
|
||||||
| `SOURCE_ROOT_DIR` | `/home/example/another-app` |
|
|
||||||
| `FRAMEWORK_ROOT_DIR` | `/home/example/another-app/vendor/crazywhalecc/static-php-cli` |
|
|
||||||
| `__DIR__` | `/home/example/another-app/vendor/crazywhalecc/static-php-cli/src/App` |
|
|
||||||
| `__FILE__` | `/home/example/another-app/vendor/crazywhalecc/static-php-cli/src/App/MyCommand.php` |
|
|
||||||
|
|
||||||
Here `SOURCE_ROOT_DIR` refers to the root directory of the project using `static-php-cli`.
|
|
||||||
|
|
||||||
### Git project Phar mode (source-phar)
|
|
||||||
|
|
||||||
Git project Phar mode refers to the mode of packaging the project directory of the Git project mode into a `phar` file. We assume that `/home/example/static-php-cli` will be packaged into a Phar file, and the directory has the following files:
|
|
||||||
|
|
||||||
```
|
|
||||||
composer.json
|
|
||||||
src/App/MyCommand.app
|
|
||||||
vendor/*
|
|
||||||
bin/entry.php
|
|
||||||
```
|
|
||||||
|
|
||||||
When packaged into `app.phar` and stored in the `/home/example/static-php-cli` directory, `app.phar` is executed at this time. Assuming that the `src/App/MyCommand` code is executed, the constant is obtained in the file:
|
|
||||||
|
|
||||||
| Constant | Value |
|
|
||||||
|----------------------|----------------------------------------------------------------------|
|
|
||||||
| `WORKING_DIR` | `/home/example/static-php-cli` |
|
|
||||||
| `SOURCE_ROOT_DIR` | `phar:///home/example/static-php-cli/app.phar/` |
|
|
||||||
| `FRAMEWORK_ROOT_DIR` | `phar:///home/example/static-php-cli/app.phar/` |
|
|
||||||
| `__DIR__` | `phar:///home/example/static-php-cli/app.phar/src/App` |
|
|
||||||
| `__FILE__` | `phar:///home/example/static-php-cli/app.phar/src/App/MyCommand.php` |
|
|
||||||
|
|
||||||
Because the `phar://` protocol is required to read files in the phar itself, the project root directory and the framework directory will be different from `WORKING_DIR`.
|
|
||||||
|
|
||||||
### Vendor Library Phar Mode (vendor-phar)
|
|
||||||
|
|
||||||
Vendor Library Phar Mode means that your project is installed as a framework in other projects and stored in the `vendor` directory.
|
|
||||||
|
|
||||||
We assume that your project directory structure is as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
composer.json # Composer configuration file of the current project
|
|
||||||
box.json # Configuration file for packaging Phar
|
|
||||||
another-app.php # Entry file of another project
|
|
||||||
vendor/crazywhalecc/static-php-cli/* # Your project is used as a dependent library
|
|
||||||
```
|
|
||||||
|
|
||||||
When packaging these files under the directory `/home/example/another-app/` into `app.phar`, the value of the following constant for your project should be:
|
|
||||||
|
|
||||||
| Constant | Value |
|
|
||||||
|----------------------|------------------------------------------------------------------------------------------------------|
|
|
||||||
| `WORKING_DIR` | `/home/example/another-app` |
|
|
||||||
| `SOURCE_ROOT_DIR` | `phar:///home/example/another-app/app.phar/` |
|
|
||||||
| `FRAMEWORK_ROOT_DIR` | `phar:///home/example/another-app/app.phar/vendor/crazywhalecc/static-php-cli` |
|
|
||||||
| `__DIR__` | `phar:///home/example/another-app/app.phar/vendor/crazywhalecc/static-php-cli/src/App` |
|
|
||||||
| `__FILE__` | `phar:///home/example/another-app/app.phar/vendor/crazywhalecc/static-php-cli/src/App/MyCommand.php` |
|
|
||||||
|
|||||||
@@ -1,242 +1,4 @@
|
|||||||
# Compilation Tools
|
# Compilation Tools
|
||||||
|
|
||||||
static-php-cli uses many system compilation tools when building static PHP. These tools mainly include:
|
<!-- TODO: Migrate and update from v2 system-build-tools.md.
|
||||||
|
Cover v3 additions: WindowsCMakeExecutor, vswhere.exe detection, LLVM/Clang for FrankenPHP. -->
|
||||||
- `autoconf`: used to generate `configure` scripts.
|
|
||||||
- `make`: used to execute `Makefile`.
|
|
||||||
- `cmake`: used to execute `CMakeLists.txt`.
|
|
||||||
- `pkg-config`: Used to find the installation path of dependent libraries.
|
|
||||||
- `gcc`: used to compile C/C++ projects under Linux.
|
|
||||||
- `clang`: used to compile C/C++ projects under macOS.
|
|
||||||
|
|
||||||
For Linux and macOS operating systems,
|
|
||||||
these tools can usually be installed through the package manager, which is written in the doctor module.
|
|
||||||
Theoretically we can also compile and download these tools manually,
|
|
||||||
but this will increase the complexity of compilation, so we do not recommend this.
|
|
||||||
|
|
||||||
## Linux Compilation Tools
|
|
||||||
|
|
||||||
For Linux systems, different distributions have different installation methods for compilation tools.
|
|
||||||
And for static compilation, the package management of some distributions cannot install libraries and tools for pure static compilation.
|
|
||||||
Therefore, for the Linux platform and its different distributions,
|
|
||||||
we currently provide a variety of compilation environment preparations.
|
|
||||||
|
|
||||||
### Glibc Environment
|
|
||||||
|
|
||||||
The glibc environment refers to the underlying `libc` library of the system
|
|
||||||
(that is, the C standard library that all programs written in C language are dynamically linked to) uses `glibc`,
|
|
||||||
which is the default environment for most distributions.
|
|
||||||
For example: Ubuntu, Debian, CentOS, RHEL, openSUSE, Arch Linux, etc.
|
|
||||||
|
|
||||||
In the glibc environment, the package management and compiler we use point to glibc by default,
|
|
||||||
and glibc cannot be statically linked well.
|
|
||||||
One of the reasons it cannot be statically linked is that its network library `nss` cannot be compiled statically.
|
|
||||||
|
|
||||||
For the glibc environment, in static-php-cli and spc in 2.0-RC8 and later, you can choose two ways to build static PHP:
|
|
||||||
|
|
||||||
1. Use Docker to build, you can use `bin/spc-alpine-docker` to build, it will build an Alpine Linux docker image.
|
|
||||||
2. Use `bin/spc doctor --auto-fix` to install the `musl-wrapper` and `musl-cross-make` packages, and then build directly.
|
|
||||||
([Related source code](https://github.com/crazywhalecc/static-php-cli/blob/main/src/SPC/doctor/item/LinuxMuslCheck.php))
|
|
||||||
|
|
||||||
Generally speaking, the build results in these two environments are consistent, and you can choose according to actual needs.
|
|
||||||
|
|
||||||
In the doctor module, static-php-cli will first detect the current Linux distribution.
|
|
||||||
If the current distribution is a glibc environment, you will be prompted to install the musl-wrapper and musl-cross-make packages.
|
|
||||||
|
|
||||||
The process of installing `musl-wrapper` in the glibc environment is as follows:
|
|
||||||
|
|
||||||
1. Download the specific version of [musl-wrapper source code](https://musl.libc.org/releases/) from the musl official website.
|
|
||||||
2. Use `gcc` installed from the package management to compile the musl-wrapper source code and generate `musl-libc` and other libraries: `./configure --disable-gcc-wrapper && make -j && sudo make install`.
|
|
||||||
3. The musl-wrapper related libraries will be installed in the `/usr/local/musl` directory.
|
|
||||||
|
|
||||||
The process of installing `musl-cross-make` in the glibc environment is as follows:
|
|
||||||
|
|
||||||
1. Download the precompiled [musl-cross-make](https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/) compressed package from dl.static-php.dev .
|
|
||||||
2. Unzip to the `/usr/local/musl` directory.
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
In the glibc environment, static compilation can be achieved by directly installing musl-wrapper,
|
|
||||||
but musl-wrapper only contains `musl-gcc` and not `musl-g++`, which means that C++ code cannot be compiled.
|
|
||||||
So we need musl-cross-make to provide `musl-g++`.
|
|
||||||
|
|
||||||
The reason why the musl-cross-make package cannot be compiled directly locally is that
|
|
||||||
its compilation environment requirements are relatively high (requires more than 36GB of memory, compiled under Alpine Linux),
|
|
||||||
so we provide precompiled binary packages that can be used for all Linux distributions.
|
|
||||||
|
|
||||||
At the same time, the package management of some distributions provides musl-wrapper,
|
|
||||||
but musl-cross-make needs to match the corresponding musl-wrapper version,
|
|
||||||
so we do not use package management to install musl-wrapper.
|
|
||||||
|
|
||||||
Compiling musl-cross-make will be introduced in the **musl-cross-make Toolchain Compilation** section of this chapter.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Musl Environment
|
|
||||||
|
|
||||||
The musl environment refers to the system's underlying `libc` library that uses `musl`,
|
|
||||||
which is a lightweight C standard library that can be well statically linked.
|
|
||||||
|
|
||||||
For the currently popular Linux distributions, Alpine Linux uses the musl environment,
|
|
||||||
so static-php-cli can directly build static PHP under Alpine Linux.
|
|
||||||
You only need to install basic compilation tools (such as `gcc`, `cmake`, etc.) directly from the package management.
|
|
||||||
|
|
||||||
For other distributions, if your distribution uses the musl environment,
|
|
||||||
you can also use static-php-cli to build static PHP directly after installing the necessary compilation tools.
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
In the musl environment, static-php-cli will automatically skip the installation of musl-wrapper and musl-cross-make.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Docker Environment
|
|
||||||
|
|
||||||
The Docker environment refers to using Docker containers to build static PHP. You can use `bin/spc-alpine-docker` to build.
|
|
||||||
Before executing this command, you need to install Docker first, and then execute `bin/spc-alpine-docker` in the project root directory.
|
|
||||||
|
|
||||||
After executing `bin/spc-alpine-docker`, static-php-cli will automatically download the Alpine Linux image and then build a `cwcc-spc-x86_64` or `cwcc-spc-aarch64` image.
|
|
||||||
Then all build process is performed within this image, which is equivalent to compiling in Alpine Linux.
|
|
||||||
|
|
||||||
## musl-cross-make Toolchain Compilation
|
|
||||||
|
|
||||||
In Linux, although you do not need to manually compile the musl-cross-make tool,
|
|
||||||
if you want to understand its compilation process, you can refer here.
|
|
||||||
Another important reason is that this may not be compiled using automated tools such as CI and Actions,
|
|
||||||
because the existing CI service compilation environment does not meet the compilation requirements of musl-cross-make,
|
|
||||||
and the configuration that meets the requirements is too expensive.
|
|
||||||
|
|
||||||
The compilation process of musl-cross-make is as follows:
|
|
||||||
|
|
||||||
Prepare an Alpine Linux environment (either directly installed or using Docker).
|
|
||||||
The compilation process requires more than **36GB** of memory,
|
|
||||||
so you need to compile on a machine with larger memory.
|
|
||||||
Without this much memory, compilation may fail.
|
|
||||||
|
|
||||||
Then write the following content into the `config.mak` file:
|
|
||||||
|
|
||||||
```makefile
|
|
||||||
STAT = -static --static
|
|
||||||
FLAG = -g0 -Os -Wno-error
|
|
||||||
|
|
||||||
ifneq ($(NATIVE),)
|
|
||||||
COMMON_CONFIG += CC="$(HOST)-gcc ${STAT}" CXX="$(HOST)-g++ ${STAT}"
|
|
||||||
else
|
|
||||||
COMMON_CONFIG += CC="gcc ${STAT}" CXX="g++ ${STAT}"
|
|
||||||
endif
|
|
||||||
|
|
||||||
COMMON_CONFIG += CFLAGS="${FLAG}" CXXFLAGS="${FLAG}" LDFLAGS="${STAT}"
|
|
||||||
|
|
||||||
BINUTILS_CONFIG += --enable-gold=yes --enable-gprofng=no
|
|
||||||
GCC_CONFIG += --enable-static-pie --disable-cet --enable-default-pie
|
|
||||||
#--enable-default-pie
|
|
||||||
|
|
||||||
CONFIG_SUB_REV = 888c8e3d5f7b
|
|
||||||
GCC_VER = 13.2.0
|
|
||||||
BINUTILS_VER = 2.40
|
|
||||||
MUSL_VER = 1.2.4
|
|
||||||
GMP_VER = 6.2.1
|
|
||||||
MPC_VER = 1.2.1
|
|
||||||
MPFR_VER = 4.2.0
|
|
||||||
LINUX_VER = 6.1.36
|
|
||||||
```
|
|
||||||
|
|
||||||
And also you need to add `gcc-13.2.0.tar.xz.sha1` file, contents here:
|
|
||||||
|
|
||||||
```
|
|
||||||
5f95b6d042fb37d45c6cbebfc91decfbc4fb493c gcc-13.2.0.tar.xz
|
|
||||||
```
|
|
||||||
|
|
||||||
If you are using Docker to build, create a new `Dockerfile` file and write the following content:
|
|
||||||
|
|
||||||
```dockerfile
|
|
||||||
FROM alpine:edge
|
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
gcc g++ git make curl perl \
|
|
||||||
rsync patch wget libtool \
|
|
||||||
texinfo autoconf automake \
|
|
||||||
bison tar xz bzip2 zlib \
|
|
||||||
file binutils flex \
|
|
||||||
linux-headers libintl \
|
|
||||||
gettext gettext-dev icu-libs pkgconf \
|
|
||||||
pkgconfig icu-dev bash \
|
|
||||||
ccache libarchive-tools zip
|
|
||||||
|
|
||||||
WORKDIR /opt
|
|
||||||
|
|
||||||
RUN git clone https://git.zv.io/toolchains/musl-cross-make.git
|
|
||||||
WORKDIR /opt/musl-cross-make
|
|
||||||
COPY config.mak /opt/musl-cross-make
|
|
||||||
COPY gcc-13.2.0.tar.xz.sha1 /opt/musl-cross-make/hashes
|
|
||||||
|
|
||||||
RUN make TARGET=x86_64-linux-musl -j || :
|
|
||||||
RUN sed -i 's/poison calloc/poison/g' ./gcc-13.2.0/gcc/system.h
|
|
||||||
RUN make TARGET=x86_64-linux-musl -j
|
|
||||||
RUN make TARGET=x86_64-linux-musl install -j
|
|
||||||
RUN tar cvzf x86_64-musl-toolchain.tgz output/*
|
|
||||||
```
|
|
||||||
|
|
||||||
If you are using Alpine Linux in a non-Docker environment, you can directly execute the commands in the Dockerfile, for example:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
apk add --no-cache \
|
|
||||||
gcc g++ git make curl perl \
|
|
||||||
rsync patch wget libtool \
|
|
||||||
texinfo autoconf automake \
|
|
||||||
bison tar xz bzip2 zlib \
|
|
||||||
file binutils flex \
|
|
||||||
linux-headers libintl \
|
|
||||||
gettext gettext-dev icu-libs pkgconf \
|
|
||||||
pkgconfig icu-dev bash \
|
|
||||||
ccache libarchive-tools zip
|
|
||||||
|
|
||||||
git clone https://git.zv.io/toolchains/musl-cross-make.git
|
|
||||||
# Copy config.mak to the working directory of musl-cross-make.
|
|
||||||
# You need to replace /path/to/config.mak with your config.mak file path.
|
|
||||||
cp /path/to/config.mak musl-cross-make/
|
|
||||||
cp /path/to/gcc-13.2.0.tar.xz.sha1 musl-cross-make/hashes
|
|
||||||
|
|
||||||
make TARGET=x86_64-linux-musl -j || :
|
|
||||||
sed -i 's/poison calloc/poison/g' ./gcc-13.2.0/gcc/system.h
|
|
||||||
make TARGET=x86_64-linux-musl -j
|
|
||||||
make TARGET=x86_64-linux-musl install -j
|
|
||||||
tar cvzf x86_64-musl-toolchain.tgz output/*
|
|
||||||
```
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
All the above scripts are suitable for x86_64 architecture Linux.
|
|
||||||
If you need to build musl-cross-make for the ARM environment, just replace all `x86_64` above with `aarch64`.
|
|
||||||
:::
|
|
||||||
|
|
||||||
This compilation process may fail due to insufficient memory, network problems, etc.
|
|
||||||
You can try a few more times, or use a machine with larger memory to compile.
|
|
||||||
If you encounter problems or you have better improvement solutions, go to [Discussion](https://github.com/crazywhalecc/static-php-cli-hosted/issues/1).
|
|
||||||
|
|
||||||
## macOS Environment
|
|
||||||
|
|
||||||
For macOS systems, the main compilation tool we use is `clang`,
|
|
||||||
which is the default compiler for macOS systems and is also the compiler of Xcode.
|
|
||||||
|
|
||||||
Compiling under macOS mainly relies on Xcode or Xcode Command Line Tools.
|
|
||||||
You can download Xcode from the App Store,
|
|
||||||
or execute `xcode-select --install` in the terminal to install Xcode Command Line Tools.
|
|
||||||
|
|
||||||
In addition, in the `doctor` environment check module, static-php-cli will check whether Homebrew,
|
|
||||||
compilation tools, etc. are installed on the macOS system.
|
|
||||||
If not, you will be prompted to install them. I will not go into details here.
|
|
||||||
|
|
||||||
## FreeBSD Environment
|
|
||||||
|
|
||||||
FreeBSD is also a Unix system, and its compilation tools are similar to macOS.
|
|
||||||
You can directly use the package management `pkg` to install `clang` and other compilation tools through the `doctor` command.
|
|
||||||
|
|
||||||
## pkg-config Compilation (*nix only)
|
|
||||||
|
|
||||||
If you observe the compilation log when using static-php-cli to build static PHP, you will find that no matter what is compiled,
|
|
||||||
`pkg-config` will be compiled first. This is because `pkg-config` is a library used to find dependencies.
|
|
||||||
In earlier versions of static-php-cli, we directly used the `pkg-config` tool installed by package management,
|
|
||||||
but this would cause some problems, such as:
|
|
||||||
|
|
||||||
- Even if `PKG_CONFIG_PATH` is specified, `pkg-config` will try to find dependent packages from the system path.
|
|
||||||
- Since `pkg-config` will look for dependent packages from the system path,
|
|
||||||
if a dependent package with the same name exists in the system, compilation may fail.
|
|
||||||
|
|
||||||
In order to avoid the above problems, we compile `pkg-config` into `buildroot/bin` in user mode and use it.
|
|
||||||
We use parameters such as `--without-sysroot` to avoid looking for dependent packages from the system path.
|
|
||||||
|
|||||||
6
docs/en/develop/vendor-mode/annotations.md
Normal file
6
docs/en/develop/vendor-mode/annotations.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Annotations Reference
|
||||||
|
|
||||||
|
<!-- TODO: Complete reference for all v3 PHP attributes.
|
||||||
|
#[Library], #[Extension], #[BuildFor], #[BeforeStage], #[AfterStage],
|
||||||
|
#[PatchBeforeBuild], #[CustomPhpConfigureArg], #[AsCheckItem], #[AsFixItem].
|
||||||
|
Per-attribute: parameters, types, allowed targets, example. -->
|
||||||
6
docs/en/develop/vendor-mode/dependency-injection.md
Normal file
6
docs/en/develop/vendor-mode/dependency-injection.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Dependency Injection
|
||||||
|
|
||||||
|
<!-- TODO: How PHP-DI autowiring works in v3.
|
||||||
|
ApplicationContext::get() usage.
|
||||||
|
Registering custom services.
|
||||||
|
Injecting into command classes, build classes, and stage methods. -->
|
||||||
6
docs/en/develop/vendor-mode/index.md
Normal file
6
docs/en/develop/vendor-mode/index.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Vendor Mode
|
||||||
|
|
||||||
|
<!-- TODO: What vendor mode is and when to use it.
|
||||||
|
Installation: `composer require crazywhalecc/static-php-cli`.
|
||||||
|
How to register an external registry pointing to your custom package classes.
|
||||||
|
Minimal working example: one Library class, one config YAML, run spc. -->
|
||||||
6
docs/en/develop/vendor-mode/lifecycle-hooks.md
Normal file
6
docs/en/develop/vendor-mode/lifecycle-hooks.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Lifecycle Hooks
|
||||||
|
|
||||||
|
<!-- TODO: Detailed explanation of hook execution order and method signatures.
|
||||||
|
#[BeforeStage('lib-name', 'build')], #[AfterStage(...)], #[PatchBeforeBuild].
|
||||||
|
How hooks from different packages are merged and ordered.
|
||||||
|
Common patterns: patching config.m4, injecting compile flags, post-install fixups. -->
|
||||||
6
docs/en/develop/vendor-mode/package-classes.md
Normal file
6
docs/en/develop/vendor-mode/package-classes.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Writing Package Classes
|
||||||
|
|
||||||
|
<!-- TODO: Step-by-step guide to writing a Library class and an Extension class.
|
||||||
|
Full annotated code examples using #[Library], #[Extension], #[BuildFor].
|
||||||
|
UnixAutoconfExecutor / UnixCmakeExecutor / WindowsCMakeExecutor usage.
|
||||||
|
File placement (src/Package/Library/, src/Package/Extension/) and autoloading. -->
|
||||||
@@ -1,64 +1,62 @@
|
|||||||
# FAQ
|
# FAQ
|
||||||
|
|
||||||
Here will be some questions that you may encounter easily. There are currently many, but I need to take time to organize them.
|
Here will be some questions that you may encounter easily.
|
||||||
|
|
||||||
## What is the path of php.ini ?
|
## What is the path of php.ini?
|
||||||
|
|
||||||
On Linux, macOS and FreeBSD, the path of `php.ini` is `/usr/local/etc/php/php.ini`.
|
On Linux, macOS and FreeBSD, the path of `php.ini` is `/usr/local/etc/php/php.ini`.
|
||||||
On Windows, the path is `C:\windows\php.ini` or the current directory of `php.exe`.
|
On Windows, the path is `C:\windows\php.ini` or the current directory of `php.exe`.
|
||||||
The directory where to look for `php.ini` can be changed on *nix using the manual build option `--with-config-file-path`.
|
The directory where to look for `php.ini` can be changed on *nix using the build option `--with-config-file-path`.
|
||||||
|
|
||||||
In addition, on Linux, macOS and FreeBSD, `.ini` files present in the `/usr/local/etc/php/conf.d` directory will also be loaded.
|
In addition, on Linux, macOS and FreeBSD, `.ini` files present in the `/usr/local/etc/php/conf.d` directory will also be loaded.
|
||||||
On Windows, this path is empty by default.
|
On Windows, this path is empty by default.
|
||||||
The directory can be changed using the manual build option `--with-config-file-scan-dir`.
|
The directory can be changed using the build option `--with-config-file-scan-dir`.
|
||||||
|
|
||||||
`php.ini` will also be searched for in [the other standard locations](https://www.php.net/manual/configuration.file.php).
|
`php.ini` will also be searched for in [the other standard locations](https://www.php.net/manual/configuration.file.php).
|
||||||
|
|
||||||
## Can statically-compiled PHP install extensions?
|
## Can statically-compiled PHP install extensions?
|
||||||
|
|
||||||
Because the principle of installing PHP extensions under the normal mode is to use `.so` type dynamic link library to install new extensions,
|
Because the principle of installing PHP extensions under the normal mode is to use `.so` type dynamic link library to install new extensions,
|
||||||
and we use the static link PHP compiled by this project. However, static linking has different definitions in different operating systems.
|
and we use the static link PHP compiled by this project. However, static linking has different definitions in different operating systems.
|
||||||
|
|
||||||
First of all, for Linux systems, statically linked binaries will not link the system's dynamic link library.
|
First of all, for Linux systems, statically linked binaries will not link the system's dynamic link library.
|
||||||
Purely statically linked binaries (`build with -all-static`) cannot load dynamic libraries, so new extensions cannot be added.
|
Purely statically linked binaries (`build with -all-static`) cannot load dynamic libraries, so new extensions cannot be added.
|
||||||
At the same time, in pure static mode, you cannot use extensions such as `ffi` to load external `.so` modules.
|
At the same time, in pure static mode, you cannot use extensions such as `ffi` to load external `.so` modules.
|
||||||
|
|
||||||
You can use the command `ldd buildroot/bin/php` to check whether the binary you built under Linux is purely statically linked.
|
You can use the command `ldd buildroot/bin/php` to check whether the binary you built under Linux is purely statically linked.
|
||||||
|
|
||||||
If you [build GNU libc based PHP](../guide/build-with-glibc), you can use the `ffi` extension to load external `.so` modules and load `.so` extensions with the same ABI.
|
If you build GNU libc based PHP, you can use the `ffi` extension to load external `.so` modules and load `.so` extensions with the same ABI.
|
||||||
|
|
||||||
For example, you can use the following command to build a static PHP binary dynamically linked with glibc,
|
For example, you can use the following command to build a static PHP binary dynamically linked with glibc,
|
||||||
supporting FFI extensions and loading the `xdebug.so` extension of the same PHP version and the same TS type:
|
supporting FFI extensions and loading the `xdebug.so` extension of the same PHP version and the same TS type:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bin/spc-gnu-docker download --for-extensions=ffi,xml --with-php=8.4
|
SPC_TARGET=native-native-gnu.2.17 spc build:php "ffi,xml" --build-cli -vvv
|
||||||
bin/spc-gnu-docker build ffi,xml --build-cli --debug
|
|
||||||
|
|
||||||
buildroot/bin/php -d "zend_extension=/path/to/php{PHP_VER}-{ts/nts}/xdebug.so" --ri xdebug
|
buildroot/bin/php -d "zend_extension=/path/to/php{PHP_VER}-{ts/nts}/xdebug.so" --ri xdebug
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This uses the Zig toolchain to produce a partially static binary dynamically linked against glibc 2.17. No Docker and no extra cross-compilation toolchain are required.
|
||||||
|
|
||||||
For macOS platform, almost all binaries under macOS cannot be truly purely statically linked, and almost all binaries will link macOS system libraries: `/usr/lib/libresolv.9.dylib` and `/usr/lib/libSystem.B.dylib`.
|
For macOS platform, almost all binaries under macOS cannot be truly purely statically linked, and almost all binaries will link macOS system libraries: `/usr/lib/libresolv.9.dylib` and `/usr/lib/libSystem.B.dylib`.
|
||||||
So on macOS, you can **directly** use SPC to build statically compiled PHP binaries with dynamically linked extensions:
|
So on macOS, you can **directly** use SPC to build statically compiled PHP binaries with dynamically linked extensions:
|
||||||
|
|
||||||
1. Build shared extension `xxx.so` using: `--build-shared=XXX` option. e.g. `bin/spc build bcmath,zlib --build-shared=xdebug --build-cli`
|
1. Build shared extension `xxx.so` using: `--build-shared=XXX` option. e.g. `spc build:php "bcmath,zlib" --build-shared=xdebug --build-cli`
|
||||||
2. You will get `buildroot/modules/xdebug.so` and `buildroot/bin/php`.
|
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.
|
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,
|
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.
|
php.exe built by static-php cannot load officially built dynamic extensions. Since StaticPHP 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.
|
However, Windows can normally use the `FFI` extension to load other dll files and call them.
|
||||||
|
|
||||||
## Can it support Oracle database extension?
|
## Can it support Oracle database extension?
|
||||||
|
|
||||||
Some extensions that rely on closed source libraries, such as `oci8`, `sourceguardian`, etc.,
|
Some extensions that rely on closed source libraries, such as `oci8`, `sourceguardian`, etc.,
|
||||||
they do not provide purely statically compiled dependent library files (`.a`), only dynamic dependent library files (`.so`).
|
they do not provide purely statically compiled dependent library files (`.a`), only dynamic dependent library files (`.so`).
|
||||||
These extensions cannot be compiled into static-php-cli using source code, so this project may never support these extensions.
|
These extensions cannot be compiled into StaticPHP using source code, so this project may never support these extensions.
|
||||||
However, in theory you can access and use such extensions under macOS and Linux according to the above questions.
|
However, in theory you can access and use such extensions under macOS and Linux according to the above questions.
|
||||||
|
|
||||||
If you have a need for such extensions, or most people have needs for these closed-source extensions,
|
|
||||||
see the discussion on [standalone-php-cli](https://github.com/crazywhalecc/static-php-cli/discussions/58). Welcome to leave a message.
|
|
||||||
|
|
||||||
## Does it support Windows?
|
## Does it support Windows?
|
||||||
|
|
||||||
The project currently supports Windows, but the number of supported extensions is small. Windows support is not perfect. There are mainly the following problems:
|
The project currently supports Windows, but the number of supported extensions is small. Windows support is not perfect. There are mainly the following problems:
|
||||||
@@ -68,26 +66,26 @@ The project currently supports Windows, but the number of supported extensions i
|
|||||||
|
|
||||||
## Can I protect my source code with micro?
|
## Can I protect my source code with micro?
|
||||||
|
|
||||||
You can't. micro.sfx is essentially combining php and php code into one file,
|
You can't. micro.sfx is essentially combining php and php code into one file,
|
||||||
there is no process of compiling or encrypting the PHP code.
|
there is no process of compiling or encrypting the PHP code.
|
||||||
|
|
||||||
First of all, php-src is the official interpreter of PHP code, and there is no PHP compiler compatible with mainstream branches on the market.
|
First of all, php-src is the official interpreter of PHP code, and there is no PHP compiler compatible with mainstream branches on the market.
|
||||||
I saw on the Internet that there is a project called BPC (Binary PHP Compiler?) that can compile PHP into binary,
|
I saw on the Internet that there is a project called BPC (Binary PHP Compiler?) that can compile PHP into binary,
|
||||||
but there are many restrictions.
|
but there are many restrictions.
|
||||||
|
|
||||||
The direction of encrypting and protecting the code is not the same as compiling.
|
The direction of encrypting and protecting the code is not the same as compiling.
|
||||||
After compiling, the code can also be obtained through reverse engineering and other methods.
|
After compiling, the code can also be obtained through reverse engineering and other methods.
|
||||||
The real protection is still carried out by means of packing and encrypting the code.
|
The real protection is still carried out by means of packing and encrypting the code.
|
||||||
|
|
||||||
Therefore, this project (static-php-cli) and related projects (lwmbs, swoole-cli) all provide a convenient compilation tool for php-src source code.
|
Therefore, this project (StaticPHP) and related projects (lwmbs, swoole-cli) all provide a convenient compilation tool for php-src source code.
|
||||||
The phpmicro referenced by this project and related projects is only a package of PHP's sapi interface, not a compilation tool for PHP code.
|
The phpmicro referenced by this project and related projects is only a package of PHP's sapi interface, not a compilation tool for PHP code.
|
||||||
The compiler for PHP code is a completely different project, so the extra cases are not taken into account.
|
The compiler for PHP code is a completely different project, so the extra cases are not taken into account.
|
||||||
If you are interested in encryption, you can consider using existing encryption technologies,
|
If you are interested in encryption, you can consider using existing encryption technologies,
|
||||||
such as Swoole Compiler, Source Guardian, etc.
|
such as Swoole Compiler, Source Guardian, etc.
|
||||||
|
|
||||||
## Unable to use ssl
|
## Unable to use ssl
|
||||||
|
|
||||||
**Update: This issue has been fixed in the latest version of static-php-cli, which now reads the system's certificate file by default. If you still have problems, try the solution below.**
|
**Update: This issue has been fixed in the latest version of StaticPHP, which now reads the system's certificate file by default. If you still have problems, try the solution below.**
|
||||||
|
|
||||||
When using curl, pgsql, etc. to request an HTTPS website or establish an SSL connection, there may be an `error:80000002:system library::No such file or directory` error.
|
When using curl, pgsql, etc. to request an HTTPS website or establish an SSL connection, there may be an `error:80000002:system library::No such file or directory` error.
|
||||||
This error is caused by statically compiled PHP without specifying `openssl.cafile` via `php.ini`.
|
This error is caused by statically compiled PHP without specifying `openssl.cafile` via `php.ini`.
|
||||||
@@ -101,8 +99,9 @@ For the certificate locations of different distros, please refer to [Golang docs
|
|||||||
|
|
||||||
## Why don't we support older versions of PHP?
|
## Why don't we support older versions of PHP?
|
||||||
|
|
||||||
Because older versions of PHP have many problems, such as security issues, performance issues, and functional issues.
|
Because older versions of PHP have many problems, such as security issues, performance issues, and functional issues.
|
||||||
In addition, many older versions of PHP are not compatible with the latest dependency libraries,
|
In addition, many older versions of PHP are not compatible with the latest dependency libraries,
|
||||||
which is one of the reasons why older versions of PHP are not supported.
|
which is one of the reasons why older versions of PHP are not supported.
|
||||||
|
|
||||||
You can use older versions compiled earlier by static-php-cli, such as PHP 8.0, but earlier versions will not be explicitly supported.
|
You can use older versions compiled earlier by StaticPHP, such as PHP 8.0, but earlier versions will not be explicitly supported.
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
# GitHub Action Build
|
|
||||||
|
|
||||||
Action Build refers to compiling directly using GitHub Action.
|
|
||||||
|
|
||||||
If you don't want to compile it yourself, you can download the artifact from the existing Action in this project,
|
|
||||||
or you can download it from a self-hosted server:[Enter](https://dl.static-php.dev/static-php-cli/common/).
|
|
||||||
|
|
||||||
> Self-hosted binaries are also built from Actions: [repo](https://github.com/static-php/static-php-cli-hosted).
|
|
||||||
> The extensions included are: bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,
|
|
||||||
> pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip
|
|
||||||
|
|
||||||
## Build Guide
|
|
||||||
|
|
||||||
Using GitHub Action makes it easy to build a statically compiled PHP and phpmicro,
|
|
||||||
while also defining the extensions to compile.
|
|
||||||
|
|
||||||
1. Fork project.
|
|
||||||
2. Go to the Actions of the project and select `CI`.
|
|
||||||
3. Select `Run workflow`, fill in the PHP version you want to compile, the target type, and the list of static extensions. (comma separated, e.g. `bcmath,curl,mbstring`)
|
|
||||||
4. If you need shared extensions (for example `xdebug`), set `shared-extensions` (comma separated, e.g. `xdebug`).
|
|
||||||
5. If you need FrankenPHP, enable `build-frankenphp` and also enable `enable-zts`.
|
|
||||||
6. After waiting for about a period of time, enter the corresponding task and get `Artifacts`.
|
|
||||||
|
|
||||||
If you enable `debug`, all logs will be output at build time, including compiled logs, for troubleshooting.
|
|
||||||
|
|
||||||
> If you need to build in other environments, you can use [manual build](./manual-build).
|
|
||||||
|
|
||||||
## Extensions
|
|
||||||
|
|
||||||
You can go to [extensions](./extensions) check here to see if all the extensions you need currently support.
|
|
||||||
and then go to [command generator](./cli-generator) select the extension you need to compile, copy the extensions string to `extensions` option.
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
# Build on Windows
|
|
||||||
|
|
||||||
Because the Windows system is an NT kernel, the compilation tools and operating system interfaces
|
|
||||||
used by Unix-like operating systems are almost completely different,
|
|
||||||
so the build process on Windows will be slightly different from that of Unix systems.
|
|
||||||
|
|
||||||
## GitHub Actions Build
|
|
||||||
|
|
||||||
Building the Windows version of static-php from Actions is now supported.
|
|
||||||
Like Linux and macOS, you need to Fork the static-php-cli repository to your GitHub account first,
|
|
||||||
then you can enter [Extension List](./extensions) to select the extension to be compiled,
|
|
||||||
and then go to your own `CI on Windows` select the PHP version, fill in the extension list (comma separated), and click Run.
|
|
||||||
|
|
||||||
If you're going to develop or build locally, please read on.
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
The tools required to build static PHP on Windows are the same as PHP's official Windows build tools.
|
|
||||||
You can read [Official Documentation](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2).
|
|
||||||
|
|
||||||
To sum up, you need the following environment and tools:
|
|
||||||
|
|
||||||
- Windows 10/11 (requires build 17063 or later)
|
|
||||||
- Visual Studio 2019/2022 (recommended 2022)
|
|
||||||
- C++ desktop development for Visual Studio
|
|
||||||
- Git for Windows
|
|
||||||
- [php-sdk-binary-tools](https://github.com/php/php-sdk-binary-tools) (can be installed automatically using doctor)
|
|
||||||
- strawberry-perl (can be installed automatically using doctor)
|
|
||||||
- nasm (can be installed automatically using doctor)
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
The construction of static-php-cli on Windows refers to using MSVC to build PHP and is not based on MinGW, Cygwin, WSL and other environments.
|
|
||||||
|
|
||||||
If you prefer to use WSL, please refer to the chapter on Building on Linux.
|
|
||||||
:::
|
|
||||||
|
|
||||||
After installing Visual Studio and selecting the C++ desktop development workload,
|
|
||||||
you may download about 8GB of compilation tools, and the download speed depends on your network conditions.
|
|
||||||
|
|
||||||
### Install Git
|
|
||||||
|
|
||||||
Git for Windows can be downloaded and installed from [here](https://git-scm.com/download/win) `Standalone Installer 64-bit` version,
|
|
||||||
installed in the default location (`C:\Program Files\Git\`).
|
|
||||||
If you don't want to download and install manually,
|
|
||||||
you can also use Visual Studio Installer and check Git in the **Individual component** tab.
|
|
||||||
|
|
||||||
### Prepare static-php-cli
|
|
||||||
|
|
||||||
Downloading the static-php-cli project is very simple, just use git clone.
|
|
||||||
It is recommended to place the project in `C:\spc-build\` or a similar directory.
|
|
||||||
It is best **not to have spaces in the path**.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
mkdir "C:\spc-build"
|
|
||||||
cd C:\spc-build
|
|
||||||
git clone https://github.com/crazywhalecc/static-php-cli.git
|
|
||||||
cd static-php-cli
|
|
||||||
```
|
|
||||||
|
|
||||||
It is a bit strange that static-php-cli itself requires a PHP environment,
|
|
||||||
but now you can quickly install the PHP environment through a script.
|
|
||||||
Generally, your computer will not have the Windows version of PHP installed,
|
|
||||||
so we recommend that you use `bin/setup-runtime` directly after downloading static-php-cli to install PHP and Composer in the current directory.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# Install PHP and Composer to the ./runtime/ directory
|
|
||||||
bin/setup-runtime
|
|
||||||
|
|
||||||
# After installation, if you need to use PHP and Composer in global commands,
|
|
||||||
# use the following command to add the runtime/ directory to PATH
|
|
||||||
bin/setup-runtime -action add-path
|
|
||||||
|
|
||||||
# Delete the runtime/ directory in PATH
|
|
||||||
bin/setup-runtime -action remove-path
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally, now that you have PHP and Composer installed, you need to install static-php-cli's Composer dependencies:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
composer install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Install other Tools (automatic)
|
|
||||||
|
|
||||||
For `php-sdk-binary-tools`, `strawberry-perl`, and `nasm`,
|
|
||||||
we recommend that you directly use the command `bin/spc doctor` to check and install them.
|
|
||||||
|
|
||||||
If doctor successfully installs automatically, please **skip** the steps below to manually install the above tools.
|
|
||||||
|
|
||||||
But if the automatic installation fails, please refer to the manual installation method below.
|
|
||||||
|
|
||||||
### Install php-sdk-binary-tools (manual)
|
|
||||||
|
|
||||||
```shell
|
|
||||||
cd C:\spc-build\static-php-cli
|
|
||||||
git clone https://github.com/php/php-sdk-binary-tools.git
|
|
||||||
```
|
|
||||||
|
|
||||||
> You can also set the global variable `PHP_SDK_PATH` in Windows settings and
|
|
||||||
> clone the project to the path corresponding to the variable.
|
|
||||||
> Under normal circumstances, you don't need to change it.
|
|
||||||
|
|
||||||
### Install strawberry-perl (manual)
|
|
||||||
|
|
||||||
> If you don't need to compile the openssl extension, you don't need to install perl.
|
|
||||||
|
|
||||||
1. Download the latest version of strawberry-perl from [GitHub](https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/).
|
|
||||||
2. Install to the `C:\spc-build\static-php-cli\pkgroot\perl\` directory.
|
|
||||||
|
|
||||||
> You can download the `-portable` version and extract it directly to the above directory.
|
|
||||||
> The last `perl.exe` should be located at `C:\spc-build\static-php-cli\pkgroot\perl\perl\bin\perl.exe`.
|
|
||||||
|
|
||||||
### Install nasm (manual)
|
|
||||||
|
|
||||||
> If you don't need to compile openssl extension, you don't need to install nasm.
|
|
||||||
|
|
||||||
1. Download the nasm tool (x64) from [official website](https://www.nasm.us/pub/nasm/releasebuilds/).
|
|
||||||
2. Place `nasm.exe` and `ndisasm.exe` in the `C:\spc-build\static-php-cli\php-sdk-binary-tools\bin\` directory.
|
|
||||||
|
|
||||||
## Download required sources
|
|
||||||
|
|
||||||
Same as [Manual build - Download](./manual-build.html#command-download)
|
|
||||||
|
|
||||||
## Build PHP
|
|
||||||
|
|
||||||
Use the build command to start building the static php binary.
|
|
||||||
Before executing the `bin/spc build` command, be sure to use the `download` command to download sources.
|
|
||||||
It is recommended to use `doctor` to check the environment.
|
|
||||||
|
|
||||||
### Build SAPI
|
|
||||||
|
|
||||||
You need to go to [Extension List](./extensions) or [Command Generator](./cli-generator) to select the extension you want to add,
|
|
||||||
and then use the command `bin/spc build` to compile.
|
|
||||||
You need to specify targets, choose from the following parameters (at least one):
|
|
||||||
|
|
||||||
- `--build-cli`: Build a cli sapi (command line interface, which can execute PHP code on the command line)
|
|
||||||
- `--build-micro`: Build a micro sapi (used to build a standalone executable binary containing PHP code)
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# Compile PHP with bcmath,openssl,zlib extensions, the compilation target is cli
|
|
||||||
bin/spc build "bcmath,openssl,zlib" --build-cli
|
|
||||||
|
|
||||||
# Compile PHP with phar,curl,posix,pcntl,tokenizer extensions, compile target is micro and cli
|
|
||||||
bin/spc build "bcmath,openssl,zlib" --build-micro --build-cli
|
|
||||||
```
|
|
||||||
|
|
||||||
::: warning
|
|
||||||
In Windows, it is best to use double quotes to wrap parameters containing commas, such as `"bcmath,openssl,mbstring"`.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Debug
|
|
||||||
|
|
||||||
If you encounter problems during the compilation process, or want to view each executing shell command,
|
|
||||||
you can use `--debug` to enable debug mode and view all terminal logs:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
bin/spc build "openssl" --build-cli --debug
|
|
||||||
```
|
|
||||||
|
|
||||||
### Build Options
|
|
||||||
|
|
||||||
During the compilation process, in some special cases,
|
|
||||||
the compiler and the content of the compilation directory need to be intervened.
|
|
||||||
You can try to use the following commands:
|
|
||||||
|
|
||||||
- `--with-clean`: clean up old make files before compiling PHP
|
|
||||||
- `--enable-zts`: Make compiled PHP thread-safe version (default is NTS version)
|
|
||||||
- `--with-libs=XXX,YYY`: Compile the specified dependent library before compiling PHP, and activate some extension optional functions
|
|
||||||
- `--with-config-file-scan-dir=XXX`: Set the directory to scan for `.ini` files after reading `php.ini` (Check [here](../faq/index.html#what-is-the-path-of-php-ini) for default paths)
|
|
||||||
- `-I xxx=yyy`: Hard compile INI options into PHP before compiling (support multiple options, alias is `--with-hardcoded-ini`)
|
|
||||||
- `--with-micro-fake-cli`: When compiling micro, let micro's `PHP_SAPI` pretend to be `cli` (for compatibility with some programs that check `PHP_SAPI`)
|
|
||||||
- `--disable-opcache-jit`: Disable opcache jit (enabled by default)
|
|
||||||
- `--without-micro-ext-test`: After building micro.sfx, do not test the running results of different extensions in micro.sfx
|
|
||||||
- `--with-suggested-exts`: Add `ext-suggests` as dependencies when compiling
|
|
||||||
- `--with-suggested-libs`: Add `lib-suggests` as dependencies when compiling
|
|
||||||
- `--with-upx-pack`: Use UPX to reduce the size of the binary file after compilation (you need to use `bin/spc install-pkg upx` to install upx first)
|
|
||||||
- `--with-micro-logo=XXX.ico`: Customize the icon of the `exe` executable file after customizing the micro build (in the format of `.ico`)
|
|
||||||
|
|
||||||
Here is a simple example where we preset a larger `memory_limit` and disable the `system` function:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
bin/spc build "bcmath,openssl" --build-cli -I "memory_limit=4G" -I "disable_functions=system"
|
|
||||||
```
|
|
||||||
|
|
||||||
Another example: Customize our hello-world.exe program logo:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
bin/spc build "ffi,bcmath" --build-micro --with-micro-logo=mylogo.ico --debug
|
|
||||||
bin/spc micro:combine hello.php
|
|
||||||
# Then we got `my-app.exe` with custom logo!
|
|
||||||
my-app.exe
|
|
||||||
```
|
|
||||||
|
|
||||||
## Use php.exe
|
|
||||||
|
|
||||||
After php.exe is compiled, it is located in the `buildroot\bin\` directory. You can copy it to any location for use.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
.\php -v
|
|
||||||
```
|
|
||||||
|
|
||||||
## Use micro.sfx
|
|
||||||
|
|
||||||
> phpmicro is a SelF-extracted eXecutable SAPI module,
|
|
||||||
> provided by [phpmicro](https://github.com/dixyes/phpmicro) project.
|
|
||||||
> But this project is using a [fork](https://github.com/static-php/phpmicro) of phpmicro, because we need to add some features to it.
|
|
||||||
> It can put php runtime and your source code together.
|
|
||||||
|
|
||||||
The final compilation result will output a file named `./micro.sfx`,
|
|
||||||
which needs to be used with your PHP source code like `code.php`.
|
|
||||||
This file will be located in the path `buildroot/bin/micro.sfx`.
|
|
||||||
|
|
||||||
Prepare your project source code, which can be a single PHP file or a Phar file, for use.
|
|
||||||
|
|
||||||
> If you want to combine phar files, you must add `phar` extension when compiling!
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# code.php "<?php echo 'Hello world' . PHP_EOL;"
|
|
||||||
bin/spc micro:combine code.php -O my-app.exe
|
|
||||||
# Run it!!! Copy it to another computer!!!
|
|
||||||
./my-app.exe
|
|
||||||
```
|
|
||||||
|
|
||||||
If you package a PHAR file, just replace `code.php` with the phar file path.
|
|
||||||
You can use [box-project/box](https://github.com/box-project/box) to package your CLI project as Phar,
|
|
||||||
It is then combined with phpmicro to produce a standalone executable binary.
|
|
||||||
|
|
||||||
For more details on the `micro:combine` command, refer to [command](./manual-build) on Unix systems.
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
# Build glibc Compatible Linux Binary
|
|
||||||
|
|
||||||
## Why Build glibc Compatible Binary
|
|
||||||
|
|
||||||
Currently, the binaries built by static-php-cli on Linux by default are based on musl-libc (statically linked).
|
|
||||||
musl-libc is a lightweight libc implementation
|
|
||||||
that aims to be compatible with glibc and provides good support for pure static linking.
|
|
||||||
This means that the compiled static PHP executable can be used on almost any Linux distribution without worrying about the versions of libc, libstdc++, etc.
|
|
||||||
|
|
||||||
However, there are some issues with pure static linking of musl-libc binaries on Linux:
|
|
||||||
|
|
||||||
- The `dl()` function in PHP cannot be used to load dynamic libraries and external PHP extensions.
|
|
||||||
- The FFI extension in PHP cannot be used.
|
|
||||||
- In some extreme cases, performance issues may occur. See [musl-libc performance issues](https://github.com/php/php-src/issues/13648).
|
|
||||||
|
|
||||||
Different Linux distributions use different default libc.
|
|
||||||
For example, Alpine Linux uses musl libc, while most Linux distributions use glibc.
|
|
||||||
However, even so, we cannot directly use any distribution using glibc to build portable static binaries because glibc has some issues:
|
|
||||||
|
|
||||||
- Binaries built with gcc and other tools on newer versions of distributions cannot run on older versions of distributions.
|
|
||||||
- glibc is not recommended to be statically linked because some of its features require the support of dynamic libraries.
|
|
||||||
|
|
||||||
However, we can use Docker to solve this problem.
|
|
||||||
The final output is a binary **dynamically linked with glibc** and some necessary libraries,
|
|
||||||
but **statically linked with all other dependencies**.
|
|
||||||
|
|
||||||
1. Use an older version of a Linux distribution (such as CentOS 7.x), which has an older version of glibc but can run on most modern Linux distributions.
|
|
||||||
2. Build the static binary of PHP in this container so that it can run on most modern Linux distributions.
|
|
||||||
|
|
||||||
> Using glibc static binaries can run on most modern Linux distributions but cannot run on musl libc distributions, such as CentOS 6, Alpine Linux, etc.
|
|
||||||
|
|
||||||
## Build glibc Compatible Linux Binary
|
|
||||||
|
|
||||||
The latest version of static-php-cli includes the `bin/spc-gnu-docker` script,
|
|
||||||
which can create a CentOS 7.x (glibc-2.17) Docker container with one click and build a glibc compatible PHP static binary in the container.
|
|
||||||
|
|
||||||
Then, run the following command once.
|
|
||||||
The first run will take a long time because it needs to download the CentOS 7.x image and some build tools.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc-gnu-docker
|
|
||||||
```
|
|
||||||
|
|
||||||
After the image is built, you will see the same command help menu as `bin/spc`, which means the container is ready.
|
|
||||||
|
|
||||||
After the container is ready, you can refer to the [local build](./manual-build) section to build your PHP static binary.
|
|
||||||
Just replace `bin/spc` or `./spc` with `bin/spc-gnu-docker`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc-gnu-docker build bcmath,ctype,openssl,pdo,phar,posix,session,tokenizer,xml,zip --build-cli --debug
|
|
||||||
```
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
In rare cases, glibc-based static PHP may encounter segment faults and other errors, but there are currently few examples.
|
|
||||||
If you encounter any issues, please submit an issue.
|
|
||||||
|
|
||||||
glibc build is an extended feature and is not part of the default static-php support.
|
|
||||||
If you have related issues or requirements, please indicate that you are building based on glibc when submitting an issue.
|
|
||||||
|
|
||||||
If you need to build glibc-based binaries without using Docker,
|
|
||||||
please refer to the `bin/spc-gnu-docker` script to manually create a similar environment.
|
|
||||||
|
|
||||||
Please keep in mind that we only support glibc build with `bin/spc-gnu-docker`. Compilation on RHEL 9 & 10 has been tested and is stable, but if you run into issues, we may choose not to fix them.
|
|
||||||
@@ -2,15 +2,10 @@
|
|||||||
aside: false
|
aside: false
|
||||||
---
|
---
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup>
|
||||||
import CliGenerator from "../../.vitepress/components/CliGenerator.vue";
|
import CliGenerator from "../../.vitepress/components/CliGenerator.vue";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
# CLI Build Command Generator
|
# Build Command Generator
|
||||||
|
|
||||||
::: tip
|
<CliGenerator lang="en" />
|
||||||
The extensions selected below may contain extensions that are not supported by the selected operating system,
|
|
||||||
which may cause compilation to fail. Please check [Supported Extensions](./extensions) first.
|
|
||||||
:::
|
|
||||||
|
|
||||||
<cli-generator lang="en" />
|
|
||||||
|
|||||||
525
docs/en/guide/cli-reference.md
Normal file
525
docs/en/guide/cli-reference.md
Normal file
@@ -0,0 +1,525 @@
|
|||||||
|
---
|
||||||
|
outline: 'deep'
|
||||||
|
---
|
||||||
|
|
||||||
|
# CLI Reference
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
If you installed spc as a pre-built binary, replace every `spc` in this page with `./spc` (or `.\spc.exe` on Windows).
|
||||||
|
|
||||||
|
If you installed from source, use `bin/spc` instead.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## download
|
||||||
|
|
||||||
|
Download source archives and pre-built binaries required for building.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc download [artifacts] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`artifacts` (optional): Specific artifacts to download, comma-separated (e.g. `"php-src,openssl,curl"`).
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Option | Short | Description |
|
||||||
|
|---------------------------------|-------|-------------------------------------------------------|
|
||||||
|
| `--for-extensions=<list>` | `-e` | Download artifacts needed by the given extensions |
|
||||||
|
| `--for-libs=<list>` | `-l` | Download artifacts needed by the given libraries |
|
||||||
|
| `--for-packages=<list>` | | Download artifacts needed by the given packages |
|
||||||
|
| `--without-suggests` | | Skip suggested packages when using `--for-extensions` |
|
||||||
|
| `--clean` | | Delete existing download cache before fetching |
|
||||||
|
| `--with-php=<ver>` | | PHP version in `major.minor` format (default: `8.4`) |
|
||||||
|
| `--prefer-binary` | `-p` | Prefer pre-built binaries over source archives |
|
||||||
|
| `--prefer-source` | | Prefer source archives over pre-built binaries |
|
||||||
|
| `--source-only` | | Only download source artifacts |
|
||||||
|
| `--binary-only` | | Only download binary artifacts |
|
||||||
|
| `--parallel=<n>` | `-P` | Number of parallel downloads (default: `1`) |
|
||||||
|
| `--retry=<n>` | `-R` | Number of retries on failure (default: `0`) |
|
||||||
|
| `--ignore-cache=<list>` | | Force re-download the specified artifacts |
|
||||||
|
| `--no-alt` | | Do not use alternative mirror URLs |
|
||||||
|
| `--no-shallow-clone` | | Do not clone git repositories shallowly |
|
||||||
|
| `--custom-url=<src:url>` | `-U` | Override the download URL for a source |
|
||||||
|
| `--custom-git=<src:branch:url>` | `-G` | Override with a custom git repository |
|
||||||
|
| `--custom-local=<src:path>` | `-L` | Use a local path as a source override |
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Download only what the chosen extensions need
|
||||||
|
spc download --for-extensions="bcmath,openssl,curl" --with-php=8.4
|
||||||
|
|
||||||
|
# Download specific artifacts
|
||||||
|
spc download "php-src,openssl"
|
||||||
|
|
||||||
|
# Speed up with parallelism and retries
|
||||||
|
spc download --for-extensions="bcmath,openssl,curl" --parallel 8 --retry=3
|
||||||
|
|
||||||
|
# Prefer pre-built binaries
|
||||||
|
spc download --for-extensions="bcmath,openssl,curl" --prefer-binary
|
||||||
|
|
||||||
|
# Force re-download the PHP source (e.g. when switching versions)
|
||||||
|
spc download --for-extensions="bcmath,curl" --ignore-cache="php-src" --with-php=8.3
|
||||||
|
|
||||||
|
# Override a download URL
|
||||||
|
spc download --for-extensions="bcmath" --custom-url "php-src:https://downloads.php.net/~user/php-8.5.0alpha1.tar.xz"
|
||||||
|
```
|
||||||
|
|
||||||
|
## build:php {#build-php}
|
||||||
|
|
||||||
|
Build PHP and extensions from source. Alias: `build`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php <extensions> [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`extensions` (required): Comma-separated list of extensions to compile statically (e.g. `"bcmath,openssl,curl"`).
|
||||||
|
|
||||||
|
All `download` options are also available on `build:php` with the `--dl-` prefix (e.g. `--dl-with-php=8.3`, `--dl-parallel=4`). These are passed to the automatic downloader that runs before the build.
|
||||||
|
|
||||||
|
### SAPI Selection {#sapi-selection}
|
||||||
|
|
||||||
|
These flags apply only to the combined `build:php` target. To build a specific SAPI in isolation, use its dedicated command (e.g. `spc build:php-cli`).
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|----------------------|---------------------------------------------------------------|
|
||||||
|
| `--build-cli` | Build the `cli` SAPI (`php` / `php.exe`) |
|
||||||
|
| `--build-fpm` | Build `php-fpm` (Linux and macOS only) |
|
||||||
|
| `--build-cgi` | Build `php-cgi` |
|
||||||
|
| `--build-micro` | Build `micro.sfx` |
|
||||||
|
| `--build-embed` | Build the embed static library (`libphp.a` / `php8embed.lib`) |
|
||||||
|
| `--build-frankenphp` | Build the FrankenPHP binary |
|
||||||
|
|
||||||
|
### Common Build Options {#common-build-options}
|
||||||
|
|
||||||
|
| Option | Short | Description |
|
||||||
|
|--------------------------------------|-------|--------------------------------------------------------------------------------------------------------|
|
||||||
|
| `--no-strip` | | Keep debug symbols; do not strip the binary |
|
||||||
|
| `--with-upx-pack` | | Compress the output binary with UPX (install first with `spc install-pkg upx`; Linux and Windows only) |
|
||||||
|
| `--disable-opcache-jit` | | Disable OPcache JIT |
|
||||||
|
| `--with-config-file-path=<path>` | | Directory where PHP looks for `php.ini` (default: `/usr/local/etc/php`) |
|
||||||
|
| `--with-config-file-scan-dir=<path>` | | Directory PHP scans for additional `.ini` files (default: `/usr/local/etc/php/conf.d`) |
|
||||||
|
| `--with-hardcoded-ini=<k=v>` | `-I` | Bake an INI setting into the binary at compile time (repeatable) |
|
||||||
|
| `--enable-zts` | | Enable thread-safe (ZTS) mode |
|
||||||
|
| `--no-smoke-test` | | Skip the post-build smoke tests |
|
||||||
|
| `--with-suggests` | | Also resolve and install suggested packages |
|
||||||
|
| `--with-packages=<list>` | | Additional packages to install alongside the build |
|
||||||
|
| `--no-download` | | Skip the download step (use existing cached files) |
|
||||||
|
| `--build-shared=<list>` | `-D` | Extensions to compile as shared `.so` / `.dll` instead of static |
|
||||||
|
|
||||||
|
### micro Options {#micro-options}
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|----------------------------|--------------------------------------------------------------------------------------|
|
||||||
|
| `--with-micro-fake-cli` | Make `micro`'s `PHP_SAPI` report `cli` instead of `micro` |
|
||||||
|
| `--without-micro-ext-test` | Disable the post-build extension test for `micro.sfx` |
|
||||||
|
| `--with-micro-logo=<path>` | Embed a custom `.ico` icon into `micro.sfx` (Windows only) |
|
||||||
|
| `--enable-micro-win32` | Build `micro.sfx` as a Win32 GUI application instead of a console app (Windows only) |
|
||||||
|
|
||||||
|
### frankenphp Options {#frankenphp-options}
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------------------------------|---------------------------------------------------|
|
||||||
|
| `--enable-zts` | Required for FrankenPHP; enables thread-safe mode |
|
||||||
|
| `--with-frankenphp-app=<path>` | Embed a directory into the FrankenPHP binary |
|
||||||
|
|
||||||
|
### embed Options {#embed-options}
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|-------------------------|-----------------------------------------------------------------------|
|
||||||
|
| `--build-shared=<list>` | Compile specific extensions as shared libraries (requires embed SAPI) |
|
||||||
|
|
||||||
|
### Download Pass-through Options {#download-options}
|
||||||
|
|
||||||
|
All downloader options are available with the `--dl-` prefix:
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|------------------------------------|--------------------------------------------|
|
||||||
|
| `--dl-with-php=<ver>` | PHP version to download (default: `8.4`) |
|
||||||
|
| `--dl-prefer-binary` | Prefer pre-built binaries for dependencies |
|
||||||
|
| `--dl-parallel=<n>` | Number of parallel downloads |
|
||||||
|
| `--dl-retry=<n>` | Number of retries on failure |
|
||||||
|
| `--dl-custom-url=<src:url>` | Override a source download URL |
|
||||||
|
| `--dl-custom-git=<src:branch:url>` | Override with a custom git repository |
|
||||||
|
|
||||||
|
Downloader options passed to `build:php` are used by the automatic downloader that runs before the build.
|
||||||
|
This allows you to control the download behavior without needing a separate `spc download` command.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,openssl,curl" --build-cli --dl-with-php=8.3 --dl-prefer-binary --dl-parallel=4
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build cli SAPI
|
||||||
|
spc build:php "bcmath,openssl,curl" --build-cli
|
||||||
|
|
||||||
|
# Build cli + micro together
|
||||||
|
spc build:php "bcmath,phar,openssl,curl" --build-cli --build-micro
|
||||||
|
|
||||||
|
# Build with a specific PHP version
|
||||||
|
spc build:php "bcmath,openssl" --build-cli --dl-with-php=8.3
|
||||||
|
|
||||||
|
# Bake INI into the binary
|
||||||
|
spc build:php "bcmath,pcntl" --build-cli -I "memory_limit=4G" -I "disable_functions=system"
|
||||||
|
|
||||||
|
# Keep debug symbols
|
||||||
|
spc build:php "bcmath,openssl" --build-cli --no-strip
|
||||||
|
|
||||||
|
# Build FrankenPHP (ZTS required)
|
||||||
|
spc build:php "bcmath,openssl,curl" --build-frankenphp --enable-zts
|
||||||
|
```
|
||||||
|
|
||||||
|
## build:php-cli, build:php-fpm, build:php-micro, build:php-embed, build:php-cgi, build:frankenphp
|
||||||
|
|
||||||
|
Dedicated single-target build commands. These accept the same options as `build:php` except the SAPI-selection flags (`--build-*`), which are implicit.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php-cli "bcmath,openssl,curl"
|
||||||
|
spc build:php-micro "bcmath,phar,openssl"
|
||||||
|
spc build:php-fpm "bcmath,openssl,curl,pdo_mysql"
|
||||||
|
spc build:php-embed "bcmath,openssl"
|
||||||
|
spc build:frankenphp "bcmath,openssl,curl" --enable-zts
|
||||||
|
```
|
||||||
|
|
||||||
|
## build:libs
|
||||||
|
|
||||||
|
Build one or more library packages from source.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:libs <libraries> [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`libraries` (required): Comma-separated list of library package names to build (e.g. `"openssl,curl,zlib"`).
|
||||||
|
|
||||||
|
All `download` options are available with the `--dl-` prefix.
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Option | Short | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `--with-suggests` | `-L`, `-E` | Also resolve and install suggested packages |
|
||||||
|
| `--with-packages=<list>` | | Additional packages to install alongside the build, comma-separated |
|
||||||
|
| `--no-download` | | Skip downloading artifacts (use existing cached files) |
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build a single library
|
||||||
|
spc build:libs openssl
|
||||||
|
|
||||||
|
# Build multiple libraries
|
||||||
|
spc build:libs "openssl,curl,zlib"
|
||||||
|
|
||||||
|
# Build with suggested packages included
|
||||||
|
spc build:libs openssl --with-suggests
|
||||||
|
|
||||||
|
# Skip the download step
|
||||||
|
spc build:libs openssl --no-download
|
||||||
|
```
|
||||||
|
|
||||||
|
## craft
|
||||||
|
|
||||||
|
Read a `craft.yml` and run the full build pipeline automatically.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc craft [path/to/craft.yml]
|
||||||
|
```
|
||||||
|
|
||||||
|
If no path is given, `craft.yml` in the current working directory is used. See [craft.yml configuration](../develop/craft-yml) for the file format.
|
||||||
|
|
||||||
|
## doctor
|
||||||
|
|
||||||
|
Diagnose whether the current environment can compile PHP normally.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc doctor [--auto-fix[=never]]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------------------|--------------------------------------------------------------------|
|
||||||
|
| `--auto-fix` | Automatically fix detected issues using the system package manager |
|
||||||
|
| `--auto-fix=never` | Report issues but never attempt automatic fixes |
|
||||||
|
|
||||||
|
## dev:shell
|
||||||
|
|
||||||
|
Enter an interactive shell with StaticPHP's build environment pre-loaded (compiler wrappers, `buildroot/`, `pkgroot/` paths, etc. on `PATH`).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc dev:shell
|
||||||
|
```
|
||||||
|
|
||||||
|
Useful for compiling small programs against `libphp.a` (embed SAPI) or inspecting the build environment manually.
|
||||||
|
|
||||||
|
## check-update
|
||||||
|
|
||||||
|
Check whether newer versions are available for downloaded artifacts.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc check-update [artifact] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`artifact` (optional): Artifact names to check, comma-separated. Defaults to all currently downloaded artifacts.
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Option | Short | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `--json` | | Output results in JSON format |
|
||||||
|
| `--bare` | | Check without requiring the artifact to be downloaded first (old version will be `null`) |
|
||||||
|
| `--parallel=<n>` | `-p` | Number of parallel update checks (default: `10`) |
|
||||||
|
| `--with-php=<ver>` | | PHP version context in `major.minor` format (default: `8.4`) |
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check all downloaded artifacts
|
||||||
|
spc check-update
|
||||||
|
|
||||||
|
# Check specific artifacts
|
||||||
|
spc check-update "openssl,curl"
|
||||||
|
|
||||||
|
# Output as JSON
|
||||||
|
spc check-update --json
|
||||||
|
|
||||||
|
# Check without requiring a prior download
|
||||||
|
spc check-update "openssl" --bare
|
||||||
|
```
|
||||||
|
|
||||||
|
## dump-extensions
|
||||||
|
|
||||||
|
Analyse a Composer project and output the list of PHP extensions it requires.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc dump-extensions [path] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`path` (optional): Path to the project root (default: `.`).
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Option | Short | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `--format=<fmt>` | `-F` | Output format (default: `default`) |
|
||||||
|
| `--no-ext-output=<list>` | `-N` | When no extensions are found, output this default comma-separated list instead of exiting with failure |
|
||||||
|
| `--no-dev` | | Exclude dev dependencies |
|
||||||
|
| `--no-spc-filter` | `-S` | Do not apply the SPC filter when determining required extensions |
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Analyse the current directory
|
||||||
|
spc dump-extensions
|
||||||
|
|
||||||
|
# Analyse a specific directory
|
||||||
|
spc dump-extensions /path/to/project
|
||||||
|
|
||||||
|
# Exclude dev dependencies
|
||||||
|
spc dump-extensions --no-dev
|
||||||
|
|
||||||
|
# Fall back to a default list when no extensions are found
|
||||||
|
spc dump-extensions --no-ext-output="bcmath,openssl"
|
||||||
|
```
|
||||||
|
|
||||||
|
## dump-license
|
||||||
|
|
||||||
|
Export open-source license files for artifacts.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc dump-license [artifacts] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`artifacts` (optional): Specific artifacts whose licenses should be dumped, comma-separated (e.g. `"php-src,openssl,curl"`).
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Option | Short | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `--for-extensions=<list>` | `-e` | Dump by extension names (automatically includes `php-src`), e.g. `"openssl,mbstring"` |
|
||||||
|
| `--for-libs=<list>` | `-l` | Dump by library names, e.g. `"openssl,zlib"` |
|
||||||
|
| `--for-packages=<list>` | `-p` | Dump by package names, e.g. `"php,libssl"` |
|
||||||
|
| `--dump-dir=<path>` | `-d` | Directory to write license files (default: `buildroot/license`) |
|
||||||
|
| `--without-suggests` | | Do not include licenses for suggested packages |
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Dump licenses for the extensions you compiled
|
||||||
|
spc dump-license --for-extensions="bcmath,openssl,curl"
|
||||||
|
|
||||||
|
# Dump licenses for specific artifacts
|
||||||
|
spc dump-license "php-src,openssl"
|
||||||
|
|
||||||
|
# Write licenses to a custom directory
|
||||||
|
spc dump-license --for-extensions="bcmath,openssl" --dump-dir=/tmp/licenses
|
||||||
|
```
|
||||||
|
|
||||||
|
## extract
|
||||||
|
|
||||||
|
Extract downloaded artifacts to their target locations in the source tree.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc extract [artifacts] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`artifacts` (optional): Specific artifacts to extract, comma-separated (e.g. `"php-src,openssl,curl"`).
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Option | Short | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `--for-extensions=<list>` | `-e` | Extract artifacts needed by the given extensions, e.g. `"openssl,mbstring"` |
|
||||||
|
| `--for-libs=<list>` | `-l` | Extract artifacts needed by the given libraries, e.g. `"libcares,openssl"` |
|
||||||
|
| `--for-packages=<list>` | | Extract artifacts needed by the given packages, e.g. `"php,libssl,libcurl"` |
|
||||||
|
| `--without-suggests` | | Skip suggested packages when using `--for-extensions` |
|
||||||
|
| `--source-only` | | Force extraction from source even if a pre-built binary is available |
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Extract artifacts for a set of extensions
|
||||||
|
spc extract --for-extensions="bcmath,openssl,curl"
|
||||||
|
|
||||||
|
# Extract specific artifacts
|
||||||
|
spc extract "php-src,openssl"
|
||||||
|
|
||||||
|
# Force source extraction
|
||||||
|
spc extract --for-extensions="bcmath,openssl" --source-only
|
||||||
|
```
|
||||||
|
|
||||||
|
## install-pkg
|
||||||
|
|
||||||
|
Install additional helper packages (e.g. UPX, toolchains). Aliases: `i`, `install-package`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc install-pkg <package> [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`package` (required): The name of the package to install.
|
||||||
|
|
||||||
|
All `download` options are available with the `--dl-` prefix.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install the UPX compressor
|
||||||
|
spc install-pkg upx
|
||||||
|
```
|
||||||
|
|
||||||
|
## micro:combine
|
||||||
|
|
||||||
|
Merge `micro.sfx` with a PHP or PHAR file to produce a standalone executable.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc micro:combine <file> [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`file` (required): Path to the PHP or PHAR file to combine.
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Option | Short | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `--with-micro=<path>` | `-M` | Path to a custom `micro.sfx` (default: `buildroot/bin/micro.sfx`) |
|
||||||
|
| `--with-ini-set=<k=v>` | `-I` | Inject an INI setting into the binary (repeatable) |
|
||||||
|
| `--with-ini-file=<path>` | `-N` | Inject INI settings from a file |
|
||||||
|
| `--output=<name>` | `-O` | Output file name (default: `my-app`) |
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Combine a PHP script
|
||||||
|
spc micro:combine app.php
|
||||||
|
|
||||||
|
# Combine a PHAR with a custom output name
|
||||||
|
spc micro:combine app.phar --output my-app
|
||||||
|
|
||||||
|
# Inject INI settings
|
||||||
|
spc micro:combine app.php -I "memory_limit=512M" -I "disable_functions=system"
|
||||||
|
|
||||||
|
# Inject from an INI file
|
||||||
|
spc micro:combine app.php --with-ini-file=custom.ini
|
||||||
|
|
||||||
|
# Use a custom micro.sfx
|
||||||
|
spc micro:combine app.php --with-micro=/path/to/micro.sfx
|
||||||
|
```
|
||||||
|
|
||||||
|
## reset
|
||||||
|
|
||||||
|
Clean build directories and reset the build environment.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc reset [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, removes `buildroot/` and `source/`.
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Option | Short | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `--with-pkgroot` | | Also remove the `pkgroot/` directory |
|
||||||
|
| `--with-download` | | Also remove the `downloads/` directory |
|
||||||
|
| `--yes` | `-y` | Skip the confirmation prompt |
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clean build directories (will prompt for confirmation)
|
||||||
|
spc reset
|
||||||
|
|
||||||
|
# Also clear the download cache
|
||||||
|
spc reset --with-download
|
||||||
|
|
||||||
|
# Full clean without prompting
|
||||||
|
spc reset --with-pkgroot --with-download --yes
|
||||||
|
```
|
||||||
|
|
||||||
|
## spc-config
|
||||||
|
|
||||||
|
Output compiler and linker flags needed to link your own program against the PHP embed static library.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc spc-config [extensions] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`extensions` (optional): Comma-separated list of extensions to include.
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Option | Short | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `--with-libs=<list>` | | Additional libraries to include, comma-separated |
|
||||||
|
| `--with-packages=<list>` | `-p` | Additional packages to include, comma-separated |
|
||||||
|
| `--with-suggested-libs` | `-L` | Include suggested libraries |
|
||||||
|
| `--with-suggests` | | Include all suggested packages |
|
||||||
|
| `--with-suggested-exts` | `-E` | Include suggested extensions |
|
||||||
|
| `--includes` | | Output only `-I` include paths (`CFLAGS`) |
|
||||||
|
| `--libs` | | Output only `-L` and `-l` linker flags (`LDFLAGS` + `LIBS`) |
|
||||||
|
| `--libs-only-deps` | | Output only `-l` dependency flags |
|
||||||
|
| `--absolute-libs` | | Use absolute paths for library files |
|
||||||
|
| `--no-php` | | Do not link against the PHP library |
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Output full compiler + linker flags
|
||||||
|
spc spc-config "bcmath,openssl,curl"
|
||||||
|
|
||||||
|
# Output include paths only
|
||||||
|
spc spc-config "bcmath,openssl" --includes
|
||||||
|
|
||||||
|
# Output linker flags only
|
||||||
|
spc spc-config "bcmath,openssl" --libs
|
||||||
|
|
||||||
|
# Use absolute library paths
|
||||||
|
spc spc-config "bcmath,openssl" --libs --absolute-libs
|
||||||
|
```
|
||||||
|
Enter an interactive shell with StaticPHP's build environment pre-loaded (compiler wrappers, `buildroot/`, `pkgroot/` paths, etc. on `PATH`).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc dev:shell
|
||||||
|
```
|
||||||
|
|
||||||
|
Useful for compiling small programs against `libphp.a` (embed SAPI) or inspecting the build environment manually.
|
||||||
@@ -1,26 +1,19 @@
|
|||||||
---
|
---
|
||||||
outline: 'deep'
|
aside: false
|
||||||
---
|
---
|
||||||
|
|
||||||
# Dependency Table
|
# Dependency Map
|
||||||
|
|
||||||
When compiling PHP, each extension and library has dependencies, which may be required or optional.
|
This page lists all supported packages (extensions and libraries) together with their dependency relationships.
|
||||||
You can choose whether to include these optional dependencies.
|
|
||||||
|
|
||||||
For example, when compiling the `gd` extension under Linux,
|
- **Required Dependencies**: packages that are always built alongside the selected package.
|
||||||
the `zlib,libpng` libraries and the `zlib` extension are forced to be compiled,
|
- **Suggested Dependencies**: packages that are not built by default; enable them with `--with-suggests` or by specifying them manually.
|
||||||
while the `libavif,libwebp,libjpeg,freetype` libraries are optional libraries and will not be compiled by default
|
- **Required By / Suggested By**: which other packages need or suggest this package.
|
||||||
unless specified by the `--with-libs=avif,webp,jpeg,freetype` option.
|
|
||||||
|
|
||||||
- For optional extensions (optional features of extensions), you need to specify them manually at compile time, for example, to enable igbinary support for Redis: `bin/spc build redis,igbinary`.
|
Run the following command to generate the dependency data (source mode required):
|
||||||
- For optional libraries, you need to compile and specify them through the `--with-libs=XXX` option.
|
|
||||||
- If you want to enable all optional extensions, you can use `bin/spc build redis --with-suggested-exts`.
|
|
||||||
- If you want to enable all optional libraries, you can use `--with-suggested-libs`.
|
|
||||||
|
|
||||||
## Extension Dependency Table
|
```bash
|
||||||
|
bin/spc dev:gen-deps-data
|
||||||
|
```
|
||||||
|
|
||||||
<!--@include: ../../deps-map-ext.md-->
|
<DepsMap />
|
||||||
|
|
||||||
## Library Dependency Table
|
|
||||||
|
|
||||||
<!--@include: ../../deps-map-lib.md-->
|
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
# Environment variables
|
# Environment Variables
|
||||||
|
|
||||||
All environment variables mentioned in the list on this page have default values unless otherwise noted.
|
All environment variables mentioned in the list on this page have default values unless otherwise noted.
|
||||||
You can override the default values by setting these environment variables.
|
You can override the default values by setting these environment variables.
|
||||||
|
|
||||||
## Environment variables list
|
## Environment variables list
|
||||||
|
|
||||||
Starting from version 2.3.5, we have centralized the environment variables in the `config/env.ini` file.
|
StaticPHP centralizes environment variables in the `config/env.ini` file.
|
||||||
You can set environment variables by modifying this file.
|
You can set environment variables by modifying this file.
|
||||||
|
|
||||||
We divide the environment variables supported by static-php-cli into three types:
|
We divide the environment variables supported by StaticPHP into three types:
|
||||||
|
|
||||||
- Global internal environment variables: declared after static-php-cli starts, you can use `getenv()` to get them internally in static-php-cli, and you can override them before starting static-php-cli.
|
- **Global internal environment variables**: declared after StaticPHP starts, you can use `getenv()` to get them internally in StaticPHP, and you can override them before starting StaticPHP.
|
||||||
- Fixed environment variables: declared after static-php-cli starts, you can only use `getenv()` to get them, but you cannot override them through shell scripts.
|
- **Fixed environment variables**: declared after StaticPHP starts, you can only use `getenv()` to get them, but you cannot override them through shell scripts.
|
||||||
- Config file environment variables: declared before static-php-cli build, you can set these environment variables by modifying the `config/env.ini` file or through shell scripts.
|
- **Config file environment variables**: declared before StaticPHP builds, you can set these environment variables by modifying the `config/env.ini` file or through shell scripts.
|
||||||
|
|
||||||
You can read the comments for each parameter in [config/env.ini](https://github.com/crazywhalecc/static-php-cli/blob/main/config/env.ini) to understand its purpose.
|
You can read the comments for each parameter in [config/env.ini](https://github.com/crazywhalecc/static-php-cli/blob/v3/config/env.ini) to understand its purpose.
|
||||||
|
|
||||||
## Custom environment variables
|
## Custom environment variables
|
||||||
|
|
||||||
Generally, you don't need to modify any of the following environment variables as they are already set to optimal values.
|
Generally, you don't need to modify any of the following environment variables as they are already set to optimal values.
|
||||||
However, if you have special needs, you can set these environment variables to meet your needs
|
However, if you have special needs, you can set these environment variables to meet your needs
|
||||||
(for example, you need to debug PHP performance under different compilation parameters).
|
(for example, you need to debug PHP performance under different compilation parameters).
|
||||||
|
|
||||||
If you want to use custom environment variables, you can use the `export` command in the terminal or set the environment variables directly before the command, for example:
|
If you want to use custom environment variables, you can use the `export` command in the terminal or set the environment variables directly before the command, for example:
|
||||||
@@ -27,25 +27,25 @@ If you want to use custom environment variables, you can use the `export` comman
|
|||||||
```shell
|
```shell
|
||||||
# export first
|
# export first
|
||||||
export SPC_CONCURRENCY=4
|
export SPC_CONCURRENCY=4
|
||||||
bin/spc build mbstring,pcntl --build-cli
|
spc build:php "mbstring,pcntl" --build-cli
|
||||||
|
|
||||||
# or direct use
|
# or direct use
|
||||||
SPC_CONCURRENCY=4 bin/spc build mbstring,pcntl --build-cli
|
SPC_CONCURRENCY=4 spc build:php "mbstring,pcntl" --build-cli
|
||||||
```
|
```
|
||||||
|
|
||||||
Or, if you need to modify an environment variable for a long time, you can modify the `config/env.ini` file.
|
Or, if you need to modify an environment variable for a long time, you can modify the `config/env.ini` file.
|
||||||
|
|
||||||
`config/env.ini` is divided into three sections, `[global]` is globally effective, `[windows]`, `[macos]`, `[linux]` are only effective for the corresponding operating system.
|
`config/env.ini` is divided into three sections: `[global]` is globally effective, `[windows]`, `[macos]`, `[linux]` are only effective for the corresponding operating system.
|
||||||
|
|
||||||
For example, if you need to modify the `./configure` command for compiling PHP, you can find the `SPC_CMD_PREFIX_PHP_CONFIGURE` environment variable in the `config/env.ini` file, and then modify its value.
|
For example, if you need to modify the `./configure` command for compiling PHP, you can find the `SPC_CMD_PREFIX_PHP_CONFIGURE` environment variable in the `config/env.ini` file, and then modify its value.
|
||||||
|
|
||||||
If your build conditions are more complex and require multiple `env.ini` files to switch,
|
If your build conditions are more complex and require multiple `env.ini` files to switch,
|
||||||
we recommend that you use the `config/env.custom.ini` file.
|
we recommend that you use the `config/env.custom.ini` file.
|
||||||
In this way, you can specify your environment variables by writing additional override items
|
In this way, you can specify your environment variables by writing additional override items
|
||||||
without modifying the default `config/env.ini` file.
|
without modifying the default `config/env.ini` file.
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
; This is an example of `config/env.custom.ini` file,
|
; This is an example of `config/env.custom.ini` file,
|
||||||
; we modify the `SPC_CONCURRENCY` and linux default CFLAGS passing to libs and PHP
|
; we modify the `SPC_CONCURRENCY` and linux default CFLAGS passing to libs and PHP
|
||||||
[global]
|
[global]
|
||||||
SPC_CONCURRENCY=4
|
SPC_CONCURRENCY=4
|
||||||
@@ -54,68 +54,3 @@ SPC_CONCURRENCY=4
|
|||||||
SPC_DEFAULT_C_FLAGS="-O3"
|
SPC_DEFAULT_C_FLAGS="-O3"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Library environment variables (Unix only)
|
|
||||||
|
|
||||||
Starting from 2.2.0, static-php-cli supports custom environment variables for all compilation dependent library commands of macOS, Linux, FreeBSD and other Unix systems.
|
|
||||||
|
|
||||||
In this way, you can adjust the behavior of compiling dependent libraries through environment variables at any time.
|
|
||||||
For example, you can set the optimization parameters for compiling the xxx library through `xxx_CFLAGS=-O0`.
|
|
||||||
|
|
||||||
Of course, not every library supports the injection of environment variables.
|
|
||||||
We currently provide three wildcard environment variables with the suffixes:
|
|
||||||
|
|
||||||
- `_CFLAGS`: CFLAGS for the compiler
|
|
||||||
- `_LDFLAGS`: LDFLAGS for the linker
|
|
||||||
- `_LIBS`: LIBS for the linker
|
|
||||||
|
|
||||||
The prefix is the name of the dependent library, and the specific name of the library is subject to `lib.json`.
|
|
||||||
Among them, the library name with `-` needs to replace `-` with `_`.
|
|
||||||
|
|
||||||
Here is an example of an optimization option that replaces the openssl library compilation:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
openssl_CFLAGS="-O0"
|
|
||||||
```
|
|
||||||
|
|
||||||
The library name uses the same name listed in `lib.json` and is case-sensitive.
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
When no relevant environment variables are specified, except for the following variables, the remaining values are empty by default:
|
|
||||||
|
|
||||||
| var name | var default value |
|
|
||||||
|-----------------------|-------------------------------------------------------------------------------------------------|
|
|
||||||
| `pkg_config_CFLAGS` | macOS: `$SPC_DEFAULT_C_FLAGS -Wimplicit-function-declaration -Wno-int-conversion`, Other: empty |
|
|
||||||
| `pkg_config_LDFLAGS` | Linux: `--static`, Other: empty |
|
|
||||||
| `imagemagick_LDFLAGS` | Linux: `-static`, Other: empty |
|
|
||||||
| `imagemagick_LIBS` | macOS: `-liconv`, Other: empty |
|
|
||||||
| `ldap_LDFLAGS` | `-L$BUILD_LIB_PATH` |
|
|
||||||
| `openssl_CFLAGS` | Linux: `$SPC_DEFAULT_C_FLAGS`, Other: empty |
|
|
||||||
| others... | empty |
|
|
||||||
:::
|
|
||||||
|
|
||||||
The following table is a list of library names that support customizing the above three variables:
|
|
||||||
|
|
||||||
| lib name |
|
|
||||||
|-------------|
|
|
||||||
| brotli |
|
|
||||||
| bzip |
|
|
||||||
| curl |
|
|
||||||
| freetype |
|
|
||||||
| gettext |
|
|
||||||
| gmp |
|
|
||||||
| imagemagick |
|
|
||||||
| ldap |
|
|
||||||
| libargon2 |
|
|
||||||
| libavif |
|
|
||||||
| libcares |
|
|
||||||
| libevent |
|
|
||||||
| openssl |
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
Because adapting custom environment variables to each library is a particularly tedious task,
|
|
||||||
and in most cases you do not need custom environment variables for these libraries,
|
|
||||||
so we currently only support custom environment variables for some libraries.
|
|
||||||
|
|
||||||
If the library you need to customize environment variables is not listed above,
|
|
||||||
you can submit your request through [GitHub Issue](https://github.com/crazywhalecc/static-php-cli/issues).
|
|
||||||
:::
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Extension Notes
|
# Extension Notes
|
||||||
|
|
||||||
Because it is a static compilation, extensions will not compile 100% perfectly,
|
Because it is a static compilation, extensions will not compile 100% perfectly,
|
||||||
and different extensions have different requirements for PHP and the environment,
|
and different extensions have different requirements for PHP and the environment,
|
||||||
which will be listed one by one here.
|
which will be listed one by one here.
|
||||||
|
|
||||||
## curl
|
## curl
|
||||||
@@ -9,7 +9,7 @@ which will be listed one by one here.
|
|||||||
HTTP3 support is not enabled by default, compile with `--with-libs="nghttp2,nghttp3,ngtcp2"` to enable HTTP3 support for PHP >= 8.4.
|
HTTP3 support is not enabled by default, compile with `--with-libs="nghttp2,nghttp3,ngtcp2"` to enable HTTP3 support for PHP >= 8.4.
|
||||||
|
|
||||||
When using curl to request HTTPS, there may be an `error:80000002:system library::No such file or directory` error.
|
When using curl to request HTTPS, there may be an `error:80000002:system library::No such file or directory` error.
|
||||||
For details on the solution, see [FAQ - Unable to use ssl](../faq/#unable-to-use-ssl).
|
For details on the solution, see [FAQ](../faq/).
|
||||||
|
|
||||||
## phpmicro
|
## phpmicro
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ For details on the solution, see [FAQ - Unable to use ssl](../faq/#unable-to-use
|
|||||||
|
|
||||||
1. swoole >= 5.0 Only PHP >= 8.0 is supported.
|
1. swoole >= 5.0 Only PHP >= 8.0 is supported.
|
||||||
2. swoole Currently, curl hooks are not supported for PHP 8.0.x (which may be fixed in the future).
|
2. swoole Currently, curl hooks are not supported for PHP 8.0.x (which may be fixed in the future).
|
||||||
3. When compiling, if only `swoole` extension is included, the supported Swoole database coroutine hook will not be fully enabled.
|
3. When compiling, if only `swoole` extension is included, the supported Swoole database coroutine hook will not be fully enabled.
|
||||||
If you need to use it, please add the corresponding `swoole-hook-xxx` extension.
|
If you need to use it, please add the corresponding `swoole-hook-xxx` extension.
|
||||||
4. The `zend_mm_heap corrupted` problem may occur in swoole under some extension combinations. The cause has not yet been found.
|
4. The `zend_mm_heap corrupted` problem may occur in swoole under some extension combinations. The cause has not yet been found.
|
||||||
|
|
||||||
@@ -70,9 +70,9 @@ This extension contains an implementation of the coroutine environment for `pdo_
|
|||||||
|
|
||||||
## gd
|
## gd
|
||||||
|
|
||||||
1. gd Extension relies on more additional Graphics library. By default,
|
1. gd Extension relies on more additional Graphics library. By default,
|
||||||
using `bin/spc build gd` directly will not support some Graphics library, such as `libjpeg`, `libavif`, etc.
|
using `bin/spc build gd` directly will not support some Graphics library, such as `libjpeg`, `libavif`, etc.
|
||||||
Currently, it supports four libraries: `freetype,libjpeg,libavif,libwebp`.
|
Currently, it supports four libraries: `freetype,libjpeg,libavif,libwebp`.
|
||||||
Therefore, the following command can be used to introduce them into the gd library:
|
Therefore, the following command can be used to introduce them into the gd library:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -85,19 +85,19 @@ bin/spc build gd --with-libs=freetype,libjpeg,libavif,libwebp --build-cli
|
|||||||
|
|
||||||
## oci8
|
## oci8
|
||||||
|
|
||||||
1. oci8 is an extension of the Oracle database, because the library on which the extension provided by Oracle does not provide a statically compiled version (`.a`) or source code,
|
1. oci8 is an extension of the Oracle database, because the library on which the extension provided by Oracle does not provide a statically compiled version (`.a`) or source code,
|
||||||
and this extension cannot be compiled into php by static linking, so it cannot be supported.
|
and this extension cannot be compiled into php by static linking, so it cannot be supported.
|
||||||
|
|
||||||
## xdebug
|
## xdebug
|
||||||
|
|
||||||
1. Xdebug is only buildable as a shared extension. On Linux, you'll need to use a SPC_TARGET like `native-native -dynamic` or `native-native-gnu`.
|
1. Xdebug is only buildable as a shared extension. On Linux, you'll need to use a `SPC_TARGET` with a glibc variant (e.g. `native-native-gnu.2.17`) instead of the default musl static target.
|
||||||
2. When using Linux/glibc or macOS, you can compile Xdebug as a shared extension using --build-shared="xdebug".
|
2. When using Linux/glibc or macOS, you can compile Xdebug as a shared extension using `--build-shared="xdebug"`.
|
||||||
The compiled `./php` binary can be configured and run by specifying the INI, eg `./php -d 'zend_extension=/path/to/xdebug.so' your-code.php`.
|
The compiled `./php` binary can be configured and run by specifying the INI, e.g. `./php -d 'zend_extension=/path/to/xdebug.so' your-code.php`.
|
||||||
|
|
||||||
## xml
|
## xml
|
||||||
|
|
||||||
1. xml includes xml, xmlreader, xmlwriter, xsl, dom, simplexml, etc.
|
1. xml includes xml, xmlreader, xmlwriter, xsl, dom, simplexml, etc.
|
||||||
When adding xml extensions, it is best to enable these extensions at the same time.
|
When adding xml extensions, it is best to enable these extensions at the same time.
|
||||||
2. libxml is included in xml extension. Enabling xml is equivalent to enabling libxml.
|
2. libxml is included in xml extension. Enabling xml is equivalent to enabling libxml.
|
||||||
|
|
||||||
## glfw
|
## glfw
|
||||||
@@ -119,14 +119,14 @@ and this extension cannot be compiled into php by static linking, so it cannot b
|
|||||||
|
|
||||||
pgsql 16.2 has fixed this bug, now it's working.
|
pgsql 16.2 has fixed this bug, now it's working.
|
||||||
|
|
||||||
When pgsql uses SSL connection, there may be `error:80000002:system library::No such file or directory` error,
|
When pgsql uses SSL connection, there may be `error:80000002:system library::No such file or directory` error.
|
||||||
For details on the solution, see [FAQ - Unable to use ssl](../faq/#unable-to-use-ssl).
|
For details on the solution, see [FAQ](../faq/).
|
||||||
|
|
||||||
## openssl
|
## openssl
|
||||||
|
|
||||||
When using openssl-based extensions (such as curl, pgsql and other network libraries),
|
When using openssl-based extensions (such as curl, pgsql and other network libraries),
|
||||||
there may be an `error:80000002:system library::No such file or directory` error.
|
there may be an `error:80000002:system library::No such file or directory` error.
|
||||||
For details on the solution, see [FAQ - Unable to use ssl](../faq/#unable-to-use-ssl).
|
For details on the solution, see [FAQ](../faq/).
|
||||||
|
|
||||||
## password-argon2
|
## password-argon2
|
||||||
|
|
||||||
@@ -135,14 +135,14 @@ For details on the solution, see [FAQ - Unable to use ssl](../faq/#unable-to-use
|
|||||||
|
|
||||||
## ffi
|
## ffi
|
||||||
|
|
||||||
1. Due to the limitation of musl libc's static linkage, you cannot use ffi because dynamic libraries cannot be loaded.
|
1. Due to the limitation of musl libc's static linkage, you cannot use ffi because dynamic libraries cannot be loaded.
|
||||||
If you need to use the ffi extension, see [Compile PHP with GNU libc](./build-with-glibc).
|
If you need to use the ffi extension, use a glibc-based `SPC_TARGET` (e.g. `native-native-gnu.2.17`). See [SAPI Reference](./sapi-reference) for details.
|
||||||
2. macOS supports the ffi extension, but errors will occur when some kernels do not contain debugging symbols.
|
2. macOS supports the ffi extension, but errors will occur when some kernels do not contain debugging symbols.
|
||||||
3. Windows x64 supports the ffi extension.
|
3. Windows x64 supports the ffi extension.
|
||||||
|
|
||||||
## xhprof
|
## xhprof
|
||||||
|
|
||||||
The xhprof extension consists of three parts: `xhprof_extension`, `xhprof_html`, `xhprof_libs`.
|
The xhprof extension consists of three parts: `xhprof_extension`, `xhprof_html`, `xhprof_libs`.
|
||||||
Only `xhprof_extension` is included in the compiled binary.
|
Only `xhprof_extension` is included in the compiled binary.
|
||||||
If you need to use xhprof,
|
If you need to use xhprof,
|
||||||
please download the source code from [pecl.php.net/package/xhprof](http://pecl.php.net/package/xhprof) and specify the `xhprof_libs` and `xhprof_html` paths for use.
|
please download the source code from [pecl.php.net/package/xhprof](http://pecl.php.net/package/xhprof) and specify the `xhprof_libs` and `xhprof_html` paths for use.
|
||||||
@@ -166,3 +166,4 @@ Parallel is only supported on PHP 8.0 ZTS and above.
|
|||||||
1. This is not technically an extension, but a library.
|
1. This is not technically an extension, but a library.
|
||||||
2. Building with `--with-libs="mimalloc"` on Linux or macOS will override the default allocator.
|
2. Building with `--with-libs="mimalloc"` on Linux or macOS will override the default allocator.
|
||||||
3. This is experimental for now, but is recommended in threaded environments.
|
3. This is experimental for now, but is recommended in threaded environments.
|
||||||
|
|
||||||
|
|||||||
@@ -2,22 +2,16 @@
|
|||||||
import SearchTable from "../../.vitepress/components/SearchTable.vue";
|
import SearchTable from "../../.vitepress/components/SearchTable.vue";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
# Extensions
|
# Supported Extensions
|
||||||
|
|
||||||
> - `yes`: supported
|
> - ✅: Supported
|
||||||
> - _blank_: not supported yet, or WIP
|
> - blank: Not supported or not yet ported
|
||||||
> - `no` with issue link: confirmed to be unavailable due to issue
|
|
||||||
> - `partial` with issue link: supported but not perfect due to issue
|
|
||||||
|
|
||||||
<search-table />
|
<search-table />
|
||||||
|
|
||||||
::: tip
|
::: tip
|
||||||
If an extension you need is missing, you can create a [Feature Request](https://github.com/crazywhalecc/static-php-cli/issues).
|
If an extension you need is missing, you can file a [feature request](https://github.com/crazywhalecc/static-php-cli/issues).
|
||||||
|
|
||||||
Some extensions or libraries that the extension depends on will have some optional features.
|
Some extensions or their library dependencies have optional features (e.g. gd can optionally use libwebp, freetype, etc.).
|
||||||
For example, the gd library optionally supports libwebp, freetype, etc.
|
Running `bin/spc build gd --build-cli` alone will not include them — StaticPHP follows a minimal-dependency principle by default.
|
||||||
If you only use `bin/spc build gd --build-cli` they will not be included (static-php-cli defaults to the minimum dependency principle).
|
|
||||||
|
|
||||||
For more information about optional libraries, see [Extensions, Library Dependency Map](./deps-map).
|
|
||||||
For optional libraries, you can also select an extension from the [Command Generator](./cli-generator) and then select optional libraries.
|
|
||||||
:::
|
:::
|
||||||
|
|||||||
181
docs/en/guide/first-build.md
Normal file
181
docs/en/guide/first-build.md
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
# Your First Build
|
||||||
|
|
||||||
|
This page walks you through building a static PHP binary from scratch, end to end.
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
If you installed spc as a pre-built binary, replace every `spc` in this page with `./spc` (or `.\spc.exe` on Windows).
|
||||||
|
|
||||||
|
If you installed from source, use `bin/spc` instead.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Two Approaches
|
||||||
|
|
||||||
|
StaticPHP supports two build workflows — pick the one that fits your situation:
|
||||||
|
|
||||||
|
| Approach | When to use |
|
||||||
|
|---|---|
|
||||||
|
| `craft` (one-shot) | Everyday use, getting started quickly |
|
||||||
|
| Step-by-step | Fine-grained control over the build pipeline |
|
||||||
|
|
||||||
|
## Option 1: One-Shot Build with `craft` (Recommended)
|
||||||
|
|
||||||
|
The `craft` command reads a `craft.yml` file and handles everything automatically — downloading dependencies, compiling libraries, and building PHP — in a single run.
|
||||||
|
|
||||||
|
### Write craft.yml
|
||||||
|
|
||||||
|
Create a `craft.yml` in your working directory and declare the PHP version, extensions, and target SAPIs:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
php-version: 8.4
|
||||||
|
extensions: bcmath,posix,phar,zlib,openssl,curl,fileinfo,tokenizer
|
||||||
|
sapi:
|
||||||
|
- cli
|
||||||
|
- micro
|
||||||
|
```
|
||||||
|
|
||||||
|
Not sure which extensions you need? Use the [command generator](./cli-generator) to produce a `craft.yml` automatically.
|
||||||
|
|
||||||
|
### Run the Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc craft
|
||||||
|
```
|
||||||
|
|
||||||
|
The build pipeline runs in order: download dependencies → compile libraries → compile PHP. No interaction required.
|
||||||
|
|
||||||
|
To see more detail, pass `-v`, `-vv`, or `-vvv`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc craft -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inspect the Output
|
||||||
|
|
||||||
|
On success, binaries land in `buildroot/bin/`:
|
||||||
|
|
||||||
|
| SAPI | Output path |
|
||||||
|
|---|---|
|
||||||
|
| cli | `buildroot/bin/php` (Windows: `buildroot/bin/php.exe`) |
|
||||||
|
| fpm | `buildroot/bin/php-fpm` |
|
||||||
|
| micro | `buildroot/bin/micro.sfx` |
|
||||||
|
| embed | `buildroot/lib/libphp.a` |
|
||||||
|
| frankenphp | `buildroot/bin/frankenphp` |
|
||||||
|
|
||||||
|
Give the CLI binary a quick smoke-test:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./buildroot/bin/php -v
|
||||||
|
./buildroot/bin/php -m
|
||||||
|
```
|
||||||
|
|
||||||
|
## Option 2: Step-by-Step Build
|
||||||
|
|
||||||
|
This approach lets you run download and compile as separate steps — useful when you want to cache downloads in CI and reuse them across builds.
|
||||||
|
|
||||||
|
### Step 1: Download Dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Download only what the chosen extensions need (recommended)
|
||||||
|
spc download --for-extensions="bcmath,posix,phar,zlib,openssl,curl,fileinfo,tokenizer" --with-php=8.4
|
||||||
|
|
||||||
|
# Download by specific package names
|
||||||
|
spc download "curl,openssl" --with-php=8.4
|
||||||
|
```
|
||||||
|
|
||||||
|
Downloads are cached in `downloads/` and reused across builds automatically.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Slow connection? Increase parallelism and retries
|
||||||
|
spc download --for-extensions="bcmath,openssl,curl" --parallel 10 --retry=3
|
||||||
|
|
||||||
|
# Use pre-built binaries where available — skips compiling those dependencies
|
||||||
|
spc download --for-extensions="bcmath,openssl,curl" --prefer-binary
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Build PHP
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build the cli SAPI
|
||||||
|
spc build:php "bcmath,phar,zlib,openssl,curl,fileinfo,tokenizer" --build-cli
|
||||||
|
|
||||||
|
# Build multiple SAPIs in one go
|
||||||
|
spc build:php "bcmath,phar,zlib,openssl,curl" --build-cli --build-micro
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Common Build Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|---|---|
|
||||||
|
| `--build-cli` | Build the cli SAPI |
|
||||||
|
| `--build-fpm` | Build php-fpm (not available on Windows) |
|
||||||
|
| `--build-micro` | Build micro.sfx |
|
||||||
|
| `--build-embed` | Build the embed SAPI |
|
||||||
|
| `--build-frankenphp` | Build FrankenPHP |
|
||||||
|
| `--enable-zts` | Enable thread-safe (ZTS) mode |
|
||||||
|
| `--no-strip` | Keep debug symbols; do not strip the binary |
|
||||||
|
| `-I key=value` | Hard-compile an INI option into PHP |
|
||||||
|
| `--with-upx-pack` | Compress output with UPX (run `spc install-pkg upx` first) |
|
||||||
|
|
||||||
|
Example — baking in a larger memory limit and disabling the `system` function:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,pcntl,posix" --build-cli -I "memory_limit=4G" -I "disable_functions=system"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Packaging a micro App
|
||||||
|
|
||||||
|
Once you have `micro.sfx`, use `micro:combine` to bundle your PHP code into a single self-contained executable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo "<?php echo 'Hello, World!' . PHP_EOL;" > hello.php
|
||||||
|
spc micro:combine hello.php --output=hello
|
||||||
|
./hello
|
||||||
|
```
|
||||||
|
|
||||||
|
Works with `.phar` files too, and you can inject INI settings at packaging time:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Bundle a phar
|
||||||
|
spc micro:combine your-app.phar --output=your-app
|
||||||
|
|
||||||
|
# Inject INI via command-line options
|
||||||
|
spc micro:combine your-app.phar --output=your-app -I "memory_limit=512M"
|
||||||
|
|
||||||
|
# Inject INI from a file
|
||||||
|
spc micro:combine your-app.phar --output=your-app -N /path/to/custom.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debugging and Rebuilding
|
||||||
|
|
||||||
|
If a build fails or you want to trace what's happening, use `-v` / `-vv` / `-vvv`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,openssl" --build-cli -vv
|
||||||
|
```
|
||||||
|
|
||||||
|
- `-v` shows `INFO`-level logs: which modules are running and what build commands are being executed.
|
||||||
|
- `-vv` shows `DEBUG`-level logs: all internal debug output from StaticPHP.
|
||||||
|
- `-vvv` shows `DEBUG`-level logs and also pipes the stdout of every shell command directly to your terminal.
|
||||||
|
|
||||||
|
To wipe compiled artifacts and start fresh without re-downloading, run `reset`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc reset
|
||||||
|
# Then rebuild
|
||||||
|
spc build:php "bcmath,openssl" --build-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
`reset` only removes `buildroot/` and `source/`. Your `downloads/` cache is preserved.
|
||||||
|
Add `--with-download` if you also want to clear the download cache.
|
||||||
|
:::
|
||||||
|
|
||||||
|
If you're stuck, open an [Issue](https://github.com/static-php/static-php-cli/issues) and include your `craft.yml` (if any) and a zip of the `log/` directory.
|
||||||
|
|
||||||
|
## What's Next
|
||||||
|
|
||||||
|
- [PHP SAPI Reference](./sapi-reference) — Build options and usage guide for each PHP SAPI
|
||||||
|
- [CLI Reference](./cli-reference) — Full documentation for every command and option
|
||||||
|
- [Extensions](./extensions) — Browse supported extensions and their dependencies
|
||||||
|
- [Troubleshooting](./troubleshooting) — Diagnose common build failures
|
||||||
|
|
||||||
@@ -1,50 +1,52 @@
|
|||||||
# Guide
|
# Guide
|
||||||
|
|
||||||
Static php cli is a tool used to build statically compiled PHP binaries,
|
::: warning
|
||||||
currently supporting Linux and macOS systems.
|
You are reading the documentation for StaticPHP v3. The v2 version will be deprecated after the stable release of v3.
|
||||||
|
The 3.0 version is currently in the alpha stage, and you can view the v2 documentation [here](https://static-php.github.io/v2-docs/).
|
||||||
|
:::
|
||||||
|
|
||||||
In the guide section, you will learn how to use static php cli to build standalone PHP programs.
|
## What is StaticPHP?
|
||||||
|
|
||||||
- [Build (local)](./manual-build)
|
StaticPHP is a build tool that compiles the PHP interpreter together with any extensions you need into a single self-contained binary. The target system doesn't need PHP or any runtime libraries installed — just copy the binary and run it. Builds target Linux, macOS, and Windows.
|
||||||
- [Build (GitHub Actions)](./action-build)
|
|
||||||
- [Supported Extensions](./extensions)
|
|
||||||
|
|
||||||
## Compilation Environment
|
StaticPHP isn't limited to PHP. Built on the same infrastructure, it can also compile standalone static binaries for common tools like `curl`, `pkg-config`, and `htop` — no dependencies required on the target machine. Support for more tools (including `openssl` and other frequently-used CLI utilities) is planned.
|
||||||
|
|
||||||
The following is the architecture support situation, where :gear: represents support for GitHub Action build,
|
## Why bother with a static PHP binary?
|
||||||
:computer: represents support for local manual build, and empty represents temporarily not supported.
|
|
||||||
|
|
||||||
| | x86_64 | aarch64 |
|
A typical PHP installation is tightly coupled to the system: you install PHP, then extensions, then spend time dealing with version mismatches across distros. A static binary sidesteps all of that — what you get is a single executable that runs on any machine of the same architecture, no setup required.
|
||||||
|---------|-------------------|-------------------|
|
|
||||||
| macOS | :gear: :computer: | :gear: :computer: |
|
|
||||||
| Linux | :gear: :computer: | :gear: :computer: |
|
|
||||||
| Windows | :gear: :computer: | |
|
|
||||||
| FreeBSD | :computer: | :computer: |
|
|
||||||
|
|
||||||
Current supported PHP versions for compilation:
|
Common use cases:
|
||||||
|
|
||||||
> :warning: Partial support, there may be issues with new beta versions and old versions.
|
- **Distributing CLI tools** — Ship tools like Composer, PHPStan, or your own CLI as a single file. Users don't need PHP installed.
|
||||||
>
|
- **Leaner containers** — Replace a bloated `php:8.x` base image with a minimal image (or even `FROM scratch`) carrying just a static binary.
|
||||||
> :heavy_check_mark: Supported
|
- **Server applications** — Build a static binary with FPM or FrankenPHP baked in. Deployment becomes a file copy, with no dependency on the host environment.
|
||||||
>
|
|
||||||
> :x: Not supported
|
|
||||||
|
|
||||||
| PHP Version | Status | Comment |
|
## phpmicro: ship PHP and your code as one file
|
||||||
|-------------|--------------------|-------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| 7.2 | :x: | |
|
|
||||||
| 7.3 | :x: | phpmicro and many extensions do not support 7.3, 7.4 versions |
|
|
||||||
| 7.4 | :x: | phpmicro and many extensions do not support 7.3, 7.4 versions |
|
|
||||||
| 8.0 | :warning: | PHP official has stopped maintaining 8.0, we no longer handle 8.0 related backport support |
|
|
||||||
| 8.1 | :warning: | PHP official only provides security updates for 8.1, we no longer handle 8.1 related backport support after 8.5 release |
|
|
||||||
| 8.2 | :heavy_check_mark: | |
|
|
||||||
| 8.3 | :heavy_check_mark: | |
|
|
||||||
| 8.4 | :heavy_check_mark: | |
|
|
||||||
| 8.5 (beta) | :warning: | PHP 8.5 is currently in beta stage |
|
|
||||||
|
|
||||||
> This table shows the support status of static-php-cli for building corresponding versions, not the PHP official support status for that version.
|
[phpmicro](https://micro.static-php.dev) is a third-party PHP SAPI that StaticPHP supports out of the box. It merges the PHP interpreter with your `.php` source or `.phar` archive into a single self-extracting executable (`.sfx`).
|
||||||
|
|
||||||
## PHP Support Versions
|
```
|
||||||
|
micro.sfx + your-app.phar = your-app # one file, zero dependencies
|
||||||
|
```
|
||||||
|
|
||||||
Currently, static-php-cli supports PHP versions 8.2 ~ 8.5, and theoretically supports PHP 8.1 and earlier versions, just select the earlier version when downloading.
|
This is ideal for distributing PHP-based CLI tools: the end user just gets an ordinary executable with no idea PHP is involved.
|
||||||
However, due to some extensions and special components that have stopped supporting earlier versions of PHP, static-php-cli will not explicitly support earlier versions.
|
|
||||||
We recommend that you compile the latest PHP version possible for a better experience.
|
## Improving how you ship and deploy PHP projects
|
||||||
|
|
||||||
|
**Drop the heavy Docker base image**
|
||||||
|
|
||||||
|
The official `php:8.x` image can be hundreds of megabytes, most of which is just the PHP runtime. Swap it for a static PHP binary with a minimal base image — or `FROM scratch` — and you can get container sizes down to single-digit megabytes with noticeably faster startup times.
|
||||||
|
|
||||||
|
**Ship PHP CLI tools like native binaries**
|
||||||
|
|
||||||
|
Build your CLI with [symfony/console](https://symfony.com/doc/current/components/console.html) or [Laravel Zero](https://laravel-zero.com), bundle it into a `.phar` with [Box](https://github.com/box-project/box), then merge it with phpmicro. The result is a single distributable executable — the same experience users expect from Go or Rust tools, with no PHP runtime required on their end.
|
||||||
|
|
||||||
|
**Single-file web apps with FrankenPHP**
|
||||||
|
|
||||||
|
[FrankenPHP](https://frankenphp.dev) is a modern PHP app server with built-in HTTP/2, HTTP/3, and automatic HTTPS. StaticPHP can compile FrankenPHP together with your chosen extensions into one binary. The result is a complete web server in a single file — no Nginx, no PHP-FPM, just deploy and run.
|
||||||
|
|
||||||
|
## Next steps
|
||||||
|
|
||||||
|
- [Installation](./installation) — Get the StaticPHP build tool
|
||||||
|
- [First Build](./first-build) — Full walkthrough: from downloading sources to a working executable
|
||||||
|
- [CLI Reference](./cli-reference) — Every command and option, in one place
|
||||||
|
|||||||
121
docs/en/guide/installation.md
Normal file
121
docs/en/guide/installation.md
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
# Installation
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
| Platform | Architecture | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Linux | x86_64, aarch64 | Major distros supported (Alpine, Debian/Ubuntu, RHEL/CentOS, etc.) |
|
||||||
|
| macOS | x86_64 (Intel), arm64 (Apple Silicon) | macOS 12 or later |
|
||||||
|
| Windows | x86_64 | Windows 10 Build 17063 or later |
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
Both glibc-based distros (Debian, Ubuntu, Arch, etc.) and musl-based ones (Alpine) are supported on Linux.
|
||||||
|
The `doctor` command will detect your environment and guide you through installing the right toolchain if needed.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Pick the installation method that fits your use case:
|
||||||
|
|
||||||
|
| Method | Best for |
|
||||||
|
|---|---|
|
||||||
|
| Pre-built binary | Most users — download and run, no dependencies |
|
||||||
|
| From source | Contributors, or anyone who needs to modify core build logic |
|
||||||
|
| Vendor mode | Integrating StaticPHP into an existing PHP project |
|
||||||
|
|
||||||
|
## Pre-built binary
|
||||||
|
|
||||||
|
`spc` has no runtime dependencies — download the binary for your platform and it's ready to go.
|
||||||
|
|
||||||
|
> Fun fact: `spc` itself is a static PHP binary built with StaticPHP. We use StaticPHP to build StaticPHP's own build tool.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Linux x86_64
|
||||||
|
curl -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-linux-x86_64 -o spc
|
||||||
|
# Linux arm64
|
||||||
|
curl -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-linux-aarch64 -o spc
|
||||||
|
# macOS x86_64 (Intel)
|
||||||
|
curl -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-macos-x86_64 -o spc
|
||||||
|
# macOS arm64 (Apple Silicon)
|
||||||
|
curl -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-macos-aarch64 -o spc
|
||||||
|
# Windows x86_64 (PowerShell)
|
||||||
|
curl.exe -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-windows-x86_64.exe -o spc.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
On Linux and macOS, mark the binary as executable before running it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x spc && ./spc --version
|
||||||
|
```
|
||||||
|
|
||||||
|
## From source
|
||||||
|
|
||||||
|
This is the right path if you want to contribute to StaticPHP, or need to modify the core registry and build scripts. You'll need PHP >= 8.4, Composer, and the `mbstring,posix,pcntl,iconv,phar,zlib` extensions.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/crazywhalecc/static-php-cli.git --branch v3
|
||||||
|
cd static-php-cli
|
||||||
|
composer install
|
||||||
|
```
|
||||||
|
|
||||||
|
If you don't have PHP or Composer installed, use the bundled setup script to install a self-contained runtime:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
```bash [Linux / macOS]
|
||||||
|
bin/setup-runtime
|
||||||
|
```
|
||||||
|
```powershell [Windows]
|
||||||
|
.\bin\setup-runtime.ps1
|
||||||
|
.\bin\setup-runtime.ps1 add-path # add runtime/ to PATH
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
The script downloads `php` and `composer` into a `runtime/` subdirectory. You then have two options:
|
||||||
|
|
||||||
|
1. **Call them directly** (no PATH changes needed):
|
||||||
|
```bash
|
||||||
|
runtime/php bin/spc --help
|
||||||
|
runtime/php runtime/composer install
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Add `runtime/` to your PATH** so you can use `php`, `composer`, and `bin/spc` without prefixes:
|
||||||
|
```bash
|
||||||
|
export PATH="/path/to/static-php-cli/runtime:$PATH"
|
||||||
|
# Add this to ~/.bashrc or ~/.zshrc to make it permanent
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
In regions with restricted access to GitHub or getcomposer.org, pass `--mirror china` to use a mirror:
|
||||||
|
```bash
|
||||||
|
bin/setup-runtime --mirror china
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Vendor mode
|
||||||
|
|
||||||
|
If you already have a PHP project and want to call StaticPHP's build APIs directly, or use a custom registry to support private libraries and extensions, pull it in as a Composer dependency:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer require crazywhalecc/static-php-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Vendor Mode guide](../develop/vendor-mode/) for details.
|
||||||
|
|
||||||
|
## Verify your build environment
|
||||||
|
|
||||||
|
> **Vendor mode users can skip this step.**
|
||||||
|
|
||||||
|
Once installed, run `doctor` to check that your system has the required build tools (cmake, make, a C compiler, etc.):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using the spc binary
|
||||||
|
./spc doctor
|
||||||
|
# From source
|
||||||
|
bin/spc doctor
|
||||||
|
```
|
||||||
|
|
||||||
|
If anything is missing, `--auto-fix` will attempt to install it for you:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./spc doctor --auto-fix
|
||||||
|
```
|
||||||
|
|
||||||
|
Once `doctor` reports everything is good, head over to [First Build](./first-build).
|
||||||
@@ -1,705 +0,0 @@
|
|||||||
---
|
|
||||||
outline: 'deep'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Build (Linux, macOS, FreeBSD)
|
|
||||||
|
|
||||||
This section covers the build process for Linux, macOS, and FreeBSD. If you want to build on Windows,
|
|
||||||
also need to read [Build on Windows](./build-on-windows).
|
|
||||||
|
|
||||||
### Build locally (using SPC binary) (recommended)
|
|
||||||
|
|
||||||
This project provides a binary file of static-php-cli.
|
|
||||||
You can directly download the binary file of the corresponding platform and then use it to build static PHP.
|
|
||||||
Currently, the platforms supported by `spc` binary are Linux and macOS.
|
|
||||||
|
|
||||||
Here's how to download from self-hosted server:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Download from self-hosted nightly builds (sync with main branch)
|
|
||||||
# For Linux x86_64
|
|
||||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64
|
|
||||||
# For Linux aarch64
|
|
||||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-aarch64
|
|
||||||
# macOS x86_64 (Intel)
|
|
||||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-x86_64
|
|
||||||
# macOS aarch64 (Apple)
|
|
||||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64
|
|
||||||
# Windows (x86_64, win10 build 17063 or later)
|
|
||||||
curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe
|
|
||||||
|
|
||||||
# Add execute perm (Linux and macOS only)
|
|
||||||
chmod +x ./spc
|
|
||||||
|
|
||||||
# Run (Linux and macOS)
|
|
||||||
./spc --version
|
|
||||||
# Run (Windows powershell)
|
|
||||||
.\spc.exe --version
|
|
||||||
```
|
|
||||||
|
|
||||||
> If you are using the packaged `spc` binary, you will need to replace the leading `bin/spc` with `./spc` in all the commands below.
|
|
||||||
|
|
||||||
### Build locally (using source code)
|
|
||||||
|
|
||||||
If you have problems using the spc binary, or if you need to modify the static-php-cli source code, download static-php-cli from the source code.
|
|
||||||
|
|
||||||
Currently, it supports building on macOS and Linux.
|
|
||||||
macOS supports the latest version of the operating system and two architectures,
|
|
||||||
while Linux supports Debian and derivative distributions, as well as Alpine Linux.
|
|
||||||
|
|
||||||
Because this project itself is developed using PHP,
|
|
||||||
it is also necessary to install PHP on the system during compilation.
|
|
||||||
This project also provides static binary PHP suitable for this project,
|
|
||||||
which can be selected and used according to actual situations.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# clone repo
|
|
||||||
git clone https://github.com/crazywhalecc/static-php-cli.git --depth=1
|
|
||||||
cd static-php-cli
|
|
||||||
|
|
||||||
# You need to install the PHP environment first before running Composer and this project. The installation method can be referred to below.
|
|
||||||
composer update
|
|
||||||
```
|
|
||||||
|
|
||||||
### Use Precompiled Static PHP Binaries
|
|
||||||
|
|
||||||
If you don't want to use Docker and install PHP in the system,
|
|
||||||
you can directly download the php binary cli program compiled by this project itself. The usage process is as follows:
|
|
||||||
|
|
||||||
Deploy the environment using the command, the command will download a static php-cli binary from [self-hosted server](https://dl.static-php.dev/static-php-cli/).
|
|
||||||
Next, it will automatically download Composer from [getcomposer](https://getcomposer.org/download/latest-stable/composer.phar) or [Aliyun mirror](https://mirrors.aliyun.com/composer/composer.phar).
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
Using precompiled static PHP binaries is currently only supported on Linux and macOS.
|
|
||||||
The FreeBSD environment is currently not supported due to the lack of an automated build environment.
|
|
||||||
:::
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/setup-runtime
|
|
||||||
|
|
||||||
# For users with special network environments such as mainland China, you can use mirror sites (aliyun) to speed up the download speed
|
|
||||||
bin/setup-runtime --mirror china
|
|
||||||
```
|
|
||||||
|
|
||||||
This script will download two files in total: `bin/php` and `bin/composer`. After the download is complete, there are two ways to use it:
|
|
||||||
|
|
||||||
1. Add the `bin/` directory to the PATH: `export PATH="/path/to/your/static-php-cli/bin:$PATH"`, after adding the path,
|
|
||||||
it is equivalent to installing PHP in the system, you can directly Use commands such as `composer`, `php -v`, or directly use `bin/spc`.
|
|
||||||
2. Direct call, such as executing static-php-cli command: `bin/php bin/spc --help`, executing Composer: `bin/php bin/composer update`.
|
|
||||||
|
|
||||||
### Use Docker
|
|
||||||
|
|
||||||
If you don't want to install PHP and Composer runtime environment on your system, you can use the built-in Docker environment build script.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# To use directly, replace `bin/spc` with `bin/spc-alpine-docker` in all used commands
|
|
||||||
bin/spc-alpine-docker
|
|
||||||
```
|
|
||||||
|
|
||||||
The first time the command is executed, `docker build` will be used to build a Docker image.
|
|
||||||
The default built Docker image is the `x86_64` architecture, and the image name is `cwcc-spc-x86_64`.
|
|
||||||
|
|
||||||
If you want to build `aarch64` static-php-cli in `x86_64` environment,
|
|
||||||
you can use qemu to emulate the arm image to run Docker, but the speed will be very slow.
|
|
||||||
Use command: `SPC_USE_ARCH=aarch64 bin/spc-alpine-docker`.
|
|
||||||
|
|
||||||
If it prompts that sudo is required to run after running,
|
|
||||||
execute the following command once to grant static-php-cli permission to execute sudo:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export SPC_USE_SUDO=yes
|
|
||||||
```
|
|
||||||
|
|
||||||
### Use System PHP
|
|
||||||
|
|
||||||
Below are some example commands for installing PHP and Composer in the system.
|
|
||||||
It is recommended to search for the specific installation method yourself or ask the AI search engine to obtain the answer,
|
|
||||||
which will not be elaborated here.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# [macOS], need install Homebrew first. See https://brew.sh/
|
|
||||||
# Remember change your composer executable path. For M1/M2 Chip mac, "/opt/homebrew/bin/", for Intel mac, "/usr/local/bin/". Or add it to your own path.
|
|
||||||
brew install php wget
|
|
||||||
wget https://getcomposer.org/download/latest-stable/composer.phar -O /path/to/your/bin/composer && chmod +x /path/to/your/bin/composer
|
|
||||||
|
|
||||||
# [Debian], you need to make sure your php version >= 8.1 and composer >= 2.0
|
|
||||||
sudo apt install php-cli composer php-tokenizer
|
|
||||||
|
|
||||||
# [Alpine]
|
|
||||||
apk add bash file wget xz php81 php81-common php81-pcntl php81-tokenizer php81-phar php81-posix php81-xml composer
|
|
||||||
```
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
Currently, some versions of Ubuntu install older PHP versions,
|
|
||||||
so no installation commands are provided. If necessary, it is recommended to add software sources such as ppa first,
|
|
||||||
and then install the latest version of PHP and tokenizer, XML, and phar extensions.
|
|
||||||
|
|
||||||
Older versions of Debian may have an older (<= 7.4) version of PHP installed by default, it is recommended to upgrade Debian first.
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Build with craft (recommended)
|
|
||||||
|
|
||||||
Using `bin/spc craft`, you can use a configuration file and a command to automatically check the environment, download source code, build dependency libraries, build PHP and extensions, etc.
|
|
||||||
|
|
||||||
You need to write a `craft.yml` file and save it in the current working directory. `craft.yml` can be generated by [command generator](./cli-generator) or written manually.
|
|
||||||
|
|
||||||
For manual writing, please refer to the comments in [craft.yml configuration](../develop/craft-yml.md) to write it.
|
|
||||||
Let's assume that you compile an extension combination and choose PHP 8.4, outputting `cli` and `fpm`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# path/to/craft.yml
|
|
||||||
php-version: 8.4
|
|
||||||
extensions: bcmath,posix,phar,zlib,openssl,curl,fileinfo,tokenizer
|
|
||||||
sapi:
|
|
||||||
- cli
|
|
||||||
- fpm
|
|
||||||
```
|
|
||||||
|
|
||||||
Then use the `bin/spc craft` command to compile:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc craft --debug
|
|
||||||
```
|
|
||||||
|
|
||||||
If the build is successful, you will see the `buildroot/bin` directory in the current directory, which contains the compiled PHP binary file, or the corresponding SAPI.
|
|
||||||
|
|
||||||
- cli: The build result is `buildroot/bin/php.exe` on Windows and `buildroot/bin/php` on other platforms.
|
|
||||||
- fpm: The build result is `buildroot/bin/php-fpm`.
|
|
||||||
- micro: The build result is `buildroot/bin/micro.sfx`. If you need to further package it with PHP code, please refer to [Packaging micro binary](./manual-build#command-micro-combine).
|
|
||||||
- embed: See [Using embed](./manual-build#embed-usage).
|
|
||||||
- frankenphp: The build result is `buildroot/bin/frankenphp`.
|
|
||||||
|
|
||||||
If the build fails, you can use the `--debug` parameter to view detailed error information,
|
|
||||||
or use the `--with-clean` to clear the old compilation results and recompile.
|
|
||||||
|
|
||||||
If the build still fails to use the above method, please submit an issue and attach your `craft.yml` and `./log` archive.
|
|
||||||
|
|
||||||
## Step-by-step build command
|
|
||||||
|
|
||||||
If you have customized requirements, or the need to download and compile PHP and dependent libraries separately, you can use the `bin/spc` command to execute step by step.
|
|
||||||
|
|
||||||
### Command download - Download dependency packages
|
|
||||||
|
|
||||||
Use the command `bin/spc download` to download the source code required for compilation,
|
|
||||||
including php-src and the source code of various dependent libraries.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Download all dependencies, defaults to php 8.4
|
|
||||||
bin/spc download --all
|
|
||||||
|
|
||||||
# Download all dependent packages, and specify the main version of PHP to download, optional: 8.1, 8.2, 8.3, 8.4
|
|
||||||
# Also supports specific version of php release: 8.3.10, 8.2.22, etc.
|
|
||||||
bin/spc download --all --with-php=8.3
|
|
||||||
|
|
||||||
# Show download progress bar while downloading (curl)
|
|
||||||
bin/spc download --all --debug
|
|
||||||
|
|
||||||
# Delete old download data
|
|
||||||
bin/spc download --clean
|
|
||||||
|
|
||||||
# Download specified dependencies
|
|
||||||
bin/spc download php-src,micro,zstd,ext-zstd
|
|
||||||
|
|
||||||
# Download only extensions and libraries to be compiled (use extensions, including suggested libraries)
|
|
||||||
bin/spc download --for-extensions=openssl,swoole,zip,pcntl,zstd
|
|
||||||
|
|
||||||
# Download resources, prefer to download dependencies with pre-built packages (reduce the time to compile dependencies)
|
|
||||||
bin/spc download --for-extensions="curl,pcntl,xml,mbstring" --prefer-pre-built
|
|
||||||
|
|
||||||
# Download only the extensions and dependent libraries to be compiled (use extensions, excluding suggested libraries)
|
|
||||||
bin/spc download --for-extensions=openssl,swoole,zip,pcntl --without-suggestions
|
|
||||||
|
|
||||||
# Download only libraries to be compiled (use libraries, including suggested libraries and required libraries, can use --for-extensions together)
|
|
||||||
bin/spc download --for-libs=liblz4,libevent --for-extensions=pcntl,rar,xml
|
|
||||||
|
|
||||||
# Download only libraries to be compiled (use libraries, excluding suggested libraries)
|
|
||||||
bin/spc download --for-libs=liblz4,libevent --without-suggestions
|
|
||||||
|
|
||||||
# When downloading sources, ignore some source caches (always force download, e.g. switching PHP version)
|
|
||||||
bin/spc download --for-extensions=curl,pcntl,xml --ignore-cache-sources=php-src --with-php=8.3.10
|
|
||||||
|
|
||||||
# Set retry times (default is 0)
|
|
||||||
bin/spc download --all --retry=2
|
|
||||||
```
|
|
||||||
|
|
||||||
If the network in your area is not good, or the speed of downloading the dependency package is too slow,
|
|
||||||
you can download `download.zip` which is packaged regularly every week from GitHub Action,
|
|
||||||
and use the command to directly use the zip archive as a dependency.
|
|
||||||
|
|
||||||
Dependent packages can be downloaded locally from [Action](https://github.com/static-php/static-php-cli-hosted/actions/workflows/download-cache.yml).
|
|
||||||
Enter Action and select the latest Workflow that has been successfully run, and download `download-files-x.y`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc download --from-zip=/path/to/your/download.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
If a source cannot be downloaded all the time, or you need to download some specific version of the package,
|
|
||||||
such as downloading the beta version of PHP, the old version of the library, etc.,
|
|
||||||
you can use the parameter `-U` or `--custom-url` to rewrite the download link,
|
|
||||||
Make the downloader force the link you specify to download packages from this source.
|
|
||||||
The method of use is `{source-name}:{url}`, which can rewrite the download URLs of multiple libraries at the same time.
|
|
||||||
Also, it is available when downloading with the `--for-extensions` option.
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Specifying to download a alpha version of PHP 8.5
|
|
||||||
bin/spc download --all -U "php-src:https://downloads.php.net/~edorian/php-8.5.0alpha2.tar.xz"
|
|
||||||
|
|
||||||
# Specifying to download an older version of the curl library
|
|
||||||
bin/spc download --all -U "curl:https://curl.se/download/curl-7.88.1.tar.gz"
|
|
||||||
```
|
|
||||||
|
|
||||||
If the source you download is not a link, but a git repository, you can use `-G` or `--custom-git` to rewrite the download link,
|
|
||||||
so that the downloader can force the use of the specified git repository to download packages from this source.
|
|
||||||
The usage method is `{source-name}:{branch}:{url}`, which can rewrite the download link of multiple libraries at the same time.
|
|
||||||
It is also available when downloading with the `--for-extensions` option.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Specifying to download the source code of the PHP extension from the specified branch of the git repository
|
|
||||||
bin/spc download --for-extensions=redis -G "php-src:master:https://github.com/php/php-src.git"
|
|
||||||
|
|
||||||
# Download the latest code from the master branch of the swoole-src repository instead of PECL release version
|
|
||||||
bin/spc download --for-extensions=swoole -G "swoole:master:https://github.com/swoole/swoole-src.git"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Command - doctor
|
|
||||||
|
|
||||||
If you can run `bin/spc` normally but cannot compile static PHP or dependent libraries normally,
|
|
||||||
you can run `bin/spc doctor` first to check whether the system itself lacks dependencies.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Quick check
|
|
||||||
bin/spc doctor
|
|
||||||
|
|
||||||
# Quickly check and fix when it can be automatically repaired (use package management to install dependent packages, only support the above-mentioned operating systems and distributions)
|
|
||||||
bin/spc doctor --auto-fix
|
|
||||||
```
|
|
||||||
|
|
||||||
### Command - build
|
|
||||||
|
|
||||||
Use the build command to start building the static php binary.
|
|
||||||
Before executing the `bin/spc build` command, be sure to use the `download` command to download sources.
|
|
||||||
It is recommended to use `doctor` to check the environment.
|
|
||||||
|
|
||||||
#### Basic build
|
|
||||||
|
|
||||||
You need to go to [Extension List](./extensions) or [Command Generator](./cli-generator) to select the extension you want to add,
|
|
||||||
and then use the command `bin/spc build` to compile.
|
|
||||||
You need to specify a compilation target, choose from the following parameters:
|
|
||||||
|
|
||||||
- `--build-cli`: Build a cli sapi (command line interface, which can execute PHP code on the command line)
|
|
||||||
- `--build-fpm`: Build a fpm sapi (php-fpm, used in conjunction with other traditional fpm architecture software such as nginx)
|
|
||||||
- `--build-cgi`: Build a cgi sapi (cgi, rarely used)
|
|
||||||
- `--build-micro`: Build a micro sapi (used to build a standalone executable binary containing PHP code)
|
|
||||||
- `--build-embed`: Build an embed sapi (used to embed into other C language programs)
|
|
||||||
- `--build-frankenphp`: Build a [FrankenPHP](https://github.com/php/frankenphp) executable
|
|
||||||
- `--build-all`: build all above sapi
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Compile PHP with bcmath,curl,openssl,ftp,posix,pcntl extensions, the compilation target is cli
|
|
||||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
|
||||||
|
|
||||||
# Compile PHP with phar,curl,posix,pcntl,tokenizer extensions, compile target is micro
|
|
||||||
bin/spc build phar,curl,posix,pcntl,tokenizer --build-micro
|
|
||||||
```
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
If you need to repeatedly build and debug, you can delete the `buildroot/` and `source/` directories so that you can re-extract and build all you need from the downloaded source code package:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# remove
|
|
||||||
rm -rf buildroot source
|
|
||||||
# build again
|
|
||||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
|
||||||
```
|
|
||||||
:::
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
If you want to build multiple versions of PHP and don't want to build other dependent libraries repeatedly each time,
|
|
||||||
you can use `switch-php-version` to quickly switch to another version and compile after compiling one version:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# switch to 8.4
|
|
||||||
bin/spc switch-php-version 8.4
|
|
||||||
# build
|
|
||||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
|
||||||
# switch to 8.1
|
|
||||||
bin/spc switch-php-version 8.1
|
|
||||||
# build
|
|
||||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
|
||||||
```
|
|
||||||
:::
|
|
||||||
|
|
||||||
#### Build Options
|
|
||||||
|
|
||||||
During the compilation process, in some special cases,
|
|
||||||
the compiler and the content of the compilation directory need to be intervened.
|
|
||||||
You can try to use the following commands:
|
|
||||||
|
|
||||||
- `--cc=XXX`: Specifies the execution command of the C language compiler (Linux default `musl-gcc` or `gcc`, macOS default `clang`)
|
|
||||||
- `--cxx=XXX`: Specifies the execution command of the C++ language compiler (Linux defaults to `g++`, macOS defaults to `clang++`)
|
|
||||||
- `--with-clean`: clean up old make files before compiling PHP
|
|
||||||
- `--enable-zts`: Make compiled PHP thread-safe version (default is NTS version)
|
|
||||||
- `--no-strip`: Do not run `strip` after compiling the PHP library to trim the binary file to reduce its size
|
|
||||||
- `--with-libs=XXX,YYY`: Compile the specified dependent library before compiling PHP, and activate some extended optional functions (such as libavif of the gd library, etc.)
|
|
||||||
- `--with-config-file-path=XXX`: Set the path in which to look for `php.ini` (Check [here](../faq/index.html#what-is-the-path-of-php-ini) for default paths)
|
|
||||||
- `--with-config-file-scan-dir=XXX`: Set the directory to scan for `.ini` files after reading `php.ini` (Check [here](../faq/index.html#what-is-the-path-of-php-ini) for default paths)
|
|
||||||
- `-I xxx=yyy`: Hard compile INI options into PHP before compiling (support multiple options, alias is `--with-hardcoded-ini`)
|
|
||||||
- `--with-micro-fake-cli`: When compiling micro, let micro's `PHP_SAPI` pretend to be `cli` (for compatibility with some programs that check `PHP_SAPI`)
|
|
||||||
- `--disable-opcache-jit`: Disable opcache jit (enabled by default)
|
|
||||||
- `-P xxx.php`: Inject external scripts during static-php-cli compilation (see **Inject external scripts** below for details)
|
|
||||||
- `--without-micro-ext-test`: After building micro.sfx, do not test the running results of different extensions in micro.sfx
|
|
||||||
- `--with-suggested-exts`: Add `ext-suggests` as dependencies when compiling
|
|
||||||
- `--with-suggested-libs`: Add `lib-suggests` as dependencies when compiling
|
|
||||||
- `--with-upx-pack`: Use UPX to reduce the size of the binary file after compilation (you need to use `bin/spc install-pkg upx` to install upx first)
|
|
||||||
- `--build-shared=XXX,YYY`: compile the specified extension into a shared library (the default is to compile into a static library)
|
|
||||||
|
|
||||||
For hardcoding INI options, it works for cli, micro, embed sapi. Here is a simple example where we preset a larger `memory_limit` and disable the `system` function:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc build bcmath,pcntl,posix --build-all -I "memory_limit=4G" -I "disable_functions=system"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Debug
|
|
||||||
|
|
||||||
If you encounter problems during the compilation process, or want to view each executing shell command,
|
|
||||||
you can use `--debug` to enable debug mode and view all terminal logs:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc build mysqlnd,pdo_mysql --build-all --debug
|
|
||||||
```
|
|
||||||
|
|
||||||
## Command - micro:combine
|
|
||||||
|
|
||||||
Use the `micro:combine` command to build the compiled `micro.sfx` and your code (`.php` or `.phar` file) into an executable binary.
|
|
||||||
You can also use this command to directly build a micro binary injected with ini configuration.
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
Injecting ini configuration refers to adding a special structure after micro.sfx to save ini configuration items before combining micro.sfx with PHP source code.
|
|
||||||
|
|
||||||
micro.sfx can identify the INI file header through a special byte, and the micro can be started with INI through the INI file header.
|
|
||||||
|
|
||||||
The original wiki of this feature is in [phpmicro - Wiki](https://github.com/easysoft/phpmicro/wiki/INI-settings), and this feature may change in the future.
|
|
||||||
:::
|
|
||||||
|
|
||||||
The following is the general usage, directly packaging the php source code into a file:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Before doing the packaging process, you should use `build --build-micro` to compile micro.sfx
|
|
||||||
echo "<?php echo 'hello';" > a.php
|
|
||||||
bin/spc micro:combine a.php
|
|
||||||
|
|
||||||
# Just use it
|
|
||||||
./my-app
|
|
||||||
```
|
|
||||||
|
|
||||||
You can use the following options to specify the file name to be output, and you can also specify micro.sfx in other paths for packaging.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# specify the output filename
|
|
||||||
bin/spc micro:combine a.php --output=custom-bin
|
|
||||||
# Use absolute path
|
|
||||||
bin/spc micro:combine a.php -O /tmp/my-custom-app
|
|
||||||
|
|
||||||
# Specify micro.sfx in other locations for packaging
|
|
||||||
bin/spc micro:combine a.app --with-micro=/path/to/your/micro.sfx
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to inject ini configuration items, you can use the following parameters to add ini to the executable file from a file or command line option.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Specified using command-line options (-I is shorthand for --with-ini-set)
|
|
||||||
bin/spc micro:combine a.php -I "a=b" -I "foo=bar"
|
|
||||||
|
|
||||||
# Use ini file specification (-N is shorthand for --with-ini-file)
|
|
||||||
bin/spc micro:combine a.php -N /path/to/your/custom.ini
|
|
||||||
```
|
|
||||||
|
|
||||||
::: warning
|
|
||||||
Note, please do not directly use the PHP source code or the `php.ini` file in the system-installed PHP,
|
|
||||||
it is best to manually write an ini configuration file that you need, for example:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
; custom.ini
|
|
||||||
curl.cainfo=/path/to/your/cafile.pem
|
|
||||||
memory_limit=1G
|
|
||||||
```
|
|
||||||
|
|
||||||
The ini injection of this command is achieved by appending a special structure after micro.sfx,
|
|
||||||
which is different from the function of inserting hard-coded INI during compilation.
|
|
||||||
:::
|
|
||||||
|
|
||||||
If you want to package phar, just replace `a.php` with the packaged phar file.
|
|
||||||
But please note that micro.sfx under phar needs extra attention to the path problem, see [Developing - Phar directory issue](../develop/structure#phar-application-directory-issue).
|
|
||||||
|
|
||||||
## Command - extract
|
|
||||||
|
|
||||||
Use the command `bin/spc extract` to unpack and copy the source code required for compilation,
|
|
||||||
including php-src and the source code of various dependent libraries (you need to specify the name of the library to be unpacked).
|
|
||||||
|
|
||||||
For example, after we have downloaded sources, we want to distribute and execute the build process,
|
|
||||||
manually unpack and copy the package to a specified location, and we can use commands.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Unzip the downloaded compressed package of php-src and libxml2, and store the decompressed source code in the source directory
|
|
||||||
bin/spc extract php-src,libxml2
|
|
||||||
```
|
|
||||||
|
|
||||||
## Command - dump-extensions
|
|
||||||
|
|
||||||
Use the command `bin/spc dump-extensions` to export required extensions of the current project.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Print the extension list of the project, pass in the root directory of the project containing composer.json
|
|
||||||
bin/spc dump-extensions /path/to/your/project/
|
|
||||||
|
|
||||||
# Print the extension list of the project, excluding development dependencies
|
|
||||||
bin/spc dump-extensions /path-to/tour/project/ --no-dev
|
|
||||||
|
|
||||||
# Output in the extension list format acceptable to the spc command (comma separated)
|
|
||||||
bin/spc dump-extensions /path-to/tour/project/ --format=text
|
|
||||||
|
|
||||||
# Output as a JSON list
|
|
||||||
bin/spc dump-extensions /path-to/tour/project/ --format=json
|
|
||||||
|
|
||||||
# When the project does not have any extensions, output the specified extension combination instead of returning failure
|
|
||||||
bin/spc dump-extensions /path-to/your/project/ --no-ext-output=mbstring,posix,pcntl,phar
|
|
||||||
|
|
||||||
# Do not exclude extensions not supported by spc when outputting
|
|
||||||
bin/spc dump-extensions /path/to/your/project/ --no-spc-filter
|
|
||||||
```
|
|
||||||
It should be noted that the project directory must contain the `vendor/installed.json` and `composer.lock` files, otherwise they cannot be found normally.
|
|
||||||
|
|
||||||
## Dev Command - dev
|
|
||||||
|
|
||||||
Debug commands refer to a collection of commands that can assist in outputting some information
|
|
||||||
when you use static-php-cli to build PHP or modify and enhance the static-php-cli project itself.
|
|
||||||
|
|
||||||
- `dev:extensions`: output all currently supported extension names, or output the specified extension information
|
|
||||||
- `dev:php-version`: output the currently compiled PHP version (by reading `php_version.h`)
|
|
||||||
- `dev:sort-config`: Sort the list of configuration files in the `config/` directory in alphabetical order
|
|
||||||
- `dev:lib-ver <lib-name>`: Read the version from the source code of the dependency library (only available for specific dependency libraries)
|
|
||||||
- `dev:ext-ver <ext-name>`: Read the corresponding version from the source code of the extension (only available for specific extensions)
|
|
||||||
- `dev:pack-lib <lib-name>`: Package the specified library into a tar.gz file (maintainer only)
|
|
||||||
- `dev:gen-ext-docs`: Generate extension documentation (maintainer only)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# output all extensions information
|
|
||||||
bin/spc dev:extensions
|
|
||||||
|
|
||||||
# Output the meta information of the specified extension
|
|
||||||
bin/spc dev:extensions mongodb,curl,openssl
|
|
||||||
|
|
||||||
# Output the specified columns
|
|
||||||
# Available column name: lib-depends, lib-suggests, ext-depends, ext-suggests, unix-only, type
|
|
||||||
bin/spc dev:extensions --columns=lib-depends,type,ext-depends
|
|
||||||
|
|
||||||
# Output the currently compiled PHP version
|
|
||||||
# You need to decompress the downloaded PHP source code to the source directory first
|
|
||||||
# You can use `bin/spc extract php-src` to decompress the source code separately
|
|
||||||
bin/spc dev:php-version
|
|
||||||
|
|
||||||
# Sort the configuration files in the config/ directory in alphabetical order (e.g. ext.json)
|
|
||||||
bin/spc dev:sort-config ext
|
|
||||||
```
|
|
||||||
|
|
||||||
## Command - install-pkg
|
|
||||||
|
|
||||||
Use the command `bin/spc install-pkg` to download some precompiled or closed source tools and install them into the `pkgroot` directory.
|
|
||||||
|
|
||||||
When `bin/spc doctor` automatically repairs the Windows environment, tools such as nasm and perl will be downloaded, and the installation process of `install-pkg` will also be used.
|
|
||||||
|
|
||||||
Here is an example of installing the tool:
|
|
||||||
|
|
||||||
- Download and install UPX (Linux and Windows only): `bin/spc install-pkg upx`
|
|
||||||
- Download and install nasm (Windows only): `bin/spc install-pkg nasm`
|
|
||||||
- Download and install go-xcaddy: `bin/spc install-pkg go-xcaddy`
|
|
||||||
|
|
||||||
## Command - del-download
|
|
||||||
|
|
||||||
In some cases, you need to delete single or multiple specified download source files and re-download them, such as switching PHP versions.
|
|
||||||
The `bin/spc del-download` command is provided after the `2.1.0-beta.4` version. Specified source files can be deleted.
|
|
||||||
|
|
||||||
Deletes downloaded source files containing precompiled packages and source code named as keys in `source.json` or `pkg.json`. Here are some examples:
|
|
||||||
|
|
||||||
- Delete the old PHP source code and switch to download the 8.3 version: `bin/spc del-download php-src && bin/spc download php-src --with-php=8.3`
|
|
||||||
- Delete the download file of redis extension: `bin/spc del-download redis`
|
|
||||||
- Delete the downloaded musl-toolchain x86_64: `bin/spc del-download musl-toolchain-x86_64-linux`
|
|
||||||
|
|
||||||
## Inject External Script
|
|
||||||
|
|
||||||
Injecting external scripts refers to inserting one or more scripts during the static-php-cli compilation process
|
|
||||||
to more flexibly support parameter modifications and source code patches in different environments.
|
|
||||||
|
|
||||||
Under normal circumstances, this function mainly solves the problem that the patch cannot be modified
|
|
||||||
by modifying the static-php-cli code when compiling with `spc` binary.
|
|
||||||
|
|
||||||
There is another situation: your project directly depends on the `crazywhalecc/static-php-cli` repository and is synchronized with main branch,
|
|
||||||
but some proprietary modifications are required, and these feature are not suitable for merging into the main branch.
|
|
||||||
|
|
||||||
In view of the above situation, in the official version 2.0.0, static-php-cli has added multiple event trigger points.
|
|
||||||
You can write an external `xx.php` script and pass it in through the command line parameter `-P` and execute.
|
|
||||||
|
|
||||||
When writing to inject external scripts, the methods you will use are `builder()` and `patch_point()`.
|
|
||||||
Among them, `patch_point()` obtains the name of the current event, and `builder()` obtains the BuilderBase object.
|
|
||||||
|
|
||||||
Because the incoming patch point does not distinguish between events,
|
|
||||||
you must write the code you want to execute in `if(patch_point() === 'your_event_name')`,
|
|
||||||
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 |
|
|
||||||
| 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:
|
|
||||||
|
|
||||||
```php
|
|
||||||
// a.php
|
|
||||||
<?php
|
|
||||||
// patch it before `./buildconf` executed
|
|
||||||
if (patch_point() === 'before-php-buildconf') {
|
|
||||||
\SPC\store\FileSystem::replaceFileStr(
|
|
||||||
SOURCE_PATH . '/php-src/sapi/cli/php_cli.c',
|
|
||||||
'sapi_module->php_ini_ignore_cwd = 1;',
|
|
||||||
'sapi_module->php_ini_ignore_cwd = 0;'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc build mbstring --build-cli -P a.php
|
|
||||||
# Write in ./
|
|
||||||
echo 'memory_limit=8G' > ./php.ini
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
$ buildroot/bin/php -i | grep Loaded
|
|
||||||
Loaded Configuration File => /Users/jerry/project/git-project/static-php-cli/php.ini
|
|
||||||
|
|
||||||
$ buildroot/bin/php -i | grep memory
|
|
||||||
memory_limit => 8G => 8G
|
|
||||||
```
|
|
||||||
|
|
||||||
For the objects, methods and interfaces supported by static-php-cli, you can read the source code. Most methods and objects have corresponding comments.
|
|
||||||
|
|
||||||
Commonly used objects and functions using the `-P` function are:
|
|
||||||
|
|
||||||
- `SPC\store\FileSystem`: file management class
|
|
||||||
- `::replaceFileStr(string $filename, string $search, $replace)`: Replace file string content
|
|
||||||
- `::replaceFileStr(string $filename, string $pattern, $replace)`: Regularly replace file content
|
|
||||||
- `::replaceFileUser(string $filename, $callback)`: User-defined function replaces file content
|
|
||||||
- `::copyDir(string $from, string $to)`: Recursively copy a directory to another location
|
|
||||||
- `::convertPath(string $path)`: Convert the path delimiter to the current system delimiter
|
|
||||||
- `::scanDirFiles(string $dir, bool $recursive = true, bool|string $relative = false, bool $include_dir = false)`: Traverse directory files
|
|
||||||
- `SPC\builder\BuilderBase`: Build object
|
|
||||||
- `->getPatchPoint()`: Get the current injection point name
|
|
||||||
- `->getOption(string $key, $default = null)`: Get command line and compile-time options
|
|
||||||
- `->getPHPVersionID()`: Get the currently compiled PHP version ID
|
|
||||||
- `->getPHPVersion()`: Get the currently compiled PHP version number
|
|
||||||
- `->setOption(string $key, $value)`: Set options
|
|
||||||
- `->setOptionIfNotExists(string $key, $value)`: Set option if option does not exist
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
static-php-cli has many open methods, which cannot be listed in the docs,
|
|
||||||
but as long as it is a `public function` and is not marked as `@internal`, it theoretically can be called.
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Multiple builds
|
|
||||||
|
|
||||||
If you need to build multiple times locally, the following method can save you time downloading resources and compiling.
|
|
||||||
|
|
||||||
- If you only switch the PHP version without changing the dependent libraries, you can use `bin/spc switch-php-version` to quickly switch the PHP version, and then re-run the same `build` command.
|
|
||||||
- If you want to rebuild once, but do not re-download the source code, you can first `rm -rf buildroot source` to delete the compilation directory and source code directory, and then rebuild.
|
|
||||||
- If you want to update a version of a dependency, you can use `bin/spc del-download <source-name>` to delete the specified source code, and then use `download <source-name>` to download it again.
|
|
||||||
- If you want to update all dependent versions, you can use `bin/spc download --clean` to delete all downloaded sources, and then download them again.
|
|
||||||
|
|
||||||
## embed usage
|
|
||||||
|
|
||||||
If you want to embed static-php into other C language programs, you can use `--build-embed` to build an embed version of PHP.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc build {your extensions} --build-embed --debug
|
|
||||||
```
|
|
||||||
|
|
||||||
Under normal circumstances, PHP embed will generate `php-config` after compilation.
|
|
||||||
For static-php, we provide `spc-config` to obtain the parameters during compilation.
|
|
||||||
In addition, when using embed SAPI (libphp.a), you need to use the same compiler as libphp, otherwise there will be a link error.
|
|
||||||
|
|
||||||
Here is the basic usage of spc-config:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# output all flags and options
|
|
||||||
bin/spc spc-config curl,zlib,phar,openssl
|
|
||||||
|
|
||||||
# output libs
|
|
||||||
bin/spc spc-config curl,zlib,phar,openssl --libs
|
|
||||||
|
|
||||||
# output includes
|
|
||||||
bin/spc spc-config curl,zlib,phar,openssl --includes
|
|
||||||
```
|
|
||||||
|
|
||||||
By default, static-php uses the following compilers on different systems:
|
|
||||||
|
|
||||||
- macOS: `clang`
|
|
||||||
- Linux (Alpine Linux): `gcc`
|
|
||||||
- Linux (glibc based distros, x86_64): `/usr/local/musl/bin/x86_64-linux-musl-gcc`
|
|
||||||
- Linux (glibc based distros, aarch64): `/usr/local/musl/bin/aarch64-linux-musl-gcc`
|
|
||||||
- FreeBSD: `clang`
|
|
||||||
|
|
||||||
Here is an example of using embed SAPI:
|
|
||||||
|
|
||||||
```c
|
|
||||||
// embed.c
|
|
||||||
#include <sapi/embed/php_embed.h>
|
|
||||||
|
|
||||||
int main(int argc,char **argv){
|
|
||||||
|
|
||||||
PHP_EMBED_START_BLOCK(argc,argv)
|
|
||||||
|
|
||||||
zend_file_handle file_handle;
|
|
||||||
|
|
||||||
zend_stream_init_filename(&file_handle,"embed.php");
|
|
||||||
|
|
||||||
if(php_execute_script(&file_handle) == FAILURE){
|
|
||||||
php_printf("Failed to execute PHP script.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
PHP_EMBED_END_BLOCK()
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
// embed.php
|
|
||||||
echo "Hello world!\n";
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# compile in debian/ubuntu x86_64
|
|
||||||
/usr/local/musl/bin/x86_64-linux-musl-gcc embed.c $(bin/spc spc-config bcmath,zlib) -static -o embed
|
|
||||||
# compile in macOS/FreeBSD
|
|
||||||
clang embed.c $(bin/spc spc-config bcmath,zlib) -o embed
|
|
||||||
|
|
||||||
./embed
|
|
||||||
# out: Hello world!
|
|
||||||
```
|
|
||||||
277
docs/en/guide/sapi-reference.md
Normal file
277
docs/en/guide/sapi-reference.md
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
---
|
||||||
|
outline: 'deep'
|
||||||
|
---
|
||||||
|
|
||||||
|
# PHP SAPI Reference
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
If you installed spc as a pre-built binary, replace every `spc` in this page with `./spc` (or `.\spc.exe` on Windows).
|
||||||
|
|
||||||
|
If you installed from source, use `bin/spc` instead.
|
||||||
|
:::
|
||||||
|
|
||||||
|
This page describes the build options and usage for each PHP SAPI supported by StaticPHP.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
| SAPI | Build flag | Output path (Linux/macOS) | Output path (Windows) | Platform support |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| cli | `--build-cli` | `buildroot/bin/php` | `buildroot/bin/php.exe` | Linux, macOS, Windows |
|
||||||
|
| fpm | `--build-fpm` | `buildroot/bin/php-fpm` | — | Linux, macOS |
|
||||||
|
| micro | `--build-micro` | `buildroot/bin/micro.sfx` | `buildroot/bin/micro.sfx` | Linux, macOS, Windows |
|
||||||
|
| embed | `--build-embed` | `buildroot/lib/libphp.a` | `buildroot/lib/php8embed.lib` | Linux, macOS, Windows |
|
||||||
|
| frankenphp | `--build-frankenphp` | `buildroot/bin/frankenphp` | `buildroot/bin/frankenphp.exe` | Linux, macOS, Windows |
|
||||||
|
|
||||||
|
## cli
|
||||||
|
|
||||||
|
The `cli` SAPI is the standard PHP command-line binary for running scripts, interactive shells, and CLI applications.
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,openssl,curl" --build-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
The output is `buildroot/bin/php` on Linux and macOS, and `buildroot/bin/php.exe` on Windows.
|
||||||
|
|
||||||
|
See [build:php — SAPI Selection](./cli-reference#sapi-selection) and [build:php — Common Build Options](./cli-reference#common-build-options) for the full option reference.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check version and loaded extensions
|
||||||
|
./buildroot/bin/php -v
|
||||||
|
./buildroot/bin/php -m
|
||||||
|
|
||||||
|
# Run a script
|
||||||
|
./buildroot/bin/php your-script.php
|
||||||
|
|
||||||
|
# Interactive mode
|
||||||
|
./buildroot/bin/php -a
|
||||||
|
```
|
||||||
|
|
||||||
|
### php.ini search path
|
||||||
|
|
||||||
|
The static PHP cli binary searches for `php.ini` in this order:
|
||||||
|
|
||||||
|
1. The path specified with the `-c /path/to/php.ini` command-line flag
|
||||||
|
2. The path set in the `PHP_INI_PATH` environment variable
|
||||||
|
3. The directory specified at compile time via `--with-config-file-path` (default: `/usr/local/etc/php`)
|
||||||
|
|
||||||
|
Run `./buildroot/bin/php --ini` to see which ini file is actually loaded.
|
||||||
|
|
||||||
|
### Hard-coded INI
|
||||||
|
|
||||||
|
Use `-I` at build time to bake INI settings directly into the binary, so no external `php.ini` is required:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,pcntl" --build-cli -I "memory_limit=4G" -I "disable_functions=system,exec"
|
||||||
|
```
|
||||||
|
|
||||||
|
Hard-coded INI applies to the `cli`, `micro`, and `embed` SAPIs.
|
||||||
|
|
||||||
|
## fpm
|
||||||
|
|
||||||
|
The `fpm` SAPI (FastCGI Process Manager) is used with web servers such as Nginx or Apache for traditional web application deployments.
|
||||||
|
|
||||||
|
::: warning
|
||||||
|
`fpm` is not supported on Windows.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,openssl,curl,pdo_mysql" --build-fpm
|
||||||
|
```
|
||||||
|
|
||||||
|
The output is `buildroot/bin/php-fpm`.
|
||||||
|
|
||||||
|
See [build:php — SAPI Selection](./cli-reference#sapi-selection) and [build:php — Common Build Options](./cli-reference#common-build-options) for the full option reference.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
Copy `buildroot/bin/php-fpm` to your server and use it like a regular `php-fpm` binary:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check version
|
||||||
|
./buildroot/bin/php-fpm -v
|
||||||
|
|
||||||
|
# Start with a specific config file
|
||||||
|
./buildroot/bin/php-fpm -c /path/to/php.ini -y /path/to/php-fpm.conf
|
||||||
|
|
||||||
|
# Test config file
|
||||||
|
./buildroot/bin/php-fpm -t
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: Nginx + php-fpm
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
root /var/www/html;
|
||||||
|
index index.php;
|
||||||
|
|
||||||
|
location ~ \.php$ {
|
||||||
|
fastcgi_pass 127.0.0.1:9000;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
include fastcgi_params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Example `php-fpm.conf`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[global]
|
||||||
|
pid = /var/run/php-fpm.pid
|
||||||
|
error_log = /var/log/php-fpm.log
|
||||||
|
|
||||||
|
[www]
|
||||||
|
listen = 127.0.0.1:9000
|
||||||
|
pm = dynamic
|
||||||
|
pm.max_children = 5
|
||||||
|
pm.start_servers = 2
|
||||||
|
pm.min_spare_servers = 1
|
||||||
|
pm.max_spare_servers = 3
|
||||||
|
```
|
||||||
|
|
||||||
|
## micro
|
||||||
|
|
||||||
|
The `micro` SAPI is built on [phpmicro](https://github.com/easysoft/phpmicro) and produces a self-contained executable stub. With `spc micro:combine`, you can merge `micro.sfx` with your PHP code into a single portable binary that requires no PHP installation on the target machine.
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,phar,openssl,curl" --build-micro
|
||||||
|
```
|
||||||
|
|
||||||
|
The output is `buildroot/bin/micro.sfx`.
|
||||||
|
|
||||||
|
See [build:php — SAPI Selection](./cli-reference#sapi-selection), [build:php — Common Build Options](./cli-reference#common-build-options), and [build:php — micro Options](./cli-reference#micro-options) for the full option reference.
|
||||||
|
|
||||||
|
### Packaging an application
|
||||||
|
|
||||||
|
Use `micro:combine` to bundle a PHP script or phar into a standalone executable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Bundle a PHP script
|
||||||
|
echo "<?php echo 'Hello, World!' . PHP_EOL;" > hello.php
|
||||||
|
spc micro:combine hello.php --output=hello
|
||||||
|
./hello
|
||||||
|
|
||||||
|
# Bundle a phar
|
||||||
|
spc micro:combine your-app.phar --output=your-app
|
||||||
|
./your-app
|
||||||
|
```
|
||||||
|
|
||||||
|
### Injecting INI settings
|
||||||
|
|
||||||
|
INI configuration can be injected at packaging time via command-line options or an ini file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Inject via command-line options (-I is shorthand for --with-ini-set)
|
||||||
|
spc micro:combine your-app.phar --output=your-app -I "memory_limit=512M" -I "curl.cainfo=/etc/ssl/certs/ca-certificates.crt"
|
||||||
|
|
||||||
|
# Inject from an ini file (-N is shorthand for --with-ini-file)
|
||||||
|
spc micro:combine your-app.phar --output=your-app -N /path/to/custom.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
The INI injected with `-I` here is runtime configuration appended to the `micro.sfx` file as a special structure. This is distinct from INI hard-coded at compile time using `-I` during `build:php`. Both can coexist.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Pretending to be the cli SAPI
|
||||||
|
|
||||||
|
Some frameworks check the `PHP_SAPI` value and refuse to run outside `cli`. Since `micro`'s `PHP_SAPI` is `micro` by default, you can make it report `cli` instead:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,phar" --build-micro --with-micro-fake-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
### Specifying a custom micro.sfx path
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc micro:combine your-app.phar --output=your-app --with-micro=/path/to/your/micro.sfx
|
||||||
|
```
|
||||||
|
|
||||||
|
### phar path considerations
|
||||||
|
|
||||||
|
When packaging a phar, internal relative paths may behave differently than expected. See the [Developer Guide — Phar directory issue](../develop/structure) for details.
|
||||||
|
|
||||||
|
## embed
|
||||||
|
|
||||||
|
The `embed` SAPI compiles PHP into a static library (`libphp.a` on Linux/macOS, `php8embed.lib` on Windows) that can be linked into C/C++ programs to run PHP code directly.
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,openssl" --build-embed
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
- Linux/macOS: `buildroot/lib/libphp.a`, headers in `buildroot/include/`
|
||||||
|
- Windows: `buildroot/lib/php8embed.lib`, headers in `buildroot/include/`
|
||||||
|
|
||||||
|
See [build:php — SAPI Selection](./cli-reference#sapi-selection), [build:php — Common Build Options](./cli-reference#common-build-options), and [build:php — embed Options](./cli-reference#embed-options) for the full option reference.
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
Detailed instructions for linking and using `libphp.a` / `php8embed.lib` in your own projects — including compiler selection, `dev:shell` usage, and a complete C example — will be covered in the Developer Guide.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## frankenphp
|
||||||
|
|
||||||
|
The `frankenphp` SAPI builds a [FrankenPHP](https://github.com/php/frankenphp) binary — a modern PHP application server with Caddy built in, supporting HTTP/2, HTTP/3, automatic HTTPS, and more.
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
The `frankenphp` binary produced by StaticPHP is a fully self-contained single-file executable. This is different from the official FrankenPHP release, which ships as a dynamically linked binary and requires a separate PHP installation.
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: warning
|
||||||
|
FrankenPHP requires thread-safe mode. Always pass `--enable-zts` when building.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,openssl,curl,pdo_mysql" --build-frankenphp --enable-zts
|
||||||
|
```
|
||||||
|
|
||||||
|
The output is `buildroot/bin/frankenphp` on Linux/macOS, and `buildroot/bin/frankenphp.exe` on Windows.
|
||||||
|
|
||||||
|
See [build:php — SAPI Selection](./cli-reference#sapi-selection), [build:php — Common Build Options](./cli-reference#common-build-options), and [build:php — frankenphp Options](./cli-reference#frankenphp-options) for the full option reference.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check version
|
||||||
|
./buildroot/bin/frankenphp version
|
||||||
|
|
||||||
|
# Run in PHP development server mode
|
||||||
|
./buildroot/bin/frankenphp php-server
|
||||||
|
|
||||||
|
# Run with a Caddyfile
|
||||||
|
./buildroot/bin/frankenphp run --config /path/to/Caddyfile
|
||||||
|
```
|
||||||
|
|
||||||
|
For full usage, refer to the [FrankenPHP documentation](https://frankenphp.dev/docs/).
|
||||||
|
|
||||||
|
## Dynamic Extension Loading
|
||||||
|
|
||||||
|
Whether a static PHP binary can load extensions at runtime via `dl()` depends on how the binary was linked.
|
||||||
|
|
||||||
|
**macOS** — The build always links dynamically against system libraries. Extensions built as `.so` files can be loaded at runtime via `dl()` or `php.ini` as usual.
|
||||||
|
|
||||||
|
**Linux** — StaticPHP's default build target is `native-native-musl`: a fully static binary linked against musl libc. Because there is no dynamic linker available at runtime, `dl()` is disabled, the FFI extension cannot be used, and no external `.so` extensions can be loaded.
|
||||||
|
|
||||||
|
To support dynamic extension loading on Linux, set the `SPC_TARGET` environment variable before building:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SPC_TARGET=native-native-gnu.2.17 spc build:php "bcmath,openssl" --build-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
If you installed from source, you can also set `SPC_TARGET=native-native-gnu.2.17` in `config/env.ini` to make it the default for all builds.
|
||||||
|
|
||||||
|
This uses the Zig toolchain to produce a partially static binary dynamically linked against glibc 2.17, compatible with most modern GNU/Linux distributions. No Docker and no extra cross-compilation toolchain are required. The resulting binary supports `dl()`, FFI, and loading `.so` extensions at runtime, but cannot run on musl-based systems such as Alpine Linux.
|
||||||
|
|
||||||
|
**Windows** — PHP extensions on Windows are distributed as `.dll` files that depend on the DLLs bundled with the official dynamically-built PHP. StaticPHP produces a standalone static executable that does not include those DLLs, so dynamic extension loading is not possible on Windows. All extensions must be compiled in statically at build time.
|
||||||
|
|
||||||
@@ -1,42 +1,43 @@
|
|||||||
# Troubleshooting
|
# Troubleshooting
|
||||||
|
|
||||||
Various failures may be encountered in the process of using static-php-cli,
|
Various failures may be encountered in the process of using StaticPHP,
|
||||||
here will describe how to check the errors by yourself and report Issue.
|
here will describe how to check the errors by yourself and report an Issue.
|
||||||
|
|
||||||
## Download Failure
|
## Download Failure
|
||||||
|
|
||||||
Problems with downloading resources are one of the most common problems with spc.
|
Problems with downloading resources are one of the most common problems with spc.
|
||||||
The main reason is that the addresses used for SPC download resources are generally the official website of the corresponding project or GitHub, etc.,
|
The main reason is that the addresses used for SPC download resources are generally the official website of the corresponding project or GitHub, etc.,
|
||||||
and these websites may occasionally go down and block IP addresses.
|
and these websites may occasionally go down and block IP addresses.
|
||||||
After encountering a download failure,
|
After encountering a download failure,
|
||||||
you can try to call the download command multiple times.
|
you can try to call the download command multiple times.
|
||||||
|
|
||||||
When downloading extensions, you may eventually see errors like `curl: (56) The requested URL returned error: 403` which are often caused by github rate limiting.
|
When downloading extensions, you may eventually see errors like `curl: (56) The requested URL returned error: 403` which are often caused by GitHub rate limiting.
|
||||||
You can verify this by adding `--debug` to the command and will see something like `[DEBU] Running command (no output) : curl -sfSL "https://api.github.com/repos/openssl/openssl/releases"`.
|
You can verify this by adding `-vvv` to the command and will see something like `[DEBU] Running command (no output) : curl -sfSL "https://api.github.com/repos/openssl/openssl/releases"`.
|
||||||
|
|
||||||
To fix this, [create](https://github.com/settings/tokens) a personal access token on GitHub and set it as an environment variable `GITHUB_TOKEN=<XXX>`.
|
To fix this, [create](https://github.com/settings/tokens) a personal access token on GitHub and set it as an environment variable `GITHUB_TOKEN=<XXX>`.
|
||||||
|
|
||||||
If you confirm that the address is indeed inaccessible,
|
If you confirm that the address is indeed inaccessible,
|
||||||
you can submit an Issue or PR to update the url or download type.
|
you can submit an Issue or PR to update the url or download type.
|
||||||
|
|
||||||
## Doctor Can't Fix Something
|
## Doctor Can't Fix Something
|
||||||
|
|
||||||
In most cases, the doctor module can automatically repair and install missing system environments,
|
In most cases, the doctor module can automatically repair and install missing system environments,
|
||||||
but there are also special circumstances where the automatic repair function cannot be used normally.
|
but there are also special circumstances where the automatic repair function cannot be used normally.
|
||||||
|
|
||||||
Due to system limitations (for example, software such as Visual Studio cannot be automatically installed under Windows),
|
Due to system limitations (for example, software such as Visual Studio cannot be automatically installed under Windows),
|
||||||
the automatic repair function cannot be used for some projects.
|
the automatic repair function cannot be used for some projects.
|
||||||
When encountering a function that cannot be automatically repaired,
|
When encountering a function that cannot be automatically repaired,
|
||||||
if you encounter the words `Some check items can not be fixed`,
|
if you encounter the words `Some check items can not be fixed`,
|
||||||
it means that it cannot be automatically repaired.
|
it means that it cannot be automatically repaired.
|
||||||
Please submit an issue according to the method displayed on the terminal or repair the environment yourself.
|
Please submit an issue according to the method displayed on the terminal or repair the environment yourself.
|
||||||
|
|
||||||
## Compile Error
|
## Compile Error
|
||||||
|
|
||||||
When you encounter a compilation error, if the `--debug` log is not enabled, please enable the debug log first,
|
When you encounter a compilation error, if the `-vvv` log is not enabled, please enable the debug log first,
|
||||||
and then determine the command that reported the error.
|
and then determine the command that reported the error.
|
||||||
The error terminal output is very important for fixing compilation errors.
|
The error terminal output is very important for fixing compilation errors.
|
||||||
When submitting an issue, please upload the last error fragment of the terminal log (or the entire terminal log output),
|
When submitting an issue, please upload the last error fragment of the terminal log (or the entire terminal log output),
|
||||||
and include the `spc` command and parameters used.
|
and include the `spc` command and parameters used.
|
||||||
|
|
||||||
If you are rebuilding, please refer to the [Local Build - Multiple Builds](./manual-build#multiple-builds) section.
|
If you are rebuilding, please refer to the [First Build - Debugging and Rebuilding](./first-build#debugging-and-rebuilding) section.
|
||||||
|
|
||||||
|
|||||||
@@ -3,23 +3,26 @@
|
|||||||
layout: home
|
layout: home
|
||||||
|
|
||||||
hero:
|
hero:
|
||||||
name: "Static PHP"
|
name: "StaticPHP"
|
||||||
tagline: "Build standalone PHP binary on Linux, macOS, FreeBSD, Windows, with PHP project together, with popular extensions included."
|
tagline: "StaticPHP is a powerful tool designed for building portable executables including PHP, extensions, and more."
|
||||||
image:
|
image:
|
||||||
src: /images/static-php_nobg.png
|
src: /images/static-php_nobg.png
|
||||||
alt: Static PHP CLI Logo
|
alt: StaticPHP Logo
|
||||||
actions:
|
actions:
|
||||||
- theme: brand
|
- theme: brand
|
||||||
text: Get Started
|
text: Get Started
|
||||||
link: ./guide/
|
link: /en/guide/
|
||||||
|
- theme: alt
|
||||||
|
text: 中文文档
|
||||||
|
link: /zh/
|
||||||
|
|
||||||
features:
|
features:
|
||||||
- title: Static CLI Binary
|
- title: Static PHP Binary
|
||||||
details: You can easily compile a standalone php binary for general use. Including CLI, FPM sapi.
|
details: You can easily compile a standalone php binary for general use. Including cli, fpm, cgi, frankenphp SAPI.
|
||||||
- title: Micro Self-Extracted Executable
|
- title: Micro Self-Extracted Executable
|
||||||
details: You can compile a self-extracted executable and build with your php source code.
|
details: You can compile a self-extracted executable and build with your php source code using micro SAPI.
|
||||||
- title: Dependency Management
|
- title: Dependency Management
|
||||||
details: static-php-cli comes with dependency management and supports installation of different types of PHP extensions.
|
details: StaticPHP comes with dependency management and supports installation of different types of PHP extensions, packages and libraries.
|
||||||
---
|
---
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
> This file is dynamically generated by `bin/spc dev:gen-ext-docs` command.
|
|
||||||
@@ -3,11 +3,11 @@
|
|||||||
layout: home
|
layout: home
|
||||||
|
|
||||||
hero:
|
hero:
|
||||||
name: "Static PHP"
|
name: "StaticPHP"
|
||||||
tagline: "Build standalone PHP binary on Linux, macOS, FreeBSD, Windows, with PHP project together, with popular extensions included."
|
tagline: "StaticPHP is a powerful tool designed for building portable executables including PHP, extensions, and more."
|
||||||
image:
|
image:
|
||||||
src: /images/static-php_nobg.png
|
src: /images/static-php_nobg.png
|
||||||
alt: Static PHP CLI Logo
|
alt: StaticPHP Logo
|
||||||
actions:
|
actions:
|
||||||
- theme: brand
|
- theme: brand
|
||||||
text: Get Started
|
text: Get Started
|
||||||
@@ -17,12 +17,12 @@ hero:
|
|||||||
link: /zh/
|
link: /zh/
|
||||||
|
|
||||||
features:
|
features:
|
||||||
- title: Static CLI Binary
|
- title: Static PHP Binary
|
||||||
details: You can easily compile a standalone php binary for general use. Including CLI, FPM sapi.
|
details: You can easily compile a standalone php binary for general use. Including cli, fpm, cgi, frankenphp SAPI.
|
||||||
- title: Micro Self-Extracted Executable
|
- title: Micro Self-Extracted Executable
|
||||||
details: You can compile a self-extracted executable and build with your php source code.
|
details: You can compile a self-extracted executable and build with your php source code using micro SAPI.
|
||||||
- title: Dependency Management
|
- title: Dependency Management
|
||||||
details: static-php-cli comes with dependency management and supports installation of different types of PHP extensions.
|
details: StaticPHP comes with dependency management and supports installation of different types of PHP extensions, packages and libraries.
|
||||||
---
|
---
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
static-php.dev
|
|
||||||
@@ -1,51 +1,5 @@
|
|||||||
# 贡献指南
|
# 贡献指南
|
||||||
|
|
||||||
感谢你能够看到这里,本项目非常欢迎你的贡献!
|
<!-- TODO: v3 贡献指南。
|
||||||
|
章节:代码风格(php-cs-fixer、phpstan)、新增 library/extension、
|
||||||
## 贡献方法
|
新增 doctor 检查项、提交 PR、安全漏洞披露。 -->
|
||||||
|
|
||||||
如果你有代码或文档要贡献,以下是你需要首先了解的内容。
|
|
||||||
|
|
||||||
1. 你要贡献什么类型的代码?(新扩展、修复 Bug、安全问题、项目框架优化、文档)
|
|
||||||
2. 如果你贡献了新文件或新片段,你的代码是否经过 `php-cs-fixer` 和 `phpstan` 的检查?
|
|
||||||
3. 在贡献代码前是否充分阅读了 [开发指南](../develop/)?
|
|
||||||
|
|
||||||
如果你能回答上述问题并对代码进行了修改,可以及时在项目 GitHub 仓库发起 Pull Request。
|
|
||||||
代码审查完成后,可以根据建议修改代码,或直接合并到主分支。
|
|
||||||
|
|
||||||
## 贡献类型
|
|
||||||
|
|
||||||
本项目的主要目的是编译静态链接的 PHP 二进制文件,命令行处理功能基于 `symfony/console` 编写。
|
|
||||||
在开发之前,如果你对它不够熟悉,请先查看 [symfony/console 文档](https://symfony.com/doc/current/components/console.html)。
|
|
||||||
|
|
||||||
### 安全更新
|
|
||||||
|
|
||||||
因为本项目基本上是一个本地运行的 PHP 项目,一般来说不会有远程攻击。
|
|
||||||
但如果你发现此类问题,请**不要**在 GitHub 仓库提交 PR 或 Issue,
|
|
||||||
你需要通过 [邮件](mailto:admin@zhamao.me) 联系项目维护者(crazywhalecc)。
|
|
||||||
|
|
||||||
### 修复 Bug
|
|
||||||
|
|
||||||
修复 Bug 一般不涉及项目结构和框架的修改,所以如果你能定位到错误代码并直接修复它,请直接提交 PR。
|
|
||||||
|
|
||||||
### 新扩展
|
|
||||||
|
|
||||||
对于添加新扩展,你需要了解项目的一些基本结构以及如何根据现有逻辑添加新扩展。
|
|
||||||
这将在本页的下一节中详细介绍。
|
|
||||||
总的来说,你需要:
|
|
||||||
|
|
||||||
1. 评估扩展是否可以内联编译到 PHP 中。
|
|
||||||
2. 评估扩展的依赖库(如果有)是否可以静态编译。
|
|
||||||
3. 编写不同平台的库编译命令。
|
|
||||||
4. 验证扩展及其依赖项与现有扩展和依赖项兼容。
|
|
||||||
5. 验证扩展在 `cli`、`micro`、`fpm`、`embed` SAPIs 中正常工作。
|
|
||||||
6. 编写文档并添加你的扩展。
|
|
||||||
|
|
||||||
### 项目框架优化
|
|
||||||
|
|
||||||
如果你已经熟悉 `symfony/console` 的工作原理,并同时要对项目的框架进行一些修改或优化,请先了解以下事情:
|
|
||||||
|
|
||||||
1. 添加扩展不属于项目框架优化,但如果你在添加新扩展时发现必须优化框架,则需要先修改框架本身,然后再添加扩展。
|
|
||||||
2. 对于一些大规模逻辑修改(例如涉及 LibraryBase、Extension 对象等的修改),建议先提交 Issue 或 Draft PR 进行讨论。
|
|
||||||
3. 在项目早期,它是一个纯私有开发项目,代码中有一些中文注释。项目国际化后,你可以提交 PR 将这些注释翻译为英语。
|
|
||||||
4. 请不要在代码中提交更多无用的代码片段,例如大量未使用的变量、方法、类以及多次重写的代码。
|
|
||||||
|
|||||||
5
docs/zh/develop/build-lifecycle.md
Normal file
5
docs/zh/develop/build-lifecycle.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# 构建生命周期
|
||||||
|
|
||||||
|
<!-- TODO: 完整构建流水线阶段顺序说明。
|
||||||
|
各 Hook 触发时机:#[BeforeStage]、#[AfterStage]、#[PatchBeforeBuild]。
|
||||||
|
#[BuildFor] 运行时平台选择机制。典型 library 和 extension 构建的阶段顺序图示。 -->
|
||||||
@@ -2,6 +2,6 @@
|
|||||||
aside: false
|
aside: false
|
||||||
---
|
---
|
||||||
|
|
||||||
# craft.yml 配置
|
# craft.yml 配置详解
|
||||||
|
|
||||||
<!--@include: ../../deps-craft-yml.md-->
|
<!-- TODO: craft.yml 字段完整参考。 -->
|
||||||
|
|||||||
@@ -1,60 +1,4 @@
|
|||||||
# Doctor 模块
|
# Doctor 环境检查
|
||||||
|
|
||||||
Doctor 模块是一个较为独立的用于检查系统环境的模块,可使用命令 `bin/spc doctor` 进入,入口的命令类在 `DoctorCommand.php` 中。
|
<!-- TODO: 从 v2 doctor-module.md 迁移并更新。
|
||||||
|
涵盖 v3 变化:--auto-fix、.spc-doctor.lock、v3 工具链新增检查项。 -->
|
||||||
Doctor 模块是一个检查单,里面有一系列的检查项目和自动修复项目。这些项目都存放在 `src/SPC/doctor/item/` 目录中,
|
|
||||||
并且使用了两种 Attribute 用作检查项标记和自动修复项目标记:`#[AsCheckItem]` 和 `#[AsFixItem]`。
|
|
||||||
|
|
||||||
以现有的检查项 `if necessary tools are installed`,它是用于检查编译必需的包是否安装在 macOS 系统内,下面是它的源码:
|
|
||||||
|
|
||||||
```php
|
|
||||||
use SPC\doctor\AsCheckItem;
|
|
||||||
use SPC\doctor\AsFixItem;
|
|
||||||
use SPC\doctor\CheckResult;
|
|
||||||
|
|
||||||
#[AsCheckItem('if necessary tools are installed', limit_os: 'Darwin', level: 997)]
|
|
||||||
public function checkCliTools(): ?CheckResult
|
|
||||||
{
|
|
||||||
$missing = [];
|
|
||||||
foreach (self::REQUIRED_COMMANDS as $cmd) {
|
|
||||||
if ($this->findCommand($cmd) === null) {
|
|
||||||
$missing[] = $cmd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!empty($missing)) {
|
|
||||||
return CheckResult::fail('missing system commands: ' . implode(', ', $missing), 'build-tools', [$missing]);
|
|
||||||
}
|
|
||||||
return CheckResult::ok();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
属性的第一个参数就是检查项目的名称,后面的 `limit_os` 参数是限制了该检查项仅在指定的系统下触发,`level` 是执行该检查项的优先级,数字越大,优先级越高。
|
|
||||||
|
|
||||||
里面用到的 `$this->findCommand()` 方法为 `SPC\builder\traits\UnixSystemUtilTrait` 的方法,用途是查找系统命令所在位置,找不到时返回 NULL。
|
|
||||||
|
|
||||||
每个检查项的方法都应该返回一个 `SPC\doctor\CheckResult`:
|
|
||||||
|
|
||||||
- 在返回 `CheckResult::fail()` 时,第一个参数用于输出终端的错误提示,第二个参数是在这个检查项可自动修复时的修复项目名称。
|
|
||||||
- 在返回 `CheckResult::ok()` 时,表明检查通过。你也可以传递一个参数,用于返回检查结果,例如:`CheckResult::ok('OS supported')`。
|
|
||||||
- 在返回 `CheckResult::fail()` 时,如果包含了第三个参数,第三个参数的数组将被当作 `AsFixItem` 的参数。
|
|
||||||
|
|
||||||
下面是这个检查项对应的自动修复项的方法:
|
|
||||||
|
|
||||||
```php
|
|
||||||
#[AsFixItem('build-tools')]
|
|
||||||
public function fixBuildTools(array $missing): bool
|
|
||||||
{
|
|
||||||
foreach ($missing as $cmd) {
|
|
||||||
try {
|
|
||||||
shell(true)->exec('brew install ' . escapeshellarg($cmd));
|
|
||||||
} catch (RuntimeException) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`#[AsFixItem()]` 属性传入的参数即修复项的名称,该方法必须返回 True 或 False。当返回 False 时,表明自动修复失败,需要手动处理。
|
|
||||||
|
|
||||||
此处的代码中 `shell()->exec()` 是项目的执行命令的方法,用于替代 `exec()`、`system()`,同时提供了 debug、获取执行状态、进入目录等特性。
|
|
||||||
|
|||||||
@@ -1,27 +1,4 @@
|
|||||||
# 开发简介
|
# 开发简介
|
||||||
|
|
||||||
开发本项目需要安装部署 PHP 环境,以及一些 PHP 项目常用的扩展和 Composer。
|
<!-- TODO: 开发者简介、环境准备、所需 PHP 扩展。
|
||||||
|
Vendor 模式链接到 vendor-mode/,代码贡献链接到 contributing/。 -->
|
||||||
项目的开发环境和运行环境几乎完全一致。你可以参照 **手动构建** 部分安装系统 PHP 或使用本项目预构建的静态 PHP 作为环境。这里不再赘述。
|
|
||||||
|
|
||||||
抛开用途,本项目本身其实就是一个 `php-cli` 程序,你可以将它当作一个正常的 PHP 项目进行编辑和开发,同时你需要了解不同系统的 Shell 命令行。
|
|
||||||
|
|
||||||
本项目目前的目的就是为了编译静态编译的独立 PHP,但主体部分也包含编译很多依赖库的静态版本,所以你可以复用这套编译逻辑,用于构建其他程序的独立二进制版本,例如 Nginx 等。
|
|
||||||
|
|
||||||
## 环境准备
|
|
||||||
|
|
||||||
开发本项目需要 PHP 环境。你可以使用系统自带的 PHP,也可以使用本项目构建的静态 PHP。
|
|
||||||
|
|
||||||
无论是使用哪种 PHP,在开发环境,你需要安装这些扩展:
|
|
||||||
|
|
||||||
```
|
|
||||||
curl,dom,filter,mbstring,openssl,pcntl,phar,posix,sodium,tokenizer,xml,xmlwriter
|
|
||||||
```
|
|
||||||
|
|
||||||
static-php-cli 项目本身不需要这么多扩展,但在开发过程中,你会用到 Composer 和 PHPUnit 等工具,它们需要这些扩展。
|
|
||||||
|
|
||||||
> 对于 static-php-cli 自身构建的 micro 自执行二进制,仅需要 `pcntl,posix,mbstring,tokenizer,phar`。
|
|
||||||
|
|
||||||
## 开始开发
|
|
||||||
|
|
||||||
继续向下查看项目结构文档,你可以学习 `static-php-cli` 是如何工作的。
|
|
||||||
|
|||||||
5
docs/zh/develop/package-model.md
Normal file
5
docs/zh/develop/package-model.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Package 模型
|
||||||
|
|
||||||
|
<!-- TODO: 统一 Package 模型说明:library / php-extension / target 类型。
|
||||||
|
config/pkg/ 下 per-package YAML 格式、depends 字段、平台覆盖(@windows / @unix 写法)。
|
||||||
|
artifact.source 和 artifact.binary 字段。附注释的 library 和 extension YAML 示例。 -->
|
||||||
@@ -1,51 +1,3 @@
|
|||||||
# 对 PHP 源码的修改
|
# 对 PHP 源码的修改
|
||||||
|
|
||||||
由于 static-php-cli 在静态编译过程中为了实现良好的兼容性、性能和安全性,对 PHP 源码进行了一些修改。下面是目前对 PHP 源码修改的说明。
|
<!-- TODO: 从 v2 php-src-changes.md 迁移并更新。补充 v3 新增 patch(FrankenPHP embed、Windows fiber 修复等)。 -->
|
||||||
|
|
||||||
## micro 相关补丁
|
|
||||||
|
|
||||||
基于 phpmicro 项目提供的补丁,static-php-cli 对 PHP 源码进行了一些修改,以适应静态编译的需求。[补丁列表](https://github.com/easysoft/phpmicro/tree/master/patches) 包含:
|
|
||||||
|
|
||||||
目前 static-php-cli 在编译时用到的补丁有:
|
|
||||||
|
|
||||||
- static_opcache
|
|
||||||
- static_extensions_win32
|
|
||||||
- cli_checks
|
|
||||||
- disable_huge_page
|
|
||||||
- vcruntime140
|
|
||||||
- win32
|
|
||||||
- zend_stream
|
|
||||||
- cli_static
|
|
||||||
- macos_iconv
|
|
||||||
- phar
|
|
||||||
|
|
||||||
## PHP <= 8.1 libxml 补丁
|
|
||||||
|
|
||||||
因为 PHP 官方仅对 8.1 进行安全更新,旧版本停止更新,所以 static-php-cli 对 PHP 8.1 及以下版本应用了在新版本 PHP 中已经应用的 libxml 编译补丁。
|
|
||||||
|
|
||||||
## gd 扩展 Windows 补丁
|
|
||||||
|
|
||||||
在 Windows 下编译 gd 扩展需要大幅改动 `config.w32` 文件,static-php-cli 对 gd 扩展进行了一些修改,使其在 Windows 下编译更加方便。
|
|
||||||
|
|
||||||
## yaml 扩展 Windows 补丁
|
|
||||||
|
|
||||||
yaml 扩展在 Windows 下编译需要修改 `config.w32` 文件,static-php-cli 对 yaml 扩展进行了一些修改,使其在 Windows 下编译更加方便。
|
|
||||||
|
|
||||||
## static-php-cli 版本信息插入
|
|
||||||
|
|
||||||
static-php-cli 在编译时会在 PHP 版本信息中插入 static-php-cli 的版本信息,以便于识别。
|
|
||||||
|
|
||||||
## 加入硬编码 INI 的选项
|
|
||||||
|
|
||||||
在使用 `-I` 参数硬编码 INI 到静态 PHP 的功能中,static-php-cli 会修改 PHP 源码以插入硬编码内容。
|
|
||||||
|
|
||||||
## Linux 系统修复补丁
|
|
||||||
|
|
||||||
部分编译环境可能缺少一些头文件或库,static-php-cli 会在编译时自动修复这些问题,如:
|
|
||||||
|
|
||||||
- HAVE_STRLCAT missing problem
|
|
||||||
- HAVE_STRLCPY missing problem
|
|
||||||
|
|
||||||
## Windows 系统下 Fiber 问题修复补丁
|
|
||||||
|
|
||||||
在 Windows 下编译 PHP 时,Fiber 扩展会出现一些问题,static-php-cli 会在编译时自动修复这些问题(修改 php-src 的 `config.w32`)。
|
|
||||||
|
|||||||
5
docs/zh/develop/registry.md
Normal file
5
docs/zh/develop/registry.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Registry 与插件系统
|
||||||
|
|
||||||
|
<!-- TODO: spc.registry.yml 结构说明。
|
||||||
|
通过 SPC_REGISTRIES 环境变量添加外部 Registry。
|
||||||
|
Vendor 特定配置、覆盖核心包。Registry 解析顺序与冲突规则。 -->
|
||||||
@@ -1,350 +1,5 @@
|
|||||||
# 资源模块
|
# 资源模块
|
||||||
|
|
||||||
static-php-cli 的下载资源模块是一个主要的功能,它包含了所依赖的库、外部扩展、PHP 源码的下载方式和资源解压方式。
|
<!-- TODO: 从 v2 source-module.md 迁移并更新。
|
||||||
下载的配置文件主要涉及 `source.json` 和 `pkg.json` 文件,这个文件记录了所有可下载的资源的下载方式。
|
记录 v3 source 类型:url、ghrel、ghtar、ghtagtar、git、pecl(新增)、filelist、custom。
|
||||||
|
per-package YAML source 块格式。并行下载(--parallel N)。 -->
|
||||||
下载功能主要涉及的命令有 `bin/spc download` 和 `bin/spc extract`。其中 `download` 命令是一个下载器,它会根据配置文件下载资源;
|
|
||||||
`extract` 命令是一个解压器,它会根据配置文件解压资源。
|
|
||||||
|
|
||||||
一般来说,下载资源可能会比较慢,因为这些资源来源于各个官网、GitHub 等不同位置,同时它们也占用了较大空间,所以你可以在一次下载资源后,可重复使用。
|
|
||||||
|
|
||||||
下载器的配置文件是 `source.json`,它包含了所有资源的下载方式,你可以在其中添加你需要的资源下载方式,也可以修改已有的资源下载方式。
|
|
||||||
|
|
||||||
每个资源的下载配置结构如下,下面是 `libevent` 扩展对应的资源下载配置:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"libevent": {
|
|
||||||
"type": "ghrel",
|
|
||||||
"repo": "libevent/libevent",
|
|
||||||
"match": "libevent.+\\.tar\\.gz",
|
|
||||||
"provide-pre-built": true,
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
这里最主要的字段是 `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` 发布版本)。
|
|
||||||
- `bitbuckettag`: 使用 BitBucket API 下载,基本和 `ghtagtar` 相同,只是这个适用于 BitBucket。
|
|
||||||
- `git`: 直接从一个 Git 地址克隆项目来下载资源,适用于任何公开 Git 仓库。
|
|
||||||
- `filelist`: 使用爬虫爬取提供文件索引的 Web 下载站点,并获取最新版本的文件名并下载。
|
|
||||||
- `custom`: 如果以上下载方式都不能满足,你可以编写 `custom` 后,在 `src/SPC/store/source/` 下新建一个类,并继承 `CustomSourceBase`,自己编写下载脚本。
|
|
||||||
|
|
||||||
## source.json 通用参数
|
|
||||||
|
|
||||||
source.json 中每个源文件拥有以下字段:
|
|
||||||
|
|
||||||
- `license`: 源代码的开源许可证,见下方 **开源许可证** 章节
|
|
||||||
- `type`: 必须为上面提到的类型之一
|
|
||||||
- `path`(可选): 释放源码到指定目录而非 `source/{name}`
|
|
||||||
- `provide-pre-built`(可选): 是否提供预编译的二进制文件,如果为 `true`,则会在 `bin/spc download` 时尝试自动下载预编译的二进制文件
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
`source.json` 中的 `path` 参数可指定相对路径或绝对路径。当指定为相对路径时,路径基于 `source/`。
|
|
||||||
:::
|
|
||||||
|
|
||||||
## 下载类型 - url
|
|
||||||
|
|
||||||
url 类型的资源指的是从 URL 直接下载文件。
|
|
||||||
|
|
||||||
包含的参数有:
|
|
||||||
|
|
||||||
- `url`: 文件的下载地址,如 `https://example.com/file.tgz`
|
|
||||||
- `filename`(可选): 保存到本地的文件名,如不指定,则使用 url 的文件名
|
|
||||||
|
|
||||||
例子(下载 imagick 扩展,并解压缩到 php 源码的扩展存放路径):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"ext-imagick": {
|
|
||||||
"type": "url",
|
|
||||||
"url": "https://pecl.php.net/get/imagick",
|
|
||||||
"path": "php-src/ext/imagick",
|
|
||||||
"filename": "imagick.tgz",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 下载类型 - 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 获取最新版本,然后根据正则匹配方式下载相应的文件。
|
|
||||||
|
|
||||||
包含的参数有:
|
|
||||||
|
|
||||||
- `repo`: GitHub 仓库名称
|
|
||||||
- `match`: 匹配 Assets 文件的正则表达式
|
|
||||||
- `prefer-stable`: 是否优先下载稳定版本(默认为 `false`)
|
|
||||||
|
|
||||||
例子(下载 libsodium 库,匹配 Release 中的 libsodium-x.y.tar.gz 文件):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"libsodium": {
|
|
||||||
"type": "ghrel",
|
|
||||||
"repo": "jedisct1/libsodium",
|
|
||||||
"match": "libsodium-\\d+(\\.\\d+)*\\.tar\\.gz",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 下载类型 - ghtar
|
|
||||||
|
|
||||||
ghtar 会从 GitHub Release Tag 下载文件,与 `ghrel` 不同的是,`ghtar` 是从项目的最新 Release 中找 `source code (tar.gz)` 下载的。
|
|
||||||
|
|
||||||
包含的参数有:
|
|
||||||
|
|
||||||
- `repo`: GitHub 仓库名称
|
|
||||||
- `prefer-stable`: 是否优先下载稳定版本(默认为 `false`)
|
|
||||||
|
|
||||||
例子(brotli 库):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"brotli": {
|
|
||||||
"type": "ghtar",
|
|
||||||
"repo": "google/brotli",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 下载类型 - ghtagtar
|
|
||||||
|
|
||||||
使用 GitHub Release API 下载,与 `ghtar` 相比,`ghtagtar` 可以从 `tags` 列表找最新的,并下载 `tar.gz` 格式的源码(因为有些项目只使用了 `tag` 发布版本)。
|
|
||||||
|
|
||||||
包含的参数有:
|
|
||||||
|
|
||||||
- `repo`: GitHub 仓库名称
|
|
||||||
- `prefer-stable`: 是否优先下载稳定版本(默认为 `false`)
|
|
||||||
|
|
||||||
例子(gmp 库):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"gmp": {
|
|
||||||
"type": "ghtagtar",
|
|
||||||
"repo": "alisw/GMP",
|
|
||||||
"license": {
|
|
||||||
"type": "text",
|
|
||||||
"text": "EXAMPLE LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 下载类型 - bitbuckettag
|
|
||||||
|
|
||||||
使用 BitBucket API 下载,基本和 `ghtagtar` 相同,只是这个适用于 BitBucket。
|
|
||||||
|
|
||||||
包含的参数有:
|
|
||||||
|
|
||||||
- `repo`: BitBucket 仓库名称
|
|
||||||
|
|
||||||
## 下载类型 - git
|
|
||||||
|
|
||||||
直接从一个 Git 地址克隆项目来下载资源,适用于任何公开 Git 仓库。
|
|
||||||
|
|
||||||
包含的参数有:
|
|
||||||
|
|
||||||
- `url`: Git 链接(仅限 HTTPS)
|
|
||||||
- `rev`: 分支名称
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"imap": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/static-php/imap.git",
|
|
||||||
"rev": "master",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 下载类型 - filelist
|
|
||||||
|
|
||||||
使用爬虫爬取提供文件索引的 Web 下载站点,并获取最新版本的文件名并下载。
|
|
||||||
|
|
||||||
注意,该方法仅限于镜像站、GNU 官网等具有页面 index 功能的静态站点使用。
|
|
||||||
|
|
||||||
包含的参数有:
|
|
||||||
|
|
||||||
- `url`: 要爬取文件最新版本的页面 URL
|
|
||||||
- `regex`: 匹配文件名及下载链接的正则表达式
|
|
||||||
|
|
||||||
例子(从 GNU 官网下载 libiconv 库):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"libiconv": {
|
|
||||||
"type": "filelist",
|
|
||||||
"url": "https://ftp.gnu.org/gnu/libiconv/",
|
|
||||||
"regex": "/href=\"(?<file>libiconv-(?<version>[^\"]+)\\.tar\\.gz)\"/",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "COPYING"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 下载类型 - custom
|
|
||||||
|
|
||||||
如果以上下载方式都不能满足,你可以编写 `custom` 后,在 `src/SPC/store/source/` 下新建一个类,并继承 `CustomSourceBase`,自己编写下载脚本。
|
|
||||||
|
|
||||||
这里不再赘述,你可以查看 `src/SPC/store/source/PhpSource.php` 或 `src/SPC/store/source/PostgreSQLSource.php` 作为例子。
|
|
||||||
|
|
||||||
## pkg.json 通用参数
|
|
||||||
|
|
||||||
pkg.json 存放的是非源码类型的文件资源,例如 musl-toolchain、UPX 等预编译的工具。它的使用包含:
|
|
||||||
|
|
||||||
- `type`: 与 `source.json` 相同的类型及不同种类的参数。
|
|
||||||
- `extract`(可选): 下载后解压缩的路径,默认为 `pkgroot/{pkg_name}`。
|
|
||||||
- `extract-files`(可选): 下载后仅解压指定的文件到指定位置。
|
|
||||||
|
|
||||||
需要注意的是,`pkg.json` 不涉及源代码的编译和修改分发,所以没有 `license` 开源许可证字段。并且你不能同时使用 `extract` 和 `extract-files` 参数。
|
|
||||||
|
|
||||||
例子(下载 nasm 到本地,并只提取程序文件到 PHP SDK):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nasm-x86_64-win": {
|
|
||||||
"type": "url",
|
|
||||||
"url": "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`extract-files` 中的键名为源文件夹下的文件,键值为存放的路径。存放的路径可以使用以下变量:
|
|
||||||
|
|
||||||
- `{php_sdk_path}`: (仅限 Windows)PHP SDK 路径
|
|
||||||
- `{pkg_root_path}`: `pkgroot/`
|
|
||||||
- `{working_dir}`: 当前工作目录
|
|
||||||
- `{download_path}`: 下载目录
|
|
||||||
- `{source_path}`: 源码解压缩目录
|
|
||||||
|
|
||||||
当 `extract-files` 不使用变量且为相对路径时,相对路径的目录为 `{working_dir}`。
|
|
||||||
|
|
||||||
## 开源许可证
|
|
||||||
|
|
||||||
对于 `source.json` 而言,每个源文件都应包含开源许可证。`license` 字段存放了开源许可证的信息。
|
|
||||||
|
|
||||||
每个 `license` 包含的参数有:
|
|
||||||
|
|
||||||
- `type`: `file` 或 `text`
|
|
||||||
- `path`: 源代码目录中的许可证文件(当 `type` 为 `file` 时,此项必填)
|
|
||||||
- `text`: 许可证文本(当 `type` 为 `text` 时,此项必填)
|
|
||||||
|
|
||||||
例子(yaml 扩展的源代码中带有 LICENSE 文件):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"yaml": {
|
|
||||||
"type": "git",
|
|
||||||
"path": "php-src/ext/yaml",
|
|
||||||
"rev": "php7",
|
|
||||||
"url": "https://github.com/php/pecl-file_formats-yaml",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
当开源项目拥有多个许可证时,可指定多个文件:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"libuv": {
|
|
||||||
"type": "ghtar",
|
|
||||||
"repo": "libuv/libuv",
|
|
||||||
"license": [
|
|
||||||
{
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "file",
|
|
||||||
"path": "LICENSE-extra"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
当一个开源项目的许可证在不同版本间使用不同的文件,`path` 参数可以使用数组将可能的许可证文件列出:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"redis": {
|
|
||||||
"type": "git",
|
|
||||||
"path": "php-src/ext/redis",
|
|
||||||
"rev": "release/6.0.2",
|
|
||||||
"url": "https://github.com/phpredis/phpredis",
|
|
||||||
"license": {
|
|
||||||
"type": "file",
|
|
||||||
"path": [
|
|
||||||
"LICENSE",
|
|
||||||
"COPYING"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,163 +1,4 @@
|
|||||||
# 项目结构简介
|
# 项目结构
|
||||||
|
|
||||||
static-php-cli 主要包含三种逻辑组件:资源、依赖库、扩展。这三种组件四个配置文件:`source.json`、`lib.json`、`ext.json`、`pkg.json`。
|
<!-- TODO: v3 目录结构说明(bin/、config/pkg/、src/StaticPHP/、src/Package/ 等)。
|
||||||
|
每个顶层目录的职责说明。内部类结构简述,深入内容见核心概念页。 -->
|
||||||
一个完整的构建静态 PHP 流程是:
|
|
||||||
|
|
||||||
1. 使用资源下载模块 `Downloader` 下载指定或所有资源,这些资源包含 PHP 源码、依赖库源码、扩展源码。
|
|
||||||
2. 使用资源解压模块 `SourceExtractor` 解压下载的资源到编译目录。
|
|
||||||
3. 使用依赖工具计算出当前加入的扩展的依赖扩展、依赖库,然后对每个需要编译的依赖库进行编译,按照依赖顺序。
|
|
||||||
4. 使用对应操作系统下的 `Builder` 构建每个依赖库后,将其安装到 `buildroot` 目录。
|
|
||||||
5. 如果包含外部扩展(源码没有包含在 PHP 内的扩展),将外部扩展拷贝到 `source/php-src/ext/` 目录。
|
|
||||||
6. 使用 `Builder` 构建 PHP 源码,将其安装到 `buildroot` 目录。
|
|
||||||
|
|
||||||
项目主要分为几个文件夹:
|
|
||||||
|
|
||||||
- `bin/`: 用于存放程序入口文件,包含 `bin/spc`、`bin/spc-alpine-docker`、`bin/setup-runtime`。
|
|
||||||
- `config/`: 包含了所有项目支持的扩展、依赖库以及这些资源下载的地址、下载方式等,:`lib.json`、`ext.json`、`source.json`、`pkg.json`、`pre-built.json`。
|
|
||||||
- `src/SPC/`: 项目的核心代码,包含了整个框架以及编译各种扩展和库的命令。
|
|
||||||
- `src/globals/`: 项目的全局方法和常量、运行时需要的测试文件(例如:扩展的可用性检查代码)。
|
|
||||||
- `vendor/`: Composer 依赖的目录,你无需对它做出任何修改。
|
|
||||||
|
|
||||||
其中运行原理就是启动一个 `symfony/console` 的 `ConsoleApplication`,然后解析用户在终端输入的命令。
|
|
||||||
|
|
||||||
## 基本命令行结构
|
|
||||||
|
|
||||||
`bin/spc` 是一个 PHP 代码入口文件,包含了 Unix 通用的 `#!/usr/bin/env php` 用来让系统自动以系统安装好的 PHP 解释器执行。
|
|
||||||
在项目执行了 `new ConsoleApplication()` 后,框架会自动使用反射的方式,解析 `src/SPC/command` 目录下的所有类,并将其注册成为命令。
|
|
||||||
|
|
||||||
项目并没有直接使用 Symfony 推荐的 Command 注册方式和命令执行方式,这里做出了一点小变动:
|
|
||||||
|
|
||||||
1. 每个命令都使用 `#[AsCommand()]` Attribute 来注册名称和简介。
|
|
||||||
2. 将 `execute()` 抽象化,让所有命令基于 `BaseCommand`(它基于 `Symfony\Component\Console\Command\Command`),每个命令本身的执行代码写到了 `handle()` 方法中。
|
|
||||||
3. `BaseCommand` 添加了变量 `$no_motd`,用于是否在该命令执行时显示 Figlet 欢迎词。
|
|
||||||
4. `BaseCommand` 将 `InputInterface` 和 `OutputInterface` 保存为成员变量,你可以在命令的类内使用 `$this->input` 和 `$this->output`。
|
|
||||||
|
|
||||||
## 基本源码结构
|
|
||||||
|
|
||||||
项目的源码位于 `src/SPC` 目录,支持 PSR-4 标准的自动加载,包含以下子目录和类:
|
|
||||||
|
|
||||||
- `src/SPC/builder/`: 用于不同操作系统下构建依赖库、PHP 及相关扩展的核心编译命令代码,还包含了一些编译的系统工具方法。
|
|
||||||
- `src/SPC/command/`: 项目的所有命令都在这里。
|
|
||||||
- `src/SPC/doctor/`: Doctor 模块,它是一个较为独立的用于检查系统环境的模块,可使用命令 `bin/spc doctor` 进入。
|
|
||||||
- `src/SPC/exception/`: 异常类。
|
|
||||||
- `src/SPC/store/`: 有关存储、文件和资源的类都在这里。
|
|
||||||
- `src/SPC/util/`: 一些可以复用的工具方法都在这里。
|
|
||||||
- `src/SPC/ConsoleApplication.php`: 命令行程序入口文件。
|
|
||||||
|
|
||||||
如果你阅读过源码,你可能会发现还有一个 `src/globals/` 目录,它是用于存放一些全局变量、全局方法、构建过程中依赖的非 PSR-4 标准的 PHP 源码,例如测试扩展代码等。
|
|
||||||
|
|
||||||
## Phar 应用目录问题
|
|
||||||
|
|
||||||
和其他 php-cli 项目一样,spc 自身对路径有额外的考虑。
|
|
||||||
因为 spc 可以在 `php-cli directly`、`micro SAPI`、`php-cli with Phar`、`vendor with Phar` 等多种模式下运行,各类根目录存在歧义。这里会进行一个完整的说明。
|
|
||||||
此问题一般常见于 PHP 项目中存取文件的基类路径选择问题,尤其是在配合 `micro.sfx` 使用时容易出现路径问题。
|
|
||||||
|
|
||||||
注意,此处仅对你在开发 Phar 项目或 PHP 框架时可能有用。
|
|
||||||
|
|
||||||
> 接下来我们都将 `static-php-cli`(也就是 spc)当作一个普通的 `php` 命令行程序来看,你可以将 spc 理解为你自己的任何 php-cli 应用以参考。
|
|
||||||
|
|
||||||
下面主要有三个基本的常量理论值,我们建议你在编写 php 项目时引入这三种常量:
|
|
||||||
|
|
||||||
- `WORKING_DIR`:执行 PHP 脚本时的工作目录
|
|
||||||
- `SOURCE_ROOT_DIR` 或 `ROOT_DIR`:项目文件夹的根目录,一般为 `composer.json` 所在目录
|
|
||||||
- `FRAMEWORK_ROOT_DIR`:使用框架的根目录,自行开发的框架可能会用到,一般框架目录为只读
|
|
||||||
|
|
||||||
你可以在你的框架或者 cli 应用程序入口中定义这些常量,以方便在你的项目中使用路径。
|
|
||||||
|
|
||||||
下面是 PHP 内置的常量值,在 PHP 解释器内部已被定义:
|
|
||||||
|
|
||||||
- `__DIR__`:当前执行脚本的文件所在目录
|
|
||||||
- `__FILE__`:当前执行脚本的文件路径
|
|
||||||
|
|
||||||
### Git 项目模式(source)
|
|
||||||
|
|
||||||
Git 项目模式指的是一个框架或程序本身在当前文件夹以纯文本形式存放,运行通过 `php path/to/entry.php` 方式。
|
|
||||||
|
|
||||||
假设你的项目存放在 `/home/example/static-php-cli/` 目录下,或你的项目就是框架本身,里面包含 `composer.json` 等项目文件:
|
|
||||||
|
|
||||||
```
|
|
||||||
composer.json
|
|
||||||
src/App/MyCommand.app
|
|
||||||
vendor/*
|
|
||||||
bin/entry.php
|
|
||||||
```
|
|
||||||
|
|
||||||
我们假设从 `src/App/MyCommand.php` 中获取以上常量:
|
|
||||||
|
|
||||||
| Constant | Value |
|
|
||||||
|----------------------|------------------------------------------------------|
|
|
||||||
| `WORKING_DIR` | `/home/example/static-php-cli` |
|
|
||||||
| `SOURCE_ROOT_DIR` | `/home/example/static-php-cli` |
|
|
||||||
| `FRAMEWORK_ROOT_DIR` | `/home/example/static-php-cli` |
|
|
||||||
| `__DIR__` | `/home/example/static-php-cli/src/App` |
|
|
||||||
| `__FILE__` | `/home/example/static-php-cli/src/App/MyCommand.php` |
|
|
||||||
|
|
||||||
这种情况下,`WORKING_DIR`、`SOURCE_ROOT_DIR`、`FRAMEWORK_ROOT_DIR` 的值是完全一致的:`/home/example/static-php-cli`。
|
|
||||||
框架的源码和应用的源码都在当前路径下。
|
|
||||||
|
|
||||||
### Vendor 库模式(vendor)
|
|
||||||
|
|
||||||
Vendor 库模式一般是指你的项目为框架类或者被其他应用作为 composer 依赖项安装到项目中,存放位置在 `vendor/author/XXX` 目录。
|
|
||||||
|
|
||||||
假设你的项目是 `crazywhalecc/static-php-cli`,你或其他人在另一个项目使用 `composer require` 安装了这个项目。
|
|
||||||
|
|
||||||
我们假设 static-php-cli 中包含同 `Git 模式` 的除 `vendor` 目录外的所有文件,并从 `src/App/MyCommand` 中获取常量值,
|
|
||||||
目录常量应该是:
|
|
||||||
|
|
||||||
| Constant | Value |
|
|
||||||
|----------------------|--------------------------------------------------------------------------------------|
|
|
||||||
| `WORKING_DIR` | `/home/example/another-app` |
|
|
||||||
| `SOURCE_ROOT_DIR` | `/home/example/another-app` |
|
|
||||||
| `FRAMEWORK_ROOT_DIR` | `/home/example/another-app/vendor/crazywhalecc/static-php-cli` |
|
|
||||||
| `__DIR__` | `/home/example/another-app/vendor/crazywhalecc/static-php-cli/src/App` |
|
|
||||||
| `__FILE__` | `/home/example/another-app/vendor/crazywhalecc/static-php-cli/src/App/MyCommand.php` |
|
|
||||||
|
|
||||||
|
|
||||||
这里的 `SOURCE_ROOT_DIR` 就指的是使用 `static-php-cli` 的项目的根目录。
|
|
||||||
|
|
||||||
### Git 项目 Phar 模式(source-phar)
|
|
||||||
|
|
||||||
Git 项目 Phar 模式指的是将 Git 项目模式的项目目录打包为一个 `phar` 文件的模式。我们假设 `/home/example/static-php-cli` 将打包为一个 Phar 文件,目录有以下文件:
|
|
||||||
|
|
||||||
```
|
|
||||||
composer.json
|
|
||||||
src/App/MyCommand.app
|
|
||||||
vendor/*
|
|
||||||
bin/entry.php
|
|
||||||
```
|
|
||||||
|
|
||||||
打包为 `app.phar` 并存放到 `/home/example/static-php-cli` 目录下时,此时执行 `app.phar`,假设执行了 `src/App/MyCommand` 代码,常量在该文件内获取:
|
|
||||||
|
|
||||||
| Constant | Value |
|
|
||||||
|----------------------|----------------------------------------------------------------------|
|
|
||||||
| `WORKING_DIR` | `/home/example/static-php-cli` |
|
|
||||||
| `SOURCE_ROOT_DIR` | `phar:///home/example/static-php-cli/app.phar/` |
|
|
||||||
| `FRAMEWORK_ROOT_DIR` | `phar:///home/example/static-php-cli/app.phar/` |
|
|
||||||
| `__DIR__` | `phar:///home/example/static-php-cli/app.phar/src/App` |
|
|
||||||
| `__FILE__` | `phar:///home/example/static-php-cli/app.phar/src/App/MyCommand.php` |
|
|
||||||
|
|
||||||
因为在 phar 内读取自身 phar 的文件需要 `phar://` 协议进行,所以项目根目录和框架目录将会和 `WORKING_DIR` 不同。
|
|
||||||
|
|
||||||
### Vendor 库 Phar 模式(vendor-phar)
|
|
||||||
|
|
||||||
Vendor 库 Phar 模式指的是你的项目作为框架安装在其他项目内,存储于 `vendor` 目录下。
|
|
||||||
|
|
||||||
我们假设你的项目目录结构如下:
|
|
||||||
|
|
||||||
```
|
|
||||||
composer.json # 当前项目的 Composer 配置文件
|
|
||||||
box.json # 打包 Phar 的配置文件
|
|
||||||
another-app.php # 另一个项目的入口文件
|
|
||||||
vendor/crazywhalecc/static-php-cli/* # 你的项目被作为依赖库
|
|
||||||
```
|
|
||||||
|
|
||||||
将该目录 `/home/example/another-app/` 下的这些文件打包为 `app.phar` 时,对于你的项目而言,下面常量的值应为:
|
|
||||||
|
|
||||||
| Constant | Value |
|
|
||||||
|----------------------|------------------------------------------------------------------------------------------------------|
|
|
||||||
| `WORKING_DIR` | `/home/example/another-app` |
|
|
||||||
| `SOURCE_ROOT_DIR` | `phar:///home/example/another-app/app.phar/` |
|
|
||||||
| `FRAMEWORK_ROOT_DIR` | `phar:///home/example/another-app/app.phar/vendor/crazywhalecc/static-php-cli` |
|
|
||||||
| `__DIR__` | `phar:///home/example/another-app/app.phar/vendor/crazywhalecc/static-php-cli/src/App` |
|
|
||||||
| `__FILE__` | `phar:///home/example/another-app/app.phar/vendor/crazywhalecc/static-php-cli/src/App/MyCommand.php` |
|
|
||||||
|
|||||||
@@ -1,204 +1,4 @@
|
|||||||
# 系统编译工具
|
# 编译工具
|
||||||
|
|
||||||
static-php-cli 在构建静态 PHP 时使用了许多系统编译工具,这些工具主要包括:
|
<!-- TODO: 从 v2 system-build-tools.md 迁移并更新。
|
||||||
|
涵盖 v3 新增内容:WindowsCMakeExecutor、vswhere.exe 检测、FrankenPHP 的 LLVM/Clang 支持。 -->
|
||||||
- `autoconf`: 用于生成 `configure` 脚本。
|
|
||||||
- `make`: 用于执行 `Makefile`。
|
|
||||||
- `cmake`: 用于执行 `CMakeLists.txt`。
|
|
||||||
- `pkg-config`: 用于查找依赖库的安装路径。
|
|
||||||
- `gcc`: 用于在 Linux 下编译 C/C++ 语言代码。
|
|
||||||
- `clang`: 用于在 macOS 下编译 C/C++ 语言代码。
|
|
||||||
|
|
||||||
对于 Linux 和 macOS 操作系统,这些工具通常可以通过包管理安装,这部分在 doctor 模块中编写了。
|
|
||||||
理论上我们也可以通过编译和手动下载这些工具,但这样会增加编译的复杂度,所以我们不推荐这样做。
|
|
||||||
|
|
||||||
## Linux 环境编译工具
|
|
||||||
|
|
||||||
对于 Linux 系统来说,不同发行版的编译工具安装方式不同。而且对于静态编译来说,某些发行版的包管理无法安装用于纯静态编译的库和工具,
|
|
||||||
所以对于 Linux 平台及其不同发行版,我们目前提供了多种编译环境的部署措施。
|
|
||||||
|
|
||||||
### glibc 环境
|
|
||||||
|
|
||||||
glibc 环境指的是系统底层的 `libc` 库(即所有 C 语言编写的程序动态链接的 C 标准库)使用的是 `glibc`,这是大多数发行版的默认环境。
|
|
||||||
例如:Ubuntu、Debian、CentOS、RHEL、openSUSE、Arch Linux 等。
|
|
||||||
|
|
||||||
而 glibc 环境下,我们使用的包管理、编译器都是默认指向 glibc 的,glibc 不能被良好地静态链接。它不能被静态链接的原因之一是它的网络库 `nss` 无法静态编译。
|
|
||||||
|
|
||||||
对于 glibc 环境,在 2.0 RC8 及以后的 static-php-cli 及 spc 中,你可以选择两种方式来构建静态 PHP:
|
|
||||||
|
|
||||||
1. 使用 Docker 构建,这是最简单的方式,你可以使用 `bin/spc-alpine-docker` 来构建,它会在 Alpine Linux 环境下构建。
|
|
||||||
2. 使用 `bin/spc doctor` 安装 musl-wrapper 和 musl-cross-make 套件,然后直接正常构建。([相关源码](https://github.com/crazywhalecc/static-php-cli/blob/main/src/SPC/doctor/item/LinuxMuslCheck.php))
|
|
||||||
|
|
||||||
一般来说,这两种构建方式的构建结果是一致的,你可以根据实际需求选择。
|
|
||||||
|
|
||||||
在 doctor 模块中,static-php-cli 会先检测当前的 Linux 发行版。如果当前发行版是 glibc 环境,会提示需要安装 musl-wrapper 和 musl-cross-make 套件。
|
|
||||||
|
|
||||||
在 glibc 环境下安装 musl-wrapper 的过程如下:
|
|
||||||
|
|
||||||
1. 从 musl 官网下载特定版本的 [musl-wrapper 源码](https://musl.libc.org/releases/)。
|
|
||||||
2. 使用从包管理安装的 `gcc` 编译 musl-wrapper 源码,生成 `musl-libc` 等库:`./configure --disable-gcc-wrapper && make -j && sudo make install`。
|
|
||||||
3. musl-wrapper 相关库将被安装在 `/usr/local/musl` 目录。
|
|
||||||
|
|
||||||
在 glibc 环境下安装 musl-cross-make 的过程如下:
|
|
||||||
|
|
||||||
1. 从 dl.static-php.dev 下载预编译好的 [musl-cross-make](https://dl.static-php.dev/static-php-cli/deps/musl-toolchain/) 压缩包。
|
|
||||||
2. 解压到 `/usr/local/musl` 目录。
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
在 glibc 环境下,静态编译可以通过直接安装 musl-wrapper 来实现,但是 musl-wrapper 仅包含了 `musl-gcc`,而没有 `musl-g++`,这也就意味着无法编译 C++ 代码。
|
|
||||||
所以我们需要 musl-cross-make 来提供 `musl-g++`。
|
|
||||||
|
|
||||||
而 musl-cross-make 套件无法在本地直接编译的原因是它的编译环境要求比较高(需要 36GB 以上内存,Alpine Linux 下编译),所以我们提供了预编译好的二进制包,可用于所有 Linux 发行版。
|
|
||||||
|
|
||||||
同时,部分发行版的包管理提供了 musl-wrapper,但 musl-cross-make 需要匹配对应的 musl-wrapper 版本,所以我们不使用包管理安装 musl-wrapper。
|
|
||||||
|
|
||||||
对于如何编译 musl-cross-make,将在本章节内的 **编译 musl-cross-make** 小节中介绍。
|
|
||||||
:::
|
|
||||||
|
|
||||||
### musl 环境
|
|
||||||
|
|
||||||
musl 环境指的是系统底层的 `libc` 库使用的是 `musl`,这是一种轻量级的 C 标准库,它的特点是可以被良好地静态链接。
|
|
||||||
|
|
||||||
对于目前流行的 Linux 发行版,Alpine Linux 使用的就是 musl 环境,所以 static-php-cli 在 Alpine Linux 下可以直接构建静态 PHP,仅需直接从包管理安装基础编译工具(如 gcc、cmake 等)即可。
|
|
||||||
|
|
||||||
对于其他发行版,如果你的发行版使用的是 musl 环境,那么你也可以在安装必要的编译工具后直接使用 static-php-cli 构建静态 PHP。
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
在 musl 环境下,static-php-cli 会自动跳过 musl-wrapper 和 musl-cross-make 的安装。
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Docker 环境
|
|
||||||
|
|
||||||
Docker 环境指的是使用 Docker 容器来构建静态 PHP,你可以使用 `bin/spc-alpine-docker` 来构建。
|
|
||||||
执行这个命令前需要先安装 Docker,然后在项目根目录执行 `bin/spc-alpine-docker` 即可。
|
|
||||||
|
|
||||||
在执行 `bin/spc-alpine-docker` 后,static-php-cli 会自动下载 Alpine Linux 镜像,然后构建一个 `cwcc-spc-x86_64` 或 `cwcc-spc-aarch64` 的镜像。
|
|
||||||
然后一切的构建都在这个镜像内进行,相当于在 Alpine Linux 内编译。总的来说,Docker 环境就是 musl 环境。
|
|
||||||
|
|
||||||
## musl-cross-make 工具链编译
|
|
||||||
|
|
||||||
在 Linux 中,尽管你不需要手动编译 musl-cross-make 工具,但是如果你想了解它的编译过程,可以参考这里。
|
|
||||||
还有一个重要的原因就是,这个可能无法使用 CI、Actions 等自动化工具编译,因为现有的 CI 服务编译环境不满足 musl-cross-make 的编译要求,满足要求的配置价格太高。
|
|
||||||
|
|
||||||
musl-cross-make 的编译过程如下:
|
|
||||||
|
|
||||||
准备一个 Alpine Linux 环境(直接安装或使用 Docker 均可),编译的过程需要 36GB 以上内存,所以你需要在内存较大的机器上编译。如果没有这么多内存,可能会导致编译失败。
|
|
||||||
|
|
||||||
然后将以下内容写入 `config.mak` 文件内:
|
|
||||||
|
|
||||||
```makefile
|
|
||||||
STAT = -static --static
|
|
||||||
FLAG = -g0 -Os -Wno-error
|
|
||||||
|
|
||||||
ifneq ($(NATIVE),)
|
|
||||||
COMMON_CONFIG += CC="$(HOST)-gcc ${STAT}" CXX="$(HOST)-g++ ${STAT}"
|
|
||||||
else
|
|
||||||
COMMON_CONFIG += CC="gcc ${STAT}" CXX="g++ ${STAT}"
|
|
||||||
endif
|
|
||||||
|
|
||||||
COMMON_CONFIG += CFLAGS="${FLAG}" CXXFLAGS="${FLAG}" LDFLAGS="${STAT}"
|
|
||||||
|
|
||||||
BINUTILS_CONFIG += --enable-gold=yes --enable-gprofng=no
|
|
||||||
GCC_CONFIG += --enable-static-pie --disable-cet --enable-default-pie
|
|
||||||
#--enable-default-pie
|
|
||||||
|
|
||||||
CONFIG_SUB_REV = 888c8e3d5f7b
|
|
||||||
GCC_VER = 13.2.0
|
|
||||||
BINUTILS_VER = 2.40
|
|
||||||
MUSL_VER = 1.2.4
|
|
||||||
GMP_VER = 6.2.1
|
|
||||||
MPC_VER = 1.2.1
|
|
||||||
MPFR_VER = 4.2.0
|
|
||||||
LINUX_VER = 6.1.36
|
|
||||||
```
|
|
||||||
|
|
||||||
同时,你需要新建一个 `gcc-13.2.0.tar.xz.sha1` 文件,文件内容如下:
|
|
||||||
|
|
||||||
```
|
|
||||||
5f95b6d042fb37d45c6cbebfc91decfbc4fb493c gcc-13.2.0.tar.xz
|
|
||||||
```
|
|
||||||
|
|
||||||
如果你使用的是 Docker 构建,新建一个 `Dockerfile` 文件,写入以下内容:
|
|
||||||
|
|
||||||
```dockerfile
|
|
||||||
FROM alpine:edge
|
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
gcc g++ git make curl perl \
|
|
||||||
rsync patch wget libtool \
|
|
||||||
texinfo autoconf automake \
|
|
||||||
bison tar xz bzip2 zlib \
|
|
||||||
file binutils flex \
|
|
||||||
linux-headers libintl \
|
|
||||||
gettext gettext-dev icu-libs pkgconf \
|
|
||||||
pkgconfig icu-dev bash \
|
|
||||||
ccache libarchive-tools zip
|
|
||||||
|
|
||||||
WORKDIR /opt
|
|
||||||
|
|
||||||
RUN git clone https://git.zv.io/toolchains/musl-cross-make.git
|
|
||||||
WORKDIR /opt/musl-cross-make
|
|
||||||
COPY config.mak /opt/musl-cross-make
|
|
||||||
COPY gcc-13.2.0.tar.xz.sha1 /opt/musl-cross-make/hashes
|
|
||||||
|
|
||||||
RUN make TARGET=x86_64-linux-musl -j || :
|
|
||||||
RUN sed -i 's/poison calloc/poison/g' ./gcc-13.2.0/gcc/system.h
|
|
||||||
RUN make TARGET=x86_64-linux-musl -j
|
|
||||||
RUN make TARGET=x86_64-linux-musl install -j
|
|
||||||
RUN tar cvzf x86_64-musl-toolchain.tgz output/*
|
|
||||||
```
|
|
||||||
|
|
||||||
如果你使用的是非 Docker 环境的 Alpine Linux,可以直接执行 Dockerfile 中的命令,例如:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
apk add --no-cache \
|
|
||||||
gcc g++ git make curl perl \
|
|
||||||
rsync patch wget libtool \
|
|
||||||
texinfo autoconf automake \
|
|
||||||
bison tar xz bzip2 zlib \
|
|
||||||
file binutils flex \
|
|
||||||
linux-headers libintl \
|
|
||||||
gettext gettext-dev icu-libs pkgconf \
|
|
||||||
pkgconfig icu-dev bash \
|
|
||||||
ccache libarchive-tools zip
|
|
||||||
|
|
||||||
git clone https://git.zv.io/toolchains/musl-cross-make.git
|
|
||||||
# 将 config.mak 拷贝到 musl-cross-make 的工作目录内,你需要将 /path/to/config.mak 替换为你的 config.mak 文件路径
|
|
||||||
cp /path/to/config.mak musl-cross-make/
|
|
||||||
cp /path/to/gcc-13.2.0.tar.xz.sha1 musl-cross-make/hashes
|
|
||||||
|
|
||||||
make TARGET=x86_64-linux-musl -j || :
|
|
||||||
sed -i 's/poison calloc/poison/g' ./gcc-13.2.0/gcc/system.h
|
|
||||||
make TARGET=x86_64-linux-musl -j
|
|
||||||
make TARGET=x86_64-linux-musl install -j
|
|
||||||
tar cvzf x86_64-musl-toolchain.tgz output/*
|
|
||||||
```
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
以上所有脚本都适用于 x86_64 架构的 Linux。如果你需要构建 ARM 环境的 musl-cross-make,只需要将上方所有 `x86_64` 替换为 `aarch64` 即可。
|
|
||||||
:::
|
|
||||||
|
|
||||||
这个编译过程可能会因为内存不足、网络问题等原因导致编译失败,你可以多尝试几次,或者使用更大内存的机器来编译。
|
|
||||||
如果遇到了问题,或者你有更好的改进方案,可以在 [讨论](https://github.com/crazywhalecc/static-php-cli-hosted/issues/1) 中提出。
|
|
||||||
|
|
||||||
## macOS 环境编译工具
|
|
||||||
|
|
||||||
对于 macOS 系统来说,我们使用的编译工具主要是 `clang`,它是 macOS 系统默认的编译器,同时也是 Xcode 的编译器。
|
|
||||||
|
|
||||||
在 macOS 下编译,主要依赖于 Xcode 或 Xcode Command Line Tools,你可以在 App Store 下载 Xcode,或者在终端执行 `xcode-select --install` 来安装 Xcode Command Line Tools。
|
|
||||||
|
|
||||||
此外,在 `doctor` 环境检查模块中,static-php-cli 会检查 macOS 系统是否安装了 Homebrew、编译工具等,如果没有,会提示你安装,这里不再赘述。
|
|
||||||
|
|
||||||
## FreeBSD 环境编译工具
|
|
||||||
|
|
||||||
FreeBSD 也是 Unix 系统,它的编译工具和 macOS 类似,你可以直接使用包管理 `pkg` 安装 `clang` 等编译工具,通过 `doctor` 命令。
|
|
||||||
|
|
||||||
## pkg-config 编译
|
|
||||||
|
|
||||||
如果你在使用 static-php-cli 构建静态 PHP 时仔细观察编译的日志,你会发现无论编译什么,都会先编译 `pkg-config`,这是因为 `pkg-config` 是一个用于查找依赖库的工具。
|
|
||||||
在早期的 static-php-cli 版本中,我们直接使用了包管理安装的 `pkg-config` 工具,但是这样会导致一些问题,例如:
|
|
||||||
|
|
||||||
- 即使指定了 `PKG_CONFIG_PATH`,`pkg-config` 也会尝试从系统路径中查找依赖包。
|
|
||||||
- 由于 `pkg-config` 会从系统路径中查找依赖包,所以如果系统中存在同名的依赖包,可能会导致编译失败。
|
|
||||||
|
|
||||||
为了避免以上问题,我们将 `pkg-config` 编译到用户态的 `buildroot/bin` 内并使用,使用了 `--without-sysroot` 等参数来避免从系统路径中查找依赖包。
|
|
||||||
|
|||||||
6
docs/zh/develop/vendor-mode/annotations.md
Normal file
6
docs/zh/develop/vendor-mode/annotations.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# 注解参考
|
||||||
|
|
||||||
|
<!-- TODO: 所有 v3 PHP 注解的完整参考。
|
||||||
|
#[Library]、#[Extension]、#[BuildFor]、#[BeforeStage]、#[AfterStage]、
|
||||||
|
#[PatchBeforeBuild]、#[CustomPhpConfigureArg]、#[AsCheckItem]、#[AsFixItem]。
|
||||||
|
每个注解:参数、类型、允许的 target、示例。 -->
|
||||||
5
docs/zh/develop/vendor-mode/dependency-injection.md
Normal file
5
docs/zh/develop/vendor-mode/dependency-injection.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# 依赖注入
|
||||||
|
|
||||||
|
<!-- TODO: v3 中 PHP-DI 自动装配的工作方式。
|
||||||
|
ApplicationContext::get() 用法。注册自定义服务。
|
||||||
|
向命令类、构建类和阶段方法注入依赖。 -->
|
||||||
6
docs/zh/develop/vendor-mode/index.md
Normal file
6
docs/zh/develop/vendor-mode/index.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Vendor 模式
|
||||||
|
|
||||||
|
<!-- TODO: Vendor 模式是什么,适用场景。
|
||||||
|
安装:`composer require crazywhalecc/static-php-cli`。
|
||||||
|
注册指向自定义包类的外部 Registry。
|
||||||
|
最小工作示例:一个 Library 类 + 一个配置 YAML + 运行 spc。 -->
|
||||||
6
docs/zh/develop/vendor-mode/lifecycle-hooks.md
Normal file
6
docs/zh/develop/vendor-mode/lifecycle-hooks.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# 生命周期 Hook
|
||||||
|
|
||||||
|
<!-- TODO: Hook 执行顺序与方法签名的详细说明。
|
||||||
|
#[BeforeStage('lib-name', 'build')]、#[AfterStage(...)]、#[PatchBeforeBuild]。
|
||||||
|
不同包的 Hook 如何合并与排序。
|
||||||
|
常见模式:修补 config.m4、注入编译标志、安装后修复。 -->
|
||||||
6
docs/zh/develop/vendor-mode/package-classes.md
Normal file
6
docs/zh/develop/vendor-mode/package-classes.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# 编写 Package 类
|
||||||
|
|
||||||
|
<!-- TODO: 编写 Library 类和 Extension 类的分步指南。
|
||||||
|
使用 #[Library]、#[Extension]、#[BuildFor] 的完整注释代码示例。
|
||||||
|
UnixAutoconfExecutor / UnixCmakeExecutor / WindowsCMakeExecutor 用法。
|
||||||
|
文件放置位置(src/Package/Library/、src/Package/Extension/)与自动加载。 -->
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
# 常见问题
|
# 常见问题
|
||||||
|
|
||||||
这里将会编写一些你容易遇到的问题。目前有很多,但是我需要花时间来整理一下。
|
这里将会编写一些你容易遇到的问题。
|
||||||
|
|
||||||
## php.ini 的路径是什么?
|
## php.ini 的路径是什么?
|
||||||
|
|
||||||
在 Linux、macOS 和 FreeBSD 上,`php.ini` 的路径是 `/usr/local/etc/php/php.ini`。
|
在 Linux、macOS 和 FreeBSD 上,`php.ini` 的路径是 `/usr/local/etc/php/php.ini`。
|
||||||
在 Windows 中,路径是 `C:\windows\php.ini` 或 `php.exe` 所在的当前目录。
|
在 Windows 中,路径是 `C:\windows\php.ini` 或 `php.exe` 所在的当前目录。
|
||||||
可以在 *nix 系统中使用手动构建选项 `--with-config-file-path` 来更改查找 `php.ini` 的目录。
|
可以在 *nix 系统中使用构建选项 `--with-config-file-path` 来更改查找 `php.ini` 的目录。
|
||||||
|
|
||||||
此外,在 Linux、macOS 和 FreeBSD 上,`/usr/local/etc/php/conf.d` 目录中的 `.ini` 文件也会被加载。
|
此外,在 Linux、macOS 和 FreeBSD 上,`/usr/local/etc/php/conf.d` 目录中的 `.ini` 文件也会被加载。
|
||||||
在 Windows 中,该路径默认为空。
|
在 Windows 中,该路径默认为空。
|
||||||
可以使用手动构建选项 `--with-config-file-scan-dir` 更改该目录。
|
可以使用构建选项 `--with-config-file-scan-dir` 更改该目录。
|
||||||
|
|
||||||
PHP 默认也会从 [其他标准位置](https://www.php.net/manual/zh/configuration.file.php) 中搜索 `php.ini`。
|
PHP 默认也会从 [其他标准位置](https://www.php.net/manual/zh/configuration.file.php) 中搜索 `php.ini`。
|
||||||
|
|
||||||
@@ -23,40 +23,38 @@ PHP 默认也会从 [其他标准位置](https://www.php.net/manual/zh/configura
|
|||||||
|
|
||||||
你可以使用命令 `ldd buildroot/bin/php` 来检查你在 Linux 下构建的二进制文件是否为纯静态链接。
|
你可以使用命令 `ldd buildroot/bin/php` 来检查你在 Linux 下构建的二进制文件是否为纯静态链接。
|
||||||
|
|
||||||
如果你 [构建基于 GNU libc 的 PHP](../guide/build-with-glibc),你可以使用 `ffi` 扩展来加载外部 `.so` 模块,并加载具有相同 ABI 的 `.so` 扩展。
|
如果你构建了基于 GNU libc 的 PHP,你可以使用 `ffi` 扩展来加载外部 `.so` 模块,并加载具有相同 ABI 的 `.so` 扩展。
|
||||||
|
|
||||||
例如,你可以使用以下命令构建一个与 glibc 动态链接的静态 PHP 二进制文件,支持 FFI 扩展并加载相同 PHP 版本和相同 TS 类型的 `xdebug.so` 扩展:
|
例如,你可以使用以下命令构建一个与 glibc 动态链接的静态 PHP 二进制文件,支持 FFI 扩展并加载相同 PHP 版本和相同 TS 类型的 `xdebug.so` 扩展:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bin/spc-gnu-docker download --for-extensions=ffi,xml --with-php=8.4
|
SPC_TARGET=native-native-gnu.2.17 spc build:php "ffi,xml" --build-cli -vvv
|
||||||
bin/spc-gnu-docker build ffi,xml --build-cli --debug
|
|
||||||
|
|
||||||
buildroot/bin/php -d "zend_extension=/path/to/php{PHP_VER}-{ts/nts}/xdebug.so" --ri xdebug
|
buildroot/bin/php -d "zend_extension=/path/to/php{PHP_VER}-{ts/nts}/xdebug.so" --ri xdebug
|
||||||
```
|
```
|
||||||
|
|
||||||
|
这将使用 Zig 工具链构建出一个动态链接 glibc 2.17 的准静态二进制,无需 Docker,也无需额外的交叉编译工具链。
|
||||||
|
|
||||||
对于 macOS 平台,macOS 下的几乎所有二进制文件都无法真正纯静态链接,几乎所有二进制文件都会链接 macOS 系统库:`/usr/lib/libresolv.9.dylib` 和 `/usr/lib/libSystem.B.dylib`。
|
对于 macOS 平台,macOS 下的几乎所有二进制文件都无法真正纯静态链接,几乎所有二进制文件都会链接 macOS 系统库:`/usr/lib/libresolv.9.dylib` 和 `/usr/lib/libSystem.B.dylib`。
|
||||||
因此,在 macOS 上,你可以**直接**使用 SPC 构建具有动态链接扩展的静态编译 PHP 二进制文件:
|
因此,在 macOS 上,你可以**直接**使用 SPC 构建具有动态链接扩展的静态编译 PHP 二进制文件:
|
||||||
|
|
||||||
1. 使用 `--build-shared=XXX` 选项构建共享扩展 `xxx.so`。例如:`bin/spc build bcmath,zlib --build-shared=xdebug --build-cli`
|
1. 使用 `--build-shared=XXX` 选项构建共享扩展 `xxx.so`。例如:`spc build:php "bcmath,zlib" --build-shared=xdebug --build-cli`
|
||||||
2. 你将获得 `buildroot/modules/xdebug.so` 和 `buildroot/bin/php`。
|
2. 你将获得 `buildroot/modules/xdebug.so` 和 `buildroot/bin/php`。
|
||||||
3. `xdebug.so` 文件可用于版本和线程安全相同的 php。
|
3. `xdebug.so` 文件可用于版本和线程安全相同的 php。
|
||||||
|
|
||||||
对于 Windows 平台,由于官方构建的扩展(如 `php_yaml.dll`)强制使用了 `php8.dll` 动态库作为链接,静态构建的 PHP 不包含任何系统库以外的动态库,
|
对于 Windows 平台,由于官方构建的扩展(如 `php_yaml.dll`)强制使用了 `php8.dll` 动态库作为链接,静态构建的 PHP 不包含任何系统库以外的动态库,
|
||||||
所以 Windows 下无法加载官方构建的动态扩展。 由于 static-php-cli 还暂未支持构建动态扩展,所以目前还没有让 static-php 加载动态扩展的方法。
|
所以 Windows 下无法加载官方构建的动态扩展。由于 StaticPHP 还暂未支持构建动态扩展,所以目前还没有让 static-php 加载动态扩展的方法。
|
||||||
|
|
||||||
不过,Windows 可以正常使用 `FFI` 扩展加载其他的 dll 文件并调用。
|
不过,Windows 可以正常使用 `FFI` 扩展加载其他的 dll 文件并调用。
|
||||||
|
|
||||||
## 可以支持 Oracle 数据库扩展吗?
|
## 可以支持 Oracle 数据库扩展吗?
|
||||||
|
|
||||||
部分依赖库闭源的扩展,如 `oci8`、`sourceguardian` 等,它们没有提供纯静态编译的依赖库文件(`.a`),仅提供了动态依赖库文件(`.so`),
|
部分依赖库闭源的扩展,如 `oci8`、`sourceguardian` 等,它们没有提供纯静态编译的依赖库文件(`.a`),仅提供了动态依赖库文件(`.so`),
|
||||||
这些扩展无法使用源码的形式编译到 static-php-cli 中,所以本项目可能永远也不会支持这些扩展。不过,理论上你可以根据上面的问题在 macOS 和 Linux 下接入和使用这类扩展。
|
这些扩展无法使用源码的形式编译到 StaticPHP 中,所以本项目可能永远也不会支持这些扩展。不过,理论上你可以根据上面的问题在 macOS 和 Linux 下接入和使用这类扩展。
|
||||||
|
|
||||||
如果你对此类扩展有需求,或者大部分人都对这些闭源扩展使用有需求,
|
|
||||||
可以看看有关 [standalone-php-cli](https://github.com/crazywhalecc/static-php-cli/discussions/58) 的讨论。欢迎留言。
|
|
||||||
|
|
||||||
## 支持 Windows 吗?
|
## 支持 Windows 吗?
|
||||||
|
|
||||||
该项目目前支持 Windows,但支持的扩展数量较少。Windows 支持并不完美。主要有以下问题:
|
该项目目前支持 Windows,但支持的扩展数量较少。Windows 支持并不完善。主要有以下问题:
|
||||||
|
|
||||||
1. Windows 的编译过程与 *nix 不同,使用的工具链也不同。用于编译每个扩展依赖库的编译工具也几乎完全不同。
|
1. Windows 的编译过程与 *nix 不同,使用的工具链也不同。用于编译每个扩展依赖库的编译工具也几乎完全不同。
|
||||||
2. Windows 版本的需求也会根据所有使用本项目的人的需求推进。如果很多人需要,我会尽快支持相关扩展。
|
2. Windows 版本的需求也会根据所有使用本项目的人的需求推进。如果很多人需要,我会尽快支持相关扩展。
|
||||||
@@ -70,14 +68,14 @@ buildroot/bin/php -d "zend_extension=/path/to/php{PHP_VER}-{ts/nts}/xdebug.so" -
|
|||||||
|
|
||||||
加密和保护代码的方向与编译不同。编译后,也可以通过逆向工程等方法获得代码。真正的保护仍然通过打包和加密代码等手段进行。
|
加密和保护代码的方向与编译不同。编译后,也可以通过逆向工程等方法获得代码。真正的保护仍然通过打包和加密代码等手段进行。
|
||||||
|
|
||||||
因此,本项目(static-php-cli)和相关项目(lwmbs、swoole-cli)都提供了 php-src 源代码的便捷编译工具。
|
因此,本项目(StaticPHP)和相关项目(lwmbs、swoole-cli)都提供了 php-src 源代码的便捷编译工具。
|
||||||
本项目和相关项目引用的 phpmicro 只是 PHP 的 sapi 接口封装,而不是 PHP 代码的编译工具。
|
本项目和相关项目引用的 phpmicro 只是 PHP 的 sapi 接口封装,而不是 PHP 代码的编译工具。
|
||||||
PHP 代码的编译器是一个完全不同的项目,因此不考虑额外的情况。
|
PHP 代码的编译器是一个完全不同的项目,因此不考虑额外的情况。
|
||||||
如果你对加密感兴趣,可以考虑使用现有的加密技术,如 Swoole Compiler、Source Guardian 等。
|
如果你对加密感兴趣,可以考虑使用现有的加密技术,如 Swoole Compiler、Source Guardian 等。
|
||||||
|
|
||||||
## 无法使用 ssl
|
## 无法使用 ssl
|
||||||
|
|
||||||
**更新:该问题已在最新版本的 static-php-cli 中修复,现在默认读取系统的证书文件。如果你仍然遇到问题,请尝试下面的解决方案。**
|
**更新:该问题已在最新版本的 StaticPHP 中修复,现在默认读取系统的证书文件。如果你仍然遇到问题,请尝试下面的解决方案。**
|
||||||
|
|
||||||
使用 curl、pgsql 等请求 HTTPS 网站或建立 SSL 连接时,可能会出现 `error:80000002:system library::No such file or directory` 错误。
|
使用 curl、pgsql 等请求 HTTPS 网站或建立 SSL 连接时,可能会出现 `error:80000002:system library::No such file or directory` 错误。
|
||||||
此错误是由于静态编译的 PHP 未通过 `php.ini` 指定 `openssl.cafile` 导致的。
|
此错误是由于静态编译的 PHP 未通过 `php.ini` 指定 `openssl.cafile` 导致的。
|
||||||
@@ -93,4 +91,5 @@ PHP 代码的编译器是一个完全不同的项目,因此不考虑额外的
|
|||||||
|
|
||||||
因为旧版本的 PHP 有很多问题,如安全问题、性能问题和功能问题。此外,许多旧版本的 PHP 与最新的依赖库不兼容,这也是不支持旧版本 PHP 的原因之一。
|
因为旧版本的 PHP 有很多问题,如安全问题、性能问题和功能问题。此外,许多旧版本的 PHP 与最新的依赖库不兼容,这也是不支持旧版本 PHP 的原因之一。
|
||||||
|
|
||||||
你可以使用 static-php-cli 早期编译的旧版本,如 PHP 8.0,但不会明确支持早期版本。
|
你可以使用 StaticPHP 早期编译的旧版本,如 PHP 8.0,但早期版本将不会被明确支持。
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
# Action 构建
|
|
||||||
|
|
||||||
Action 构建指的是直接使用 GitHub Action 进行编译。
|
|
||||||
|
|
||||||
如果你不想自行编译,可以从本项目现有的 Action 下载 Artifact,也可以从自托管的服务器下载:[进入](https://dl.static-php.dev/static-php-cli/common/)
|
|
||||||
|
|
||||||
> 自托管的二进制也是由 Action 构建而来,[项目仓库地址](https://github.com/static-php/static-php-cli-hosted)。
|
|
||||||
> 包含的扩展有:bcmath,bz2,calendar,ctype,curl,dom,exif,fileinfo,filter,ftp,gd,gmp,iconv,xml,mbstring,mbregex,mysqlnd,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,redis,session,simplexml,soap,sockets,sqlite3,tokenizer,xmlwriter,xmlreader,zlib,zip
|
|
||||||
|
|
||||||
## 构建方法
|
|
||||||
|
|
||||||
使用 GitHub Action 可以方便地构建一个静态编译的 PHP 和 phpmicro,同时可以自行定义要编译的扩展。
|
|
||||||
|
|
||||||
1. Fork 本项目。
|
|
||||||
2. 进入项目的 Actions,选择 CI 开头的 Workflow(根据你需要的操作系统选择)。
|
|
||||||
3. 选择 `Run workflow`,填入你要编译的 PHP 版本、目标类型、扩展列表。(扩展列表使用英文逗号分割,例如 `bcmath,curl,mbstring`)
|
|
||||||
4. 如果需要共享扩展(例如 `xdebug`),请设置 `shared-extensions`(使用英文逗号分割,例如 `xdebug`)。
|
|
||||||
5. 如果需要 FrankenPHP,请启用 `build-frankenphp`,同时也需要启用 `enable-zts`。
|
|
||||||
6. 等待大约一段时间后,进入对应的任务中,获取 `Artifacts`。
|
|
||||||
|
|
||||||
如果你选择了 `debug`,则会在构建时输出所有日志,包括编译的日志,以供排查错误。
|
|
||||||
|
|
||||||
> 如果你需要在其他环境构建,可以使用 [手动构建](./manual-build)。
|
|
||||||
|
|
||||||
## 扩展选择
|
|
||||||
|
|
||||||
你可以到 [扩展列表](./extensions) 中查看目前你需要的扩展是否均支持,
|
|
||||||
然后到 [在线命令生成](./cli-generator) 中选择你需要编译的扩展,复制扩展字符串到 Action 的 `extensions` 中,编译即可。
|
|
||||||
@@ -1,204 +0,0 @@
|
|||||||
# 在 Windows 上构建
|
|
||||||
|
|
||||||
因为 Windows 系统是 NT 内核,与类 Unix 的操作系统使用的编译工具及操作系统接口几乎完全不同,所以在 Windows 上的构建流程会与 Unix 系统有些许不同。
|
|
||||||
|
|
||||||
## GitHub Actions 构建
|
|
||||||
|
|
||||||
现在已支持从 Actions 构建 Windows 版本的 static-php 了。
|
|
||||||
和 Linux、macOS 一样,你需要先 Fork static-php-cli 仓库到你的 GitHub 账户中,然后你可以进入 [扩展列表](./extensions) 选择要编译的扩展,然后进入自己仓库的 `CI on Windows` 选择 PHP 版本、填入扩展列表(逗号分割),点击 Run 即可。
|
|
||||||
|
|
||||||
如果你要在本地开发或构建,请继续向下阅读。
|
|
||||||
|
|
||||||
## 环境准备
|
|
||||||
|
|
||||||
在 Windows 上构建静态 PHP 所需要的工具与 PHP 官方的 Windows 构建工具是相同的。你可以阅读 [官方文档](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2)。
|
|
||||||
|
|
||||||
总结下来,你需要以下环境及工具:
|
|
||||||
|
|
||||||
- Windows 10(需要 build 17063 或以后的更新)
|
|
||||||
- Visual Studio 2019/2022(推荐 2022)
|
|
||||||
- Visual Studio 的 C++ 桌面开发
|
|
||||||
- Git for Windows
|
|
||||||
- static-php-cli 仓库
|
|
||||||
- PHP 和 Composer(static-php-cli 需要它们,可使用 `bin/setup-runtime` 自动安装)
|
|
||||||
- [php-sdk-binary-tools](https://github.com/php/php-sdk-binary-tools)(可使用 doctor 自动安装)
|
|
||||||
- strawberry-perl(可使用 doctor 自动安装)
|
|
||||||
- nasm(可使用 doctor 自动安装)
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
static-php-cli 在 Windows 上的构建指的是使用 MSVC 构建 PHP,不基于 MinGW、Cygwin、WSL 等环境。
|
|
||||||
|
|
||||||
如果你更倾向使用 WSL,请参考在 Linux 上构建的章节。
|
|
||||||
:::
|
|
||||||
|
|
||||||
在安装 Visual Studio 后,选择 C++ 桌面开发的工作负荷后,可能会下载 8GB 左右的编译工具,下载速度取决于你的网络状况。
|
|
||||||
|
|
||||||
### 安装 Git
|
|
||||||
|
|
||||||
Git for Windows 可以从 [这里](https://git-scm.com/download/win) 下载并安装 `Standalone Installer 64-bit` 版本,安装在默认位置(`C:\Program Files\Git\`)。
|
|
||||||
如果不想手动下载和安装,你也可以使用 Visual Studio Installer,在**单个组件**的选择列表中,勾选 Git。
|
|
||||||
|
|
||||||
### 准备 static-php-cli
|
|
||||||
|
|
||||||
static-php-cli 项目的下载方式很简单,只需要使用 git clone 即可。推荐将项目放在 `C:\spc-build\` 或类似目录,路径最好不要有空格。
|
|
||||||
|
|
||||||
```shell
|
|
||||||
mkdir "C:\spc-build"
|
|
||||||
cd C:\spc-build
|
|
||||||
git clone https://github.com/crazywhalecc/static-php-cli.git
|
|
||||||
cd static-php-cli
|
|
||||||
```
|
|
||||||
|
|
||||||
static-php-cli 自身需要 PHP 环境,是有点奇怪,但现在可以通过脚本快速安装 PHP 环境。
|
|
||||||
一般你的电脑不会安装 Windows 版本的 PHP,所以我们建议你在下载 static-php-cli 后,直接使用 `bin/setup-runtime`,在当前目录安装 PHP 和 Composer。
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# 安装 PHP 和 Composer 到 ./runtime/ 目录
|
|
||||||
bin/setup-runtime
|
|
||||||
|
|
||||||
# 安装后,如需在全局命令中使用 PHP 和 Composer,使用下面的命令将 runtime/ 目录添加到 PATH
|
|
||||||
bin/setup-runtime -action add-path
|
|
||||||
# 删除 PATH 中的 runtime/ 目录
|
|
||||||
bin/setup-runtime -action remove-path
|
|
||||||
```
|
|
||||||
|
|
||||||
在准备好 PHP 和 Composer 环境后,使用 `composer` 安装 static-php-cli 的依赖:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
cd C:\spc-build\static-php-cli
|
|
||||||
runtime/composer install --no-dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### 自动安装其他依赖
|
|
||||||
|
|
||||||
对于 `php-sdk-binary-tools`、`strawberry-perl`、`nasm`,我们更建议你直接使用命令 `bin/spc doctor --auto-fix` 检查并安装。
|
|
||||||
|
|
||||||
如果 doctor 成功自动安装,请**跳过**下方手动安装上述工具的步骤。
|
|
||||||
|
|
||||||
如果自动安装无法成功的话,再参考下方手动安装的方式。
|
|
||||||
|
|
||||||
### 手动安装 php-sdk-binary-tools
|
|
||||||
|
|
||||||
```bat
|
|
||||||
cd C:\spc-build\static-php-cli
|
|
||||||
git clone https://github.com/php/php-sdk-binary-tools.git
|
|
||||||
```
|
|
||||||
|
|
||||||
> 你也可以在 Windows 设置中设置全局变量 `PHP_SDK_PATH`,并将该项目克隆至变量对应的路径。一般情况下,默认即可。
|
|
||||||
|
|
||||||
### 手动安装 strawberry-perl
|
|
||||||
|
|
||||||
> 如果你不需要编译 openssl 扩展,可不安装 perl。
|
|
||||||
|
|
||||||
1. 从 [GitHub](https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/) 下载 strawberry-perl 最新版。
|
|
||||||
2. 安装到 `C:\spc-build\static-php-cli\pkgroot\perl\` 目录。
|
|
||||||
|
|
||||||
> 你可以下载 `-portable` 版本,并直接解压到上述目录。
|
|
||||||
> 最后的 `perl.exe` 应该位于 `C:\spc-build\static-php-cli\pkgroot\perl\perl\bin\perl.exe`。
|
|
||||||
|
|
||||||
### 手动安装 nasm
|
|
||||||
|
|
||||||
> 如果你不需要编译 openssl 扩展,可不安装 nasm。
|
|
||||||
|
|
||||||
1. 从 [官网](https://www.nasm.us/pub/nasm/releasebuilds/) 下载 nasm 工具(x64)。
|
|
||||||
2. 将 `nasm.exe`、`ndisasm.exe` 放在 `C:\spc-build\static-php-cli\php-sdk-binary-tools\bin\` 目录。
|
|
||||||
|
|
||||||
|
|
||||||
## 下载源码
|
|
||||||
|
|
||||||
见 [本地构建 - download](./manual-build.html#命令-download-下载依赖包)
|
|
||||||
|
|
||||||
## 编译 PHP
|
|
||||||
|
|
||||||
使用 build 命令可以开始构建静态 php 二进制,在执行 `bin/spc build` 命令前,务必先使用 `download` 命令下载资源,建议使用 `doctor` 检查环境。
|
|
||||||
|
|
||||||
### 基本用法
|
|
||||||
|
|
||||||
你需要先到 [扩展列表](./extensions) 或 [命令生成器](./cli-generator) 选择你要加入的扩展,然后使用命令 `bin/spc build` 进行编译。你需要指定编译目标,从如下参数中选择:
|
|
||||||
|
|
||||||
- `--build-cli`: 构建一个 cli sapi(命令行界面,可在命令行执行 PHP 代码)
|
|
||||||
- `--build-micro`: 构建一个 micro sapi(用于构建一个包含 PHP 代码的独立可执行二进制)
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# 编译 PHP,附带 bcmath,openssl,zlib 扩展,编译目标为 cli
|
|
||||||
bin/spc build "bcmath,openssl,zlib" --build-cli
|
|
||||||
|
|
||||||
# 编译 PHP,附带 bcmath,openssl,zlib 扩展,编译目标为 micro 和 cli
|
|
||||||
bin/spc build "bcmath,openssl,zlib" --build-micro --build-cli
|
|
||||||
```
|
|
||||||
|
|
||||||
::: warning
|
|
||||||
在Windows中,最好使用双引号包裹包含逗号的参数,例如 `"bcmath,openssl,mbstring"`
|
|
||||||
:::
|
|
||||||
|
|
||||||
### 调试
|
|
||||||
|
|
||||||
如果你在编译过程中遇到了问题,或者想查看每个执行的 shell 命令,可以使用 `--debug` 开启 debug 模式,查看所有终端日志:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
bin/spc build "openssl" --build-cli --debug
|
|
||||||
```
|
|
||||||
|
|
||||||
### 编译运行选项
|
|
||||||
|
|
||||||
在编译过程中,有些特殊情况需要对编译器、编译目录的内容进行干预,可以尝试使用以下命令:
|
|
||||||
|
|
||||||
- `--with-clean`: 编译 PHP 前先清理旧的 make 产生的文件
|
|
||||||
- `--enable-zts`: 让编译的 PHP 为线程安全版本(默认为 NTS 版本)
|
|
||||||
- `--with-libs=XXX,YYY`: 编译 PHP 前先编译指定的依赖库,激活部分扩展的可选功能
|
|
||||||
- `--with-config-file-scan-dir=XXX`: 读取 `php.ini` 后扫描 `.ini` 文件的目录(在 [这里](../faq/index.html#php-ini-的路径是什么) 查看默认路径)
|
|
||||||
- `-I xxx=yyy`: 编译前将 INI 选项硬编译到 PHP 内(支持多个选项,别名是 `--with-hardcoded-ini`)
|
|
||||||
- `--with-micro-fake-cli`: 在编译 micro 时,让 micro 的 SAPI 伪装为 `cli`(用于兼容一些检查 `PHP_SAPI` 的程序)
|
|
||||||
- `--disable-opcache-jit`: 禁用 opcache jit(默认启用)
|
|
||||||
- `--without-micro-ext-test`: 在构建 micro.sfx 后,禁用测试不同扩展在 micro.sfx 的运行结果
|
|
||||||
- `--with-suggested-exts`: 编译时将 `ext-suggests` 也作为编译依赖加入
|
|
||||||
- `--with-suggested-libs`: 编译时将 `lib-suggests` 也作为编译依赖加入
|
|
||||||
- `--with-upx-pack`: 编译后使用 UPX 减小二进制文件体积(需先使用 `bin/spc install-pkg upx` 安装 upx)
|
|
||||||
- `--with-micro-logo=XXX.ico`: 自定义 micro 构建组合后的 `exe` 可执行文件的图标(格式为 `.ico`)
|
|
||||||
|
|
||||||
有关硬编码 INI 选项,下面是一个简单的例子,我们预设一个更大的 `memory_limit`,并且禁用 `system` 函数:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
bin/spc build "bcmath,openssl" --build-cli -I "memory_limit=4G" -I "disable_functions=system"
|
|
||||||
```
|
|
||||||
|
|
||||||
另一个例子:自定义 micro 构建后的 `exe` 程序图标:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
bin/spc build "ffi,bcmath" --build-micro --with-micro-logo=mylogo.ico --debug
|
|
||||||
bin/spc micro:combine hello.php
|
|
||||||
# Then we got `my-app.exe` with custom logo!
|
|
||||||
my-app.exe
|
|
||||||
```
|
|
||||||
|
|
||||||
## 使用 php.exe
|
|
||||||
|
|
||||||
php.exe 编译后位于 `buildroot\bin\` 目录,你可以将其拷贝到任意位置使用。
|
|
||||||
|
|
||||||
```shell
|
|
||||||
.\php -v
|
|
||||||
```
|
|
||||||
|
|
||||||
## 使用 micro
|
|
||||||
|
|
||||||
> phpmicro 是一个提供自执行二进制 PHP 的项目,本项目依赖 phpmicro 进行编译自执行二进制。详见 [dixyes/phpmicro](https://github.com/dixyes/phpmicro)。
|
|
||||||
|
|
||||||
最后编译结果会输出一个 `./micro.sfx` 的文件,此文件需要配合你的 PHP 源码使用。
|
|
||||||
该文件编译后会存放在 `buildroot/bin/` 目录中。
|
|
||||||
|
|
||||||
使用时应准备好你的项目源码文件,可以是单个 PHP 文件,也可以是 Phar 文件。
|
|
||||||
|
|
||||||
> 如果要结合 phar 文件,编译时必须包含 phar 扩展!
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# code.php "<?php echo 'Hello world' . PHP_EOL;"
|
|
||||||
bin/spc micro:combine code.php -O my-app.exe
|
|
||||||
# Run it!!! Copy it to another computer!!!
|
|
||||||
./my-app.exe
|
|
||||||
```
|
|
||||||
|
|
||||||
如果打包 PHAR 文件,仅需把 code.php 更换为 phar 文件路径即可。
|
|
||||||
你可以使用 [box-project/box](https://github.com/box-project/box) 将你的 CLI 项目打包为 Phar,
|
|
||||||
然后将它与 phpmicro 结合,生成独立可执行的二进制文件。
|
|
||||||
|
|
||||||
有关 `micro:combine` 命令的更多细节,请参考 Unix 系统上的 [命令](./manual-build)。
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
# 构建 glibc 兼容的 Linux 二进制
|
|
||||||
|
|
||||||
## 为什么要构建 glibc 兼容的二进制
|
|
||||||
|
|
||||||
目前,static-php-cli 在默认条件下在 Linux 系统构建的二进制都是基于 musl-libc(静态链接)的。
|
|
||||||
musl-libc 是一个轻量级的 libc 实现,它的目标是与 glibc 兼容,并且提供良好的纯静态链接支持。
|
|
||||||
这意味着,编译出来的静态 PHP 可执行文件在几乎任何 Linux 发行版都可以使用,而不需要考虑 libc、libstdc++ 等库的版本问题。
|
|
||||||
|
|
||||||
但是,Linux 系统的纯静态链接 musl-libc 二进制文件存在以下问题:
|
|
||||||
|
|
||||||
- 无法使用 PHP 的 `dl()` 函数加载动态链接库和外部 PHP 扩展。
|
|
||||||
- 无法使用 PHP 的 FFI 扩展。
|
|
||||||
- 部分极端情况下,可能会出现性能问题,参见 [musl-libc 的性能问题](https://github.com/php/php-src/issues/13648)。
|
|
||||||
|
|
||||||
对于不同的 Linux 发行版,它们使用的默认 libc 可能不同,比如 Alpine Linux 使用 musl libc,而大多数 Linux 发行版使用 glibc。
|
|
||||||
但即便如此,我们也不能直接使用任意的发行版和 glibc 构建便携的静态二进制文件,因为 glibc 有一些问题:
|
|
||||||
|
|
||||||
- 基于新版本的发行版在使用 gcc 等工具构建的二进制,无法在旧版本的发行版上运行。
|
|
||||||
- glibc 不推荐被静态链接,因为它的一些特性需要动态链接库的支持。
|
|
||||||
|
|
||||||
但是,我们可以使用 Docker 容器来解决这个问题,最终输出的结果是一个动态链接 glibc 和一些必要库的二进制,但它静态链接所有其他依赖。
|
|
||||||
|
|
||||||
1. 使用一个旧版本的 Linux 发行版(如 CentOS 7.x),它的 glibc 版本比较旧,但是可以在大多数现代 Linux 发行版上运行。
|
|
||||||
2. 在这个容器中构建 PHP 的静态二进制文件,这样就可以在大多数现代 Linux 发行版上运行了。
|
|
||||||
|
|
||||||
> 使用 glibc 的静态二进制文件,可以在大多数现代 Linux 发行版上运行,但是不能在 musl libc 的发行版上运行,如 CentOS 6、Alpine Linux 等。
|
|
||||||
|
|
||||||
## 构建 glibc 兼容的 Linux 二进制
|
|
||||||
|
|
||||||
最新版的 static-php-cli 内置了 `bin/spc-gnu-docker` 脚本,可以一键创建一个 CentOS 7.x (glibc-2.17) 的 Docker 容器,并在容器中构建 glibc 兼容的 PHP 静态二进制文件。
|
|
||||||
|
|
||||||
然后,先运行一次以下命令。首次运行时时间较长,因为需要下载 CentOS 7.x 的镜像和一些编译工具。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc-gnu-docker
|
|
||||||
```
|
|
||||||
|
|
||||||
构建镜像完成后,你将看到和 `bin/spc` 一样的命令帮助菜单,这时说明容器已经准备好了。
|
|
||||||
|
|
||||||
在容器准备好后,你可以参考 [本地构建](./manual-build) 章节的内容,构建你的 PHP 静态二进制文件。仅需要把 `bin/spc` 或 `./spc` 替换为 `bin/spc-gnu-docker` 即可。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc-gnu-docker build bcmath,ctype,openssl,pdo,phar,posix,session,tokenizer,xml,zip --build-cli --debug
|
|
||||||
```
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
极少数情况下,基于 glibc 的静态 PHP 可能会出现 segment fault 等错误,但目前例子较少,如果遇到问题请提交 issue。
|
|
||||||
|
|
||||||
glibc 构建为扩展的特性,不属于默认 static-php 的支持范围。如果有相关问题或需求,请在提交 Issue 时注明你是基于 glibc 构建的。
|
|
||||||
|
|
||||||
如果你需要不使用 Docker 构建基于 glibc 的二进制,请参考 `bin/spc-gnu-docker` 脚本,手动构建一个类似的环境。
|
|
||||||
|
|
||||||
请注意,我们仅支持使用 bin/spc-gnu-docker 构建的 glibc 版本。已在 RHEL 9 和 10 上进行了编译测试并验证其稳定性,但如果您遇到问题,我们可能不会进行修复。
|
|
||||||
@@ -2,14 +2,10 @@
|
|||||||
aside: false
|
aside: false
|
||||||
---
|
---
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup>
|
||||||
import CliGenerator from "../../.vitepress/components/CliGenerator.vue";
|
import CliGenerator from "../../.vitepress/components/CliGenerator.vue";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
# CLI 编译命令生成器
|
# 编译命令生成器
|
||||||
|
|
||||||
::: tip
|
<CliGenerator lang="zh" />
|
||||||
下面选择扩展可能包含所选操作系统不支持的扩展,这可能导致编译失败。请先查阅 [支持的扩展](./extensions)。
|
|
||||||
:::
|
|
||||||
|
|
||||||
<cli-generator lang="zh" />
|
|
||||||
|
|||||||
522
docs/zh/guide/cli-reference.md
Normal file
522
docs/zh/guide/cli-reference.md
Normal file
@@ -0,0 +1,522 @@
|
|||||||
|
---
|
||||||
|
outline: 'deep'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 命令行参考
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
如果你采用的是 spc 二进制方式安装,请将本章节中的所有 `spc` 替换为 `./spc` 或 `.\spc.exe`。
|
||||||
|
|
||||||
|
如果你采用的是源码安装,请将 `spc` 替换为 `bin/spc`。
|
||||||
|
:::
|
||||||
|
|
||||||
|
## download
|
||||||
|
|
||||||
|
下载构建所需的源码包和预编译二进制。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc download [artifacts] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`artifacts`(可选):指定要下载的制品名称,逗号分隔(如 `"php-src,openssl,curl"`)。
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
| 选项 | 缩写 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `--for-extensions=<list>` | `-e` | 按扩展名下载其所需的制品 |
|
||||||
|
| `--for-libs=<list>` | `-l` | 按库名下载其所需的制品 |
|
||||||
|
| `--for-packages=<list>` | | 按包名下载其所需的制品 |
|
||||||
|
| `--without-suggests` | | 使用 `--for-extensions` 时跳过建议包 |
|
||||||
|
| `--clean` | | 下载前删除旧的下载缓存 |
|
||||||
|
| `--with-php=<ver>` | | PHP 版本,格式为 `major.minor`(默认 `8.4`)|
|
||||||
|
| `--prefer-binary` | `-p` | 优先使用预编译二进制 |
|
||||||
|
| `--prefer-source` | | 优先使用源码包 |
|
||||||
|
| `--source-only` | | 仅下载源码制品 |
|
||||||
|
| `--binary-only` | | 仅下载二进制制品 |
|
||||||
|
| `--parallel=<n>` | `-P` | 并行下载数(默认 `1`)|
|
||||||
|
| `--retry=<n>` | `-R` | 失败重试次数(默认 `0`)|
|
||||||
|
| `--ignore-cache=<list>` | | 强制重新下载指定制品 |
|
||||||
|
| `--no-alt` | | 不使用镜像站 |
|
||||||
|
| `--no-shallow-clone` | | 不使用浅层克隆 |
|
||||||
|
| `--custom-url=<src:url>` | `-U` | 覆盖指定源的下载地址 |
|
||||||
|
| `--custom-git=<src:branch:url>` | `-G` | 覆盖为自定义 git 仓库 |
|
||||||
|
| `--custom-local=<src:path>` | `-L` | 使用本地路径作为制品来源 |
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 按扩展名下载(推荐)
|
||||||
|
spc download --for-extensions="bcmath,openssl,curl" --with-php=8.4
|
||||||
|
|
||||||
|
# 下载指定制品
|
||||||
|
spc download "php-src,openssl"
|
||||||
|
|
||||||
|
# 增加并行数和重试次数
|
||||||
|
spc download --for-extensions="bcmath,openssl,curl" --parallel 8 --retry=3
|
||||||
|
|
||||||
|
# 优先使用预编译二进制
|
||||||
|
spc download --for-extensions="bcmath,openssl,curl" --prefer-binary
|
||||||
|
|
||||||
|
# 强制重新下载 PHP 源码(如切换版本)
|
||||||
|
spc download --for-extensions="bcmath,curl" --ignore-cache="php-src" --with-php=8.3
|
||||||
|
|
||||||
|
# 覆盖下载地址
|
||||||
|
spc download --for-extensions="bcmath" --custom-url "php-src:https://downloads.php.net/~user/php-8.5.0alpha1.tar.xz"
|
||||||
|
```
|
||||||
|
|
||||||
|
## build:php {#build-php}
|
||||||
|
|
||||||
|
从源码编译 PHP 及扩展。别名:`build`。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php <extensions> [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`extensions`(必填):要静态编译的扩展名列表,逗号分隔(如 `"bcmath,openssl,curl"`)。
|
||||||
|
|
||||||
|
`build:php` 上也可使用所有 `download` 选项,只需加上 `--dl-` 前缀(如 `--dl-with-php=8.3`、`--dl-parallel=4`),这些参数将传递给构建前自动运行的下载器。
|
||||||
|
|
||||||
|
### SAPI 选择 {#sapi-selection}
|
||||||
|
|
||||||
|
以下选项仅适用于 `build:php` 组合目标。如需单独构建某个 SAPI,请使用对应的专用命令(如 `spc build:php-cli`)。
|
||||||
|
|
||||||
|
| 选项 | 说明 |
|
||||||
|
|---|---|
|
||||||
|
| `--build-cli` | 构建 `cli` SAPI(`php` / `php.exe`)|
|
||||||
|
| `--build-fpm` | 构建 `php-fpm`(仅 Linux 和 macOS)|
|
||||||
|
| `--build-cgi` | 构建 `php-cgi` |
|
||||||
|
| `--build-micro` | 构建 `micro.sfx` |
|
||||||
|
| `--build-embed` | 构建 embed 静态库(`libphp.a` / `php8embed.lib`)|
|
||||||
|
| `--build-frankenphp` | 构建 FrankenPHP 二进制 |
|
||||||
|
|
||||||
|
### 通用构建选项 {#common-build-options}
|
||||||
|
|
||||||
|
| 选项 | 缩写 | 说明 |
|
||||||
|
|--------------------------------------|------|--------------------------------------------------------|
|
||||||
|
| `--no-strip` | | 保留调试符号,不精简二进制 |
|
||||||
|
| `--with-upx-pack` | | 用 UPX 压缩产物(需先 `spc install-pkg upx`;仅 Linux 和 Windows) |
|
||||||
|
| `--disable-opcache-jit` | | 禁用 OPcache JIT |
|
||||||
|
| `--with-config-file-path=<path>` | | PHP 查找 `php.ini` 的目录(默认:`/usr/local/etc/php`) |
|
||||||
|
| `--with-config-file-scan-dir=<path>` | | PHP 扫描追加 `.ini` 文件的目录(默认:`/usr/local/etc/php/conf.d`) |
|
||||||
|
| `--with-hardcoded-ini=<k=v>` | `-I` | 编译时将 INI 配置硬编码进二进制(可重复使用) |
|
||||||
|
| `--enable-zts` | | 启用线程安全(ZTS)模式 |
|
||||||
|
| `--no-smoke-test` | | 跳过构建后的冒烟测试 |
|
||||||
|
| `--with-suggests` | | 同时解析并安装建议包 |
|
||||||
|
| `--with-packages=<list>` | | 额外安装的包 |
|
||||||
|
| `--no-download` | | 跳过下载步骤(使用已有缓存) |
|
||||||
|
| `--build-shared=<list>` | `-D` | 指定编译为共享 `.so` / `.dll` 的扩展 |
|
||||||
|
|
||||||
|
### micro 专用选项 {#micro-options}
|
||||||
|
|
||||||
|
| 选项 | 说明 |
|
||||||
|
|----------------------------|--------------------------------------------------|
|
||||||
|
| `--with-micro-fake-cli` | 让 `micro` 的 `PHP_SAPI` 报告为 `cli` 而非 `micro` |
|
||||||
|
| `--without-micro-ext-test` | 跳过构建后的 `micro.sfx` 扩展测试 |
|
||||||
|
| `--with-micro-logo=<path>` | 为 `micro.sfx` 嵌入自定义 `.ico` 图标(仅 Windows) |
|
||||||
|
| `--enable-micro-win32` | 将 `micro.sfx` 构建为 Win32 GUI 程序而非控制台程序(仅 Windows) |
|
||||||
|
|
||||||
|
### frankenphp 专用选项 {#frankenphp-options}
|
||||||
|
|
||||||
|
| 选项 | 说明 |
|
||||||
|
|---|---|
|
||||||
|
| `--enable-zts` | FrankenPHP 必须开启线程安全 |
|
||||||
|
| `--with-frankenphp-app=<path>` | 将指定目录嵌入到 FrankenPHP 二进制中 |
|
||||||
|
|
||||||
|
### embed 专用选项 {#embed-options}
|
||||||
|
|
||||||
|
| 选项 | 说明 |
|
||||||
|
|---|---|
|
||||||
|
| `--build-shared=<list>` | 将指定扩展编译为共享库(需要 embed SAPI)|
|
||||||
|
|
||||||
|
### 下载透传选项 {#download-options}
|
||||||
|
|
||||||
|
所有下载器选项均可加 `--dl-` 前缀使用:
|
||||||
|
|
||||||
|
| 选项 | 说明 |
|
||||||
|
|---|---|
|
||||||
|
| `--dl-with-php=<ver>` | 指定下载的 PHP 版本(默认 `8.4`)|
|
||||||
|
| `--dl-prefer-binary` | 优先使用预编译二进制依赖 |
|
||||||
|
| `--dl-parallel=<n>` | 并行下载数 |
|
||||||
|
| `--dl-retry=<n>` | 失败重试次数 |
|
||||||
|
| `--dl-custom-url=<src:url>` | 覆盖指定源的下载地址 |
|
||||||
|
| `--dl-custom-git=<src:branch:url>` | 覆盖为自定义 git 仓库 |
|
||||||
|
|
||||||
|
Downloader 选项传递给 `build:php` 命令时,会被自动下载器在构建前使用。
|
||||||
|
这样你就可以直接通过构建命令控制下载行为,无需单独执行 `spc download` 命令。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,openssl,curl" --build-cli --dl-with-php=8.3 --dl-prefer-binary --dl-parallel=4
|
||||||
|
```
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建 cli SAPI
|
||||||
|
spc build:php "bcmath,openssl,curl" --build-cli
|
||||||
|
|
||||||
|
# 同时构建 cli + micro
|
||||||
|
spc build:php "bcmath,phar,openssl,curl" --build-cli --build-micro
|
||||||
|
|
||||||
|
# 指定 PHP 版本
|
||||||
|
spc build:php "bcmath,openssl" --build-cli --dl-with-php=8.3
|
||||||
|
|
||||||
|
# 硬编码 INI 到二进制
|
||||||
|
spc build:php "bcmath,pcntl" --build-cli -I "memory_limit=4G" -I "disable_functions=system"
|
||||||
|
|
||||||
|
# 保留调试符号
|
||||||
|
spc build:php "bcmath,openssl" --build-cli --no-strip
|
||||||
|
|
||||||
|
# 构建 FrankenPHP(需开启 ZTS)
|
||||||
|
spc build:php "bcmath,openssl,curl" --build-frankenphp --enable-zts
|
||||||
|
```
|
||||||
|
|
||||||
|
## build:php-cli, build:php-fpm, build:php-micro, build:php-embed, build:php-cgi, build:frankenphp
|
||||||
|
|
||||||
|
专用单目标构建命令,接受与 `build:php` 相同的选项,但不需要 SAPI 选择标志(`--build-*`),目标已隐式确定。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php-cli "bcmath,openssl,curl"
|
||||||
|
spc build:php-micro "bcmath,phar,openssl"
|
||||||
|
spc build:php-fpm "bcmath,openssl,curl,pdo_mysql"
|
||||||
|
spc build:php-embed "bcmath,openssl"
|
||||||
|
spc build:frankenphp "bcmath,openssl,curl" --enable-zts
|
||||||
|
```
|
||||||
|
|
||||||
|
## build:libs
|
||||||
|
|
||||||
|
从源码构建一个或多个库包。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:libs <libraries> [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`libraries`(必填):要构建的库包名称列表,逗号分隔(如 `"openssl,curl,zlib"`)。
|
||||||
|
|
||||||
|
支持所有 `download` 命令的选项,加 `--dl-` 前缀传递。
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
| 选项 | 缩写 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `--with-suggests` | `-L`、`-E` | 同时解析并安装建议包 |
|
||||||
|
| `--with-packages=<list>` | | 额外安装的包,逗号分隔 |
|
||||||
|
| `--no-download` | | 跳过下载步骤(使用已有缓存) |
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建单个库
|
||||||
|
spc build:libs openssl
|
||||||
|
|
||||||
|
# 构建多个库
|
||||||
|
spc build:libs "openssl,curl,zlib"
|
||||||
|
|
||||||
|
# 构建时包含建议包
|
||||||
|
spc build:libs openssl --with-suggests
|
||||||
|
|
||||||
|
# 跳过下载步骤
|
||||||
|
spc build:libs openssl --no-download
|
||||||
|
```
|
||||||
|
|
||||||
|
## craft
|
||||||
|
|
||||||
|
读取 `craft.yml` 并自动完成全流程构建。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc craft [path/to/craft.yml]
|
||||||
|
```
|
||||||
|
|
||||||
|
未指定路径时,使用当前工作目录下的 `craft.yml`。配置格式参见 [craft.yml 配置](../develop/craft-yml)。
|
||||||
|
|
||||||
|
## doctor
|
||||||
|
|
||||||
|
检查当前环境是否满足编译要求。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc doctor [--auto-fix[=never]]
|
||||||
|
```
|
||||||
|
|
||||||
|
| 选项 | 说明 |
|
||||||
|
|--------------------|----------------------|
|
||||||
|
| `--auto-fix` | 自动修复检测到的问题(使用系统包管理器) |
|
||||||
|
| `--auto-fix=never` | 仅报告问题,不尝试自动修复 |
|
||||||
|
|
||||||
|
## dev:shell
|
||||||
|
|
||||||
|
进入加载了 StaticPHP 构建环境的交互式 Shell(编译器 wrapper、`buildroot/`、`pkgroot/` 等均已添加到 `PATH`)。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc dev:shell
|
||||||
|
```
|
||||||
|
|
||||||
|
可用于在 embed SAPI 的 `libphp.a` 上编译小型 C 程序,或手动检查构建环境。
|
||||||
|
|
||||||
|
## check-update
|
||||||
|
|
||||||
|
检查指定制品是否有可用更新。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc check-update [artifact] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`artifact`(可选):要检查更新的制品名称,逗号分隔。默认检查所有已下载的制品。
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
| 选项 | 缩写 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `--json` | | 以 JSON 格式输出结果 |
|
||||||
|
| `--bare` | | 检查时不要求制品已下载(旧版本显示为 null)|
|
||||||
|
| `--parallel=<n>` | `-p` | 并行检查数(默认 `10`)|
|
||||||
|
| `--with-php=<ver>` | | PHP 版本上下文,格式为 `major.minor`(默认 `8.4`)|
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 检查所有已下载制品
|
||||||
|
spc check-update
|
||||||
|
|
||||||
|
# 检查指定制品
|
||||||
|
spc check-update "openssl,curl"
|
||||||
|
|
||||||
|
# 以 JSON 格式输出
|
||||||
|
spc check-update --json
|
||||||
|
|
||||||
|
# 无需先下载即可检查
|
||||||
|
spc check-update "openssl" --bare
|
||||||
|
```
|
||||||
|
|
||||||
|
## dump-extensions
|
||||||
|
|
||||||
|
从 Composer 项目中分析所需的 PHP 扩展列表。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc dump-extensions [path] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`path`(可选):项目根目录路径,默认为当前目录(`.`)。
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
| 选项 | 缩写 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `--format=<fmt>` | `-F` | 输出格式(默认 `default`)|
|
||||||
|
| `--no-ext-output=<list>` | `-N` | 未找到扩展时输出的默认组合(逗号分隔),而不是以失败退出 |
|
||||||
|
| `--no-dev` | | 不包含 dev 依赖 |
|
||||||
|
| `--no-spc-filter` | `-S` | 不使用 SPC 过滤器筛选扩展 |
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 分析当前目录的 Composer 项目
|
||||||
|
spc dump-extensions
|
||||||
|
|
||||||
|
# 分析指定目录
|
||||||
|
spc dump-extensions /path/to/project
|
||||||
|
|
||||||
|
# 不包含 dev 依赖
|
||||||
|
spc dump-extensions --no-dev
|
||||||
|
|
||||||
|
# 未找到扩展时输出默认组合
|
||||||
|
spc dump-extensions --no-ext-output="bcmath,openssl"
|
||||||
|
```
|
||||||
|
|
||||||
|
## dump-license
|
||||||
|
|
||||||
|
导出制品的开源许可证文件。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc dump-license [artifacts] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`artifacts`(可选):要导出许可证的制品名称,逗号分隔(如 `"php-src,openssl,curl"`)。
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
| 选项 | 缩写 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `--for-extensions=<list>` | `-e` | 按扩展名导出(自动包含 php-src),如 `"openssl,mbstring"` |
|
||||||
|
| `--for-libs=<list>` | `-l` | 按库名导出,如 `"openssl,zlib"` |
|
||||||
|
| `--for-packages=<list>` | `-p` | 按包名导出,如 `"php,libssl"` |
|
||||||
|
| `--dump-dir=<path>` | `-d` | 许可证输出目录(默认 `buildroot/license`)|
|
||||||
|
| `--without-suggests` | | 不包含建议包的许可证 |
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 按扩展名导出许可证
|
||||||
|
spc dump-license --for-extensions="bcmath,openssl,curl"
|
||||||
|
|
||||||
|
# 导出指定制品的许可证
|
||||||
|
spc dump-license "php-src,openssl"
|
||||||
|
|
||||||
|
# 指定输出目录
|
||||||
|
spc dump-license --for-extensions="bcmath,openssl" --dump-dir=/tmp/licenses
|
||||||
|
```
|
||||||
|
|
||||||
|
## extract
|
||||||
|
|
||||||
|
将已下载的制品解压到对应的目标位置。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc extract [artifacts] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`artifacts`(可选):要解压的制品名称,逗号分隔(如 `"php-src,openssl,curl"`)。
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
| 选项 | 缩写 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `--for-extensions=<list>` | `-e` | 按扩展名解压所需制品,如 `"openssl,mbstring"` |
|
||||||
|
| `--for-libs=<list>` | `-l` | 按库名解压所需制品,如 `"libcares,openssl"` |
|
||||||
|
| `--for-packages=<list>` | | 按包名解压所需制品,如 `"php,libssl,libcurl"` |
|
||||||
|
| `--without-suggests` | | 使用 `--for-extensions` 时跳过建议包 |
|
||||||
|
| `--source-only` | | 强制解压源码,即使已有预编译二进制 |
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 按扩展名解压
|
||||||
|
spc extract --for-extensions="bcmath,openssl,curl"
|
||||||
|
|
||||||
|
# 解压指定制品
|
||||||
|
spc extract "php-src,openssl"
|
||||||
|
|
||||||
|
# 强制解压源码
|
||||||
|
spc extract --for-extensions="bcmath,openssl" --source-only
|
||||||
|
```
|
||||||
|
|
||||||
|
## install-pkg
|
||||||
|
|
||||||
|
安装额外的辅助包(如 UPX、工具链等)。别名:`i`、`install-package`。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc install-pkg <package> [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`package`(必填):要安装的包名称。
|
||||||
|
|
||||||
|
支持所有 `download` 命令的选项,加 `--dl-` 前缀传递。
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 安装 UPX 压缩工具
|
||||||
|
spc install-pkg upx
|
||||||
|
|
||||||
|
# 安装时优先使用预编译二进制(默认行为)
|
||||||
|
spc install-pkg upx
|
||||||
|
```
|
||||||
|
|
||||||
|
## micro:combine
|
||||||
|
|
||||||
|
将 `micro.sfx` 与 PHP/PHAR 文件合并为独立可执行文件。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc micro:combine <file> [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`file`(必填):要合并的 PHP 或 PHAR 文件路径。
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
| 选项 | 缩写 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `--with-micro=<path>` | `-M` | 指定自定义 `micro.sfx` 文件路径(默认使用 `buildroot/bin/micro.sfx`)|
|
||||||
|
| `--with-ini-set=<k=v>` | `-I` | 合并时注入 INI 配置(可重复使用)|
|
||||||
|
| `--with-ini-file=<path>` | `-N` | 合并时注入 INI 文件 |
|
||||||
|
| `--output=<name>` | `-O` | 自定义输出文件名(默认 `my-app`)|
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 合并 PHP 文件
|
||||||
|
spc micro:combine app.php
|
||||||
|
|
||||||
|
# 合并 PHAR 文件并指定输出名
|
||||||
|
spc micro:combine app.phar --output my-app
|
||||||
|
|
||||||
|
# 注入 INI 配置
|
||||||
|
spc micro:combine app.php -I "memory_limit=512M" -I "disable_functions=system"
|
||||||
|
|
||||||
|
# 注入 INI 文件
|
||||||
|
spc micro:combine app.php --with-ini-file=custom.ini
|
||||||
|
|
||||||
|
# 使用自定义 micro.sfx
|
||||||
|
spc micro:combine app.php --with-micro=/path/to/micro.sfx
|
||||||
|
```
|
||||||
|
|
||||||
|
## reset
|
||||||
|
|
||||||
|
清理构建目录,重置构建环境。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc reset [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
默认清理 `buildroot/` 和 `source/` 目录。
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
| 选项 | 缩写 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `--with-pkgroot` | | 同时删除 `pkgroot/` 目录 |
|
||||||
|
| `--with-download` | | 同时删除 `downloads/` 目录 |
|
||||||
|
| `--yes` | `-y` | 跳过确认提示 |
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 清理构建目录(会提示确认)
|
||||||
|
spc reset
|
||||||
|
|
||||||
|
# 同时清理下载缓存
|
||||||
|
spc reset --with-download
|
||||||
|
|
||||||
|
# 完全清理(不提示)
|
||||||
|
spc reset --with-pkgroot --with-download --yes
|
||||||
|
```
|
||||||
|
|
||||||
|
## spc-config
|
||||||
|
|
||||||
|
输出静态编译所需的编译器和链接器标志,适用于将 PHP embed 库链接到自定义程序。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc spc-config [extensions] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
`extensions`(可选):要包含的扩展名列表,逗号分隔。
|
||||||
|
|
||||||
|
### 选项
|
||||||
|
|
||||||
|
| 选项 | 缩写 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `--with-libs=<list>` | | 额外包含的库,逗号分隔 |
|
||||||
|
| `--with-packages=<list>` | `-p` | 额外包含的包,逗号分隔 |
|
||||||
|
| `--with-suggested-libs` | `-L` | 包含建议库 |
|
||||||
|
| `--with-suggests` | | 包含所有建议包 |
|
||||||
|
| `--with-suggested-exts` | `-E` | 包含建议扩展 |
|
||||||
|
| `--includes` | | 仅输出 `-I` 头文件路径(`CFLAGS`)|
|
||||||
|
| `--libs` | | 仅输出 `-L` 和 `-l` 链接标志(`LDFLAGS + LIBS`)|
|
||||||
|
| `--libs-only-deps` | | 仅输出依赖库的 `-l` 标志 |
|
||||||
|
| `--absolute-libs` | | 使用库文件的绝对路径输出 |
|
||||||
|
| `--no-php` | | 不链接 PHP 库 |
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 输出完整编译标志
|
||||||
|
spc spc-config "bcmath,openssl,curl"
|
||||||
|
|
||||||
|
# 仅输出头文件路径
|
||||||
|
spc spc-config "bcmath,openssl" --includes
|
||||||
|
|
||||||
|
# 仅输出链接标志
|
||||||
|
spc spc-config "bcmath,openssl" --libs
|
||||||
|
|
||||||
|
# 使用绝对路径
|
||||||
|
spc spc-config "bcmath,openssl" --libs --absolute-libs
|
||||||
|
```
|
||||||
|
|
||||||
@@ -1,22 +1,19 @@
|
|||||||
---
|
---
|
||||||
outline: 'deep'
|
aside: false
|
||||||
---
|
---
|
||||||
|
|
||||||
# 依赖关系图表
|
# 依赖关系图
|
||||||
|
|
||||||
在编译 PHP 时,每个扩展、库都有依赖关系,这些依赖关系可能是必需的,也可能是可选的。在编译 PHP 时,可以选择是否包含这些可选的依赖关系。
|
这里列出了所有支持的包(扩展、库)及其依赖关系。
|
||||||
|
|
||||||
例如,在 Linux 下编译 `gd` 扩展时,会强制编译 `zlib,libpng` 库和 `zlib` 扩展,而 `libavif,libwebp,libjpeg,freetype` 库都是可选的库,默认不会编译,除非通过 `--with-libs=avif,webp,jpeg,freetype` 选项指定。
|
- **必需依赖**:构建该包时会强制一同构建的包。
|
||||||
|
- **可选依赖**:默认不构建,使用 `--with-suggests` 参数可启用,或在构建命令中手动指定。
|
||||||
|
- **被依赖**:其他哪些包需要当前包。
|
||||||
|
|
||||||
- 对于可选扩展(扩展的可选特性),需手动在编译时指定,例如启用 Redis 的 igbinary 支持:`bin/spc build redis,igbinary`。
|
运行以下命令生成依赖数据(需要在源码模式下):
|
||||||
- 对于可选库,需通过 `--with-libs=XXX` 选项编译指定。
|
|
||||||
- 如果想启用所有的可选扩展,可以使用 `bin/spc build redis --with-suggested-exts` 参数。
|
|
||||||
- 如果想启用所有的可选库,可以使用 `--with-suggested-libs` 参数。
|
|
||||||
|
|
||||||
## 扩展的依赖图
|
```bash
|
||||||
|
bin/spc dev:gen-deps-data
|
||||||
|
```
|
||||||
|
|
||||||
<!--@include: ../../deps-map-ext.md-->
|
<DepsMap />
|
||||||
|
|
||||||
## 库的依赖表
|
|
||||||
|
|
||||||
<!--@include: ../../deps-map-lib.md-->
|
|
||||||
|
|||||||
@@ -4,15 +4,15 @@
|
|||||||
|
|
||||||
## 环境变量列表
|
## 环境变量列表
|
||||||
|
|
||||||
在 2.3.5 版本之后,我们将环境变量集中到了 `config/env.ini` 文件中,你可以通过修改这个文件来设置环境变量。
|
StaticPHP 将环境变量集中到了 `config/env.ini` 文件中,你可以通过修改这个文件来设置环境变量。
|
||||||
|
|
||||||
我们将 static-php-cli 支持的环境变量分为三种:
|
我们将 StaticPHP 支持的环境变量分为三种:
|
||||||
|
|
||||||
- 全局内部环境变量:在 static-php-cli 启动后即声明,你可以在 static-php-cli 的内部使用 `getenv()` 来获取他们,也可以在启动 static-php-cli 前覆盖。
|
- **全局内部环境变量**:在 StaticPHP 启动后即声明,你可以在 StaticPHP 的内部使用 `getenv()` 来获取他们,也可以在启动 StaticPHP 前覆盖。
|
||||||
- 固定环境变量:在 static-php-cli 启动后声明,你仅可使用 `getenv()` 获取,但无法通过 shell 脚本对其覆盖。
|
- **固定环境变量**:在 StaticPHP 启动后声明,你仅可使用 `getenv()` 获取,但无法通过 shell 脚本对其覆盖。
|
||||||
- 配置文件环境变量:在 static-php-cli 构建前声明,你可以通过修改 `config/env.ini` 文件或通过 shell 脚本来设置这些环境变量。
|
- **配置文件环境变量**:在 StaticPHP 构建前声明,你可以通过修改 `config/env.ini` 文件或通过 shell 脚本来设置这些环境变量。
|
||||||
|
|
||||||
你可以阅读 [config/env.ini](https://github.com/crazywhalecc/static-php-cli/blob/main/config/env.ini) 中每项参数的注释来了解其作用(仅限英文版)。
|
你可以阅读 [config/env.ini](https://github.com/crazywhalecc/static-php-cli/blob/v3/config/env.ini) 中每项参数的注释来了解其作用(仅限英文版)。
|
||||||
|
|
||||||
## 自定义环境变量
|
## 自定义环境变量
|
||||||
|
|
||||||
@@ -24,10 +24,10 @@
|
|||||||
```shell
|
```shell
|
||||||
# export 方式
|
# export 方式
|
||||||
export SPC_CONCURRENCY=4
|
export SPC_CONCURRENCY=4
|
||||||
bin/spc build mbstring,pcntl --build-cli
|
spc build:php "mbstring,pcntl" --build-cli
|
||||||
|
|
||||||
# 直接设置方式
|
# 直接设置方式
|
||||||
SPC_CONCURRENCY=4 bin/spc build mbstring,pcntl --build-cli
|
SPC_CONCURRENCY=4 spc build:php "mbstring,pcntl" --build-cli
|
||||||
```
|
```
|
||||||
|
|
||||||
或者,如果你需要长期修改某个环境变量,你可以通过修改 `config/env.ini` 文件来实现。
|
或者,如果你需要长期修改某个环境变量,你可以通过修改 `config/env.ini` 文件来实现。
|
||||||
@@ -40,7 +40,7 @@ SPC_CONCURRENCY=4 bin/spc build mbstring,pcntl --build-cli
|
|||||||
通过写入额外的重载项目指定你的环境变量。
|
通过写入额外的重载项目指定你的环境变量。
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
; This is an example of `config/env.custom.ini` file,
|
; This is an example of `config/env.custom.ini` file,
|
||||||
; we modify the `SPC_CONCURRENCY` and linux default CFLAGS passing to libs and PHP
|
; we modify the `SPC_CONCURRENCY` and linux default CFLAGS passing to libs and PHP
|
||||||
[global]
|
[global]
|
||||||
SPC_CONCURRENCY=4
|
SPC_CONCURRENCY=4
|
||||||
@@ -49,64 +49,3 @@ SPC_CONCURRENCY=4
|
|||||||
SPC_DEFAULT_C_FLAGS="-O3"
|
SPC_DEFAULT_C_FLAGS="-O3"
|
||||||
```
|
```
|
||||||
|
|
||||||
## 编译依赖库的环境变量(仅限 Unix 系统)
|
|
||||||
|
|
||||||
从 2.2.0 开始,static-php-cli 对所有 macOS、Linux、FreeBSD 等 Unix 系统的编译依赖库的命令均支持自定义环境变量。
|
|
||||||
|
|
||||||
这样你就可以随时通过环境变量来调整编译依赖库的行为。例如你可以通过 `xxx_CFLAGS=-O0` 来设置编译 xxx 库的优化参数。
|
|
||||||
|
|
||||||
当然,不是每个依赖库都支持注入环境变量,我们目前提供了三个通配的环境变量,后缀分别为:
|
|
||||||
|
|
||||||
- `_CFLAGS`: C 编译器的参数
|
|
||||||
- `_LDFLAGS`: 链接器的参数
|
|
||||||
- `_LIBS`: 额外的链接库
|
|
||||||
|
|
||||||
前缀为依赖库的名称,具体依赖库的名称以 `lib.json` 为准。其中,带有 `-` 的依赖库名称需要将 `-` 替换为 `_`。
|
|
||||||
|
|
||||||
下面是一个替换 openssl 库编译的优化选项示例:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
openssl_CFLAGS="-O0"
|
|
||||||
```
|
|
||||||
|
|
||||||
库名称使用同 `lib.json` 中列举的名称,区分大小写。
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
当未指定相关环境变量时,除以下变量外,其余值均默认为空:
|
|
||||||
|
|
||||||
| var name | var default value |
|
|
||||||
|-----------------------|-------------------------------------------------------------------------------------------------|
|
|
||||||
| `pkg_config_CFLAGS` | macOS: `$SPC_DEFAULT_C_FLAGS -Wimplicit-function-declaration -Wno-int-conversion`, Other: empty |
|
|
||||||
| `pkg_config_LDFLAGS` | Linux: `--static`, Other: empty |
|
|
||||||
| `imagemagick_LDFLAGS` | Linux: `-static`, Other: empty |
|
|
||||||
| `imagemagick_LIBS` | macOS: `-liconv`, Other: empty |
|
|
||||||
| `ldap_LDFLAGS` | `-L$BUILD_LIB_PATH` |
|
|
||||||
| `openssl_CFLAGS` | Linux: `$SPC_DEFAULT_C_FLAGS`, Other: empty |
|
|
||||||
| others... | empty |
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
下表是支持自定义以上三种变量的依赖库名称列表:
|
|
||||||
|
|
||||||
| lib name |
|
|
||||||
|-------------|
|
|
||||||
| brotli |
|
|
||||||
| bzip |
|
|
||||||
| curl |
|
|
||||||
| freetype |
|
|
||||||
| gettext |
|
|
||||||
| gmp |
|
|
||||||
| imagemagick |
|
|
||||||
| ldap |
|
|
||||||
| libargon2 |
|
|
||||||
| libavif |
|
|
||||||
| libcares |
|
|
||||||
| libevent |
|
|
||||||
| openssl |
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
因为给每个库适配自定义环境变量是一项特别繁琐的工作,且大部分情况下你都不需要这些库的自定义环境变量,所以我们目前只支持了部分库的自定义环境变量。
|
|
||||||
|
|
||||||
如果你需要自定义环境变量的库不在上方列表,可以通过 [GitHub Issue](https://github.com/crazywhalecc/static-php-cli/issues)
|
|
||||||
来提出需求。
|
|
||||||
:::
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
HTTP3 支持默认未启用,需在编译时添加 `--with-libs="nghttp2,nghttp3,ngtcp2"` 以启用 PHP 8.4 及以上版本的 HTTP3 支持。
|
HTTP3 支持默认未启用,需在编译时添加 `--with-libs="nghttp2,nghttp3,ngtcp2"` 以启用 PHP 8.4 及以上版本的 HTTP3 支持。
|
||||||
|
|
||||||
使用 curl 请求 HTTPS 时,可能存在 `error:80000002:system library::No such file or directory` 错误,
|
使用 curl 请求 HTTPS 时,可能存在 `error:80000002:system library::No such file or directory` 错误,
|
||||||
解决办法详见 [FAQ - 无法使用 ssl](../faq/#无法使用-ssl)。
|
解决办法详见 [FAQ](../faq/)。
|
||||||
|
|
||||||
## phpmicro
|
## phpmicro
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ swoole-hook-odbc 与 `pdo_odbc` 扩展冲突。如需使用 Swoole 和 `pdo_odbc
|
|||||||
## imap
|
## imap
|
||||||
|
|
||||||
1. 该扩展目前不支持 Kerberos。
|
1. 该扩展目前不支持 Kerberos。
|
||||||
2. 由于底层的 c-client、ext-imap 不是线程安全的。 无法在 `--enable-zts` 构建中使用它。
|
2. 由于底层的 c-client、ext-imap 不是线程安全的。无法在 `--enable-zts` 构建中使用它。
|
||||||
3. 该扩展已在 PHP 8.4 中被移除,因此我们建议您寻找替代实现,例如 [Webklex/php-imap](https://github.com/Webklex/php-imap)。
|
3. 该扩展已在 PHP 8.4 中被移除,因此我们建议您寻找替代实现,例如 [Webklex/php-imap](https://github.com/Webklex/php-imap)。
|
||||||
|
|
||||||
## gd
|
## gd
|
||||||
@@ -84,18 +84,18 @@ bin/spc build gd --with-libs=freetype,libjpeg,libavif,libwebp --build-cli
|
|||||||
|
|
||||||
## xdebug
|
## xdebug
|
||||||
|
|
||||||
1. Xdebug 只能作为共享扩展进行构建。您需要使用除了 `musl-static` 外的其他 `SPC_TARGET` 构建目标。
|
1. Xdebug 只能作为共享扩展进行构建。在 Linux 上,您需要使用 glibc 变体的 `SPC_TARGET`(例如 `native-native-gnu.2.17`),而不是默认的 musl 静态目标。
|
||||||
2. 使用 Linux/glibc 或 macOS 时,您可以使用 `--build-shared=xdebug` 将 Xdebug 编译为共享扩展。
|
2. 使用 Linux/glibc 或 macOS 时,您可以使用 `--build-shared=xdebug` 将 Xdebug 编译为共享扩展。
|
||||||
编译后的 `./php` 二进制文件可以通过指定 INI 文件进行配置和运行,例如 `./php -d 'zend_extension=/path/to/xdebug.so' your-code.php`。
|
编译后的 `./php` 二进制文件可以通过指定 INI 文件进行配置和运行,例如 `./php -d 'zend_extension=/path/to/xdebug.so' your-code.php`。
|
||||||
|
|
||||||
## xml
|
## xml
|
||||||
|
|
||||||
1. xml包括 xmlreader、xmlwriter、dom、simplexml 等,添加 xml 扩展时最好同时启用这些扩展。
|
1. xml 包括 xmlreader、xmlwriter、dom、simplexml 等,添加 xml 扩展时最好同时启用这些扩展。
|
||||||
2. libxml 包含在 xml 扩展中。 启用 xml 相当于启用 libxml。
|
2. libxml 包含在 xml 扩展中。启用 xml 相当于启用 libxml。
|
||||||
|
|
||||||
## glfw
|
## glfw
|
||||||
|
|
||||||
1. glfw 扩展依赖 OpenGL,在 Linux 平台还依赖 X11 等环境,这些库都无法被轻易地动态链接。
|
1. glfw 扩展依赖 OpenGL,在 Linux 平台还依赖 X11 等环境,这些库都无法被轻易地静态链接。
|
||||||
2. 在 macOS 系统下,我们可以动态链接系统的 OpenGL 和一些相关的库。
|
2. 在 macOS 系统下,我们可以动态链接系统的 OpenGL 和一些相关的库。
|
||||||
|
|
||||||
## rar
|
## rar
|
||||||
@@ -113,22 +113,22 @@ bin/spc build gd --with-libs=freetype,libjpeg,libavif,libwebp --build-cli
|
|||||||
pgsql 16.2 修复了这个 Bug,现在正常工作了。
|
pgsql 16.2 修复了这个 Bug,现在正常工作了。
|
||||||
|
|
||||||
在 pgsql 使用 SSL 连接时,可能存在 `error:80000002:system library::No such file or directory` 错误,
|
在 pgsql 使用 SSL 连接时,可能存在 `error:80000002:system library::No such file or directory` 错误,
|
||||||
解决办法详见 [FAQ - 无法使用 ssl](../faq/#无法使用-ssl)。
|
解决办法详见 [FAQ](../faq/)。
|
||||||
|
|
||||||
## openssl
|
## openssl
|
||||||
|
|
||||||
使用基于 openssl 的扩展(如 curl、pgsql 等网络库)时,可能存在 `error:80000002:system library::No such file or directory` 错误,
|
使用基于 openssl 的扩展(如 curl、pgsql 等网络库)时,可能存在 `error:80000002:system library::No such file or directory` 错误,
|
||||||
解决办法详见 [FAQ - 无法使用 ssl](../faq/#无法使用-ssl)。
|
解决办法详见 [FAQ](../faq/)。
|
||||||
|
|
||||||
## password-argon2
|
## password-argon2
|
||||||
|
|
||||||
1. password-argon2不是一个标准的扩展。`password_hash` 函数的 `PASSWORD_ARGON2ID` 算法需要 libsodium 或 libargon2 才能工作。
|
1. password-argon2 不是一个标准的扩展。`password_hash` 函数的 `PASSWORD_ARGON2ID` 算法需要 libsodium 或 libargon2 才能工作。
|
||||||
2. 使用 password-argon2 可以为此启用多线程支持。
|
2. 使用 password-argon2 可以为此启用多线程支持。
|
||||||
|
|
||||||
## ffi
|
## ffi
|
||||||
|
|
||||||
1. 由于 musl libc 静态链接的限制,无法加载动态库,因此无法使用 ffi。
|
1. 由于 musl libc 静态链接的限制,无法加载动态库,因此无法使用 ffi。
|
||||||
如果您需要使用 ffi 扩展,请参阅 [使用 GNU libc 编译 PHP](./build-with-glibc)。
|
如果您需要使用 ffi 扩展,请使用基于 glibc 的 `SPC_TARGET`(例如 `native-native-gnu.2.17`),详见 [SAPI 参考](./sapi-reference)。
|
||||||
2. macOS 支持 ffi 扩展,但某些内核不包含调试符号时会出现错误。
|
2. macOS 支持 ffi 扩展,但某些内核不包含调试符号时会出现错误。
|
||||||
3. Windows x64 支持 ffi 扩展。
|
3. Windows x64 支持 ffi 扩展。
|
||||||
|
|
||||||
@@ -156,3 +156,4 @@ parallel 扩展只支持 PHP 8.0 及以上版本,并只支持 ZTS 构建(`--
|
|||||||
1. 从技术上讲,这不是扩展,而是一个库。
|
1. 从技术上讲,这不是扩展,而是一个库。
|
||||||
2. 在 Linux 或 macOS 上使用 `--with-libs="mimalloc"` 进行构建将覆盖默认分配器。
|
2. 在 Linux 或 macOS 上使用 `--with-libs="mimalloc"` 进行构建将覆盖默认分配器。
|
||||||
3. 目前,这还处于实验阶段,但建议在线程环境中使用。
|
3. 目前,这还处于实验阶段,但建议在线程环境中使用。
|
||||||
|
|
||||||
|
|||||||
@@ -2,21 +2,16 @@
|
|||||||
import SearchTable from "../../.vitepress/components/SearchTable.vue";
|
import SearchTable from "../../.vitepress/components/SearchTable.vue";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
# 扩展列表
|
# 支持的扩展列表
|
||||||
|
|
||||||
> - `yes`: 已支持
|
> - ✅: 已支持
|
||||||
> - 空白: 目前还不支持,或正在支持中
|
> - 空白: 目前还不支持,或正在支持中
|
||||||
> - `no` with issue link: 确定不支持或无法支持
|
|
||||||
> - `partial` with issue link: 已支持,但是无法完美工作
|
|
||||||
|
|
||||||
|
|
||||||
<search-table />
|
<search-table />
|
||||||
|
|
||||||
::: tip
|
::: tip
|
||||||
如果缺少您需要的扩展,您可以创建 [功能请求](https://github.com/crazywhalecc/static-php-cli/issues)。
|
如果缺少您需要的扩展,您可以创建 [功能请求](https://github.com/crazywhalecc/static-php-cli/issues)。
|
||||||
|
|
||||||
有些扩展或扩展依赖的库会有一些可选的特性,例如 gd 库可选支持 libwebp、freetype 等。
|
某些扩展或其依赖的库会有可选特性(例如 gd 可选支持 libwebp、freetype 等)。
|
||||||
如果你只使用 `bin/spc build gd --build-cli` 是不会包含它们(static-php-cli 默认为最小依赖原则)。
|
仅使用 `bin/spc build gd --build-cli` 不会包含这些可选依赖——StaticPHP 默认遵循最小依赖原则。
|
||||||
|
|
||||||
有关编译可选库,请参考 [扩展、库的依赖关系图表](./deps-map)。对于可选的库,你也可以从 [编译命令生成器](./cli-generator) 中选择扩展后展开选择可选库。
|
|
||||||
:::
|
:::
|
||||||
|
|||||||
188
docs/zh/guide/first-build.md
Normal file
188
docs/zh/guide/first-build.md
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
# 第一次构建
|
||||||
|
|
||||||
|
本页通过完整的示例演示如何从零开始构建一个静态 PHP 二进制。
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
如果你采用的是 spc 二进制方式安装,请将本章节中的所有 `spc` 替换为 `./spc` 或 `.\spc.exe`。
|
||||||
|
|
||||||
|
如果你采用的是源码安装,请将 `spc` 替换为 `bin/spc`。
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 两种构建方式
|
||||||
|
|
||||||
|
StaticPHP 提供两种构建方式,根据使用场景选择:
|
||||||
|
|
||||||
|
| 方式 | 适合场景 |
|
||||||
|
|--------------|--------------------------|
|
||||||
|
| `craft` 一键构建 | 日常使用、快速上手 |
|
||||||
|
| 分步构建 | 细化构建流程 |
|
||||||
|
|
||||||
|
## 方式一:`craft` 一键构建(推荐)
|
||||||
|
|
||||||
|
`craft` 命令读取一个 `craft.yml` 配置文件,自动完成依赖下载、库编译、PHP 构建的全流程。
|
||||||
|
|
||||||
|
### 编写 craft.yml
|
||||||
|
|
||||||
|
在当前目录创建 `craft.yml`,声明要编译的 PHP 版本、扩展和目标 SAPI:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
php-version: 8.4
|
||||||
|
extensions: bcmath,posix,phar,zlib,openssl,curl,fileinfo,tokenizer
|
||||||
|
sapi:
|
||||||
|
- cli
|
||||||
|
- micro
|
||||||
|
```
|
||||||
|
|
||||||
|
不想手动编写?试试[命令行生成器](./cli-generator)自动生成配置。
|
||||||
|
|
||||||
|
### 开始构建
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc craft
|
||||||
|
```
|
||||||
|
|
||||||
|
构建过程依次执行:下载依赖 → 编译依赖库 → 编译 PHP。全程无需人工干预。
|
||||||
|
|
||||||
|
如需查看详细日志,加上 `-v`、`-vv` 或 `-vvv` 参数:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc craft -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### 查看产物
|
||||||
|
|
||||||
|
构建成功后,产物均位于 `buildroot/bin/`:
|
||||||
|
|
||||||
|
| SAPI | 产物路径 |
|
||||||
|
|------------|------------------------------------------------------|
|
||||||
|
| cli | `buildroot/bin/php`(Windows:`buildroot/bin/php.exe`) |
|
||||||
|
| fpm | `buildroot/bin/php-fpm` |
|
||||||
|
| micro | `buildroot/bin/micro.sfx` |
|
||||||
|
| embed | `buildroot/lib/libphp.a` |
|
||||||
|
| frankenphp | `buildroot/bin/frankenphp` |
|
||||||
|
|
||||||
|
验证一下 cli 是否可用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./buildroot/bin/php -v
|
||||||
|
./buildroot/bin/php -m
|
||||||
|
```
|
||||||
|
|
||||||
|
## 方式二:分步构建
|
||||||
|
|
||||||
|
分步方式适合需要将下载与编译拆分为独立阶段的场景,例如在 CI 中缓存下载内容以加速后续构建。
|
||||||
|
|
||||||
|
### 第一步:下载依赖
|
||||||
|
|
||||||
|
v3 版本中,你可以省略这一步骤,直接构建想要的内容,StaticPHP 会自动下载所需的依赖库和扩展源码。
|
||||||
|
|
||||||
|
但如果你想提前下载,或在网络环境较差的情况下分阶段构建,可以使用 `download` 命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 按扩展列表下载(推荐,只下载实际需要的内容)
|
||||||
|
spc download --for-extensions="bcmath,posix,phar,zlib,openssl,curl,fileinfo,tokenizer" --with-php=8.4
|
||||||
|
|
||||||
|
# 按依赖包列表下载
|
||||||
|
spc download "curl,openssl" --with-php=8.4
|
||||||
|
```
|
||||||
|
|
||||||
|
下载内容缓存在 `downloads/` 目录,重复构建时会直接复用。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 网络较慢时,可增大并发数和重试次数
|
||||||
|
spc download --for-extensions="bcmath,openssl,curl" --parallel 10 --retry=3
|
||||||
|
|
||||||
|
# 优先使用预编译的二进制依赖,跳过源码编译(大幅加速构建)
|
||||||
|
spc download --for-extensions="bcmath,openssl,curl" --prefer-binary
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第二步:构建 PHP
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建 cli SAPI
|
||||||
|
spc build:php "bcmath,phar,zlib,openssl,curl,fileinfo,tokenizer" --build-cli
|
||||||
|
|
||||||
|
# 同时构建多个 SAPI
|
||||||
|
spc build:php "bcmath,phar,zlib,openssl,curl" --build-cli --build-micro
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 常用构建选项
|
||||||
|
|
||||||
|
| 选项 | 说明 |
|
||||||
|
|----------------------|--------------------------------------|
|
||||||
|
| `--build-cli` | 构建 cli SAPI |
|
||||||
|
| `--build-fpm` | 构建 php-fpm(不支持 Windows) |
|
||||||
|
| `--build-micro` | 构建 micro.sfx |
|
||||||
|
| `--build-embed` | 构建嵌入式 SAPI |
|
||||||
|
| `--build-frankenphp` | 构建 FrankenPHP |
|
||||||
|
| `--enable-zts` | 启用线程安全(ZTS)版本 |
|
||||||
|
| `--no-strip` | 保留调试符号,不精简二进制 |
|
||||||
|
| `-I key=value` | 硬编译 INI 选项到 PHP 中 |
|
||||||
|
| `--with-upx-pack` | 用 UPX 压缩产物(需先 `spc install-pkg upx`) |
|
||||||
|
|
||||||
|
硬编译 INI 的例子——预设更大的内存限制,并禁用 `system` 函数:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,pcntl,posix" --build-cli -I "memory_limit=4G" -I "disable_functions=system"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 打包 micro 应用
|
||||||
|
|
||||||
|
构建 `micro.sfx` 后,用 `micro:combine` 将你的 PHP 代码打包进去,生成一个完全独立的可执行文件:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo "<?php echo 'Hello, World!' . PHP_EOL;" > hello.php
|
||||||
|
spc micro:combine hello.php --output=hello
|
||||||
|
./hello
|
||||||
|
```
|
||||||
|
|
||||||
|
也支持打包 `.phar` 文件,以及注入 INI 配置:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 打包 phar
|
||||||
|
spc micro:combine your-app.phar --output=your-app
|
||||||
|
|
||||||
|
# 打包时注入 INI
|
||||||
|
spc micro:combine your-app.phar --output=your-app -I "memory_limit=512M"
|
||||||
|
|
||||||
|
# 从 ini 文件注入配置
|
||||||
|
spc micro:combine your-app.phar --output=your-app -N /path/to/custom.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
## 调试与重新构建
|
||||||
|
|
||||||
|
构建失败,或想查看详细过程,使用 `-v` / `-vv` / `-vvv`:
|
||||||
|
|
||||||
|
- `-v` 将显示 `INFO` 级别的日志,包含执行到的模块和执行的编译命令等。
|
||||||
|
- `-vv` 将显示 `DEBUG` 级别的日志,包含所有 StaticPHP 中调试级别的日志。
|
||||||
|
- `-vvv` 将显示 `DEBUG` 级别的日志,并将其他 shell 命令执行的 STDOUT 输出到终端。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,openssl" --build-cli -vv
|
||||||
|
```
|
||||||
|
|
||||||
|
或者,你也可以查看 `log/spc.shell.log` 和 `log/spc.output.log` 获取终端输出和 StaticPHP 日志。
|
||||||
|
|
||||||
|
如需清理编译中间产物、从头重新构建(不重新下载),使用 `reset`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc reset
|
||||||
|
# 然后重新构建
|
||||||
|
spc build:php "bcmath,openssl" --build-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
`reset` 只清理 `buildroot/` 和 `source/` 目录,不会删除 `downloads/` 缓存。
|
||||||
|
如需同时清理下载缓存,加上 `--with-download` 参数。
|
||||||
|
:::
|
||||||
|
|
||||||
|
如果问题持续无法解决,欢迎提交 [Issue](https://github.com/crazywhalecc/static-php-cli/issues),并附上 `craft.yml`(如有)和 `log/` 目录的压缩包。
|
||||||
|
|
||||||
|
## 接下来
|
||||||
|
|
||||||
|
- [PHP SAPI 构建参考](./sapi-reference) - 各个 PHP 的 SAPI 构建及使用指南
|
||||||
|
- [命令行参考](./cli-reference) — 所有命令与选项的完整说明
|
||||||
|
- [扩展列表](./extensions) — 查看支持的扩展及其依赖关系
|
||||||
|
- [常见问题](./troubleshooting) — 构建失败时的排查指南
|
||||||
@@ -1,48 +1,60 @@
|
|||||||
# 指南
|
# 构建指南
|
||||||
|
|
||||||
static-php-cli 是一个用于构建静态编译的 PHP 二进制的工具,目前支持 Linux 和 macOS 系统。
|
::: warning
|
||||||
|
你正在阅读 StaticPHP v3 版本的文档,v2 版本将在 v3 稳定发布后废弃。v3 版本目前仍处于 alpha 阶段,
|
||||||
|
你可以在 [这里](https://static-php.github.io/v2-docs/) 查看 v2 文档。
|
||||||
|
:::
|
||||||
|
|
||||||
在指南章节中,你将了解到如何使用 static-php-cli 构建独立的 php 程序。
|
## StaticPHP 是什么
|
||||||
|
|
||||||
- [本地构建](./manual-build)
|
StaticPHP 是一个构建工具,能够将 PHP 解释器与你所需的扩展一起编译成一个独立的二进制文件,无需在目标系统上预先安装 PHP 或任何依赖库。
|
||||||
- [Action 构建](./action-build)
|
构建产物可以直接分发和运行,适用于 Linux、macOS 和 Windows 平台。
|
||||||
- [扩展列表](./extensions)
|
|
||||||
|
|
||||||
## 编译环境
|
StaticPHP 的能力不止于 PHP。依托同一套构建基础设施,它还可以将 `curl`、`pkg-config`、`htop` 等常用命令行工具编译为独立的静态二进制,无需在目标机器上安装任何依赖即可直接运行。后续还会持续扩充内置支持的工具集。
|
||||||
|
|
||||||
下面是架构支持情况,:gear: 代表支持 GitHub Action 构建,:computer: 代表支持本地构建,空 代表暂不支持。
|
## 为什么要构建静态 PHP
|
||||||
|
|
||||||
| | x86_64 | aarch64 |
|
普通 PHP 安装依赖系统环境:你需要先安装 PHP、再装扩展、再处理各个发行版之间的差异。
|
||||||
|---------|-------------------|-------------------|
|
将 PHP 构建为静态二进制之后,这些问题都不再存在——你得到的是一个单文件可执行程序,在任何相同架构的系统上开箱即用。
|
||||||
| macOS | :gear: :computer: | :gear: :computer: |
|
|
||||||
| Linux | :gear: :computer: | :gear: :computer: |
|
|
||||||
| Windows | :gear: :computer: | |
|
|
||||||
| FreeBSD | :computer: | :computer: |
|
|
||||||
|
|
||||||
当前支持编译的 PHP 版本:
|
典型使用场景:
|
||||||
|
|
||||||
> :warning: 部分支持,对于新的测试版和旧版本可能存在问题。
|
- **部署命令行工具**:把 PHP 工具(如 Composer、PHPStan、自研 CLI)打包后直接分发,用户无需安装 PHP。
|
||||||
>
|
- **容器和嵌入式环境**:用最小体积的静态 PHP 替代臃肿的基础镜像。
|
||||||
> :heavy_check_mark: 支持
|
- **服务端应用**:构建包含 FPM 或 FrankenPHP SAPI 的静态二进制,部署更简单,不依赖宿主机环境。
|
||||||
>
|
|
||||||
> :x: 不支持
|
|
||||||
|
|
||||||
| PHP Version | Status | Comment |
|
## phpmicro:把 PHP 和你的代码打包成一个文件
|
||||||
|-------------|--------------------|---------------------------------------------------------|
|
|
||||||
| 7.2 | :x: | |
|
|
||||||
| 7.3 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
|
|
||||||
| 7.4 | :x: | phpmicro 和许多扩展不支持 7.3、7.4 版本 |
|
|
||||||
| 8.0 | :warning: | PHP 官方已停止 8.0 的维护,我们不再处理 8.0 相关的 backport 支持 |
|
|
||||||
| 8.1 | :warning: | PHP 官方仅对 8.1 提供安全更新,在 8.5 发布后我们不再处理 8.1 相关的 backport 支持 |
|
|
||||||
| 8.2 | :heavy_check_mark: | |
|
|
||||||
| 8.3 | :heavy_check_mark: | |
|
|
||||||
| 8.4 | :heavy_check_mark: | |
|
|
||||||
| 8.5 (beta) | :warning: | PHP 8.5 目前处于 beta 阶段 |
|
|
||||||
|
|
||||||
> 这个表格的支持状态是 static-php-cli 对构建对应版本的支持情况,不是 PHP 官方对该版本的支持情况。
|
[phpmicro](https://micro.static-php.dev) 是一个第三方 PHP SAPI,StaticPHP 对其提供原生支持。
|
||||||
|
它能将 PHP 解释器本身和你的 `.php` 源文件(或 `.phar` 打包文件)合并成单个自解压可执行文件(`sfx`)。
|
||||||
|
|
||||||
## PHP 支持版本
|
```
|
||||||
|
micro.sfx + your-app.phar = your-app (可直接运行,无任何依赖)
|
||||||
|
```
|
||||||
|
|
||||||
目前,static-php-cli 对 PHP 8.2 ~ 8.5 版本是支持的,对于 PHP 8.1 及更早版本理论上支持,只需下载时选择早期版本即可。
|
这特别适合分发 PHP 编写的命令行工具:用户拿到的只是一个普通的可执行文件,完全感知不到背后是 PHP。
|
||||||
但由于部分扩展和特殊组件已对早期版本的 PHP 停止了支持,所以 static-php-cli 不会明确支持早期版本。
|
|
||||||
我们推荐你编译尽可能新的 PHP 版本,以获得更好的体验。
|
## 改善你的项目分发与部署
|
||||||
|
|
||||||
|
**取代臃肿的 Docker 基础镜像**
|
||||||
|
|
||||||
|
官方 `php:8.x` 镜像动辄数百 MB,大多数情况下只是为了提供一个 PHP 运行环境。
|
||||||
|
改用静态 PHP 二进制配合极简基础镜像(甚至 `FROM scratch`),镜像体积可以压缩到个位数 MB,启动速度也更快。
|
||||||
|
|
||||||
|
**构建可分发的 PHP CLI 工具**
|
||||||
|
|
||||||
|
用 [symfony/console](https://symfony.com/doc/current/components/console.html) 或 [Laravel Zero](https://laravel-zero.com) 写好你的 CLI 程序,
|
||||||
|
再用 [Box](https://github.com/box-project/box) 打包成 `.phar`,最后通过 phpmicro 合并为单文件可执行程序。
|
||||||
|
最终产物可以直接分发,用户无需安装任何 PHP 环境,和 Go、Rust 工具的体验完全一致。
|
||||||
|
|
||||||
|
**基于 FrankenPHP 构建单文件 Web 应用**
|
||||||
|
|
||||||
|
[FrankenPHP](https://frankenphp.dev) 是一个现代 PHP 应用服务器,内置 HTTP/2、HTTP/3 和 HTTPS 自动管理。
|
||||||
|
StaticPHP 支持将 FrankenPHP 连同所需扩展一起静态编译,
|
||||||
|
最终产物是一个包含完整 Web 服务器的单一可执行文件,无需 Nginx、PHP-FPM,直接部署即可运行。
|
||||||
|
|
||||||
|
## 接下来
|
||||||
|
|
||||||
|
- [安装 StaticPHP](./installation) — 安装 StaticPHP 构建工具
|
||||||
|
- [第一次构建](./first-build) — 完整流程演示:从下载源码到得到可执行文件
|
||||||
|
- [命令行参考](./cli-reference) — 所有命令与选项速查
|
||||||
|
|||||||
108
docs/zh/guide/installation.md
Normal file
108
docs/zh/guide/installation.md
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
# 安装 StaticPHP
|
||||||
|
|
||||||
|
## 系统要求
|
||||||
|
|
||||||
|
| 平台 | 架构 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| Linux | x86_64、aarch64 | 支持主流发行版(Alpine、Debian/Ubuntu、RHEL/CentOS 等) |
|
||||||
|
| macOS | x86_64 (Intel)、arm64 (Apple Silicon) | 需要 macOS 12 或更高版本 |
|
||||||
|
| Windows | x86_64 | 需要 Windows 10 Build 17063 或更高版本 |
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
Linux 下,glibc 环境(Debian、Ubuntu、Arch 等)和 musl 环境(Alpine)均受支持。
|
||||||
|
`doctor` 命令会自动检测当前环境并在必要时引导安装合适的工具链。
|
||||||
|
:::
|
||||||
|
|
||||||
|
StaticPHP 有多种安装方式,选择适合你的场景:
|
||||||
|
|
||||||
|
| 方式 | 适合谁 |
|
||||||
|
|---|---|
|
||||||
|
| 预编译二进制 | 大多数用户,直接下载开箱即用 |
|
||||||
|
| 从源码安装 | 参与开发、或需要修改核心构建逻辑的开发者 |
|
||||||
|
| Vendor 模式 | 在已有 PHP 项目中集成 StaticPHP 能力 |
|
||||||
|
|
||||||
|
## 预编译二进制
|
||||||
|
|
||||||
|
spc 无须任何依赖,下载即可运行,支持 Linux、macOS 和 Windows。
|
||||||
|
|
||||||
|
> spc 本身是由 StaticPHP 构建的静态 PHP 二进制,幽默地说:我们用 StaticPHP 构建了 StaticPHP 的构建工具。
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Linux x86_64
|
||||||
|
curl -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-linux-x86_64 -o spc
|
||||||
|
# Linux arm64
|
||||||
|
curl -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-linux-aarch64 -o spc
|
||||||
|
# macOS x86_64 (Intel)
|
||||||
|
curl -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-macos-x86_64 -o spc
|
||||||
|
# macOS arm64 (Apple Silicon)
|
||||||
|
curl -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-macos-aarch64 -o spc
|
||||||
|
# Windows x86_64 (PowerShell)
|
||||||
|
curl.exe -#fSL https://dl.static-php.dev/v3/spc-bin/latest/spc-windows-x86_64.exe -o spc.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
*nix 系统下载完成后需要赋予可执行权限:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x spc && ./spc --version
|
||||||
|
```
|
||||||
|
|
||||||
|
## 从源码安装
|
||||||
|
|
||||||
|
适合想参与开发、或需要修改核心注册表和构建脚本的开发者。需要系统已安装 PHP >= 8.4、Composer,以及 `mbstring,posix,pcntl,iconv,phar,zlib` 扩展。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/static-php/static-php.git --branch v3
|
||||||
|
cd static-php-cli
|
||||||
|
composer install
|
||||||
|
```
|
||||||
|
|
||||||
|
如果系统还没有 PHP 和 Composer,可以用内置脚本一键安装运行环境:
|
||||||
|
|
||||||
|
::: code-group
|
||||||
|
```bash [Linux / macOS]
|
||||||
|
bin/setup-runtime
|
||||||
|
```
|
||||||
|
```powershell [Windows]
|
||||||
|
.\bin\setup-runtime.ps1
|
||||||
|
.\bin\setup-runtime.ps1 add-path # 将 runtime/ 加入 PATH
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
脚本执行完成后,会在项目目录下生成 `runtime/` 子目录,其中包含 `php` 和 `composer` 两个可执行文件。安装完成后有两种使用方式:
|
||||||
|
|
||||||
|
1. **直接通过路径调用**(无需修改环境变量):
|
||||||
|
```bash
|
||||||
|
runtime/php bin/spc --help
|
||||||
|
runtime/php runtime/composer install
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **将 `runtime/` 加入 PATH**(之后可直接使用 `php`、`composer`、`bin/spc`):
|
||||||
|
```bash
|
||||||
|
export PATH="/path/to/static-php/runtime:$PATH"
|
||||||
|
# 建议写入 ~/.bashrc 或 ~/.zshrc 使其永久生效
|
||||||
|
```
|
||||||
|
|
||||||
|
## Vendor 模式
|
||||||
|
|
||||||
|
适合在已有 PHP 项目中直接集成 StaticPHP 能力,或通过自定义 registry 支持私有库和扩展的构建。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer require crazywhalecc/static-php-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
Vendor 模式的详细用法见 [Vendor 模式指南](../develop/vendor-mode/)。
|
||||||
|
|
||||||
|
## 验证构建环境
|
||||||
|
|
||||||
|
> **Vendor 模式用户可跳过此步骤。**
|
||||||
|
|
||||||
|
安装完成后,运行 `doctor` 检查系统构建工具链是否就绪(cmake、make、编译器等):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 使用 spc 二进制
|
||||||
|
./spc doctor --auto-fix
|
||||||
|
# 使用源码安装
|
||||||
|
bin/spc doctor --auto-fix
|
||||||
|
```
|
||||||
|
|
||||||
|
检查通过后,继续阅读[第一次构建](./first-build)。
|
||||||
@@ -1,640 +0,0 @@
|
|||||||
---
|
|
||||||
outline: 'deep'
|
|
||||||
---
|
|
||||||
|
|
||||||
# 本地构建(Linux、macOS、FreeBSD)
|
|
||||||
|
|
||||||
本章节为 Linux、macOS、FreeBSD 的构建过程,如果你要在 Windows 上构建,请到 [在 Windows 上构建](./build-on-windows)。
|
|
||||||
|
|
||||||
## 手动构建(使用 SPC 二进制)(推荐)
|
|
||||||
|
|
||||||
本项目提供了一个 static-php-cli 的二进制文件,你可以直接下载对应平台的二进制文件,然后使用它来构建静态的 PHP。目前 `spc` 二进制支持的平台有 Linux 和 macOS。
|
|
||||||
|
|
||||||
使用以下命令从自托管服务器下载:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Download from self-hosted nightly builds (sync with main branch)
|
|
||||||
# For Linux x86_64
|
|
||||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64
|
|
||||||
# For Linux aarch64
|
|
||||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-aarch64
|
|
||||||
# macOS x86_64 (Intel)
|
|
||||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-x86_64
|
|
||||||
# macOS aarch64 (Apple)
|
|
||||||
curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64
|
|
||||||
# Windows (x86_64, win10 build 17063 or later)
|
|
||||||
curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe
|
|
||||||
|
|
||||||
# Add execute perm (Linux and macOS only)
|
|
||||||
chmod +x ./spc
|
|
||||||
|
|
||||||
# Run (Linux and macOS)
|
|
||||||
./spc --version
|
|
||||||
# Run (Windows powershell)
|
|
||||||
.\spc.exe --version
|
|
||||||
```
|
|
||||||
|
|
||||||
> 如果你使用的是打包好的 `spc` 二进制,你需要将下面所有命令中 `bin/spc` 开头替换为 `./spc`。
|
|
||||||
|
|
||||||
## 手动构建(使用源码)
|
|
||||||
|
|
||||||
如果使用 spc 二进制出现问题,或你有修改 static-php-cli 源码需求,请从源码下载 static-php-cli。
|
|
||||||
|
|
||||||
目前支持在 macOS、Linux 上构建,macOS 支持最新版操作系统和两种架构,Linux 支持 Debian、RHEL 及衍生发行版、Alpine Linux 等。
|
|
||||||
|
|
||||||
因为本项目本身采用 PHP 开发,所以在编译时也需要系统安装 PHP。本项目本身也提供了适用于本项目的静态二进制 php,可以根据实际情况自行选择使用。
|
|
||||||
|
|
||||||
### 下载本项目
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/crazywhalecc/static-php-cli.git --depth=1
|
|
||||||
cd static-php-cli
|
|
||||||
|
|
||||||
# 你需要先安装 PHP 环境后再运行 Composer 和本项目,安装方式可参考下面。
|
|
||||||
composer update
|
|
||||||
```
|
|
||||||
|
|
||||||
### 使用预编译静态 PHP 二进制运行 static-php-cli
|
|
||||||
|
|
||||||
如果你不想使用 Docker、在系统内安装 PHP,可以直接下载本项目自身编译好的 php 二进制 cli 程序。使用流程如下:
|
|
||||||
|
|
||||||
使用命令部署环境,此脚本会从 [自托管的服务器](https://dl.static-php.dev/static-php-cli/) 下载一个当前操作系统的 php-cli 包,
|
|
||||||
并从 [getcomposer](https://getcomposer.org/download/latest-stable/composer.phar) 或 [Aliyun(镜像)](https://mirrors.aliyun.com/composer/composer.phar) 下载 Composer。
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
使用预编译静态 PHP 二进制目前仅支持 Linux 和 macOS。FreeBSD 环境因为缺少自动化构建环境,所以暂不支持。
|
|
||||||
:::
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/setup-runtime
|
|
||||||
|
|
||||||
# 对于中国大陆地区等网络环境特殊的用户,可使用镜像站加快下载速度
|
|
||||||
bin/setup-runtime --mirror china
|
|
||||||
```
|
|
||||||
|
|
||||||
此脚本总共会下载两个文件:`bin/php` 和 `bin/composer`,下载完成后,有两种使用方式:
|
|
||||||
|
|
||||||
1. 将 `bin/` 目录添加到 PATH 路径中:`export PATH="/path/to/your/static-php-cli/bin:$PATH"`,添加路径后,相当于系统安装了 PHP,可直接使用 `composer`、`php -v` 等命令,也可以直接使用 `bin/spc`。
|
|
||||||
2. 直接调用,比如执行 static-php-cli 命令:`bin/php bin/spc --help`,执行 Composer:`bin/php bin/composer update`。
|
|
||||||
|
|
||||||
### 使用 Docker 环境
|
|
||||||
|
|
||||||
如果你不愿意在系统安装 PHP 和 Composer 运行环境,可以使用内置的 Docker 环境构建脚本。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 直接使用,将所有使用的命令中 `bin/spc` 替换为 `bin/spc-alpine-docker` 即可
|
|
||||||
bin/spc-alpine-docker
|
|
||||||
```
|
|
||||||
|
|
||||||
首次执行命令会使用 `docker build` 构建一个 Docker 镜像,默认构建的 Docker 镜像为 `x86_64` 架构,镜像名称为 `cwcc-spc-x86_64`。
|
|
||||||
|
|
||||||
如果你想在 `x86_64` 环境下构建 `aarch64` 的 static-php-cli,可以使用 qemu 模拟 arm 镜像运行 Docker,但速度会非常慢。使用参数:`SPC_USE_ARCH=aarch64 bin/spc-alpine-docker`。
|
|
||||||
|
|
||||||
如果运行后提示需要 sudo 才能运行,执行一次以下命令可授予 static-php-cli 执行 sudo 的权限:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export SPC_USE_SUDO=yes
|
|
||||||
```
|
|
||||||
|
|
||||||
### 使用系统 PHP 环境
|
|
||||||
|
|
||||||
下面是系统安装 PHP、Composer 的一些示例命令。具体安装方式建议自行搜索或询问 AI 搜索引擎获取答案,这里不多赘述。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# [macOS], 需要先安装 Homebrew. See https://brew.sh/
|
|
||||||
# Remember change your composer executable path. For M1/M2 Chip mac, "/opt/homebrew/bin/", for Intel mac, "/usr/local/bin/". Or add it to your own path.
|
|
||||||
brew install php wget
|
|
||||||
wget https://getcomposer.org/download/latest-stable/composer.phar -O /path/to/your/bin/composer && chmod +x /path/to/your/bin/composer
|
|
||||||
|
|
||||||
# [Debian], you need to make sure your php version >= 8.4 and composer >= 2.0
|
|
||||||
sudo apt install php-cli composer php-tokenizer
|
|
||||||
```
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
目前 Ubuntu 部分版本的 apt 安装的 php 版本较旧,故不提供安装命令。如有需要,建议先添加 ppa 等软件源后,安装最新版的 PHP 以及 tokenizer、xml、phar 扩展。
|
|
||||||
|
|
||||||
较老版本的 Debian 默认安装的可能为旧版本(<= 8.3)版本的 PHP,建议先升级 Debian 或使用 Docker 或自带的静态二进制环境。
|
|
||||||
:::
|
|
||||||
|
|
||||||
## 使用 craft 构建(推荐)
|
|
||||||
|
|
||||||
使用 `bin/spc craft` 可以使用一个配置文件,一个命令实现自动检查环境、下载源代码、构建依赖库、构建 PHP 及扩展等。
|
|
||||||
|
|
||||||
你需要编写一个 `craft.yml` 文件,存放在当前工作目录下。`craft.yml` 可以由 [命令生成器](./cli-generator) 生成,或者手动编写。
|
|
||||||
|
|
||||||
手动编写可参考 [craft.yml 配置](../develop/craft-yml.md) 中的注释来编写。我们下面假设你编译一个扩展组合,并选用 PHP 8.4,输出 `cli` 和 `fpm`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# path/to/craft.yml
|
|
||||||
php-version: 8.4
|
|
||||||
extensions: bcmath,posix,phar,zlib,openssl,curl,fileinfo,tokenizer
|
|
||||||
sapi:
|
|
||||||
- cli
|
|
||||||
- fpm
|
|
||||||
```
|
|
||||||
|
|
||||||
然后使用 `bin/spc craft` 命令来编译:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc craft --debug
|
|
||||||
```
|
|
||||||
|
|
||||||
如果构建成功,你会在当前目录下看到 `buildroot/bin` 目录,里面包含了编译好的 PHP 二进制文件,或相应的 SAPI。
|
|
||||||
|
|
||||||
- cli: Windows 下构建结果为 `buildroot/bin/php.exe`,其他平台为 `buildroot/bin/php`。
|
|
||||||
- fpm: 构建结果为 `buildroot/bin/php-fpm`。
|
|
||||||
- micro: 构建结果为 `buildroot/bin/micro.sfx`,如需进一步与 PHP 代码打包,请查看 [打包 micro 二进制](./manual-build#命令-micro-combine-打包-micro-二进制)。
|
|
||||||
- embed: 参见 [embed 使用](./manual-build#embed-使用)。
|
|
||||||
- frankenphp: 构建结果为 `buildroot/bin/frankenphp`。
|
|
||||||
|
|
||||||
如果中途构建出错,你可以使用 `--debug` 参数查看详细的错误信息,或者使用 `--with-clean` 参数清除旧的编译结果,重新编译。
|
|
||||||
|
|
||||||
如使用以上方式仍构建失败,请提交一个 issue,附上你的 `craft.yml` 文件、`log/` 目录的压缩包。
|
|
||||||
|
|
||||||
## 分步构建命令
|
|
||||||
|
|
||||||
如果你有定制化需求,或分开下载、编译 PHP 和依赖库的需求,可以使用 `bin/spc` 命令分步执行。
|
|
||||||
|
|
||||||
### 命令 download - 下载依赖包
|
|
||||||
|
|
||||||
使用命令 `bin/spc download` 可以下载编译需要的源代码,包括 php-src 以及依赖的各种库的源码。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 仅下载要编译的扩展及依赖库(使用扩展名,包含可选库)
|
|
||||||
bin/spc download --for-extensions=openssl,swoole,zip,pcntl,zstd
|
|
||||||
|
|
||||||
# 仅下载要编译的扩展及依赖库(使用扩展名,不包含可选库)
|
|
||||||
bin/spc download --for-extensions=openssl,swoole,zip,pcntl --without-suggestions
|
|
||||||
|
|
||||||
# 仅下载要编译的库(包括其依赖,使用库名,包含可选库,可以和 --for-extensions 组合使用)
|
|
||||||
bin/spc download --for-libs=liblz4,libevent --for-extensions=pcntl,rar,xml
|
|
||||||
|
|
||||||
# 仅下载要编译的库(包括其依赖,使用库名,不包含可选库)
|
|
||||||
bin/spc download --for-libs=liblz4,libevent --without-suggestions
|
|
||||||
|
|
||||||
# 下载资源时,忽略部分资源的缓存,强制下载(如切换特定 PHP 版本)
|
|
||||||
bin/spc download --for-extensions=curl,pcntl,xml --ignore-cache-sources=php-src --with-php=8.3.10
|
|
||||||
|
|
||||||
# 下载资源时,优先下载有预编译包的依赖库(减少编译依赖的时间)
|
|
||||||
bin/spc download --for-extensions="curl,pcntl,xml,mbstring" --prefer-pre-built
|
|
||||||
|
|
||||||
# 下载所有依赖包
|
|
||||||
bin/spc download --all
|
|
||||||
|
|
||||||
# 下载所有依赖包,并指定下载的 PHP 主版本,可选:8.1,8.2,8.3,8.4,也可以使用特定的版本,如 8.3.10。
|
|
||||||
bin/spc download --all --with-php=8.3
|
|
||||||
|
|
||||||
# 下载时显示下载进度条(curl)
|
|
||||||
bin/spc download --all --debug
|
|
||||||
|
|
||||||
# 删除旧的下载数据
|
|
||||||
bin/spc download --clean
|
|
||||||
|
|
||||||
# 仅下载指定的资源(使用资源名)
|
|
||||||
bin/spc download php-src,micro,zstd,ext-zstd
|
|
||||||
|
|
||||||
# 设置重试次数
|
|
||||||
bin/spc download --all --retry=2
|
|
||||||
```
|
|
||||||
|
|
||||||
如果你所在地区的网络不好,或者下载依赖包速度过于缓慢,可以从 GitHub Action 下载每周定时打包的 `download.zip`,并使用命令直接使用 zip 压缩包作为依赖。
|
|
||||||
依赖包可以从 [Action](https://github.com/static-php/static-php-cli-hosted/actions/workflows/download-cache.yml) 下载到本地。
|
|
||||||
进入 Action 并选择一个最新成功运行的 Workflow,下载 `download-files-x.y` 即可。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc download --from-zip=/path/to/your/download.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
如果某个 source 始终无法下载,或者你需要下载一些特定版本的包,例如下载测试版 PHP、旧版本库等,可以使用参数 `-U` 或 `--custom-url` 重写下载链接,
|
|
||||||
让下载器强制使用你指定的链接下载此 source 的包。使用方法为 `{source-name}:{url}` 即可,可同时重写多个库的下载地址。在使用 `--for-extensions` 选项下载时同样可用。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 例如:指定下载 Alpha 版的 PHP8.5
|
|
||||||
bin/spc download --all -U "php-src:https://downloads.php.net/~edorian/php-8.5.0alpha2.tar.xz"
|
|
||||||
|
|
||||||
# 指定下载旧版本的 curl 库
|
|
||||||
bin/spc download --all -U "curl:https://curl.se/download/curl-7.88.1.tar.gz"
|
|
||||||
```
|
|
||||||
|
|
||||||
如果你下载的资源不是链接,而是一个 Git 仓库,你可以使用 `-G` 或 `--custom-git` 重写下载链接,让下载器强制使用你指定的 Git 仓库下载此 source 的包。
|
|
||||||
使用方法为 `{source-name}:{branch}:{url}` 即可,可同时重写多个库的下载地址。在使用 `--for-extensions` 选项下载时同样可用。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 例如:下载 master 分支的 php-src
|
|
||||||
bin/spc download --for-extensions=redis,phar -G "php-src:master:https://github.com/php/php-src.git"
|
|
||||||
|
|
||||||
# 从 swoole-src 仓库下载 master 分支的最新代码,而不是发行版
|
|
||||||
bin/spc download --for-extensions=swoole -G "swoole:master:https://github.com/swoole/swoole-src.git"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 命令 doctor - 环境检查
|
|
||||||
|
|
||||||
如果你可以正常运行 `bin/spc` 但无法正常编译静态的 PHP 或依赖库,可以先运行 `bin/spc doctor` 检查系统自身是否缺少依赖。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 快速检查
|
|
||||||
bin/spc doctor
|
|
||||||
|
|
||||||
# 快速检查,并在可以自动修复的时候修复(使用包管理安装依赖包,仅支持上述提到的操作系统及发行版)
|
|
||||||
bin/spc doctor --auto-fix
|
|
||||||
```
|
|
||||||
|
|
||||||
### 命令 build - 编译 PHP
|
|
||||||
|
|
||||||
使用 build 命令可以开始构建静态 php 二进制,在执行 `bin/spc build` 命令前,务必先使用 `download` 命令下载资源,建议使用 `doctor` 检查环境。
|
|
||||||
|
|
||||||
#### 基本用法
|
|
||||||
|
|
||||||
你需要先到 [扩展列表](./extensions) 或 [命令生成器](./cli-generator) 选择你要加入的扩展,然后使用命令 `bin/spc build` 进行编译。你需要指定一个编译目标,从如下参数中选择:
|
|
||||||
|
|
||||||
- `--build-cli`: 构建一个 cli sapi(命令行界面,可在命令行执行 PHP 代码)
|
|
||||||
- `--build-fpm`: 构建一个 fpm sapi(php-fpm,用于和其他传统的 fpm 架构的软件如 nginx 配合使用)
|
|
||||||
- `--build-cgi`: 构建一个 cgi sapi(cgi,可用于传统的 cgi 架构的软件如 apache 配合使用)
|
|
||||||
- `--build-micro`: 构建一个 micro sapi(用于构建一个包含 PHP 代码的独立可执行二进制)
|
|
||||||
- `--build-embed`: 构建一个 embed sapi(用于嵌入到其他 C 语言程序中)
|
|
||||||
- `--build-frankenphp`: 构建一个 [frankenphp](https://github.com/php/frankenphp) 二进制
|
|
||||||
- `--build-all`: 构建以上所有 sapi
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 编译 PHP,附带 bcmath,curl,openssl,ftp,posix,pcntl 扩展,编译目标为 cli
|
|
||||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
|
||||||
|
|
||||||
# 编译 PHP,附带 phar,curl,posix,pcntl,tokenizer 扩展,编译目标为 micro
|
|
||||||
bin/spc build phar,curl,posix,pcntl,tokenizer --build-micro
|
|
||||||
```
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
如果你需要重复构建、调试,你可以删除 `buildroot/` 和 `source/` 两个目录,这样你可以从已下载的源码压缩包重新解压并构建:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# remove
|
|
||||||
rm -rf buildroot source
|
|
||||||
# build again
|
|
||||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
|
||||||
```
|
|
||||||
:::
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
如果你想构建多个版本的 PHP,且不想每次都重复构建其他依赖库,可以使用 `switch-php-version` 在编译好一个版本后快速切换至另一个版本并编译:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# switch to 8.4
|
|
||||||
bin/spc switch-php-version 8.4
|
|
||||||
# build
|
|
||||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
|
||||||
# switch to 8.1
|
|
||||||
bin/spc switch-php-version 8.1
|
|
||||||
# build
|
|
||||||
bin/spc build bcmath,curl,openssl,ftp,posix,pcntl --build-cli
|
|
||||||
```
|
|
||||||
:::
|
|
||||||
|
|
||||||
#### 编译运行选项
|
|
||||||
|
|
||||||
在编译过程中,有些特殊情况需要对编译器、编译目录的内容进行干预,可以尝试使用以下命令:
|
|
||||||
|
|
||||||
- `--cc=XXX`: 指定 C 语言编译器的执行命令(Linux 默认 `musl-gcc` 或 `gcc`,macOS 默认 `clang`)
|
|
||||||
- `--cxx=XXX`: 指定 C++ 语言编译器的执行命令(Linux 默认 `g++`,macOS 默认 `clang++`)
|
|
||||||
- `--with-clean`: 编译 PHP 前先清理旧的 make 产生的文件
|
|
||||||
- `--enable-zts`: 让编译的 PHP 为线程安全版本(默认为 NTS 版本)
|
|
||||||
- `--no-strip`: 编译 PHP 库后不运行 `strip` 裁剪二进制文件缩小体积
|
|
||||||
- `--with-libs=XXX,YYY`: 编译 PHP 前先编译指定的依赖库,激活部分扩展的可选功能(例如 gd 库的 libavif 等)
|
|
||||||
- `--with-config-file-path=XXX`: 查找 `php.ini` 的路径(在 [这里](../faq/index.html#php-ini-的路径是什么) 查看默认路径)
|
|
||||||
- `--with-config-file-scan-dir=XXX`: 读取 `php.ini` 后扫描 `.ini` 文件的目录(在 [这里](../faq/index.html#php-ini-的路径是什么) 查看默认路径)
|
|
||||||
- `-I xxx=yyy`: 编译前将 INI 选项硬编译到 PHP 内(支持多个选项,别名是 `--with-hardcoded-ini`)
|
|
||||||
- `--with-micro-fake-cli`: 在编译 micro 时,让 micro 的 SAPI 伪装为 `cli`(用于兼容一些检查 `PHP_SAPI` 的程序)
|
|
||||||
- `--disable-opcache-jit`: 禁用 opcache jit(默认启用)
|
|
||||||
- `-P xxx.php`: 在 static-php-cli 编译过程中注入外部脚本(详见下方 **注入外部脚本**)
|
|
||||||
- `--without-micro-ext-test`: 在构建 micro.sfx 后,禁用测试不同扩展在 micro.sfx 的运行结果
|
|
||||||
- `--with-suggested-exts`: 编译时将 `ext-suggests` 也作为编译依赖加入
|
|
||||||
- `--with-suggested-libs`: 编译时将 `lib-suggests` 也作为编译依赖加入
|
|
||||||
- `--with-upx-pack`: 编译后使用 UPX 减小二进制文件体积(需先使用 `bin/spc install-pkg upx` 安装 upx)
|
|
||||||
- `--build-shared=XXX,YYY`: 编译时将指定的扩展编译为共享库(默认编译为静态库)
|
|
||||||
|
|
||||||
硬编码 INI 选项适用于 cli、micro、embed。有关硬编码 INI 选项,下面是一个简单的例子,我们预设一个更大的 `memory_limit`,并且禁用 `system` 函数:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc build bcmath,pcntl,posix --build-all -I "memory_limit=4G" -I "disable_functions=system"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 命令 micro:combine - 打包 micro 二进制
|
|
||||||
|
|
||||||
使用 `micro:combine` 命令可以将上面编译好的 `micro.sfx` 和你的代码(`.php` 或 `.phar` 文件)构建为一个可执行二进制。
|
|
||||||
你也可以使用该命令直接构建一个注入了 ini 配置的 micro 自执行二进制文件。
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
注入 ini 配置指的是,在将 micro.sfx 和 PHP 源码结合前,在 micro.sfx 后追加一段特殊的结构用于保存 ini 配置项。
|
|
||||||
|
|
||||||
micro.sfx 可通过特殊的字节来标识 INI 文件头,通过 INI 文件头可以实现 micro 带 INI 启动。
|
|
||||||
|
|
||||||
此特性的原说明地址在 [phpmicro - Wiki](https://github.com/easysoft/phpmicro/wiki/INI-settings),这个特性也有可能在未来发生变化。
|
|
||||||
:::
|
|
||||||
|
|
||||||
下面是常规用法,直接打包 php 源码到一个文件中:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 在做打包流程前,你应该先使用 `build --build-micro` 编译好 micro.sfx
|
|
||||||
echo "<?php echo 'hello';" > a.php
|
|
||||||
bin/spc micro:combine a.php
|
|
||||||
|
|
||||||
# 使用
|
|
||||||
./my-app
|
|
||||||
```
|
|
||||||
|
|
||||||
你可以使用以下参数指定要输出的文件名,你也可以指定其他路径的 micro.sfx 进行打包。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 指定输出文件名
|
|
||||||
bin/spc micro:combine a.php --output=custom-bin
|
|
||||||
# 使用绝对路径,也可以使用简化参数名
|
|
||||||
bin/spc micro:combine a.php -O /tmp/my-custom-app
|
|
||||||
|
|
||||||
# 指定其他位置的 micro.sfx 进行打包
|
|
||||||
bin/spc micro:combine a.app --with-micro=/path/to/your/micro.sfx
|
|
||||||
```
|
|
||||||
|
|
||||||
如果想注入 ini 配置项,可以使用下面的参数,从文件或命令行选项添加 ini 到可执行文件中。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 使用命令行选项指定(-I 是 --with-ini-set 的简写)
|
|
||||||
bin/spc micro:combine a.php -I "a=b" -I "foo=bar"
|
|
||||||
|
|
||||||
# 使用 ini 文件指定(-N 是 --with-ini-file 的简写)
|
|
||||||
bin/spc micro:combine a.php -N /path/to/your/custom.ini
|
|
||||||
```
|
|
||||||
|
|
||||||
::: warning
|
|
||||||
注意,请不要直接使用 PHP 源码或系统安装的 PHP 中的 `php.ini` 文件,最好手动编写一个自己需要的参数配置文件,例如:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
; custom.ini
|
|
||||||
curl.cainfo=/path/to/your/cafile.pem
|
|
||||||
memory_limit=1G
|
|
||||||
```
|
|
||||||
|
|
||||||
该命令的注入 ini 是通过在 micro.sfx 后追加一段特殊的结构来实现的,和编译时插入硬编码 INI 的功能不同。
|
|
||||||
:::
|
|
||||||
|
|
||||||
如果要打包 phar,只需要将 `a.php` 替换为打包好的 phar 文件即可。但要注意,phar 下的 micro.sfx 需要额外注意路径问题,见 [Developing - Phar 路径问题](../develop/structure#phar-应用目录问题)
|
|
||||||
|
|
||||||
## 调试
|
|
||||||
|
|
||||||
如果你在编译过程中遇到了问题,或者想查看每个执行的 shell 命令,可以使用 `--debug` 开启 debug 模式,查看所有终端日志:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc build mysqlnd,pdo_mysql --build-all --debug
|
|
||||||
```
|
|
||||||
|
|
||||||
## 命令 extract - 手动解压某个库
|
|
||||||
|
|
||||||
使用命令 `bin/spc extract` 可以解包和拷贝编译需要的源代码,包括 php-src 以及依赖的各种库的源码(需要自己指定要解包的库名)。
|
|
||||||
|
|
||||||
例如,我们在下载好资源后,想分布执行构建流程,手动解包和拷贝包到指定位置,可以使用命令。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 解压 php-src 和 libxml2 的下载压缩包,解压的源码存放在 source 目录
|
|
||||||
bin/spc extract php-src,libxml2
|
|
||||||
```
|
|
||||||
|
|
||||||
## 命令 dump-extensions - 导出项目扩展依赖
|
|
||||||
|
|
||||||
使用命令 `bin/spc dump-extensions` 可以导出当前项目的扩展依赖。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 打印项目的扩展列表,传入项目包含composer.json的根目录
|
|
||||||
bin/spc dump-extensions /path/to/your/project/
|
|
||||||
|
|
||||||
# 打印项目的扩展列表,不包含开发依赖
|
|
||||||
bin/spc dump-extensions /path-to/tour/project/ --no-dev
|
|
||||||
|
|
||||||
# 输出为 spc 命令可接受的扩展列表格式(逗号分割)
|
|
||||||
bin/spc dump-extensions /path-to/tour/project/ --format=text
|
|
||||||
|
|
||||||
# 输出为 JSON 列表
|
|
||||||
bin/spc dump-extensions /path-to/tour/project/ --format=json
|
|
||||||
|
|
||||||
# 当项目没有任何扩展时,输出指定扩展组合,而不是返回失败
|
|
||||||
bin/spc dump-extensions /path-to/your/project/ --no-ext-output=mbstring,posix,pcntl,phar
|
|
||||||
|
|
||||||
# 输出时不排除 spc 不支持的扩展
|
|
||||||
bin/spc dump-extensions /path/to/your/project/ --no-spc-filter
|
|
||||||
```
|
|
||||||
|
|
||||||
需要注意的是,项目的目录下必须包含 `vendor/installed.json` 和 `composer.lock` 文件,否则无法正常获取。
|
|
||||||
|
|
||||||
## 调试命令 dev - 调试命令集合
|
|
||||||
|
|
||||||
调试命令指的是你在使用 static-php-cli 构建 PHP 或改造、增强 static-php-cli 项目本身的时候,可以辅助输出一些信息的命令集合。
|
|
||||||
|
|
||||||
- `dev:extensions`: 输出目前所有支持的扩展信息,或者输出指定的扩展信息
|
|
||||||
- `dev:php-version`: 输出当前编译的 PHP 版本(通过读取 `php_version.h` 实现)
|
|
||||||
- `dev:sort-config`: 对 `config/` 目录下的配置文件的列表按照字母表排序
|
|
||||||
- `dev:lib-ver <lib-name>`: 从依赖库的源码中读取版本(仅特定依赖库可用)
|
|
||||||
- `dev:ext-ver <ext-name>`: 从扩展的源码中读取对应版本(仅特定扩展可用)
|
|
||||||
- `dev:pack-lib <lib-name>`: 打包指定的依赖库(仅发布者可用)
|
|
||||||
- `dev:gen-ext-docs`: 生成扩展文档(仅发布者可用)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 输出所有扩展
|
|
||||||
bin/spc dev:extensions
|
|
||||||
|
|
||||||
# 输出指定扩展的信息
|
|
||||||
bin/spc dev:extensions mongodb,curl,openssl
|
|
||||||
|
|
||||||
# 输出指定列,可选:lib-depends, lib-suggests, ext-depends, ext-suggests, unix-only, type
|
|
||||||
bin/spc dev:extensions --columns=lib-depends,type,ext-depends
|
|
||||||
|
|
||||||
# 输出当前编译的 PHP 版本(需要先将下载好的 PHP 源码解压到 source 目录,你可以使用 `bin/spc extract php-src` 单独解压缩源码)
|
|
||||||
bin/spc dev:php-version
|
|
||||||
|
|
||||||
# 排序配置文件 ext.json(也可以排序 lib、source)
|
|
||||||
bin/spc dev:sort-config ext
|
|
||||||
```
|
|
||||||
|
|
||||||
## 命令 install-pkg - 下载二进制包
|
|
||||||
|
|
||||||
使用命令 `bin/spc install-pkg` 可以下载一些预编译或闭源的工具,并将其安装到 `pkgroot` 目录中。
|
|
||||||
|
|
||||||
在 `bin/spc doctor` 自动修复 Windows 环境时会下载 nasm、perl 等工具,使用的也是 `install-pkg` 的安装过程。
|
|
||||||
|
|
||||||
下面是安装工具的示例:
|
|
||||||
|
|
||||||
- 下载安装 UPX(仅限 Linux 和 Windows): `bin/spc install-pkg upx`
|
|
||||||
- 下载安装 nasm(仅限 Windows): `bin/spc install-pkg nasm`
|
|
||||||
- 下载安装 go-xcaddy: `bin/spc install-pkg go-xcaddy`
|
|
||||||
|
|
||||||
## 命令 del-download - 删除已下载的资源
|
|
||||||
|
|
||||||
一些情况下,你需要删除单个或多个指定的下载源文件,并重新下载他们,例如切换 PHP 版本,`2.1.0-beta.4` 版本后提供了 `bin/spc del-download` 命令,可以删除指定源文件。
|
|
||||||
|
|
||||||
删除已下载的源文件包含预编译的包以及源代码,名称是 `source.json` 或 `pkg.json` 中的键名。下面是一些例子:
|
|
||||||
|
|
||||||
- 删除 PHP 8.2 源码并切换下载为 8.3 版本: `bin/spc del-download php-src && bin/spc download php-src --with-php=8.3`
|
|
||||||
- 删除 redis 扩展的下载文件: `bin/spc del-download redis`
|
|
||||||
- 删除下载好的 musl-toolchain x86_64: `bin/spc del-download musl-toolchain-x86_64-linux`
|
|
||||||
|
|
||||||
## 注入外部脚本
|
|
||||||
|
|
||||||
注入外部脚本指的是在 static-php-cli 编译过程中插入一个或多个脚本,用于更灵活地支持不同环境下的参数修改、源代码补丁。
|
|
||||||
|
|
||||||
一般情况下,该功能主要解决使用 `spc` 二进制进行编译时无法通过修改 static-php-cli 代码来实现修改补丁的功能。
|
|
||||||
还有一种情况:你的项目直接依赖了 `crazywhalecc/static-php-cli` 仓库并同步,但因为项目特性需要做出一些专有的修改,而这些特性并不适合合并到主分支。
|
|
||||||
|
|
||||||
鉴于以上情况,在 2.0.1 正式版本中,static-php-cli 加入了多个事件的触发点,你可以通过编写外部的 `xx.php` 脚本,并通过命令行参数 `-P` 传入并执行。
|
|
||||||
|
|
||||||
在编写注入外部脚本时,你一定会用到的方法是 `builder()` 和 `patch_point()`。其中,`patch_point()` 获取的是当前正在执行的事件名称,`builder()` 获取的是 BuilderBase 对象。
|
|
||||||
|
|
||||||
因为传入的注入点不区分事件,所以你必须将你要执行的代码写在 `if(patch_point() === 'your_event_name')` 中,否则会重复在其他事件中执行。
|
|
||||||
|
|
||||||
下面是支持的 patch_point 事件名称及对应位置:
|
|
||||||
|
|
||||||
| 事件名称 | 事件描述 |
|
|
||||||
|------------------------------|-----------------------------------------------------------|
|
|
||||||
| before-libs-extract | 在编译的依赖库解压前触发 |
|
|
||||||
| after-libs-extract | 在编译的依赖库解压后触发 |
|
|
||||||
| before-php-extract | 在 PHP 源码解压前触发 |
|
|
||||||
| after-php-extract | 在 PHP 源码解压后触发 |
|
|
||||||
| before-micro-extract | 在 phpmicro 解压前触发 |
|
|
||||||
| after-micro-extract | 在 phpmicro 解压后触发 |
|
|
||||||
| before-exts-extract | 在要编译的扩展解压到 PHP 源码目录前触发 |
|
|
||||||
| 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` 前触发 |
|
|
||||||
| before-sanity-check | 在编译 PHP 后,运行扩展检查前触发 |
|
|
||||||
|
|
||||||
下面是一个简单的临时修改 PHP 源码的例子,开启 CLI 下在当前工作目录查找 `php.ini` 配置的功能:
|
|
||||||
|
|
||||||
```php
|
|
||||||
// a.php
|
|
||||||
<?php
|
|
||||||
if (patch_point() === 'before-php-buildconf') {
|
|
||||||
// replace php source code
|
|
||||||
\SPC\store\FileSystem::replaceFileStr(
|
|
||||||
SOURCE_PATH . '/php-src/sapi/cli/php_cli.c',
|
|
||||||
'sapi_module->php_ini_ignore_cwd = 1;',
|
|
||||||
'sapi_module->php_ini_ignore_cwd = 0;'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc build mbstring --build-cli -P a.php
|
|
||||||
echo 'memory_limit=8G' > ./php.ini
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
$ buildroot/bin/php -i | grep Loaded
|
|
||||||
Loaded Configuration File => /Users/jerry/project/git-project/static-php-cli/php.ini
|
|
||||||
|
|
||||||
$ buildroot/bin/php -i | grep memory
|
|
||||||
memory_limit => 8G => 8G
|
|
||||||
```
|
|
||||||
|
|
||||||
对于 static-php-cli 支持的对象、方法及接口,可以阅读源码,大部分的方法和对象都有相应的注释。
|
|
||||||
|
|
||||||
一般使用 `-P` 功能常用的对象及函数有:
|
|
||||||
|
|
||||||
- `SPC\store\FileSystem`: 文件管理类
|
|
||||||
- `::replaceFileStr(string $filename, string $search, $replace)`: 替换文件字符串内容
|
|
||||||
- `::replaceFileStr(string $filename, string $pattern, $replace)`: 正则替换文件内容
|
|
||||||
- `::replaceFileUser(string $filename, $callback)`: 用户自定义函数替换文件内容
|
|
||||||
- `::copyDir(string $from, string $to)`: 递归拷贝某个目录到另一个位置
|
|
||||||
- `::convertPath(string $path)`: 转换路径的分隔符为当前系统分隔符
|
|
||||||
- `::scanDirFiles(string $dir, bool $recursive = true, bool|string $relative = false, bool $include_dir = false)`: 遍历目录文件
|
|
||||||
- `SPC\builder\BuilderBase`: 构建对象
|
|
||||||
- `->getPatchPoint()`: 获取当前的注入点名称
|
|
||||||
- `->getOption(string $key, $default = null)`: 获取命令行和编译时的选项
|
|
||||||
- `->getPHPVersionID()`: 获取当前编译的 PHP 版本 ID
|
|
||||||
- `->getPHPVersion()`: 获取当前编译的 PHP 版本号
|
|
||||||
- `->setOption(string $key, $value)`: 设定选项
|
|
||||||
- `->setOptionIfNotExists(string $key, $value)`: 如果选项不存在则设定选项
|
|
||||||
|
|
||||||
::: tip
|
|
||||||
static-php-cli 开放的方法非常多,文档中无法一一列举,但只要是 `public function` 并且不被标注为 `@internal`,均可调用。
|
|
||||||
:::
|
|
||||||
|
|
||||||
## 多次构建
|
|
||||||
|
|
||||||
如果你在本地要多次构建,以下方法可以为你节省下载资源、编译的时间。
|
|
||||||
|
|
||||||
- 仅切换 PHP 版本,不更换依赖库版本时,可以使用 `bin/spc switch-php-version` 快速切换 PHP 版本,然后重新运行同样的 `build` 命令。
|
|
||||||
- 如果你想重新构建一次,但不重新下载源码,可以先 `rm -rf buildroot source` 删除编译目录和源码目录,然后重新构建。
|
|
||||||
- 如果你想更新某个依赖的版本,可以使用 `bin/spc del-download <source-name>` 删除指定的源码,然后使用 `download <source-name>` 重新下载。
|
|
||||||
- 如果你想更新所有依赖的版本,可以使用 `bin/spc download --clean` 删除所有下载的源码,然后重新下载。
|
|
||||||
|
|
||||||
## embed 使用
|
|
||||||
|
|
||||||
如果你想将 static-php 嵌入到其他 C 语言程序中,可以使用 `--build-embed` 构建一个 embed 版本的 PHP。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/spc build {your extensions} --build-embed --debug
|
|
||||||
```
|
|
||||||
|
|
||||||
在通常的情况下,PHP embed 编译后会生成 `php-config`。对于 static-php,我们提供了 `spc-config`,用于获取编译时的参数。
|
|
||||||
另外,在使用 embed SAPI(libphp.a)时,你需要使用和编译 libphp 相同的编译器,否则会出现链接错误。
|
|
||||||
|
|
||||||
下面是 spc-config 的基本用法:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# output all flags and options
|
|
||||||
bin/spc spc-config curl,zlib,phar,openssl
|
|
||||||
|
|
||||||
# output libs
|
|
||||||
bin/spc spc-config curl,zlib,phar,openssl --libs
|
|
||||||
|
|
||||||
# output includes
|
|
||||||
bin/spc spc-config curl,zlib,phar,openssl --includes
|
|
||||||
```
|
|
||||||
|
|
||||||
默认情况下,static-php 在不同系统使用的编译器分别是:
|
|
||||||
|
|
||||||
- macOS: `clang`
|
|
||||||
- Linux (Alpine Linux): `gcc`
|
|
||||||
- Linux (glibc based distros, x86_64): `/usr/local/musl/bin/x86_64-linux-musl-gcc`
|
|
||||||
- Linux (glibc based distros, aarch64): `/usr/local/musl/bin/aarch64-linux-musl-gcc`
|
|
||||||
- FreeBSD: `clang`
|
|
||||||
|
|
||||||
下面是一个使用 embed SAPI 的例子:
|
|
||||||
|
|
||||||
```c
|
|
||||||
// embed.c
|
|
||||||
#include <sapi/embed/php_embed.h>
|
|
||||||
|
|
||||||
int main(int argc,char **argv){
|
|
||||||
|
|
||||||
PHP_EMBED_START_BLOCK(argc,argv)
|
|
||||||
|
|
||||||
zend_file_handle file_handle;
|
|
||||||
|
|
||||||
zend_stream_init_filename(&file_handle,"embed.php");
|
|
||||||
|
|
||||||
if(php_execute_script(&file_handle) == FAILURE){
|
|
||||||
php_printf("Failed to execute PHP script.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
PHP_EMBED_END_BLOCK()
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
// embed.php
|
|
||||||
echo "Hello world!\n";
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# compile in debian/ubuntu x86_64
|
|
||||||
/usr/local/musl/bin/x86_64-linux-musl-gcc embed.c $(bin/spc spc-config bcmath,zlib) -static -o embed
|
|
||||||
# compile in macOS/FreeBSD
|
|
||||||
clang embed.c $(bin/spc spc-config bcmath,zlib) -o embed
|
|
||||||
|
|
||||||
./embed
|
|
||||||
# out: Hello world!
|
|
||||||
```
|
|
||||||
277
docs/zh/guide/sapi-reference.md
Normal file
277
docs/zh/guide/sapi-reference.md
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
---
|
||||||
|
outline: 'deep'
|
||||||
|
---
|
||||||
|
|
||||||
|
# PHP SAPI 构建参考
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
如果你采用的是 spc 二进制方式安装,请将本章节中的所有 `spc` 替换为 `./spc` 或 `.\spc.exe`。
|
||||||
|
|
||||||
|
如果你采用的是源码安装,请将 `spc` 替换为 `bin/spc`。
|
||||||
|
:::
|
||||||
|
|
||||||
|
本页详细介绍 StaticPHP 支持的各类 PHP SAPI 的构建参数和使用方式。
|
||||||
|
|
||||||
|
## 概览
|
||||||
|
|
||||||
|
| SAPI | 构建参数 | 产物路径(Linux/macOS)| 产物路径(Windows)| 平台支持 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| cli | `--build-cli` | `buildroot/bin/php` | `buildroot/bin/php.exe` | Linux、macOS、Windows |
|
||||||
|
| fpm | `--build-fpm` | `buildroot/bin/php-fpm` | — | Linux、macOS |
|
||||||
|
| micro | `--build-micro` | `buildroot/bin/micro.sfx` | `buildroot/bin/micro.sfx` | Linux、macOS、Windows |
|
||||||
|
| embed | `--build-embed` | `buildroot/lib/libphp.a` | `buildroot/lib/php8embed.lib` | Linux、macOS、Windows |
|
||||||
|
| frankenphp | `--build-frankenphp` | `buildroot/bin/frankenphp` | `buildroot/bin/frankenphp.exe` | Linux、macOS、Windows |
|
||||||
|
|
||||||
|
## cli
|
||||||
|
|
||||||
|
`cli` 是标准的 PHP 命令行程序,适用于在终端执行 PHP 脚本、交互式 shell 等场景。
|
||||||
|
|
||||||
|
### 构建
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,openssl,curl" --build-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
Windows 下产物为 `buildroot/bin/php.exe`,其他平台为 `buildroot/bin/php`。
|
||||||
|
|
||||||
|
完整选项参见 [build:php — SAPI 选择](./cli-reference#sapi-selection) 和 [build:php — 通用构建选项](./cli-reference#common-build-options)。
|
||||||
|
|
||||||
|
### 使用
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看版本和已加载扩展
|
||||||
|
./buildroot/bin/php -v
|
||||||
|
./buildroot/bin/php -m
|
||||||
|
|
||||||
|
# 执行脚本
|
||||||
|
./buildroot/bin/php your-script.php
|
||||||
|
|
||||||
|
# 交互模式
|
||||||
|
./buildroot/bin/php -a
|
||||||
|
```
|
||||||
|
|
||||||
|
### php.ini 路径
|
||||||
|
|
||||||
|
静态编译的 PHP cli 按以下顺序搜索 `php.ini`:
|
||||||
|
|
||||||
|
1. 命令行参数 `-c /path/to/php.ini` 指定的路径
|
||||||
|
2. `PHP_INI_PATH` 环境变量指定的路径
|
||||||
|
3. 编译时通过 `--with-config-file-path` 指定的目录(默认为 `/usr/local/etc/php`)
|
||||||
|
|
||||||
|
可以通过 `./buildroot/bin/php --ini` 查看 PHP 实际使用的 ini 路径。
|
||||||
|
|
||||||
|
### 硬编码 INI
|
||||||
|
|
||||||
|
使用 `-I` 参数可以在编译时将 INI 配置硬编码到二进制中,无需额外的 `php.ini` 文件:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,pcntl" --build-cli -I "memory_limit=4G" -I "disable_functions=system,exec"
|
||||||
|
```
|
||||||
|
|
||||||
|
硬编码 INI 适用于 `cli`、`micro`、`embed` SAPI。
|
||||||
|
|
||||||
|
## fpm
|
||||||
|
|
||||||
|
`fpm`(FastCGI Process Manager)与 Nginx、Apache 等 Web 服务器配合使用,适用于传统的 Web 应用部署场景。
|
||||||
|
|
||||||
|
::: warning
|
||||||
|
`fpm` 不支持 Windows 平台。
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 构建
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,openssl,curl,pdo_mysql" --build-fpm
|
||||||
|
```
|
||||||
|
|
||||||
|
产物为 `buildroot/bin/php-fpm`。
|
||||||
|
|
||||||
|
完整选项参见 [build:php — SAPI 选择](./cli-reference#sapi-selection) 和 [build:php — 通用构建选项](./cli-reference#common-build-options)。
|
||||||
|
|
||||||
|
### 使用
|
||||||
|
|
||||||
|
将 `buildroot/bin/php-fpm` 拷贝到服务器,像普通的 `php-fpm` 一样使用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看版本
|
||||||
|
./buildroot/bin/php-fpm -v
|
||||||
|
|
||||||
|
# 指定配置文件启动
|
||||||
|
./buildroot/bin/php-fpm -c /path/to/php.ini -y /path/to/php-fpm.conf
|
||||||
|
|
||||||
|
# 测试配置文件
|
||||||
|
./buildroot/bin/php-fpm -t
|
||||||
|
```
|
||||||
|
|
||||||
|
### 与 Nginx 配合使用示例
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
root /var/www/html;
|
||||||
|
index index.php;
|
||||||
|
|
||||||
|
location ~ \.php$ {
|
||||||
|
fastcgi_pass 127.0.0.1:9000;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
include fastcgi_params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`php-fpm.conf` 示例:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[global]
|
||||||
|
pid = /var/run/php-fpm.pid
|
||||||
|
error_log = /var/log/php-fpm.log
|
||||||
|
|
||||||
|
[www]
|
||||||
|
listen = 127.0.0.1:9000
|
||||||
|
pm = dynamic
|
||||||
|
pm.max_children = 5
|
||||||
|
pm.start_servers = 2
|
||||||
|
pm.min_spare_servers = 1
|
||||||
|
pm.max_spare_servers = 3
|
||||||
|
```
|
||||||
|
|
||||||
|
## micro
|
||||||
|
|
||||||
|
`micro` 是基于 [phpmicro](https://github.com/easysoft/phpmicro) 的自包含可执行文件 SAPI。通过 `spc micro:combine` 命令,可以将 `micro.sfx` 与 PHP 代码合并为一个独立的可执行文件,无需在目标机器上安装 PHP。
|
||||||
|
|
||||||
|
### 构建
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,phar,openssl,curl" --build-micro
|
||||||
|
```
|
||||||
|
|
||||||
|
产物为 `buildroot/bin/micro.sfx`。
|
||||||
|
|
||||||
|
完整选项参见 [build:php — SAPI 选择](./cli-reference#sapi-selection)、[build:php — 通用构建选项](./cli-reference#common-build-options) 和 [build:php — micro 专用选项](./cli-reference#micro-options)。
|
||||||
|
|
||||||
|
### 打包应用
|
||||||
|
|
||||||
|
使用 `micro:combine` 命令将 PHP 脚本或 phar 文件打包:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 打包 PHP 脚本
|
||||||
|
echo "<?php echo 'Hello, World!' . PHP_EOL;" > hello.php
|
||||||
|
spc micro:combine hello.php --output=hello
|
||||||
|
./hello
|
||||||
|
|
||||||
|
# 打包 phar 文件
|
||||||
|
spc micro:combine your-app.phar --output=your-app
|
||||||
|
./your-app
|
||||||
|
```
|
||||||
|
|
||||||
|
### 注入 INI 配置
|
||||||
|
|
||||||
|
打包时可以通过命令行参数或 ini 文件注入运行时配置:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 通过命令行参数注入(-I 是 --with-ini-set 的简写)
|
||||||
|
spc micro:combine your-app.phar --output=your-app -I "memory_limit=512M" -I "curl.cainfo=/etc/ssl/certs/ca-certificates.crt"
|
||||||
|
|
||||||
|
# 通过 ini 文件注入(-N 是 --with-ini-file 的简写)
|
||||||
|
spc micro:combine your-app.phar --output=your-app -N /path/to/custom.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
`-I` 注入的 INI 是运行时配置,通过在 `micro.sfx` 末尾追加特殊结构实现。这与编译时用 `-I` 硬编码 INI 不同,两者可以共存。
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 伪装为 cli SAPI
|
||||||
|
|
||||||
|
部分框架会检查 `PHP_SAPI` 的值,并限制在非 `cli` 环境下运行。`micro` 的 `PHP_SAPI` 默认值为 `micro`,可通过编译参数让其伪装为 `cli`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,phar" --build-micro --with-micro-fake-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
### 指定自定义 micro.sfx 路径
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc micro:combine your-app.phar --output=your-app --with-micro=/path/to/your/micro.sfx
|
||||||
|
```
|
||||||
|
|
||||||
|
### 关于 phar 的路径问题
|
||||||
|
|
||||||
|
将应用打包为 phar 后,phar 内部使用相对路径可能与预期不符。请参考[开发者文档 - Phar 目录问题](../develop/structure)了解详情。
|
||||||
|
|
||||||
|
## embed
|
||||||
|
|
||||||
|
`embed` SAPI 将 PHP 编译为静态库(Linux/macOS 下为 `libphp.a`,Windows 下为 `php8embed.lib`),可嵌入到其他 C/C++ 程序中运行 PHP 代码。
|
||||||
|
|
||||||
|
### 构建
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,openssl" --build-embed
|
||||||
|
```
|
||||||
|
|
||||||
|
产物:
|
||||||
|
- Linux/macOS:`buildroot/lib/libphp.a`,头文件在 `buildroot/include/`
|
||||||
|
- Windows:`buildroot/lib/php8embed.lib`,头文件在 `buildroot/include/`
|
||||||
|
|
||||||
|
完整选项参见 [build:php — SAPI 选择](./cli-reference#sapi-selection)、[build:php — 通用构建选项](./cli-reference#common-build-options) 和 [build:php — embed 专用选项](./cli-reference#embed-options)。
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
如何将 `libphp.a` / `php8embed.lib` 链接到你自己的项目(包括编译器选择、`dev:shell` 使用方式和完整 C 示例),将在开发者文档中专门介绍。
|
||||||
|
:::
|
||||||
|
|
||||||
|
## frankenphp
|
||||||
|
|
||||||
|
`frankenphp` 是基于 [FrankenPHP](https://github.com/php/frankenphp) 的现代 PHP 应用服务器,内置 Caddy,支持 HTTP/2、HTTP/3、自动 HTTPS 等特性。
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
StaticPHP 构建出的 `frankenphp` 是单个完全自包含的可执行文件。这与 FrankenPHP 官方提供的发行版不同,官方版本为动态链接二进制,需要单独安装 PHP。
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: warning
|
||||||
|
FrankenPHP 必须启用线程安全模式,构建时务必加上 `--enable-zts`。
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 构建
|
||||||
|
|
||||||
|
```bash
|
||||||
|
spc build:php "bcmath,openssl,curl,pdo_mysql" --build-frankenphp --enable-zts
|
||||||
|
```
|
||||||
|
|
||||||
|
Linux/macOS 下产物为 `buildroot/bin/frankenphp`,Windows 下为 `buildroot/bin/frankenphp.exe`。
|
||||||
|
|
||||||
|
完整选项参见 [build:php — SAPI 选择](./cli-reference#sapi-selection)、[build:php — 通用构建选项](./cli-reference#common-build-options) 和 [build:php — frankenphp 专用选项](./cli-reference#frankenphp-options)。
|
||||||
|
|
||||||
|
### 使用
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看版本
|
||||||
|
./buildroot/bin/frankenphp version
|
||||||
|
|
||||||
|
# 以 PHP 内置服务器模式运行(用于开发调试)
|
||||||
|
./buildroot/bin/frankenphp php-server
|
||||||
|
|
||||||
|
# 运行 Worker 模式
|
||||||
|
./buildroot/bin/frankenphp run --config /path/to/Caddyfile
|
||||||
|
```
|
||||||
|
|
||||||
|
更多用法请参考 [FrankenPHP 官方文档](https://frankenphp.dev/docs/)。
|
||||||
|
|
||||||
|
## 动态扩展加载
|
||||||
|
|
||||||
|
静态 PHP 二进制是否能够通过 `dl()` 在运行时加载扩展,取决于其链接方式。
|
||||||
|
|
||||||
|
**macOS** — 构建产物始终动态链接系统库,支持通过 `dl()` 或 `php.ini` 在运行时加载 `.so` 扩展。
|
||||||
|
|
||||||
|
**Linux** — StaticPHP 默认构建目标为 `native-native-musl`:完全静态链接 musl libc 的二进制。由于运行时不存在动态链接器,`dl()` 被禁用,FFI 扩展无法使用,也无法加载任何外部 `.so` 扩展。
|
||||||
|
|
||||||
|
如需在 Linux 上支持动态扩展加载,请在构建前设置 `SPC_TARGET` 环境变量:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SPC_TARGET=native-native-gnu.2.17 spc build:php "bcmath,openssl" --build-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
如果你采用的是源码安装,也可以在 `config/env.ini` 中设置 `SPC_TARGET=native-native-gnu.2.17`,将其作为所有构建的默认值。
|
||||||
|
|
||||||
|
这将使用 Zig 工具链构建出一个准静态二进制,动态链接 glibc 2.17,可运行于大多数现代 GNU/Linux 发行版,无需 Docker,也无需额外的交叉编译工具链。该产物支持 `dl()`、FFI 和运行时加载 `.so` 扩展,但无法运行于 Alpine Linux 等基于 musl 的系统。
|
||||||
|
|
||||||
|
**Windows** — Windows 上的 PHP 扩展均以 `.dll` 形式分发,且依赖官方动态构建的 PHP 中附带的 DLL 文件。StaticPHP 构建的静态 PHP 可执行文件不包含这些 DLL,因此 Windows 不支持动态扩展加载,所有扩展必须在构建时静态编译进去。
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# 故障排除
|
# 故障排除
|
||||||
|
|
||||||
使用 static-php-cli 过程中可能会碰到各种各样的故障,这里将讲述如何自行查看错误并反馈 Issue。
|
使用 StaticPHP 过程中可能会碰到各种各样的故障,这里将讲述如何自行查看错误并反馈 Issue。
|
||||||
|
|
||||||
## 下载失败问题
|
## 下载失败问题
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
在遇到下载失败后,可以多次尝试调用下载命令。
|
在遇到下载失败后,可以多次尝试调用下载命令。
|
||||||
|
|
||||||
当下载资源时,你可能最终会看到类似 `curl: (56) The requested URL returned error: 403` 的错误,这通常是由于 GitHub 限制导致的。
|
当下载资源时,你可能最终会看到类似 `curl: (56) The requested URL returned error: 403` 的错误,这通常是由于 GitHub 限制导致的。
|
||||||
你可以通过在命令中添加 `--debug` 来验证,会看到类似 `[DEBU] Running command (no output) : curl -sfSL "https://api.github.com/repos/openssl/openssl/releases"` 的输出。
|
你可以通过在命令中添加 `-vvv` 来验证,会看到类似 `[DEBU] Running command (no output) : curl -sfSL "https://api.github.com/repos/openssl/openssl/releases"` 的输出。
|
||||||
|
|
||||||
要解决这个问题,可以在 GitHub 上 [创建](https://github.com/settings/tokens) 一个个人访问令牌,并将其设置为环境变量 `GITHUB_TOKEN=<XXX>`。
|
要解决这个问题,可以在 GitHub 上 [创建](https://github.com/settings/tokens) 一个个人访问令牌,并将其设置为环境变量 `GITHUB_TOKEN=<XXX>`。
|
||||||
|
|
||||||
@@ -24,8 +24,9 @@
|
|||||||
|
|
||||||
## 编译错误
|
## 编译错误
|
||||||
|
|
||||||
遇到编译错误时,如果没有开启 `--debug` 日志,请先开启调试日志,然后确定报错的命令。
|
遇到编译错误时,如果没有开启 `-vvv` 日志,请先开启调试日志,然后确定报错的命令。
|
||||||
报错的终端输出对于修复编译错误非常重要。
|
报错的终端输出对于修复编译错误非常重要。
|
||||||
在提交 Issue 时,请上传终端日志的最后报错片段(或整个终端日志输出),并且包含使用的 `spc` 命令和参数。
|
在提交 Issue 时,请上传终端日志的最后报错片段(或整个终端日志输出),并且包含使用的 `spc` 命令和参数。
|
||||||
|
|
||||||
如果你是重复构建,请参考 [本地构建 - 多次构建](./manual-build#多次构建) 章节。
|
如果你是重复构建,请参考 [首次构建 - 调试与重新构建](./first-build#调试与重新构建) 章节。
|
||||||
|
|
||||||
|
|||||||
@@ -3,23 +3,26 @@
|
|||||||
layout: home
|
layout: home
|
||||||
|
|
||||||
hero:
|
hero:
|
||||||
name: "Static PHP"
|
name: "StaticPHP"
|
||||||
tagline: "在 Linux、macOS、FreeBSD、Windows 上与 PHP 项目一起构建独立的 PHP 二进制文件,并包含流行的扩展。"
|
tagline: "StaticPHP 是一款强大的工具,旨在构建包含 PHP、扩展等在内的可移植可执行文件。"
|
||||||
image:
|
image:
|
||||||
src: /images/static-php_nobg.png
|
src: /images/static-php_nobg.png
|
||||||
alt: Static PHP CLI Logo
|
alt: StaticPHP Logo
|
||||||
actions:
|
actions:
|
||||||
- theme: brand
|
- theme: brand
|
||||||
text: 开始使用
|
text: 开始使用
|
||||||
link: ./guide/
|
link: /zh/guide/
|
||||||
|
- theme: alt
|
||||||
|
text: English Docs
|
||||||
|
link: /en/
|
||||||
|
|
||||||
features:
|
features:
|
||||||
- title: 静态 CLI 二进制
|
- title: 静态 CLI 二进制
|
||||||
details: 您可以轻松地编译一个独立的 PHP 二进制文件以供通用使用,包括 CLI、FPM SAPI。
|
details: 您可以轻松编译一个可独立运行的 PHP 二进制文件用于通用场景,支持 CLI、FPM、CGI、FrankenPHP SAPI。
|
||||||
- title: Micro 自解压可执行文件
|
- title: Micro 自解压可执行文件
|
||||||
details: 您可以编译一个自解压的可执行文件,并将 PHP 源代码与二进制文件打包在一起。
|
details: 您可以编译一个自解压可执行文件,并通过 Micro SAPI 将其与 PHP 源代码一起构建。
|
||||||
- title: 依赖管理
|
- title: 依赖管理
|
||||||
details: static-php-cli 附带依赖项管理,支持安装不同类型的 PHP 扩展。
|
details: StaticPHP 内置依赖管理,支持安装不同类型的 PHP 扩展、包和库。
|
||||||
---
|
---
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|||||||
12
netlify.toml
Normal file
12
netlify.toml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[build]
|
||||||
|
publish = "docs/.vitepress/dist"
|
||||||
|
command = "bin/setup-runtime && export PATH=\"$(pwd)/bin:$PATH\" && php --version && npm run docs:build"
|
||||||
|
|
||||||
|
[context.deploy-preview]
|
||||||
|
ignore = """
|
||||||
|
curl -s -H "Authorization: token $GITHUB_PAT" \
|
||||||
|
https://api.github.com/repos/$REPOSITORY/pulls/$REVIEW_ID \
|
||||||
|
| grep -q '"documentation"' || exit 0
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
"""
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
{
|
{
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"docs:dev": "vitepress dev docs",
|
"docs:dev": "vitepress dev docs",
|
||||||
"docs:build": "vitepress build docs",
|
"docs:gen-meta": "node docs/.vitepress/gen-meta.js",
|
||||||
|
"docs:build": "npm run docs:gen-meta && vitepress build docs",
|
||||||
"docs:preview": "vitepress preview docs"
|
"docs:preview": "vitepress preview docs"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"mermaid": "^11.0.0",
|
||||||
"vitepress": "^2.0.0-alpha.5",
|
"vitepress": "^2.0.0-alpha.5",
|
||||||
"vue": "^3.2.47"
|
"vue": "^3.2.47"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -296,18 +296,29 @@ class php extends TargetPackage
|
|||||||
$x->isBuildStatic());
|
$x->isBuildStatic());
|
||||||
$shared_extensions = parse_extension_list($package->getBuildOption('build-shared') ?? []);
|
$shared_extensions = parse_extension_list($package->getBuildOption('build-shared') ?? []);
|
||||||
$install_packages = array_filter($installer->getResolvedPackages(), fn ($x) => $x->getType() !== 'php-extension' && $x->getName() !== 'php' && !str_starts_with($x->getName(), 'php-'));
|
$install_packages = array_filter($installer->getResolvedPackages(), fn ($x) => $x->getType() !== 'php-extension' && $x->getName() !== 'php' && !str_starts_with($x->getName(), 'php-'));
|
||||||
return [
|
|
||||||
|
$builder = ApplicationContext::get(PackageBuilder::class);
|
||||||
|
$ignore_cache = $builder->getOption('dl-ignore-cache', false);
|
||||||
|
$php_will_be_refreshed = $ignore_cache !== false && (
|
||||||
|
$ignore_cache === null || // --dl-ignore-cache with no value (ignore all)
|
||||||
|
str_contains((string) $ignore_cache, 'php-src')
|
||||||
|
);
|
||||||
|
|
||||||
|
$info = [
|
||||||
'Build OS' => SystemTarget::getTargetOS() . ' (' . SystemTarget::getTargetArch() . ')',
|
'Build OS' => SystemTarget::getTargetOS() . ' (' . SystemTarget::getTargetArch() . ')',
|
||||||
'Build Target' => getenv('SPC_TARGET') ?: '',
|
'Build Target' => getenv('SPC_TARGET') ?: '',
|
||||||
'Build Toolchain' => ToolchainManager::getToolchainClass(),
|
'Build Toolchain' => ToolchainManager::getToolchainClass(),
|
||||||
'Build SAPI' => implode(', ', $sapis),
|
'Build SAPI' => implode(', ', $sapis),
|
||||||
'PHP Version' => self::getPHPVersion(return_null_if_failed: true) ?? self::getPHPVersionFromArchive(return_null_if_failed: true) ?? 'Unknown',
|
|
||||||
'Static Extensions (' . count($static_extensions) . ')' => implode(',', array_map(fn ($x) => substr($x->getName(), 4), $static_extensions)),
|
|
||||||
'Shared Extensions (' . count($shared_extensions) . ')' => implode(',', $shared_extensions),
|
|
||||||
'Install Packages (' . count($install_packages) . ')' => implode(',', array_map(fn ($x) => $x->getName(), $install_packages)),
|
|
||||||
'Strip Binaries' => $package->getBuildOption('no-strip') ? 'No' : 'Yes',
|
|
||||||
'Enable ZTS' => $package->getBuildOption('enable-zts') ? 'Yes' : 'No',
|
|
||||||
];
|
];
|
||||||
|
if (!$php_will_be_refreshed) {
|
||||||
|
$info['PHP Version'] = self::getPHPVersion(return_null_if_failed: true) ?? self::getPHPVersionFromArchive(return_null_if_failed: true) ?? 'Unknown';
|
||||||
|
}
|
||||||
|
$info['Static Extensions (' . count($static_extensions) . ')'] = implode(',', array_map(fn ($x) => substr($x->getName(), 4), $static_extensions));
|
||||||
|
$info['Shared Extensions (' . count($shared_extensions) . ')'] = implode(',', $shared_extensions);
|
||||||
|
$info['Install Packages (' . count($install_packages) . ')'] = implode(',', array_map(fn ($x) => $x->getName(), $install_packages));
|
||||||
|
$info['Strip Binaries'] = $package->getBuildOption('no-strip') ? 'No' : 'Yes';
|
||||||
|
$info['Enable ZTS'] = $package->getBuildOption('enable-zts') ? 'Yes' : 'No';
|
||||||
|
return $info;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[BeforeStage('php', 'build')]
|
#[BeforeStage('php', 'build')]
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ use StaticPHP\Util\InteractiveTerm;
|
|||||||
use StaticPHP\Util\SourcePatcher;
|
use StaticPHP\Util\SourcePatcher;
|
||||||
use StaticPHP\Util\SPCConfigUtil;
|
use StaticPHP\Util\SPCConfigUtil;
|
||||||
use StaticPHP\Util\System\UnixUtil;
|
use StaticPHP\Util\System\UnixUtil;
|
||||||
use StaticPHP\Util\V2CompatLayer;
|
|
||||||
use ZM\Logger\ConsoleColor;
|
use ZM\Logger\ConsoleColor;
|
||||||
|
|
||||||
trait unix
|
trait unix
|
||||||
@@ -62,7 +61,6 @@ trait unix
|
|||||||
public function buildconfForUnix(TargetPackage $package): void
|
public function buildconfForUnix(TargetPackage $package): void
|
||||||
{
|
{
|
||||||
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('./buildconf'));
|
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('./buildconf'));
|
||||||
V2CompatLayer::emitPatchPoint('before-php-buildconf');
|
|
||||||
shell()->cd($package->getSourceDir())->exec(getenv('SPC_CMD_PREFIX_PHP_BUILDCONF'));
|
shell()->cd($package->getSourceDir())->exec(getenv('SPC_CMD_PREFIX_PHP_BUILDCONF'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +68,6 @@ trait unix
|
|||||||
public function configureForUnix(TargetPackage $package, PackageInstaller $installer): void
|
public function configureForUnix(TargetPackage $package, PackageInstaller $installer): void
|
||||||
{
|
{
|
||||||
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('./configure'));
|
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('./configure'));
|
||||||
V2CompatLayer::emitPatchPoint('before-php-configure');
|
|
||||||
$cmd = getenv('SPC_CMD_PREFIX_PHP_CONFIGURE');
|
$cmd = getenv('SPC_CMD_PREFIX_PHP_CONFIGURE');
|
||||||
|
|
||||||
$args = [];
|
$args = [];
|
||||||
@@ -183,8 +180,6 @@ trait unix
|
|||||||
#[Stage]
|
#[Stage]
|
||||||
public function makeForUnix(TargetPackage $package, PackageInstaller $installer): void
|
public function makeForUnix(TargetPackage $package, PackageInstaller $installer): void
|
||||||
{
|
{
|
||||||
V2CompatLayer::emitPatchPoint('before-php-make');
|
|
||||||
|
|
||||||
logger()->info('cleaning up php-src build files');
|
logger()->info('cleaning up php-src build files');
|
||||||
shell()->cd($package->getSourceDir())->exec('make clean');
|
shell()->cd($package->getSourceDir())->exec('make clean');
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ use StaticPHP\Util\FileSystem;
|
|||||||
use StaticPHP\Util\InteractiveTerm;
|
use StaticPHP\Util\InteractiveTerm;
|
||||||
use StaticPHP\Util\SourcePatcher;
|
use StaticPHP\Util\SourcePatcher;
|
||||||
use StaticPHP\Util\System\WindowsUtil;
|
use StaticPHP\Util\System\WindowsUtil;
|
||||||
use StaticPHP\Util\V2CompatLayer;
|
|
||||||
use ZM\Logger\ConsoleColor;
|
use ZM\Logger\ConsoleColor;
|
||||||
|
|
||||||
trait windows
|
trait windows
|
||||||
@@ -38,7 +37,6 @@ trait windows
|
|||||||
public function buildconfForWindows(TargetPackage $package, PackageInstaller $installer): void
|
public function buildconfForWindows(TargetPackage $package, PackageInstaller $installer): void
|
||||||
{
|
{
|
||||||
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('./buildconf.bat'));
|
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('./buildconf.bat'));
|
||||||
V2CompatLayer::emitPatchPoint('before-php-buildconf');
|
|
||||||
cmd()->cd($package->getSourceDir())->exec('.\buildconf.bat');
|
cmd()->cd($package->getSourceDir())->exec('.\buildconf.bat');
|
||||||
|
|
||||||
if ($package->getBuildOption('enable-micro-win32') && $installer->isPackageResolved('php-micro')) {
|
if ($package->getBuildOption('enable-micro-win32') && $installer->isPackageResolved('php-micro')) {
|
||||||
@@ -52,7 +50,6 @@ trait windows
|
|||||||
public function configureForWindows(TargetPackage $package, PackageInstaller $installer): void
|
public function configureForWindows(TargetPackage $package, PackageInstaller $installer): void
|
||||||
{
|
{
|
||||||
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('./configure.bat'));
|
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('./configure.bat'));
|
||||||
V2CompatLayer::emitPatchPoint('before-php-configure');
|
|
||||||
$args = [
|
$args = [
|
||||||
'--disable-all',
|
'--disable-all',
|
||||||
"--with-php-build={$package->getBuildRootPath()}",
|
"--with-php-build={$package->getBuildRootPath()}",
|
||||||
@@ -232,7 +229,6 @@ trait windows
|
|||||||
#[Stage]
|
#[Stage]
|
||||||
public function makeForWindows(TargetPackage $package, PackageInstaller $installer): void
|
public function makeForWindows(TargetPackage $package, PackageInstaller $installer): void
|
||||||
{
|
{
|
||||||
V2CompatLayer::emitPatchPoint('before-php-make');
|
|
||||||
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('nmake clean'));
|
InteractiveTerm::setMessage('Building php: ' . ConsoleColor::yellow('nmake clean'));
|
||||||
cmd()->cd($package->getSourceDir())->exec('nmake clean');
|
cmd()->cd($package->getSourceDir())->exec('nmake clean');
|
||||||
|
|
||||||
|
|||||||
95
src/StaticPHP/Command/Dev/GenDepsDataCommand.php
Normal file
95
src/StaticPHP/Command/Dev/GenDepsDataCommand.php
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace StaticPHP\Command\Dev;
|
||||||
|
|
||||||
|
use StaticPHP\Command\BaseCommand;
|
||||||
|
use StaticPHP\Config\PackageConfig;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
|
||||||
|
#[AsCommand('dev:gen-deps-data', 'Generate package dependency data JSON for documentation', [], true)]
|
||||||
|
class GenDepsDataCommand extends BaseCommand
|
||||||
|
{
|
||||||
|
private const PLATFORMS = ['linux', 'macos', 'windows'];
|
||||||
|
|
||||||
|
protected bool $no_motd = true;
|
||||||
|
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
if (!spc_mode(SPC_MODE_SOURCE)) {
|
||||||
|
$this->output->writeln('<error>This command is only available in source mode.</error>');
|
||||||
|
return static::USER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
$all = PackageConfig::getAll();
|
||||||
|
$packages = [];
|
||||||
|
|
||||||
|
foreach ($all as $pkg_name => $config) {
|
||||||
|
$type = $config['type'] ?? 'unknown';
|
||||||
|
|
||||||
|
// Build platform-specific dep/suggest data
|
||||||
|
$platforms = [];
|
||||||
|
foreach (self::PLATFORMS as $platform) {
|
||||||
|
$platforms[$platform] = [
|
||||||
|
'depends' => $this->resolvePlatformList($config, 'depends', $platform),
|
||||||
|
'suggests' => $this->resolvePlatformList($config, 'suggests', $platform),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry = [
|
||||||
|
'type' => $type,
|
||||||
|
'platforms' => $platforms,
|
||||||
|
];
|
||||||
|
|
||||||
|
// For php-extension, add OS support info
|
||||||
|
if ($type === 'php-extension') {
|
||||||
|
$os_list = $config['php-extension']['os'] ?? null;
|
||||||
|
if ($os_list !== null) {
|
||||||
|
$entry['os'] = $os_list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$packages[$pkg_name] = $entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by type then name for readability
|
||||||
|
uksort($packages, function ($a, $b) use ($packages) {
|
||||||
|
$ta = $packages[$a]['type'];
|
||||||
|
$tb = $packages[$b]['type'];
|
||||||
|
if ($ta !== $tb) {
|
||||||
|
return strcmp($ta, $tb);
|
||||||
|
}
|
||||||
|
return strcmp($a, $b);
|
||||||
|
});
|
||||||
|
|
||||||
|
$output_data = [
|
||||||
|
'generated_at' => date('c'),
|
||||||
|
'packages' => $packages,
|
||||||
|
];
|
||||||
|
|
||||||
|
$output_path = ROOT_DIR . '/docs/.vitepress/deps-data.json';
|
||||||
|
file_put_contents($output_path, json_encode($output_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL);
|
||||||
|
|
||||||
|
$this->output->writeln('<info>Generated ' . $output_path . ' with ' . count($packages) . ' packages.</info>');
|
||||||
|
return static::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the value of a platform-specific array field, applying the suffix fallback chain.
|
||||||
|
*
|
||||||
|
* Fallback rules (same as PackageConfig::get):
|
||||||
|
* linux : @linux → @unix → (base)
|
||||||
|
* macos : @macos → @unix → (base)
|
||||||
|
* windows : @windows → (base)
|
||||||
|
*/
|
||||||
|
private function resolvePlatformList(array $config, string $field, string $platform): array
|
||||||
|
{
|
||||||
|
return match ($platform) {
|
||||||
|
'linux' => $config["{$field}@linux"] ?? $config["{$field}@unix"] ?? $config[$field] ?? [],
|
||||||
|
'macos' => $config["{$field}@macos"] ?? $config["{$field}@unix"] ?? $config[$field] ?? [],
|
||||||
|
'windows' => $config["{$field}@windows"] ?? $config[$field] ?? [],
|
||||||
|
default => $config[$field] ?? [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
87
src/StaticPHP/Command/Dev/GenExtDocsCommand.php
Normal file
87
src/StaticPHP/Command/Dev/GenExtDocsCommand.php
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace StaticPHP\Command\Dev;
|
||||||
|
|
||||||
|
use StaticPHP\Command\BaseCommand;
|
||||||
|
use StaticPHP\Config\PackageConfig;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
|
||||||
|
#[AsCommand('dev:gen-ext-docs', 'Generate extension list JSON for documentation', [], true)]
|
||||||
|
class GenExtDocsCommand extends BaseCommand
|
||||||
|
{
|
||||||
|
protected bool $no_motd = true;
|
||||||
|
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
if (!spc_mode(SPC_MODE_SOURCE)) {
|
||||||
|
$this->output->writeln('<error>This command is only available in source mode.</error>');
|
||||||
|
return static::USER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
$all = PackageConfig::getAll();
|
||||||
|
$extensions = [];
|
||||||
|
|
||||||
|
foreach ($all as $pkg_name => $config) {
|
||||||
|
if (($config['type'] ?? '') !== 'php-extension') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip ext- prefix for display name
|
||||||
|
$name = str_starts_with($pkg_name, 'ext-') ? substr($pkg_name, 4) : $pkg_name;
|
||||||
|
|
||||||
|
// Determine OS support from php-extension.os field.
|
||||||
|
// If the field is absent, the extension supports all three OSes.
|
||||||
|
$os_list = $config['php-extension']['os'] ?? null;
|
||||||
|
if ($os_list === null) {
|
||||||
|
$linux = true;
|
||||||
|
$macos = true;
|
||||||
|
$windows = true;
|
||||||
|
} else {
|
||||||
|
$linux = in_array('Linux', $os_list, true);
|
||||||
|
$macos = in_array('Darwin', $os_list, true);
|
||||||
|
$windows = in_array('Windows', $os_list, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$extensions[] = [
|
||||||
|
'name' => $name,
|
||||||
|
'linux' => $linux,
|
||||||
|
'macos' => $macos,
|
||||||
|
'windows' => $windows,
|
||||||
|
'url' => $this->resolveSourceUrl($config, $name),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort alphabetically by name
|
||||||
|
usort($extensions, fn ($a, $b) => strcmp($a['name'], $b['name']));
|
||||||
|
|
||||||
|
$output = [
|
||||||
|
'generated_at' => date('c'),
|
||||||
|
'extensions' => $extensions,
|
||||||
|
];
|
||||||
|
|
||||||
|
$output_path = ROOT_DIR . '/docs/.vitepress/ext-data.json';
|
||||||
|
file_put_contents($output_path, json_encode($output, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL);
|
||||||
|
|
||||||
|
$this->output->writeln("<info>Generated {$output_path} with " . count($extensions) . ' extensions.</info>');
|
||||||
|
return static::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveSourceUrl(array $config, string $ext_name): ?string
|
||||||
|
{
|
||||||
|
$source = $config['artifact']['source'] ?? null;
|
||||||
|
if ($source === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return match ($source['type'] ?? '') {
|
||||||
|
'pecl' => 'https://pecl.php.net/package/' . ($source['name'] ?? $ext_name),
|
||||||
|
'git' => rtrim($source['url'] ?? '', '/'),
|
||||||
|
'ghtar', 'ghrel', 'ghtagtar', 'pie' => isset($source['repo'])
|
||||||
|
? 'https://github.com/' . $source['repo']
|
||||||
|
: null,
|
||||||
|
default => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ class SPCConfigCommand extends BaseCommand
|
|||||||
{
|
{
|
||||||
$this->addArgument('extensions', InputArgument::OPTIONAL, 'The extensions will be compiled, comma separated');
|
$this->addArgument('extensions', InputArgument::OPTIONAL, 'The extensions will be compiled, comma separated');
|
||||||
$this->addOption('with-libs', null, InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', '');
|
$this->addOption('with-libs', null, InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', '');
|
||||||
$this->addOption('with-packages', null, InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', '');
|
$this->addOption('with-packages', 'p', InputOption::VALUE_REQUIRED, 'add additional libraries, comma separated', '');
|
||||||
$this->addOption('with-suggested-libs', 'L', null, 'Build with suggested libs for selected exts and libs');
|
$this->addOption('with-suggested-libs', 'L', null, 'Build with suggested libs for selected exts and libs');
|
||||||
$this->addOption('with-suggests', null, null, 'Build with suggested packages for selected exts and libs');
|
$this->addOption('with-suggests', null, null, 'Build with suggested packages for selected exts and libs');
|
||||||
$this->addOption('with-suggested-exts', 'E', null, 'Build with suggested extensions for selected exts');
|
$this->addOption('with-suggested-exts', 'E', null, 'Build with suggested extensions for selected exts');
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ use StaticPHP\Command\CraftCommand;
|
|||||||
use StaticPHP\Command\Dev\DumpCapabilitiesCommand;
|
use StaticPHP\Command\Dev\DumpCapabilitiesCommand;
|
||||||
use StaticPHP\Command\Dev\DumpStagesCommand;
|
use StaticPHP\Command\Dev\DumpStagesCommand;
|
||||||
use StaticPHP\Command\Dev\EnvCommand;
|
use StaticPHP\Command\Dev\EnvCommand;
|
||||||
|
use StaticPHP\Command\Dev\GenDepsDataCommand;
|
||||||
|
use StaticPHP\Command\Dev\GenExtDocsCommand;
|
||||||
use StaticPHP\Command\Dev\IsInstalledCommand;
|
use StaticPHP\Command\Dev\IsInstalledCommand;
|
||||||
use StaticPHP\Command\Dev\LintConfigCommand;
|
use StaticPHP\Command\Dev\LintConfigCommand;
|
||||||
use StaticPHP\Command\Dev\PackageInfoCommand;
|
use StaticPHP\Command\Dev\PackageInfoCommand;
|
||||||
@@ -81,6 +83,8 @@ class ConsoleApplication extends Application
|
|||||||
new DumpStagesCommand(),
|
new DumpStagesCommand(),
|
||||||
new DumpCapabilitiesCommand(),
|
new DumpCapabilitiesCommand(),
|
||||||
new PackageInfoCommand(),
|
new PackageInfoCommand(),
|
||||||
|
new GenExtDocsCommand(),
|
||||||
|
new GenDepsDataCommand(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// add additional commands from registries
|
// add additional commands from registries
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ class PackageInstaller
|
|||||||
ApplicationContext::set(PackageInstaller::class, $this);
|
ApplicationContext::set(PackageInstaller::class, $this);
|
||||||
$builder = new PackageBuilder($options);
|
$builder = new PackageBuilder($options);
|
||||||
ApplicationContext::set(PackageBuilder::class, $builder);
|
ApplicationContext::set(PackageBuilder::class, $builder);
|
||||||
ApplicationContext::set('patch_point', '');
|
|
||||||
|
|
||||||
// Check for no-download option
|
// Check for no-download option
|
||||||
if (!empty($options['no-download'])) {
|
if (!empty($options['no-download'])) {
|
||||||
|
|||||||
@@ -5,11 +5,6 @@ declare(strict_types=1);
|
|||||||
namespace StaticPHP\Util;
|
namespace StaticPHP\Util;
|
||||||
|
|
||||||
use StaticPHP\Artifact\Artifact;
|
use StaticPHP\Artifact\Artifact;
|
||||||
use StaticPHP\DI\ApplicationContext;
|
|
||||||
use StaticPHP\Exception\InterruptException;
|
|
||||||
use StaticPHP\Exception\WrongUsageException;
|
|
||||||
use StaticPHP\Package\PackageBuilder;
|
|
||||||
use StaticPHP\Package\PackageInstaller;
|
|
||||||
use StaticPHP\Package\TargetPackage;
|
use StaticPHP\Package\TargetPackage;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
@@ -70,71 +65,15 @@ class V2CompatLayer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function beforeExtractHook(Artifact $artifact): void
|
public static function beforeExtractHook(Artifact $artifact): void {}
|
||||||
{
|
|
||||||
self::emitPatchPoint(match ($artifact->getName()) {
|
|
||||||
'php-src' => 'before-php-extract',
|
|
||||||
'micro' => 'before-micro-extract',
|
|
||||||
default => '',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function afterExtractHook(Artifact $artifact): void
|
public static function afterExtractHook(Artifact $artifact): void {}
|
||||||
{
|
|
||||||
self::emitPatchPoint(match ($artifact->getName()) {
|
|
||||||
'php-src' => 'after-php-extract',
|
|
||||||
'micro' => 'after-micro-extract',
|
|
||||||
default => '',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function beforeExtsExtractHook(): void
|
public static function beforeExtsExtractHook(): void {}
|
||||||
{
|
|
||||||
self::emitPatchPoint('before-exts-extract');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function afterExtsExtractHook(): void
|
public static function afterExtsExtractHook(): void {}
|
||||||
{
|
|
||||||
self::emitPatchPoint('after-exts-extract');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function beforeLibExtractHook(string $pkg): void
|
public static function beforeLibExtractHook(string $pkg): void {}
|
||||||
{
|
|
||||||
self::emitPatchPoint("before-library[{$pkg}]-extract");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function afterLibExtractHook(string $pkg): void
|
public static function afterLibExtractHook(string $pkg): void {}
|
||||||
{
|
|
||||||
self::emitPatchPoint("after-library[{$pkg}]-extract");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function emitPatchPoint(string $point_name): void
|
|
||||||
{
|
|
||||||
if ($point_name === '') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!ApplicationContext::has(PackageInstaller::class)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$builder = ApplicationContext::get(PackageBuilder::class);
|
|
||||||
$patch_points = $builder->getOption('with-added-patch', []);
|
|
||||||
ApplicationContext::set('patch_point', $point_name);
|
|
||||||
foreach ($patch_points as $patch_point) {
|
|
||||||
if (!file_exists($patch_point)) {
|
|
||||||
throw new WrongUsageException("Additional patch script {$patch_point} does not exist!");
|
|
||||||
}
|
|
||||||
logger()->debug("Applying additional patch script {$patch_point}");
|
|
||||||
|
|
||||||
try {
|
|
||||||
require $patch_point;
|
|
||||||
} catch (InterruptException $e) {
|
|
||||||
if ($e->getCode() === 0) {
|
|
||||||
logger()->notice('Patch script ' . $patch_point . ' interrupted' . ($e->getMessage() ? (': ' . $e->getMessage()) : '.'));
|
|
||||||
} else {
|
|
||||||
logger()->error('Patch script ' . $patch_point . ' interrupted with error code [' . $e->getCode() . ']' . ($e->getMessage() ? (': ' . $e->getMessage()) : '.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ApplicationContext::set('patch_point', '');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use StaticPHP\Exception\ExecutionException;
|
use StaticPHP\Exception\ExecutionException;
|
||||||
use StaticPHP\Exception\InterruptException;
|
|
||||||
use StaticPHP\Exception\WrongUsageException;
|
use StaticPHP\Exception\WrongUsageException;
|
||||||
use StaticPHP\Runtime\Shell\DefaultShell;
|
use StaticPHP\Runtime\Shell\DefaultShell;
|
||||||
use StaticPHP\Runtime\Shell\UnixShell;
|
use StaticPHP\Runtime\Shell\UnixShell;
|
||||||
@@ -120,18 +119,6 @@ function cmd(?bool $debug = null): WindowsCmd
|
|||||||
return new WindowsCmd($debug);
|
return new WindowsCmd($debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get current patch point.
|
|
||||||
*/
|
|
||||||
function patch_point(): string
|
|
||||||
{
|
|
||||||
if (StaticPHP\DI\ApplicationContext::has('patch_point')) {
|
|
||||||
/* @phpstan-ignore-next-line */
|
|
||||||
return StaticPHP\DI\ApplicationContext::get('patch_point');
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add log filter value(s) to prevent secret leak
|
// Add log filter value(s) to prevent secret leak
|
||||||
function spc_add_log_filter(array|string $filter): void
|
function spc_add_log_filter(array|string $filter): void
|
||||||
{
|
{
|
||||||
@@ -158,11 +145,6 @@ function spc_write_log(mixed $stream, string $data): false|int
|
|||||||
return fwrite($stream, $data);
|
return fwrite($stream, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function patch_point_interrupt(int $retcode, string $msg = ''): InterruptException
|
|
||||||
{
|
|
||||||
return new InterruptException(message: $msg, code: $retcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------- function f_* part -------
|
// ------- function f_* part -------
|
||||||
// f_ means standard function wrapper
|
// f_ means standard function wrapper
|
||||||
|
|
||||||
|
|||||||
459
yarn.lock
459
yarn.lock
@@ -4,24 +4,24 @@
|
|||||||
|
|
||||||
"@babel/helper-string-parser@^7.27.1":
|
"@babel/helper-string-parser@^7.27.1":
|
||||||
version "7.27.1"
|
version "7.27.1"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687"
|
resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz"
|
||||||
integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==
|
integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==
|
||||||
|
|
||||||
"@babel/helper-validator-identifier@^7.27.1":
|
"@babel/helper-validator-identifier@^7.27.1":
|
||||||
version "7.27.1"
|
version "7.27.1"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8"
|
resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz"
|
||||||
integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==
|
integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==
|
||||||
|
|
||||||
"@babel/parser@^7.28.3":
|
"@babel/parser@^7.28.3":
|
||||||
version "7.28.3"
|
version "7.28.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.3.tgz#d2d25b814621bca5fe9d172bc93792547e7a2a71"
|
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz"
|
||||||
integrity sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==
|
integrity sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.28.2"
|
"@babel/types" "^7.28.2"
|
||||||
|
|
||||||
"@babel/types@^7.28.2":
|
"@babel/types@^7.28.2":
|
||||||
version "7.28.2"
|
version "7.28.2"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.2.tgz#da9db0856a9a88e0a13b019881d7513588cf712b"
|
resolved "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz"
|
||||||
integrity sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==
|
integrity sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-string-parser" "^7.27.1"
|
"@babel/helper-string-parser" "^7.27.1"
|
||||||
@@ -29,269 +29,49 @@
|
|||||||
|
|
||||||
"@docsearch/css@^4.0.0-beta.7":
|
"@docsearch/css@^4.0.0-beta.7":
|
||||||
version "4.0.0-beta.8"
|
version "4.0.0-beta.8"
|
||||||
resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.0.0-beta.8.tgz#836ac7c3eeecf87cfc9c518210f4dfd27e49b05f"
|
resolved "https://registry.npmjs.org/@docsearch/css/-/css-4.0.0-beta.8.tgz"
|
||||||
integrity sha512-/ZlyvZCjIJM4aaOYoJpVNHPJckX7J5KIbt6IWjnZXvo0QAUI1aH976vKEJUC9olgUbE3LWafB8yuX4qoqahIQg==
|
integrity sha512-/ZlyvZCjIJM4aaOYoJpVNHPJckX7J5KIbt6IWjnZXvo0QAUI1aH976vKEJUC9olgUbE3LWafB8yuX4qoqahIQg==
|
||||||
|
|
||||||
"@docsearch/js@^4.0.0-beta.7":
|
"@docsearch/js@^4.0.0-beta.7":
|
||||||
version "4.0.0-beta.8"
|
version "4.0.0-beta.8"
|
||||||
resolved "https://registry.yarnpkg.com/@docsearch/js/-/js-4.0.0-beta.8.tgz#eca030c793fad34487c0c1c9147112544edb02bc"
|
resolved "https://registry.npmjs.org/@docsearch/js/-/js-4.0.0-beta.8.tgz"
|
||||||
integrity sha512-elgqPYpykRQr5MlfqoO8U2uC3BcPgjUQhzmHt/H4lSzP7khJ9Jpv/cCB4tiZreXb6GkdRgWr5csiItNq6jjnhg==
|
integrity sha512-elgqPYpykRQr5MlfqoO8U2uC3BcPgjUQhzmHt/H4lSzP7khJ9Jpv/cCB4tiZreXb6GkdRgWr5csiItNq6jjnhg==
|
||||||
|
|
||||||
"@esbuild/aix-ppc64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz#bef96351f16520055c947aba28802eede3c9e9a9"
|
|
||||||
integrity sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==
|
|
||||||
|
|
||||||
"@esbuild/android-arm64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz#d2e70be7d51a529425422091e0dcb90374c1546c"
|
|
||||||
integrity sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==
|
|
||||||
|
|
||||||
"@esbuild/android-arm@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.9.tgz#d2a753fe2a4c73b79437d0ba1480e2d760097419"
|
|
||||||
integrity sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==
|
|
||||||
|
|
||||||
"@esbuild/android-x64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.9.tgz#5278836e3c7ae75761626962f902a0d55352e683"
|
|
||||||
integrity sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==
|
|
||||||
|
|
||||||
"@esbuild/darwin-arm64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz#f1513eaf9ec8fa15dcaf4c341b0f005d3e8b47ae"
|
|
||||||
integrity sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==
|
|
||||||
|
|
||||||
"@esbuild/darwin-x64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz#e27dbc3b507b3a1cea3b9280a04b8b6b725f82be"
|
|
||||||
integrity sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==
|
|
||||||
|
|
||||||
"@esbuild/freebsd-arm64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz#364e3e5b7a1fd45d92be08c6cc5d890ca75908ca"
|
|
||||||
integrity sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==
|
|
||||||
|
|
||||||
"@esbuild/freebsd-x64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz#7c869b45faeb3df668e19ace07335a0711ec56ab"
|
|
||||||
integrity sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==
|
|
||||||
|
|
||||||
"@esbuild/linux-arm64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz#48d42861758c940b61abea43ba9a29b186d6cb8b"
|
|
||||||
integrity sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==
|
|
||||||
|
|
||||||
"@esbuild/linux-arm@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz#6ce4b9cabf148274101701d112b89dc67cc52f37"
|
|
||||||
integrity sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==
|
|
||||||
|
|
||||||
"@esbuild/linux-ia32@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz#207e54899b79cac9c26c323fc1caa32e3143f1c4"
|
|
||||||
integrity sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==
|
|
||||||
|
|
||||||
"@esbuild/linux-loong64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz#0ba48a127159a8f6abb5827f21198b999ffd1fc0"
|
|
||||||
integrity sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==
|
|
||||||
|
|
||||||
"@esbuild/linux-mips64el@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz#a4d4cc693d185f66a6afde94f772b38ce5d64eb5"
|
|
||||||
integrity sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==
|
|
||||||
|
|
||||||
"@esbuild/linux-ppc64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz#0f5805c1c6d6435a1dafdc043cb07a19050357db"
|
|
||||||
integrity sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==
|
|
||||||
|
|
||||||
"@esbuild/linux-riscv64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz#6776edece0f8fca79f3386398b5183ff2a827547"
|
|
||||||
integrity sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==
|
|
||||||
|
|
||||||
"@esbuild/linux-s390x@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz#3f6f29ef036938447c2218d309dc875225861830"
|
|
||||||
integrity sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==
|
|
||||||
|
|
||||||
"@esbuild/linux-x64@0.25.9":
|
"@esbuild/linux-x64@0.25.9":
|
||||||
version "0.25.9"
|
version "0.25.9"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz#831fe0b0e1a80a8b8391224ea2377d5520e1527f"
|
resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz"
|
||||||
integrity sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==
|
integrity sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==
|
||||||
|
|
||||||
"@esbuild/netbsd-arm64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz#06f99d7eebe035fbbe43de01c9d7e98d2a0aa548"
|
|
||||||
integrity sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==
|
|
||||||
|
|
||||||
"@esbuild/netbsd-x64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz#db99858e6bed6e73911f92a88e4edd3a8c429a52"
|
|
||||||
integrity sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==
|
|
||||||
|
|
||||||
"@esbuild/openbsd-arm64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz#afb886c867e36f9d86bb21e878e1185f5d5a0935"
|
|
||||||
integrity sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==
|
|
||||||
|
|
||||||
"@esbuild/openbsd-x64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz#30855c9f8381fac6a0ef5b5f31ac6e7108a66ecf"
|
|
||||||
integrity sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==
|
|
||||||
|
|
||||||
"@esbuild/openharmony-arm64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz#2f2144af31e67adc2a8e3705c20c2bd97bd88314"
|
|
||||||
integrity sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==
|
|
||||||
|
|
||||||
"@esbuild/sunos-x64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz#69b99a9b5bd226c9eb9c6a73f990fddd497d732e"
|
|
||||||
integrity sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==
|
|
||||||
|
|
||||||
"@esbuild/win32-arm64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz#d789330a712af916c88325f4ffe465f885719c6b"
|
|
||||||
integrity sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==
|
|
||||||
|
|
||||||
"@esbuild/win32-ia32@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz#52fc735406bd49688253e74e4e837ac2ba0789e3"
|
|
||||||
integrity sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==
|
|
||||||
|
|
||||||
"@esbuild/win32-x64@0.25.9":
|
|
||||||
version "0.25.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz#585624dc829cfb6e7c0aa6c3ca7d7e6daa87e34f"
|
|
||||||
integrity sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==
|
|
||||||
|
|
||||||
"@iconify-json/simple-icons@^1.2.47":
|
"@iconify-json/simple-icons@^1.2.47":
|
||||||
version "1.2.49"
|
version "1.2.49"
|
||||||
resolved "https://registry.yarnpkg.com/@iconify-json/simple-icons/-/simple-icons-1.2.49.tgz#2465a3d7e24d32b57dd3ce873914417af6e6dbea"
|
resolved "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.49.tgz"
|
||||||
integrity sha512-nRLwrHzz+cTAQYBNQrcr4eWOmQIcHObTj/QSi7nj0SFwVh5MvBsgx8OhoDC/R8iGklNmMpmoE/NKU0cPXMlOZw==
|
integrity sha512-nRLwrHzz+cTAQYBNQrcr4eWOmQIcHObTj/QSi7nj0SFwVh5MvBsgx8OhoDC/R8iGklNmMpmoE/NKU0cPXMlOZw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@iconify/types" "*"
|
"@iconify/types" "*"
|
||||||
|
|
||||||
"@iconify/types@*":
|
"@iconify/types@*":
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57"
|
resolved "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz"
|
||||||
integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==
|
integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==
|
||||||
|
|
||||||
"@jridgewell/sourcemap-codec@^1.5.5":
|
"@jridgewell/sourcemap-codec@^1.5.5":
|
||||||
version "1.5.5"
|
version "1.5.5"
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba"
|
resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz"
|
||||||
integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==
|
integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==
|
||||||
|
|
||||||
"@rolldown/pluginutils@1.0.0-beta.29":
|
"@rolldown/pluginutils@1.0.0-beta.29":
|
||||||
version "1.0.0-beta.29"
|
version "1.0.0-beta.29"
|
||||||
resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz#f8fc9a8788757dccba0d3b7fee93183621773d4c"
|
resolved "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz"
|
||||||
integrity sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==
|
integrity sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==
|
||||||
|
|
||||||
"@rollup/rollup-android-arm-eabi@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.49.0.tgz#ba432433f5e7b419dba2be407d1d59fea6b8de48"
|
|
||||||
integrity sha512-rlKIeL854Ed0e09QGYFlmDNbka6I3EQFw7iZuugQjMb11KMpJCLPFL4ZPbMfaEhLADEL1yx0oujGkBQ7+qW3eA==
|
|
||||||
|
|
||||||
"@rollup/rollup-android-arm64@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.49.0.tgz#4e05c86e0fb9af6eaf52fc298dcdec577477e35c"
|
|
||||||
integrity sha512-cqPpZdKUSQYRtLLr6R4X3sD4jCBO1zUmeo3qrWBCqYIeH8Q3KRL4F3V7XJ2Rm8/RJOQBZuqzQGWPjjvFUcYa/w==
|
|
||||||
|
|
||||||
"@rollup/rollup-darwin-arm64@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.49.0.tgz#788fad425b4129875639e0c14b6441c5f3b69d46"
|
|
||||||
integrity sha512-99kMMSMQT7got6iYX3yyIiJfFndpojBmkHfTc1rIje8VbjhmqBXE+nb7ZZP3A5skLyujvT0eIUCUsxAe6NjWbw==
|
|
||||||
|
|
||||||
"@rollup/rollup-darwin-x64@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.49.0.tgz#d44e05bee55b781d7c2cf535d9f9169787c3599d"
|
|
||||||
integrity sha512-y8cXoD3wdWUDpjOLMKLx6l+NFz3NlkWKcBCBfttUn+VGSfgsQ5o/yDUGtzE9HvsodkP0+16N0P4Ty1VuhtRUGg==
|
|
||||||
|
|
||||||
"@rollup/rollup-freebsd-arm64@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.49.0.tgz#107786b4d604495224c3543bfd2cae33ddf76500"
|
|
||||||
integrity sha512-3mY5Pr7qv4GS4ZvWoSP8zha8YoiqrU+e0ViPvB549jvliBbdNLrg2ywPGkgLC3cmvN8ya3za+Q2xVyT6z+vZqA==
|
|
||||||
|
|
||||||
"@rollup/rollup-freebsd-x64@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.49.0.tgz#54e105c3da27f31084ca6913fed603627755abde"
|
|
||||||
integrity sha512-C9KzzOAQU5gU4kG8DTk+tjdKjpWhVWd5uVkinCwwFub2m7cDYLOdtXoMrExfeBmeRy9kBQMkiyJ+HULyF1yj9w==
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm-gnueabihf@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.49.0.tgz#725c23e0766b5d9368180bc2c427a51e31d0e147"
|
|
||||||
integrity sha512-OVSQgEZDVLnTbMq5NBs6xkmz3AADByCWI4RdKSFNlDsYXdFtlxS59J+w+LippJe8KcmeSSM3ba+GlsM9+WwC1w==
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm-musleabihf@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.49.0.tgz#6946b0d2f132f2baf5657945b81565d8abd51cc0"
|
|
||||||
integrity sha512-ZnfSFA7fDUHNa4P3VwAcfaBLakCbYaxCk0jUnS3dTou9P95kwoOLAMlT3WmEJDBCSrOEFFV0Y1HXiwfLYJuLlA==
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm64-gnu@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.49.0.tgz#83510a6d03e748619241a17f5a879418a963c5ed"
|
|
||||||
integrity sha512-Z81u+gfrobVK2iV7GqZCBfEB1y6+I61AH466lNK+xy1jfqFLiQ9Qv716WUM5fxFrYxwC7ziVdZRU9qvGHkYIJg==
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm64-musl@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.49.0.tgz#085b98d44c10908626dd40f26bf924433bbd8471"
|
|
||||||
integrity sha512-zoAwS0KCXSnTp9NH/h9aamBAIve0DXeYpll85shf9NJ0URjSTzzS+Z9evmolN+ICfD3v8skKUPyk2PO0uGdFqg==
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-loongarch64-gnu@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.49.0.tgz#13e0a4808e9f7924f2cc8c133603f627c7a00543"
|
|
||||||
integrity sha512-2QyUyQQ1ZtwZGiq0nvODL+vLJBtciItC3/5cYN8ncDQcv5avrt2MbKt1XU/vFAJlLta5KujqyHdYtdag4YEjYQ==
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-ppc64-gnu@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.49.0.tgz#aeee4e47fc9ca5d6687e686fea4696202af6b2f4"
|
|
||||||
integrity sha512-k9aEmOWt+mrMuD3skjVJSSxHckJp+SiFzFG+v8JLXbc/xi9hv2icSkR3U7uQzqy+/QbbYY7iNB9eDTwrELo14g==
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-riscv64-gnu@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.49.0.tgz#603e4591643f1d7851a96d096cf7fcd273f7b0e1"
|
|
||||||
integrity sha512-rDKRFFIWJ/zJn6uk2IdYLc09Z7zkE5IFIOWqpuU0o6ZpHcdniAyWkwSUWE/Z25N/wNDmFHHMzin84qW7Wzkjsw==
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-riscv64-musl@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.49.0.tgz#f8fd9b01f1888e1816d5a398789d430511286c00"
|
|
||||||
integrity sha512-FkkhIY/hYFVnOzz1WeV3S9Bd1h0hda/gRqvZCMpHWDHdiIHn6pqsY3b5eSbvGccWHMQ1uUzgZTKS4oGpykf8Tw==
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-s390x-gnu@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.49.0.tgz#37a1fd372d9b93d2b75b2f37c482ecf52f52849b"
|
|
||||||
integrity sha512-gRf5c+A7QiOG3UwLyOOtyJMD31JJhMjBvpfhAitPAoqZFcOeK3Kc1Veg1z/trmt+2P6F/biT02fU19GGTS529A==
|
|
||||||
|
|
||||||
"@rollup/rollup-linux-x64-gnu@4.49.0":
|
"@rollup/rollup-linux-x64-gnu@4.49.0":
|
||||||
version "4.49.0"
|
version "4.49.0"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.49.0.tgz#131e66dbf7e71cb2a389acc45319bd4c990e093a"
|
resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.49.0.tgz"
|
||||||
integrity sha512-BR7+blScdLW1h/2hB/2oXM+dhTmpW3rQt1DeSiCP9mc2NMMkqVgjIN3DDsNpKmezffGC9R8XKVOLmBkRUcK/sA==
|
integrity sha512-BR7+blScdLW1h/2hB/2oXM+dhTmpW3rQt1DeSiCP9mc2NMMkqVgjIN3DDsNpKmezffGC9R8XKVOLmBkRUcK/sA==
|
||||||
|
|
||||||
"@rollup/rollup-linux-x64-musl@4.49.0":
|
"@shikijs/core@^3.9.2", "@shikijs/core@3.12.0":
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.49.0.tgz#b7245a5ea57db9679e8bf3032c25a5d2c5f54056"
|
|
||||||
integrity sha512-hDMOAe+6nX3V5ei1I7Au3wcr9h3ktKzDvF2ne5ovX8RZiAHEtX1A5SNNk4zt1Qt77CmnbqT+upb/umzoPMWiPg==
|
|
||||||
|
|
||||||
"@rollup/rollup-win32-arm64-msvc@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.49.0.tgz#768a128bb5da3c5472c3c56aec77507d28bc7209"
|
|
||||||
integrity sha512-wkNRzfiIGaElC9kXUT+HLx17z7D0jl+9tGYRKwd8r7cUqTL7GYAvgUY++U2hK6Ar7z5Z6IRRoWC8kQxpmM7TDA==
|
|
||||||
|
|
||||||
"@rollup/rollup-win32-ia32-msvc@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.49.0.tgz#ce3f3b2eebe585340631498666718f00983a6a62"
|
|
||||||
integrity sha512-gq5aW/SyNpjp71AAzroH37DtINDcX1Qw2iv9Chyz49ZgdOP3NV8QCyKZUrGsYX9Yyggj5soFiRCgsL3HwD8TdA==
|
|
||||||
|
|
||||||
"@rollup/rollup-win32-x64-msvc@4.49.0":
|
|
||||||
version "4.49.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.49.0.tgz#c2a0e3b81262a7e9dd12ce18b350a97558dd50bc"
|
|
||||||
integrity sha512-gEtqFbzmZLFk2xKh7g0Rlo8xzho8KrEFEkzvHbfUGkrgXOpZ4XagQ6n+wIZFNh1nTb8UD16J4nFSFKXYgnbdBg==
|
|
||||||
|
|
||||||
"@shikijs/core@3.12.0", "@shikijs/core@^3.9.2":
|
|
||||||
version "3.12.0"
|
version "3.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-3.12.0.tgz#b193f7460c22bfdc2f4cd9b28fb2a88cb2a3c1f2"
|
resolved "https://registry.npmjs.org/@shikijs/core/-/core-3.12.0.tgz"
|
||||||
integrity sha512-rPfCBd6gHIKBPpf2hKKWn2ISPSrmRKAFi+bYDjvZHpzs3zlksWvEwaF3Z4jnvW+xHxSRef7qDooIJkY0RpA9EA==
|
integrity sha512-rPfCBd6gHIKBPpf2hKKWn2ISPSrmRKAFi+bYDjvZHpzs3zlksWvEwaF3Z4jnvW+xHxSRef7qDooIJkY0RpA9EA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@shikijs/types" "3.12.0"
|
"@shikijs/types" "3.12.0"
|
||||||
@@ -301,7 +81,7 @@
|
|||||||
|
|
||||||
"@shikijs/engine-javascript@3.12.0":
|
"@shikijs/engine-javascript@3.12.0":
|
||||||
version "3.12.0"
|
version "3.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-3.12.0.tgz#a66b13dbde02cafe32dba95b0e0c4c758bd2779d"
|
resolved "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.12.0.tgz"
|
||||||
integrity sha512-Ni3nm4lnKxyKaDoXQQJYEayX052BL7D0ikU5laHp+ynxPpIF1WIwyhzrMU6WDN7AoAfggVR4Xqx3WN+JTS+BvA==
|
integrity sha512-Ni3nm4lnKxyKaDoXQQJYEayX052BL7D0ikU5laHp+ynxPpIF1WIwyhzrMU6WDN7AoAfggVR4Xqx3WN+JTS+BvA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@shikijs/types" "3.12.0"
|
"@shikijs/types" "3.12.0"
|
||||||
@@ -310,7 +90,7 @@
|
|||||||
|
|
||||||
"@shikijs/engine-oniguruma@3.12.0":
|
"@shikijs/engine-oniguruma@3.12.0":
|
||||||
version "3.12.0"
|
version "3.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-3.12.0.tgz#060ca540c857fd7851a75d1280254392da96015b"
|
resolved "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.12.0.tgz"
|
||||||
integrity sha512-IfDl3oXPbJ/Jr2K8mLeQVpnF+FxjAc7ZPDkgr38uEw/Bg3u638neSrpwqOTnTHXt1aU0Fk1/J+/RBdst1kVqLg==
|
integrity sha512-IfDl3oXPbJ/Jr2K8mLeQVpnF+FxjAc7ZPDkgr38uEw/Bg3u638neSrpwqOTnTHXt1aU0Fk1/J+/RBdst1kVqLg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@shikijs/types" "3.12.0"
|
"@shikijs/types" "3.12.0"
|
||||||
@@ -318,29 +98,29 @@
|
|||||||
|
|
||||||
"@shikijs/langs@3.12.0":
|
"@shikijs/langs@3.12.0":
|
||||||
version "3.12.0"
|
version "3.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@shikijs/langs/-/langs-3.12.0.tgz#8c3c2035ee15a05566691f28eeb91084edd9ed75"
|
resolved "https://registry.npmjs.org/@shikijs/langs/-/langs-3.12.0.tgz"
|
||||||
integrity sha512-HIca0daEySJ8zuy9bdrtcBPhcYBo8wR1dyHk1vKrOuwDsITtZuQeGhEkcEfWc6IDyTcom7LRFCH6P7ljGSCEiQ==
|
integrity sha512-HIca0daEySJ8zuy9bdrtcBPhcYBo8wR1dyHk1vKrOuwDsITtZuQeGhEkcEfWc6IDyTcom7LRFCH6P7ljGSCEiQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@shikijs/types" "3.12.0"
|
"@shikijs/types" "3.12.0"
|
||||||
|
|
||||||
"@shikijs/themes@3.12.0":
|
"@shikijs/themes@3.12.0":
|
||||||
version "3.12.0"
|
version "3.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@shikijs/themes/-/themes-3.12.0.tgz#704f9bec156b25b873e42474c6dc8472ad96f246"
|
resolved "https://registry.npmjs.org/@shikijs/themes/-/themes-3.12.0.tgz"
|
||||||
integrity sha512-/lxvQxSI5s4qZLV/AuFaA4Wt61t/0Oka/P9Lmpr1UV+HydNCczO3DMHOC/CsXCCpbv4Zq8sMD0cDa7mvaVoj0Q==
|
integrity sha512-/lxvQxSI5s4qZLV/AuFaA4Wt61t/0Oka/P9Lmpr1UV+HydNCczO3DMHOC/CsXCCpbv4Zq8sMD0cDa7mvaVoj0Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@shikijs/types" "3.12.0"
|
"@shikijs/types" "3.12.0"
|
||||||
|
|
||||||
"@shikijs/transformers@^3.9.2":
|
"@shikijs/transformers@^3.9.2":
|
||||||
version "3.12.0"
|
version "3.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@shikijs/transformers/-/transformers-3.12.0.tgz#1f91f3c504f3d5110996690d58be72ec377a46e6"
|
resolved "https://registry.npmjs.org/@shikijs/transformers/-/transformers-3.12.0.tgz"
|
||||||
integrity sha512-HcJwlvMAyZzOY+ayEAGE891BdJ7Vtio+qdWUTF9ki4d0LIkDb6DBz8ynOWGAEglHv6eQs/WcAWf/h6ina6IgCw==
|
integrity sha512-HcJwlvMAyZzOY+ayEAGE891BdJ7Vtio+qdWUTF9ki4d0LIkDb6DBz8ynOWGAEglHv6eQs/WcAWf/h6ina6IgCw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@shikijs/core" "3.12.0"
|
"@shikijs/core" "3.12.0"
|
||||||
"@shikijs/types" "3.12.0"
|
"@shikijs/types" "3.12.0"
|
||||||
|
|
||||||
"@shikijs/types@3.12.0", "@shikijs/types@^3.9.2":
|
"@shikijs/types@^3.9.2", "@shikijs/types@3.12.0":
|
||||||
version "3.12.0"
|
version "3.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-3.12.0.tgz#3d5f30acb6a3e6a72a1089fa8ca4764fc9f61336"
|
resolved "https://registry.npmjs.org/@shikijs/types/-/types-3.12.0.tgz"
|
||||||
integrity sha512-jsFzm8hCeTINC3OCmTZdhR9DOl/foJWplH2Px0bTi4m8z59fnsueLsweX82oGcjRQ7mfQAluQYKGoH2VzsWY4A==
|
integrity sha512-jsFzm8hCeTINC3OCmTZdhR9DOl/foJWplH2Px0bTi4m8z59fnsueLsweX82oGcjRQ7mfQAluQYKGoH2VzsWY4A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@shikijs/vscode-textmate" "^10.0.2"
|
"@shikijs/vscode-textmate" "^10.0.2"
|
||||||
@@ -348,29 +128,29 @@
|
|||||||
|
|
||||||
"@shikijs/vscode-textmate@^10.0.2":
|
"@shikijs/vscode-textmate@^10.0.2":
|
||||||
version "10.0.2"
|
version "10.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz#a90ab31d0cc1dfb54c66a69e515bf624fa7b2224"
|
resolved "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz"
|
||||||
integrity sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==
|
integrity sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==
|
||||||
|
|
||||||
"@types/estree@1.0.8":
|
"@types/estree@1.0.8":
|
||||||
version "1.0.8"
|
version "1.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e"
|
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz"
|
||||||
integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==
|
integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==
|
||||||
|
|
||||||
"@types/hast@^3.0.0", "@types/hast@^3.0.4":
|
"@types/hast@^3.0.0", "@types/hast@^3.0.4":
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa"
|
resolved "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz"
|
||||||
integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==
|
integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/unist" "*"
|
"@types/unist" "*"
|
||||||
|
|
||||||
"@types/linkify-it@^5":
|
"@types/linkify-it@^5":
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-5.0.0.tgz#21413001973106cda1c3a9b91eedd4ccd5469d76"
|
resolved "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz"
|
||||||
integrity sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==
|
integrity sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==
|
||||||
|
|
||||||
"@types/markdown-it@^14.1.2":
|
"@types/markdown-it@^14.1.2":
|
||||||
version "14.1.2"
|
version "14.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-14.1.2.tgz#57f2532a0800067d9b934f3521429a2e8bfb4c61"
|
resolved "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz"
|
||||||
integrity sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==
|
integrity sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/linkify-it" "^5"
|
"@types/linkify-it" "^5"
|
||||||
@@ -378,41 +158,41 @@
|
|||||||
|
|
||||||
"@types/mdast@^4.0.0":
|
"@types/mdast@^4.0.0":
|
||||||
version "4.0.4"
|
version "4.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6"
|
resolved "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz"
|
||||||
integrity sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==
|
integrity sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/unist" "*"
|
"@types/unist" "*"
|
||||||
|
|
||||||
"@types/mdurl@^2":
|
"@types/mdurl@^2":
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-2.0.0.tgz#d43878b5b20222682163ae6f897b20447233bdfd"
|
resolved "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz"
|
||||||
integrity sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==
|
integrity sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==
|
||||||
|
|
||||||
"@types/unist@*", "@types/unist@^3.0.0":
|
"@types/unist@*", "@types/unist@^3.0.0":
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c"
|
resolved "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz"
|
||||||
integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==
|
integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==
|
||||||
|
|
||||||
"@types/web-bluetooth@^0.0.21":
|
"@types/web-bluetooth@^0.0.21":
|
||||||
version "0.0.21"
|
version "0.0.21"
|
||||||
resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz#525433c784aed9b457aaa0ee3d92aeb71f346b63"
|
resolved "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz"
|
||||||
integrity sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==
|
integrity sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==
|
||||||
|
|
||||||
"@ungap/structured-clone@^1.0.0":
|
"@ungap/structured-clone@^1.0.0":
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8"
|
resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz"
|
||||||
integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==
|
integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==
|
||||||
|
|
||||||
"@vitejs/plugin-vue@^6.0.1":
|
"@vitejs/plugin-vue@^6.0.1":
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz#4c7f559621af104a22255c6ace5626e6d8349689"
|
resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz"
|
||||||
integrity sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==
|
integrity sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@rolldown/pluginutils" "1.0.0-beta.29"
|
"@rolldown/pluginutils" "1.0.0-beta.29"
|
||||||
|
|
||||||
"@vue/compiler-core@3.5.20":
|
"@vue/compiler-core@3.5.20":
|
||||||
version "3.5.20"
|
version "3.5.20"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.20.tgz#ea100646460703c98117b88900aab4aa7e6f797e"
|
resolved "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.20.tgz"
|
||||||
integrity sha512-8TWXUyiqFd3GmP4JTX9hbiTFRwYHgVL/vr3cqhr4YQ258+9FADwvj7golk2sWNGHR67QgmCZ8gz80nQcMokhwg==
|
integrity sha512-8TWXUyiqFd3GmP4JTX9hbiTFRwYHgVL/vr3cqhr4YQ258+9FADwvj7golk2sWNGHR67QgmCZ8gz80nQcMokhwg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/parser" "^7.28.3"
|
"@babel/parser" "^7.28.3"
|
||||||
@@ -423,7 +203,7 @@
|
|||||||
|
|
||||||
"@vue/compiler-dom@3.5.20":
|
"@vue/compiler-dom@3.5.20":
|
||||||
version "3.5.20"
|
version "3.5.20"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.20.tgz#7eb0d4b761a48b93723cf264d27c1385b90dae6d"
|
resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.20.tgz"
|
||||||
integrity sha512-whB44M59XKjqUEYOMPYU0ijUV0G+4fdrHVKDe32abNdX/kJe1NUEMqsi4cwzXa9kyM9w5S8WqFsrfo1ogtBZGQ==
|
integrity sha512-whB44M59XKjqUEYOMPYU0ijUV0G+4fdrHVKDe32abNdX/kJe1NUEMqsi4cwzXa9kyM9w5S8WqFsrfo1ogtBZGQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/compiler-core" "3.5.20"
|
"@vue/compiler-core" "3.5.20"
|
||||||
@@ -431,7 +211,7 @@
|
|||||||
|
|
||||||
"@vue/compiler-sfc@3.5.20":
|
"@vue/compiler-sfc@3.5.20":
|
||||||
version "3.5.20"
|
version "3.5.20"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.20.tgz#7bf92fc65951fd888076f1c71128dda4507a9328"
|
resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.20.tgz"
|
||||||
integrity sha512-SFcxapQc0/feWiSBfkGsa1v4DOrnMAQSYuvDMpEaxbpH5dKbnEM5KobSNSgU+1MbHCl+9ftm7oQWxvwDB6iBfw==
|
integrity sha512-SFcxapQc0/feWiSBfkGsa1v4DOrnMAQSYuvDMpEaxbpH5dKbnEM5KobSNSgU+1MbHCl+9ftm7oQWxvwDB6iBfw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/parser" "^7.28.3"
|
"@babel/parser" "^7.28.3"
|
||||||
@@ -446,7 +226,7 @@
|
|||||||
|
|
||||||
"@vue/compiler-ssr@3.5.20":
|
"@vue/compiler-ssr@3.5.20":
|
||||||
version "3.5.20"
|
version "3.5.20"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.5.20.tgz#6cdae8662bf36974ffb4fe894ba08192f89d5660"
|
resolved "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.20.tgz"
|
||||||
integrity sha512-RSl5XAMc5YFUXpDQi+UQDdVjH9FnEpLDHIALg5J0ITHxkEzJ8uQLlo7CIbjPYqmZtt6w0TsIPbo1izYXwDG7JA==
|
integrity sha512-RSl5XAMc5YFUXpDQi+UQDdVjH9FnEpLDHIALg5J0ITHxkEzJ8uQLlo7CIbjPYqmZtt6w0TsIPbo1izYXwDG7JA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/compiler-dom" "3.5.20"
|
"@vue/compiler-dom" "3.5.20"
|
||||||
@@ -454,14 +234,14 @@
|
|||||||
|
|
||||||
"@vue/devtools-api@^8.0.0":
|
"@vue/devtools-api@^8.0.0":
|
||||||
version "8.0.1"
|
version "8.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-8.0.1.tgz#142f94161ec80698f57ee8379bffad969868b251"
|
resolved "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.0.1.tgz"
|
||||||
integrity sha512-YBvjfpM7LEp5+b7ZDm4+mFrC+TgGjUmN8ff9lZcbHQ1MKhmftT/urCTZP0y1j26YQWr25l9TPaEbNLbILRiGoQ==
|
integrity sha512-YBvjfpM7LEp5+b7ZDm4+mFrC+TgGjUmN8ff9lZcbHQ1MKhmftT/urCTZP0y1j26YQWr25l9TPaEbNLbILRiGoQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/devtools-kit" "^8.0.1"
|
"@vue/devtools-kit" "^8.0.1"
|
||||||
|
|
||||||
"@vue/devtools-kit@^8.0.1":
|
"@vue/devtools-kit@^8.0.1":
|
||||||
version "8.0.1"
|
version "8.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/devtools-kit/-/devtools-kit-8.0.1.tgz#84b8741bbd16fa7d6d5ce0baf3c2e8b3822237c2"
|
resolved "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.0.1.tgz"
|
||||||
integrity sha512-7kiPhgTKNtNeXltEHnJJjIDlndlJP4P+UJvCw54uVHNDlI6JzwrSiRmW4cxKTug2wDbc/dkGaMnlZghcwV+aWA==
|
integrity sha512-7kiPhgTKNtNeXltEHnJJjIDlndlJP4P+UJvCw54uVHNDlI6JzwrSiRmW4cxKTug2wDbc/dkGaMnlZghcwV+aWA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/devtools-shared" "^8.0.1"
|
"@vue/devtools-shared" "^8.0.1"
|
||||||
@@ -474,21 +254,21 @@
|
|||||||
|
|
||||||
"@vue/devtools-shared@^8.0.1":
|
"@vue/devtools-shared@^8.0.1":
|
||||||
version "8.0.1"
|
version "8.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/devtools-shared/-/devtools-shared-8.0.1.tgz#ace79d39fec42f35e02d1053d5c83c4f492423a9"
|
resolved "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.0.1.tgz"
|
||||||
integrity sha512-PqtWqPPRpMwZ9FjTzyugb5KeV9kmg2C3hjxZHwjl0lijT4QIJDd0z6AWcnbM9w2nayjDymyTt0+sbdTv3pVeNg==
|
integrity sha512-PqtWqPPRpMwZ9FjTzyugb5KeV9kmg2C3hjxZHwjl0lijT4QIJDd0z6AWcnbM9w2nayjDymyTt0+sbdTv3pVeNg==
|
||||||
dependencies:
|
dependencies:
|
||||||
rfdc "^1.4.1"
|
rfdc "^1.4.1"
|
||||||
|
|
||||||
"@vue/reactivity@3.5.20":
|
"@vue/reactivity@3.5.20":
|
||||||
version "3.5.20"
|
version "3.5.20"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.5.20.tgz#95b959380af1f49780247686467e8858641209bc"
|
resolved "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.20.tgz"
|
||||||
integrity sha512-hS8l8x4cl1fmZpSQX/NXlqWKARqEsNmfkwOIYqtR2F616NGfsLUm0G6FQBK6uDKUCVyi1YOL8Xmt/RkZcd/jYQ==
|
integrity sha512-hS8l8x4cl1fmZpSQX/NXlqWKARqEsNmfkwOIYqtR2F616NGfsLUm0G6FQBK6uDKUCVyi1YOL8Xmt/RkZcd/jYQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/shared" "3.5.20"
|
"@vue/shared" "3.5.20"
|
||||||
|
|
||||||
"@vue/runtime-core@3.5.20":
|
"@vue/runtime-core@3.5.20":
|
||||||
version "3.5.20"
|
version "3.5.20"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.5.20.tgz#298eb83fc08887e21adf098a8c6ffeaa9e24c867"
|
resolved "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.20.tgz"
|
||||||
integrity sha512-vyQRiH5uSZlOa+4I/t4Qw/SsD/gbth0SW2J7oMeVlMFMAmsG1rwDD6ok0VMmjXY3eI0iHNSSOBilEDW98PLRKw==
|
integrity sha512-vyQRiH5uSZlOa+4I/t4Qw/SsD/gbth0SW2J7oMeVlMFMAmsG1rwDD6ok0VMmjXY3eI0iHNSSOBilEDW98PLRKw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/reactivity" "3.5.20"
|
"@vue/reactivity" "3.5.20"
|
||||||
@@ -496,7 +276,7 @@
|
|||||||
|
|
||||||
"@vue/runtime-dom@3.5.20":
|
"@vue/runtime-dom@3.5.20":
|
||||||
version "3.5.20"
|
version "3.5.20"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.5.20.tgz#bbeb73b51745bf4065d3d42c9a2f18266c3269b7"
|
resolved "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.20.tgz"
|
||||||
integrity sha512-KBHzPld/Djw3im0CQ7tGCpgRedryIn4CcAl047EhFTCCPT2xFf4e8j6WeKLgEEoqPSl9TYqShc3Q6tpWpz/Xgw==
|
integrity sha512-KBHzPld/Djw3im0CQ7tGCpgRedryIn4CcAl047EhFTCCPT2xFf4e8j6WeKLgEEoqPSl9TYqShc3Q6tpWpz/Xgw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/reactivity" "3.5.20"
|
"@vue/reactivity" "3.5.20"
|
||||||
@@ -506,20 +286,20 @@
|
|||||||
|
|
||||||
"@vue/server-renderer@3.5.20":
|
"@vue/server-renderer@3.5.20":
|
||||||
version "3.5.20"
|
version "3.5.20"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.5.20.tgz#6e075ef0386d099e8ec09c4662b6e8af1c1a086f"
|
resolved "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.20.tgz"
|
||||||
integrity sha512-HthAS0lZJDH21HFJBVNTtx+ULcIbJQRpjSVomVjfyPkFSpCwvsPTA+jIzOaUm3Hrqx36ozBHePztQFg6pj5aKg==
|
integrity sha512-HthAS0lZJDH21HFJBVNTtx+ULcIbJQRpjSVomVjfyPkFSpCwvsPTA+jIzOaUm3Hrqx36ozBHePztQFg6pj5aKg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/compiler-ssr" "3.5.20"
|
"@vue/compiler-ssr" "3.5.20"
|
||||||
"@vue/shared" "3.5.20"
|
"@vue/shared" "3.5.20"
|
||||||
|
|
||||||
"@vue/shared@3.5.20", "@vue/shared@^3.5.18":
|
"@vue/shared@^3.5.18", "@vue/shared@3.5.20":
|
||||||
version "3.5.20"
|
version "3.5.20"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.20.tgz#8740b370738c8c7e29e02fa9051cfe6d20114cb4"
|
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.5.20.tgz"
|
||||||
integrity sha512-SoRGP596KU/ig6TfgkCMbXkr4YJ91n/QSdMuqeP5r3hVIYA3CPHUBCc7Skak0EAKV+5lL4KyIh61VA/pK1CIAA==
|
integrity sha512-SoRGP596KU/ig6TfgkCMbXkr4YJ91n/QSdMuqeP5r3hVIYA3CPHUBCc7Skak0EAKV+5lL4KyIh61VA/pK1CIAA==
|
||||||
|
|
||||||
"@vueuse/core@13.8.0", "@vueuse/core@^13.6.0":
|
"@vueuse/core@^13.6.0", "@vueuse/core@13.8.0":
|
||||||
version "13.8.0"
|
version "13.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-13.8.0.tgz#760800f866dd8a1152a0a28e412ed53336e9ad7e"
|
resolved "https://registry.npmjs.org/@vueuse/core/-/core-13.8.0.tgz"
|
||||||
integrity sha512-rmBcgpEpxY0ZmyQQR94q1qkUcHREiLxQwNyWrtjMDipD0WTH/JBcAt0gdcn2PsH0SA76ec291cHFngmyaBhlxA==
|
integrity sha512-rmBcgpEpxY0ZmyQQR94q1qkUcHREiLxQwNyWrtjMDipD0WTH/JBcAt0gdcn2PsH0SA76ec291cHFngmyaBhlxA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/web-bluetooth" "^0.0.21"
|
"@types/web-bluetooth" "^0.0.21"
|
||||||
@@ -528,7 +308,7 @@
|
|||||||
|
|
||||||
"@vueuse/integrations@^13.6.0":
|
"@vueuse/integrations@^13.6.0":
|
||||||
version "13.8.0"
|
version "13.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/@vueuse/integrations/-/integrations-13.8.0.tgz#4ed1e7ce5a4691f171e53f7430f51d67c4976fc6"
|
resolved "https://registry.npmjs.org/@vueuse/integrations/-/integrations-13.8.0.tgz"
|
||||||
integrity sha512-64mD5Q7heVkr8JsqBFDh9xnQJrPLmWJghy8Qtj9UeLosQL9n+JYTcS7d+eNsEVwuvZvxfF7hUSi87jABm/eYpw==
|
integrity sha512-64mD5Q7heVkr8JsqBFDh9xnQJrPLmWJghy8Qtj9UeLosQL9n+JYTcS7d+eNsEVwuvZvxfF7hUSi87jABm/eYpw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vueuse/core" "13.8.0"
|
"@vueuse/core" "13.8.0"
|
||||||
@@ -536,71 +316,71 @@
|
|||||||
|
|
||||||
"@vueuse/metadata@13.8.0":
|
"@vueuse/metadata@13.8.0":
|
||||||
version "13.8.0"
|
version "13.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-13.8.0.tgz#5bf97b8733346fc1abf0c20c31e01ea672279c0e"
|
resolved "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.8.0.tgz"
|
||||||
integrity sha512-BYMp3Gp1kBUPv7AfQnJYP96mkX7g7cKdTIgwv/Jgd+pfQhz678naoZOAcknRtPLP4cFblDDW7rF4e3KFa+PfIA==
|
integrity sha512-BYMp3Gp1kBUPv7AfQnJYP96mkX7g7cKdTIgwv/Jgd+pfQhz678naoZOAcknRtPLP4cFblDDW7rF4e3KFa+PfIA==
|
||||||
|
|
||||||
"@vueuse/shared@13.8.0":
|
"@vueuse/shared@13.8.0":
|
||||||
version "13.8.0"
|
version "13.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-13.8.0.tgz#ed7baa8ad19e164a7626592531694bfe6c94d2e3"
|
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-13.8.0.tgz"
|
||||||
integrity sha512-x4nfM0ykW+RmNJ4/1IzZsuLuWWrNTxlTWUiehTGI54wnOxIgI9EDdu/O5S77ac6hvQ3hk2KpOVFHaM0M796Kbw==
|
integrity sha512-x4nfM0ykW+RmNJ4/1IzZsuLuWWrNTxlTWUiehTGI54wnOxIgI9EDdu/O5S77ac6hvQ3hk2KpOVFHaM0M796Kbw==
|
||||||
|
|
||||||
birpc@^2.5.0:
|
birpc@^2.5.0:
|
||||||
version "2.5.0"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/birpc/-/birpc-2.5.0.tgz#3a014e54c17eceba0ce15738d484ea371dbf6527"
|
resolved "https://registry.npmjs.org/birpc/-/birpc-2.5.0.tgz"
|
||||||
integrity sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==
|
integrity sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==
|
||||||
|
|
||||||
ccount@^2.0.0:
|
ccount@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5"
|
resolved "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz"
|
||||||
integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==
|
integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==
|
||||||
|
|
||||||
character-entities-html4@^2.0.0:
|
character-entities-html4@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b"
|
resolved "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz"
|
||||||
integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==
|
integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==
|
||||||
|
|
||||||
character-entities-legacy@^3.0.0:
|
character-entities-legacy@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b"
|
resolved "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz"
|
||||||
integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==
|
integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==
|
||||||
|
|
||||||
comma-separated-tokens@^2.0.0:
|
comma-separated-tokens@^2.0.0:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee"
|
resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz"
|
||||||
integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==
|
integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==
|
||||||
|
|
||||||
copy-anything@^3.0.2:
|
copy-anything@^3.0.2:
|
||||||
version "3.0.5"
|
version "3.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-3.0.5.tgz#2d92dce8c498f790fa7ad16b01a1ae5a45b020a0"
|
resolved "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz"
|
||||||
integrity sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==
|
integrity sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==
|
||||||
dependencies:
|
dependencies:
|
||||||
is-what "^4.1.8"
|
is-what "^4.1.8"
|
||||||
|
|
||||||
csstype@^3.1.3:
|
csstype@^3.1.3:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
|
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
|
||||||
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
||||||
|
|
||||||
dequal@^2.0.0:
|
dequal@^2.0.0:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
|
resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz"
|
||||||
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
|
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
|
||||||
|
|
||||||
devlop@^1.0.0:
|
devlop@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018"
|
resolved "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz"
|
||||||
integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==
|
integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==
|
||||||
dependencies:
|
dependencies:
|
||||||
dequal "^2.0.0"
|
dequal "^2.0.0"
|
||||||
|
|
||||||
entities@^4.5.0:
|
entities@^4.5.0:
|
||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
|
resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz"
|
||||||
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
|
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
|
||||||
|
|
||||||
esbuild@^0.25.0:
|
esbuild@^0.25.0:
|
||||||
version "0.25.9"
|
version "0.25.9"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.9.tgz#15ab8e39ae6cdc64c24ff8a2c0aef5b3fd9fa976"
|
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz"
|
||||||
integrity sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==
|
integrity sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@esbuild/aix-ppc64" "0.25.9"
|
"@esbuild/aix-ppc64" "0.25.9"
|
||||||
@@ -632,29 +412,24 @@ esbuild@^0.25.0:
|
|||||||
|
|
||||||
estree-walker@^2.0.2:
|
estree-walker@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
|
resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz"
|
||||||
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
|
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
|
||||||
|
|
||||||
fdir@^6.4.4, fdir@^6.5.0:
|
fdir@^6.4.4, fdir@^6.5.0:
|
||||||
version "6.5.0"
|
version "6.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350"
|
resolved "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz"
|
||||||
integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==
|
integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==
|
||||||
|
|
||||||
focus-trap@^7.6.5:
|
focus-trap@^7, focus-trap@^7.6.5:
|
||||||
version "7.6.5"
|
version "7.6.5"
|
||||||
resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-7.6.5.tgz#56f0814286d43c1a2688e9bc4f31f17ae047fb76"
|
resolved "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.5.tgz"
|
||||||
integrity sha512-7Ke1jyybbbPZyZXFxEftUtxFGLMpE2n6A+z//m4CRDlj0hW+o3iYSmh8nFlYMurOiJVDmJRilUQtJr08KfIxlg==
|
integrity sha512-7Ke1jyybbbPZyZXFxEftUtxFGLMpE2n6A+z//m4CRDlj0hW+o3iYSmh8nFlYMurOiJVDmJRilUQtJr08KfIxlg==
|
||||||
dependencies:
|
dependencies:
|
||||||
tabbable "^6.2.0"
|
tabbable "^6.2.0"
|
||||||
|
|
||||||
fsevents@~2.3.2, fsevents@~2.3.3:
|
|
||||||
version "2.3.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
|
||||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
|
||||||
|
|
||||||
hast-util-to-html@^9.0.5:
|
hast-util-to-html@^9.0.5:
|
||||||
version "9.0.5"
|
version "9.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz#ccc673a55bb8e85775b08ac28380f72d47167005"
|
resolved "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz"
|
||||||
integrity sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==
|
integrity sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/hast" "^3.0.0"
|
"@types/hast" "^3.0.0"
|
||||||
@@ -671,41 +446,41 @@ hast-util-to-html@^9.0.5:
|
|||||||
|
|
||||||
hast-util-whitespace@^3.0.0:
|
hast-util-whitespace@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz#7778ed9d3c92dd9e8c5c8f648a49c21fc51cb621"
|
resolved "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz"
|
||||||
integrity sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==
|
integrity sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/hast" "^3.0.0"
|
"@types/hast" "^3.0.0"
|
||||||
|
|
||||||
hookable@^5.5.3:
|
hookable@^5.5.3:
|
||||||
version "5.5.3"
|
version "5.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/hookable/-/hookable-5.5.3.tgz#6cfc358984a1ef991e2518cb9ed4a778bbd3215d"
|
resolved "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz"
|
||||||
integrity sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==
|
integrity sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==
|
||||||
|
|
||||||
html-void-elements@^3.0.0:
|
html-void-elements@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7"
|
resolved "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz"
|
||||||
integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==
|
integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==
|
||||||
|
|
||||||
is-what@^4.1.8:
|
is-what@^4.1.8:
|
||||||
version "4.1.16"
|
version "4.1.16"
|
||||||
resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.16.tgz#1ad860a19da8b4895ad5495da3182ce2acdd7a6f"
|
resolved "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz"
|
||||||
integrity sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==
|
integrity sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==
|
||||||
|
|
||||||
magic-string@^0.30.17:
|
magic-string@^0.30.17:
|
||||||
version "0.30.18"
|
version "0.30.18"
|
||||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.18.tgz#905bfbbc6aa5692703a93db26a9edcaa0007d2bb"
|
resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz"
|
||||||
integrity sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==
|
integrity sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jridgewell/sourcemap-codec" "^1.5.5"
|
"@jridgewell/sourcemap-codec" "^1.5.5"
|
||||||
|
|
||||||
mark.js@8.11.1:
|
mark.js@8.11.1:
|
||||||
version "8.11.1"
|
version "8.11.1"
|
||||||
resolved "https://registry.yarnpkg.com/mark.js/-/mark.js-8.11.1.tgz#180f1f9ebef8b0e638e4166ad52db879beb2ffc5"
|
resolved "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz"
|
||||||
integrity sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==
|
integrity sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==
|
||||||
|
|
||||||
mdast-util-to-hast@^13.0.0:
|
mdast-util-to-hast@^13.0.0:
|
||||||
version "13.2.0"
|
version "13.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz#5ca58e5b921cc0a3ded1bc02eed79a4fe4fe41f4"
|
resolved "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz"
|
||||||
integrity sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==
|
integrity sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/hast" "^3.0.0"
|
"@types/hast" "^3.0.0"
|
||||||
@@ -720,7 +495,7 @@ mdast-util-to-hast@^13.0.0:
|
|||||||
|
|
||||||
micromark-util-character@^2.0.0:
|
micromark-util-character@^2.0.0:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.1.tgz#2f987831a40d4c510ac261e89852c4e9703ccda6"
|
resolved "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz"
|
||||||
integrity sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==
|
integrity sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
micromark-util-symbol "^2.0.0"
|
micromark-util-symbol "^2.0.0"
|
||||||
@@ -728,12 +503,12 @@ micromark-util-character@^2.0.0:
|
|||||||
|
|
||||||
micromark-util-encode@^2.0.0:
|
micromark-util-encode@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz#0d51d1c095551cfaac368326963cf55f15f540b8"
|
resolved "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz"
|
||||||
integrity sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==
|
integrity sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==
|
||||||
|
|
||||||
micromark-util-sanitize-uri@^2.0.0:
|
micromark-util-sanitize-uri@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz#ab89789b818a58752b73d6b55238621b7faa8fd7"
|
resolved "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz"
|
||||||
integrity sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==
|
integrity sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
micromark-util-character "^2.0.0"
|
micromark-util-character "^2.0.0"
|
||||||
@@ -742,37 +517,37 @@ micromark-util-sanitize-uri@^2.0.0:
|
|||||||
|
|
||||||
micromark-util-symbol@^2.0.0:
|
micromark-util-symbol@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz#e5da494e8eb2b071a0d08fb34f6cefec6c0a19b8"
|
resolved "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz"
|
||||||
integrity sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==
|
integrity sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==
|
||||||
|
|
||||||
micromark-util-types@^2.0.0:
|
micromark-util-types@^2.0.0:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.2.tgz#f00225f5f5a0ebc3254f96c36b6605c4b393908e"
|
resolved "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz"
|
||||||
integrity sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==
|
integrity sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==
|
||||||
|
|
||||||
minisearch@^7.1.2:
|
minisearch@^7.1.2:
|
||||||
version "7.1.2"
|
version "7.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/minisearch/-/minisearch-7.1.2.tgz#296ee8d1906cc378f7e57a3a71f07e5205a75df5"
|
resolved "https://registry.npmjs.org/minisearch/-/minisearch-7.1.2.tgz"
|
||||||
integrity sha512-R1Pd9eF+MD5JYDDSPAp/q1ougKglm14uEkPMvQ/05RGmx6G9wvmLTrTI/Q5iPNJLYqNdsDQ7qTGIcNWR+FrHmA==
|
integrity sha512-R1Pd9eF+MD5JYDDSPAp/q1ougKglm14uEkPMvQ/05RGmx6G9wvmLTrTI/Q5iPNJLYqNdsDQ7qTGIcNWR+FrHmA==
|
||||||
|
|
||||||
mitt@^3.0.1:
|
mitt@^3.0.1:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1"
|
resolved "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz"
|
||||||
integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==
|
integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==
|
||||||
|
|
||||||
nanoid@^3.3.11:
|
nanoid@^3.3.11:
|
||||||
version "3.3.11"
|
version "3.3.11"
|
||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b"
|
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz"
|
||||||
integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==
|
integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==
|
||||||
|
|
||||||
oniguruma-parser@^0.12.1:
|
oniguruma-parser@^0.12.1:
|
||||||
version "0.12.1"
|
version "0.12.1"
|
||||||
resolved "https://registry.yarnpkg.com/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz#82ba2208d7a2b69ee344b7efe0ae930c627dcc4a"
|
resolved "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz"
|
||||||
integrity sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==
|
integrity sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==
|
||||||
|
|
||||||
oniguruma-to-es@^4.3.3:
|
oniguruma-to-es@^4.3.3:
|
||||||
version "4.3.3"
|
version "4.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/oniguruma-to-es/-/oniguruma-to-es-4.3.3.tgz#50db2c1e28ec365e102c1863dfd3d1d1ad18613e"
|
resolved "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.3.tgz"
|
||||||
integrity sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==
|
integrity sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==
|
||||||
dependencies:
|
dependencies:
|
||||||
oniguruma-parser "^0.12.1"
|
oniguruma-parser "^0.12.1"
|
||||||
@@ -781,22 +556,22 @@ oniguruma-to-es@^4.3.3:
|
|||||||
|
|
||||||
perfect-debounce@^1.0.0:
|
perfect-debounce@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz#9c2e8bc30b169cc984a58b7d5b28049839591d2a"
|
resolved "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz"
|
||||||
integrity sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==
|
integrity sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==
|
||||||
|
|
||||||
picocolors@^1.1.1:
|
picocolors@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
|
resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz"
|
||||||
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
|
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
|
||||||
|
|
||||||
picomatch@^4.0.2, picomatch@^4.0.3:
|
"picomatch@^3 || ^4", picomatch@^4.0.2, picomatch@^4.0.3:
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042"
|
resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz"
|
||||||
integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==
|
integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==
|
||||||
|
|
||||||
postcss@^8.5.6:
|
postcss@^8, postcss@^8.5.6:
|
||||||
version "8.5.6"
|
version "8.5.6"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c"
|
resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz"
|
||||||
integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==
|
integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==
|
||||||
dependencies:
|
dependencies:
|
||||||
nanoid "^3.3.11"
|
nanoid "^3.3.11"
|
||||||
@@ -805,36 +580,36 @@ postcss@^8.5.6:
|
|||||||
|
|
||||||
property-information@^7.0.0:
|
property-information@^7.0.0:
|
||||||
version "7.1.0"
|
version "7.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/property-information/-/property-information-7.1.0.tgz#b622e8646e02b580205415586b40804d3e8bfd5d"
|
resolved "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz"
|
||||||
integrity sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==
|
integrity sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==
|
||||||
|
|
||||||
regex-recursion@^6.0.2:
|
regex-recursion@^6.0.2:
|
||||||
version "6.0.2"
|
version "6.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/regex-recursion/-/regex-recursion-6.0.2.tgz#a0b1977a74c87f073377b938dbedfab2ea582b33"
|
resolved "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz"
|
||||||
integrity sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==
|
integrity sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==
|
||||||
dependencies:
|
dependencies:
|
||||||
regex-utilities "^2.3.0"
|
regex-utilities "^2.3.0"
|
||||||
|
|
||||||
regex-utilities@^2.3.0:
|
regex-utilities@^2.3.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/regex-utilities/-/regex-utilities-2.3.0.tgz#87163512a15dce2908cf079c8960d5158ff43280"
|
resolved "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz"
|
||||||
integrity sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==
|
integrity sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==
|
||||||
|
|
||||||
regex@^6.0.1:
|
regex@^6.0.1:
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/regex/-/regex-6.0.1.tgz#282fa4435d0c700b09c0eb0982b602e05ab6a34f"
|
resolved "https://registry.npmjs.org/regex/-/regex-6.0.1.tgz"
|
||||||
integrity sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==
|
integrity sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==
|
||||||
dependencies:
|
dependencies:
|
||||||
regex-utilities "^2.3.0"
|
regex-utilities "^2.3.0"
|
||||||
|
|
||||||
rfdc@^1.4.1:
|
rfdc@^1.4.1:
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca"
|
resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz"
|
||||||
integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==
|
integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==
|
||||||
|
|
||||||
rollup@^4.43.0:
|
rollup@^4.43.0:
|
||||||
version "4.49.0"
|
version "4.49.0"
|
||||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.49.0.tgz#9751ad9d06a47a4496c3c5c238b27b1422c8b0eb"
|
resolved "https://registry.npmjs.org/rollup/-/rollup-4.49.0.tgz"
|
||||||
integrity sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA==
|
integrity sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/estree" "1.0.8"
|
"@types/estree" "1.0.8"
|
||||||
@@ -863,7 +638,7 @@ rollup@^4.43.0:
|
|||||||
|
|
||||||
shiki@^3.9.2:
|
shiki@^3.9.2:
|
||||||
version "3.12.0"
|
version "3.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/shiki/-/shiki-3.12.0.tgz#a0668393d04c02402522abcd221ad3a0774b2d44"
|
resolved "https://registry.npmjs.org/shiki/-/shiki-3.12.0.tgz"
|
||||||
integrity sha512-E+ke51tciraTHpaXYXfqnPZFSViKHhSQ3fiugThlfs/om/EonlQ0hSldcqgzOWWqX6PcjkKKzFgrjIaiPAXoaA==
|
integrity sha512-E+ke51tciraTHpaXYXfqnPZFSViKHhSQ3fiugThlfs/om/EonlQ0hSldcqgzOWWqX6PcjkKKzFgrjIaiPAXoaA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@shikijs/core" "3.12.0"
|
"@shikijs/core" "3.12.0"
|
||||||
@@ -877,22 +652,22 @@ shiki@^3.9.2:
|
|||||||
|
|
||||||
source-map-js@^1.2.1:
|
source-map-js@^1.2.1:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
|
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz"
|
||||||
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||||
|
|
||||||
space-separated-tokens@^2.0.0:
|
space-separated-tokens@^2.0.0:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f"
|
resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz"
|
||||||
integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==
|
integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==
|
||||||
|
|
||||||
speakingurl@^14.0.1:
|
speakingurl@^14.0.1:
|
||||||
version "14.0.1"
|
version "14.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/speakingurl/-/speakingurl-14.0.1.tgz#f37ec8ddc4ab98e9600c1c9ec324a8c48d772a53"
|
resolved "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz"
|
||||||
integrity sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==
|
integrity sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==
|
||||||
|
|
||||||
stringify-entities@^4.0.0:
|
stringify-entities@^4.0.0:
|
||||||
version "4.0.4"
|
version "4.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.4.tgz#b3b79ef5f277cc4ac73caeb0236c5ba939b3a4f3"
|
resolved "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz"
|
||||||
integrity sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==
|
integrity sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==
|
||||||
dependencies:
|
dependencies:
|
||||||
character-entities-html4 "^2.0.0"
|
character-entities-html4 "^2.0.0"
|
||||||
@@ -900,19 +675,19 @@ stringify-entities@^4.0.0:
|
|||||||
|
|
||||||
superjson@^2.2.2:
|
superjson@^2.2.2:
|
||||||
version "2.2.2"
|
version "2.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/superjson/-/superjson-2.2.2.tgz#9d52bf0bf6b5751a3c3472f1292e714782ba3173"
|
resolved "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz"
|
||||||
integrity sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==
|
integrity sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
copy-anything "^3.0.2"
|
copy-anything "^3.0.2"
|
||||||
|
|
||||||
tabbable@^6.2.0:
|
tabbable@^6.2.0:
|
||||||
version "6.2.0"
|
version "6.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97"
|
resolved "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz"
|
||||||
integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==
|
integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==
|
||||||
|
|
||||||
tinyglobby@^0.2.14:
|
tinyglobby@^0.2.14:
|
||||||
version "0.2.14"
|
version "0.2.14"
|
||||||
resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.14.tgz#5280b0cf3f972b050e74ae88406c0a6a58f4079d"
|
resolved "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz"
|
||||||
integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==
|
integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
fdir "^6.4.4"
|
fdir "^6.4.4"
|
||||||
@@ -920,33 +695,33 @@ tinyglobby@^0.2.14:
|
|||||||
|
|
||||||
trim-lines@^3.0.0:
|
trim-lines@^3.0.0:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338"
|
resolved "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz"
|
||||||
integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==
|
integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==
|
||||||
|
|
||||||
unist-util-is@^6.0.0:
|
unist-util-is@^6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.0.tgz#b775956486aff107a9ded971d996c173374be424"
|
resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz"
|
||||||
integrity sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==
|
integrity sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/unist" "^3.0.0"
|
"@types/unist" "^3.0.0"
|
||||||
|
|
||||||
unist-util-position@^5.0.0:
|
unist-util-position@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-5.0.0.tgz#678f20ab5ca1207a97d7ea8a388373c9cf896be4"
|
resolved "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz"
|
||||||
integrity sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==
|
integrity sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/unist" "^3.0.0"
|
"@types/unist" "^3.0.0"
|
||||||
|
|
||||||
unist-util-stringify-position@^4.0.0:
|
unist-util-stringify-position@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz#449c6e21a880e0855bf5aabadeb3a740314abac2"
|
resolved "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz"
|
||||||
integrity sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==
|
integrity sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/unist" "^3.0.0"
|
"@types/unist" "^3.0.0"
|
||||||
|
|
||||||
unist-util-visit-parents@^6.0.0:
|
unist-util-visit-parents@^6.0.0:
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz#4d5f85755c3b8f0dc69e21eca5d6d82d22162815"
|
resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz"
|
||||||
integrity sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==
|
integrity sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/unist" "^3.0.0"
|
"@types/unist" "^3.0.0"
|
||||||
@@ -954,7 +729,7 @@ unist-util-visit-parents@^6.0.0:
|
|||||||
|
|
||||||
unist-util-visit@^5.0.0:
|
unist-util-visit@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz#a7de1f31f72ffd3519ea71814cccf5fd6a9217d6"
|
resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz"
|
||||||
integrity sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==
|
integrity sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/unist" "^3.0.0"
|
"@types/unist" "^3.0.0"
|
||||||
@@ -963,7 +738,7 @@ unist-util-visit@^5.0.0:
|
|||||||
|
|
||||||
vfile-message@^4.0.0:
|
vfile-message@^4.0.0:
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-4.0.3.tgz#87b44dddd7b70f0641c2e3ed0864ba73e2ea8df4"
|
resolved "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz"
|
||||||
integrity sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==
|
integrity sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/unist" "^3.0.0"
|
"@types/unist" "^3.0.0"
|
||||||
@@ -971,15 +746,15 @@ vfile-message@^4.0.0:
|
|||||||
|
|
||||||
vfile@^6.0.0:
|
vfile@^6.0.0:
|
||||||
version "6.0.3"
|
version "6.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.3.tgz#3652ab1c496531852bf55a6bac57af981ebc38ab"
|
resolved "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz"
|
||||||
integrity sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==
|
integrity sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/unist" "^3.0.0"
|
"@types/unist" "^3.0.0"
|
||||||
vfile-message "^4.0.0"
|
vfile-message "^4.0.0"
|
||||||
|
|
||||||
vite@^7.1.2:
|
"vite@^5.0.0 || ^6.0.0 || ^7.0.0", vite@^7.1.2:
|
||||||
version "7.1.3"
|
version "7.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/vite/-/vite-7.1.3.tgz#8d70cb02fd6346b4bf1329a6760800538ef0faea"
|
resolved "https://registry.npmjs.org/vite/-/vite-7.1.3.tgz"
|
||||||
integrity sha512-OOUi5zjkDxYrKhTV3V7iKsoS37VUM7v40+HuwEmcrsf11Cdx9y3DIr2Px6liIcZFwt3XSRpQvFpL3WVy7ApkGw==
|
integrity sha512-OOUi5zjkDxYrKhTV3V7iKsoS37VUM7v40+HuwEmcrsf11Cdx9y3DIr2Px6liIcZFwt3XSRpQvFpL3WVy7ApkGw==
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild "^0.25.0"
|
esbuild "^0.25.0"
|
||||||
@@ -993,7 +768,7 @@ vite@^7.1.2:
|
|||||||
|
|
||||||
vitepress@^2.0.0-alpha.5:
|
vitepress@^2.0.0-alpha.5:
|
||||||
version "2.0.0-alpha.12"
|
version "2.0.0-alpha.12"
|
||||||
resolved "https://registry.yarnpkg.com/vitepress/-/vitepress-2.0.0-alpha.12.tgz#e75648eec6c43bff1d669f9a7f81f777acc6e4fd"
|
resolved "https://registry.npmjs.org/vitepress/-/vitepress-2.0.0-alpha.12.tgz"
|
||||||
integrity sha512-yZwCwRRepcpN5QeAhwSnEJxS3I6zJcVixqL1dnm6km4cnriLpQyy2sXQDsE5Ti3pxGPbhU51nTMwI+XC1KNnJg==
|
integrity sha512-yZwCwRRepcpN5QeAhwSnEJxS3I6zJcVixqL1dnm6km4cnriLpQyy2sXQDsE5Ti3pxGPbhU51nTMwI+XC1KNnJg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@docsearch/css" "^4.0.0-beta.7"
|
"@docsearch/css" "^4.0.0-beta.7"
|
||||||
@@ -1015,9 +790,9 @@ vitepress@^2.0.0-alpha.5:
|
|||||||
vite "^7.1.2"
|
vite "^7.1.2"
|
||||||
vue "^3.5.18"
|
vue "^3.5.18"
|
||||||
|
|
||||||
vue@^3.2.47, vue@^3.5.18:
|
vue@^3.2.25, vue@^3.2.47, vue@^3.5.0, vue@^3.5.18, vue@3.5.20:
|
||||||
version "3.5.20"
|
version "3.5.20"
|
||||||
resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.20.tgz#855c3f4c0a1260abc894f729c3ffb6cb687d0d34"
|
resolved "https://registry.npmjs.org/vue/-/vue-3.5.20.tgz"
|
||||||
integrity sha512-2sBz0x/wis5TkF1XZ2vH25zWq3G1bFEPOfkBcx2ikowmphoQsPH6X0V3mmPCXA2K1N/XGTnifVyDQP4GfDDeQw==
|
integrity sha512-2sBz0x/wis5TkF1XZ2vH25zWq3G1bFEPOfkBcx2ikowmphoQsPH6X0V3mmPCXA2K1N/XGTnifVyDQP4GfDDeQw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/compiler-dom" "3.5.20"
|
"@vue/compiler-dom" "3.5.20"
|
||||||
@@ -1028,5 +803,5 @@ vue@^3.2.47, vue@^3.5.18:
|
|||||||
|
|
||||||
zwitch@^2.0.4:
|
zwitch@^2.0.4:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7"
|
resolved "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz"
|
||||||
integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==
|
integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==
|
||||||
|
|||||||
Reference in New Issue
Block a user