diff --git a/build-static.sh b/build-static.sh index 685984d63d..d8bee0114a 100755 --- a/build-static.sh +++ b/build-static.sh @@ -21,6 +21,7 @@ os="$(uname -s | tr '[:upper:]' '[:lower:]')" # - MIMALLOC: Use mimalloc as the allocator if set to 1 (default: none) # - XCADDY_ARGS: Additional arguments to pass to xcaddy # - RELEASE: [maintainer only] Create a GitHub release if set to 1 (default: none) +# - INCLUDE_CLI: embeds the PHP CLI in FrankenPHP and enables a command for extracting it (default: none) # - SPC_REL_TYPE: Release type to download (accept "source" and "binary", default: "source") # - SPC_OPT_BUILD_ARGS: Additional arguments to pass to spc build @@ -55,6 +56,10 @@ fi if [ -n "${DEBUG_SYMBOLS}" ]; then SPC_OPT_BUILD_ARGS="${SPC_OPT_BUILD_ARGS} --no-strip" fi +# build php-cli for embedding it +if [ -n "${INCLUDE_CLI}" ]; then + SPC_OPT_BUILD_ARGS="${SPC_OPT_BUILD_ARGS} --build-cli" +fi # php version to build if [ -z "${PHP_VERSION}" ]; then get_latest_php_version() { @@ -215,6 +220,10 @@ else echo -n "${cache_key}" >../cache_key fi +if [ "${INCLUDE_CLI}" ]; then + cp "${PWD}/buildroot/bin/php" ../../caddy/frankenphp/php-cli +fi + if ! type "go" >/dev/null 2>&1; then echo "The \"go\" command must be installed." exit 1 @@ -315,12 +324,17 @@ if [ "${SPC_LIBC}" = "musl" ]; then muslStackSizeFix="-Wl,-z,stack-size=0x80000" fi +INCLUDE_CLI_TAG="" +if [ "${INCLUDE_CLI}" ]; then + INCLUDE_CLI_TAG="include_php_cli," +fi + go env cd caddy/ if [ -z "${SPC_LIBC}" ] || [ "${SPC_LIBC}" = "musl" ]; then - xcaddyGoBuildFlags="-buildmode=pie -tags cgo,netgo,osusergo,static_build,nobadger,nomysql,nopgx -ldflags \"-linkmode=external -extldflags '-static-pie ${muslStackSizeFix}' ${extraLdflags} -X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ${FRANKENPHP_VERSION} PHP ${LIBPHP_VERSION} Caddy'\"" + xcaddyGoBuildFlags="-buildmode=pie -tags cgo,${INCLUDE_CLI_TAG}netgo,osusergo,static_build,nobadger,nomysql,nopgx -ldflags \"-linkmode=external -extldflags '-static-pie ${muslStackSizeFix}' ${extraLdflags} -X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ${FRANKENPHP_VERSION} PHP ${LIBPHP_VERSION} Caddy'\"" elif [ "${SPC_LIBC}" = "glibc" ]; then - xcaddyGoBuildFlags="-buildmode=pie -tags cgo,netgo,osusergo,nobadger,nomysql,nopgx -ldflags \"-linkmode=external -extldflags '-pie' ${extraLdflags} -X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ${FRANKENPHP_VERSION} PHP ${LIBPHP_VERSION} Caddy'\"" + xcaddyGoBuildFlags="-buildmode=pie -tags cgo,${INCLUDE_CLI_TAG}netgo,osusergo,nobadger,nomysql,nopgx -ldflags \"-linkmode=external -extldflags '-pie' ${extraLdflags} -X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ${FRANKENPHP_VERSION} PHP ${LIBPHP_VERSION} Caddy'\"" fi # shellcheck disable=SC2086 diff --git a/caddy/frankenphp/main.go b/caddy/frankenphp/main.go index 5b5fc0d7c9..825b1f1bb2 100644 --- a/caddy/frankenphp/main.go +++ b/caddy/frankenphp/main.go @@ -2,7 +2,6 @@ package main import ( caddycmd "github.com/caddyserver/caddy/v2/cmd" - // plug in Caddy modules here. _ "github.com/caddyserver/caddy/v2/modules/standard" _ "github.com/dunglas/caddy-cbrotli" diff --git a/caddy/php-installer.go b/caddy/php-installer.go new file mode 100644 index 0000000000..c97cb8d16b --- /dev/null +++ b/caddy/php-installer.go @@ -0,0 +1,52 @@ +//go:build include_php_cli + +package caddy + +import ( + _ "embed" + "errors" + "fmt" + caddycmd "github.com/caddyserver/caddy/v2/cmd" + "github.com/spf13/cobra" + "os" +) + +//go:embed frankenphp/php-cli +var phpcli []byte + +func init() { + caddycmd.RegisterCommand(caddycmd.Command{ + Name: "install-php", + Usage: "location", + Short: "Installs the embedded PHP binary to the desired location", + Long: ` +FrankenPHP was embedded with a php-cli binary. You can extract this to the desired location.`, + CobraFunc: func(cmd *cobra.Command) { + cmd.DisableFlagParsing = true + cmd.RunE = caddycmd.WrapCommandFuncForCobra(extractPHP) + }, + }) +} + +func extractPHP(fs caddycmd.Flags) (int, error) { + args := os.Args[2:] + if len(args) < 1 { + return 1, errors.New("the location is required") + } + + destPath := args[0] + + err := os.WriteFile(destPath, phpcli, 0777) + if err != nil { + err = fmt.Errorf("Failed to write php-cli to %s: %v\n", destPath, err) + if err != nil { + panic(err) + } + os.Exit(1) + return 1, nil + } + + os.Exit(0) + + return 0, nil +} diff --git a/docs/static.md b/docs/static.md index dd11f36cb0..d88488aff8 100644 --- a/docs/static.md +++ b/docs/static.md @@ -128,6 +128,7 @@ script to customize the static build: - `DEBUG_SYMBOLS`: when set, debug-symbols will not be stripped and will be added to the binary - `MIMALLOC`: (experimental, Linux-only) replace musl's mallocng by [mimalloc](https://github.com/microsoft/mimalloc) for improved performance. We only recommend using this for musl targeting builds, for glibc prefer disabling this option and using [`LD_PRELOAD`](https://microsoft.github.io/mimalloc/overrides.html) when you run your binary instead. - `RELEASE`: (maintainers only) when set, the resulting binary will be uploaded on GitHub +- `INCLUDE_CLI`: embeds the PHP CLI in the resulting binary which can be installed with the `install-php` command ## Extensions diff --git a/static-builder-gnu.Dockerfile b/static-builder-gnu.Dockerfile index 7d6a7391cb..14520beb5d 100644 --- a/static-builder-gnu.Dockerfile +++ b/static-builder-gnu.Dockerfile @@ -11,6 +11,9 @@ ARG BUILD_PACKAGES='' ARG PHP_VERSION='' ENV PHP_VERSION=${PHP_VERSION} +ARG INCLUDE_CLI='' +ENV INCLUDE_CLI=${INCLUDE_CLI} + # args passed to static-php-cli ARG PHP_EXTENSIONS='' ARG PHP_EXTENSION_LIBS='' diff --git a/static-builder-musl.Dockerfile b/static-builder-musl.Dockerfile index 2bea7d8fe9..b17f9d92ba 100644 --- a/static-builder-musl.Dockerfile +++ b/static-builder-musl.Dockerfile @@ -20,6 +20,8 @@ ARG EMBED='' ARG DEBUG_SYMBOLS='' ARG MIMALLOC='' ARG NO_COMPRESS='' +ARG INCLUDE_CLI='' +ENV INCLUDE_CLI=${INCLUDE_CLI} ENV GOTOOLCHAIN=local