Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/env.ini
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ SPC_SKIP_PHP_VERSION_CHECK="no"
; Ignore some check item for bin/spc doctor command, comma separated (e.g. SPC_SKIP_DOCTOR_CHECK_ITEMS="if homebrew has installed")
SPC_SKIP_DOCTOR_CHECK_ITEMS=""
; extra modules that xcaddy will include in the FrankenPHP build
SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES="--with github.com/dunglas/frankenphp/caddy --with github.com/dunglas/mercure/caddy --with github.com/dunglas/vulcain/caddy --with github.com/dunglas/caddy-cbrotli"
SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES="--with github.com/dunglas/mercure/caddy --with github.com/dunglas/vulcain/caddy --with github.com/dunglas/caddy-cbrotli"
; The display message for php version output (PHP >= 8.4 available)
PHP_BUILD_PROVIDER="static-php-cli ${SPC_VERSION}"

Expand Down
7 changes: 6 additions & 1 deletion config/lib.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"source": "php-src",
"lib-depends": [
"lib-base",
"micro"
"micro",
"frankenphp"
],
"lib-suggests-linux": [
"libacl",
Expand Down Expand Up @@ -940,5 +941,9 @@
"liburing/",
"liburing.h"
]
},
"frankenphp": {
"source": "frankenphp",
"type": "target"
}
}
10 changes: 10 additions & 0 deletions config/source.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,16 @@
"path": "LICENSE"
}
},
"frankenphp": {
"type": "ghtar",
"repo": "php/frankenphp",
"prefer-stable": true,
"provide-pre-build": false,
"license": {
"type": "file",
"path": "LICENSE"
}
},
"icu-static-win": {
"type": "url",
"url": "https://dl.static-php.dev/static-php-cli/deps/icu-static-windows-x64/icu-static-windows-x64.zip",
Expand Down
63 changes: 56 additions & 7 deletions src/SPC/builder/unix/UnixBuilderBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use SPC\store\Config;
use SPC\store\FileSystem;
use SPC\store\pkg\GoXcaddy;
use SPC\store\SourceManager;
use SPC\toolchain\GccNativeToolchain;
use SPC\toolchain\ToolchainManager;
use SPC\util\DependencyUtil;
Expand Down Expand Up @@ -264,22 +265,70 @@ protected function patchPhpScripts(): void
}
}

/**
* Process the --with-frankenphp-app option
* Creates app.tar and app.checksum in source/frankenphp directory
*/
protected function processFrankenphpApp(): void
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about processing frankenphp app before building everything? Although I don't have any build requirements for frankenphp embed app, but if something goes wrong here, it would be annoying to wait for dozens of minutes to build and then report an error.

{
$frankenphpSourceDir = SOURCE_PATH . '/frankenphp';
SourceManager::initSource(['frankenphp'], ['frankenphp']);
$frankenphpAppPath = $this->getOption('with-frankenphp-app');

if ($frankenphpAppPath) {
if (!is_dir($frankenphpAppPath)) {
throw new WrongUsageException("The path provided to --with-frankenphp-app is not a valid directory: {$frankenphpAppPath}");
}
$appTarPath = $frankenphpSourceDir . '/app.tar';
logger()->info("Creating app.tar from {$frankenphpAppPath}");

shell()->exec('tar -cf ' . escapeshellarg($appTarPath) . ' -C ' . escapeshellarg($frankenphpAppPath) . ' .');

$checksum = hash_file('md5', $appTarPath);
file_put_contents($frankenphpSourceDir . '/app_checksum.txt', $checksum);
} else {
FileSystem::removeFileIfExists($frankenphpSourceDir . '/app.tar');
FileSystem::removeFileIfExists($frankenphpSourceDir . '/app_checksum.txt');
file_put_contents($frankenphpSourceDir . '/app.tar', '');
file_put_contents($frankenphpSourceDir . '/app_checksum.txt', '');
}
}

protected function getFrankenPHPVersion(): string
{
$goModPath = SOURCE_PATH . '/frankenphp/caddy/go.mod';

if (!file_exists($goModPath)) {
throw new SPCInternalException("FrankenPHP caddy/go.mod file not found at {$goModPath}, why did we not download FrankenPHP?");
}

$content = file_get_contents($goModPath);
if (preg_match('/github\.com\/dunglas\/frankenphp\s+v?(\d+\.\d+\.\d+)/', $content, $matches)) {
return $matches[1];
}

throw new SPCInternalException('Could not find FrankenPHP version in caddy/go.mod');
}

protected function buildFrankenphp(): void
{
GlobalEnvManager::addPathIfNotExists(GoXcaddy::getEnvironment()['PATH']);
$this->processFrankenphpApp();
$nobrotli = $this->getLib('brotli') === null ? ',nobrotli' : '';
$nowatcher = $this->getLib('watcher') === null ? ',nowatcher' : '';
$xcaddyModules = getenv('SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULES');
// make it possible to build from a different frankenphp directory!
if (!str_contains($xcaddyModules, '--with github.com/dunglas/frankenphp')) {
$xcaddyModules = '--with github.com/dunglas/frankenphp ' . $xcaddyModules;
}
$frankenphpSourceDir = SOURCE_PATH . '/frankenphp';

$xcaddyModules = preg_replace('#--with github.com/dunglas/frankenphp(=\S+)?#', '', $xcaddyModules);
$xcaddyModules = preg_replace('#--with github.com/dunglas/frankenphp/caddy(=\S+)?#', '', $xcaddyModules);
$xcaddyModules = "--with github.com/dunglas/frankenphp={$frankenphpSourceDir} " .
"--with github.com/dunglas/frankenphp/caddy={$frankenphpSourceDir}/caddy {$xcaddyModules}";
if ($this->getLib('brotli') === null && str_contains($xcaddyModules, '--with github.com/dunglas/caddy-cbrotli')) {
logger()->warning('caddy-cbrotli module is enabled, but brotli library is not built. Disabling caddy-cbrotli.');
$xcaddyModules = str_replace('--with github.com/dunglas/caddy-cbrotli', '', $xcaddyModules);
}
[, $out] = shell()->execWithResult('go list -m github.com/dunglas/frankenphp@latest');
$frankenPhpVersion = str_replace('github.com/dunglas/frankenphp v', '', $out[0]);

$frankenPhpVersion = $this->getFrankenPHPVersion();
$libphpVersion = $this->getPHPVersion();
$dynamic_exports = '';
if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') {
Expand Down Expand Up @@ -317,7 +366,7 @@ protected function buildFrankenphp(): void
'XCADDY_GO_BUILD_FLAGS' => '-buildmode=pie ' .
'-ldflags \"-linkmode=external ' . $extLdFlags . ' ' . $debugFlags .
'-X \'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP ' .
"{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " .
"v{$frankenPhpVersion} PHP {$libphpVersion} Caddy'\\\" " .
"-tags={$muslTags}nobadger,nomysql,nopgx{$nobrotli}{$nowatcher}",
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
];
Expand Down
1 change: 1 addition & 0 deletions src/SPC/command/BuildPHPCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public function configure(): void
$this->addOption('with-upx-pack', null, null, 'Compress / pack binary using UPX tool (linux/windows only)');
$this->addOption('with-micro-logo', null, InputOption::VALUE_REQUIRED, 'Use custom .ico for micro.sfx (windows only)');
$this->addOption('enable-micro-win32', null, null, 'Enable win32 mode for phpmicro (Windows only)');
$this->addOption('with-frankenphp-app', null, InputOption::VALUE_REQUIRED, 'Path to a folder to be embedded in FrankenPHP');
}

public function handle(): int
Expand Down