diff --git a/config/env.ini b/config/env.ini index 58668cc5..65fad077 100644 --- a/config/env.ini +++ b/config/env.ini @@ -103,7 +103,7 @@ AR=${SPC_DEFAULT_AR} RANLIB=${SPC_DEFAULT_RANLIB} LD=${SPC_DEFAULT_LD} ; default compiler flags, used in CMake toolchain file, openssl and pkg-config build -SPC_DEFAULT_CFLAGS="-fPIC -O3 -pipe -fno-plt -fno-semantic-interposition -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffunction-sections -fdata-sections" +SPC_DEFAULT_CFLAGS="-fPIC -O3 -pipe -fno-plt -fno-semantic-interposition -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffunction-sections -fdata-sections -Wno-unused-command-line-argument" SPC_DEFAULT_CXXFLAGS="${SPC_DEFAULT_CFLAGS}" SPC_DEFAULT_LDFLAGS="-Wl,-z,relro -Wl,--as-needed -Wl,-z,now -Wl,-z,noexecstack -Wl,--gc-sections" ; upx executable path diff --git a/src/Package/Target/php.php b/src/Package/Target/php.php index b2dd3af2..caf0eb18 100644 --- a/src/Package/Target/php.php +++ b/src/Package/Target/php.php @@ -270,12 +270,14 @@ class php extends TargetPackage } } // linux does not support loading shared libraries when target is pure static - $embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static'; - if (SystemTarget::getTargetOS() === 'Linux' && ApplicationContext::get(ToolchainInterface::class)->isStatic() && $embed_type === 'shared') { - throw new WrongUsageException( - 'Linux does not support loading shared libraries when linking libc statically. ' . - 'Change SPC_CMD_VAR_PHP_EMBED_TYPE to static.' - ); + if ($package->getName() === 'php-embed') { + $embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static'; + if (SystemTarget::getTargetOS() === 'Linux' && ApplicationContext::get(ToolchainInterface::class)->isStatic() && $embed_type === 'shared') { + throw new WrongUsageException( + 'Linux does not support loading shared libraries when linking libc statically. ' . + 'Change SPC_CMD_VAR_PHP_EMBED_TYPE to static.' + ); + } } } diff --git a/src/Package/Target/php/unix.php b/src/Package/Target/php/unix.php index b8d3371a..805813ea 100644 --- a/src/Package/Target/php/unix.php +++ b/src/Package/Target/php/unix.php @@ -128,6 +128,10 @@ trait unix $args[] = $installer->isPackageResolved('php-cgi') ? '--enable-cgi' : '--disable-cgi'; $embed_type = getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') ?: 'static'; $args[] = $installer->isPackageResolved('php-embed') ? "--enable-embed={$embed_type}" : '--disable-embed'; + // Cross-compile: pass --host so configure picks the correct fiber asm file and host_cpu logic + if ($host_triple = SystemTarget::getAutoconfHostTriple()) { + $args[] = "--host={$host_triple}"; + } $args[] = getenv('SPC_EXTRA_PHP_VARS') ?: null; $args = implode(' ', array_filter($args)); diff --git a/src/StaticPHP/Package/PackageBuilder.php b/src/StaticPHP/Package/PackageBuilder.php index 582fa474..e24db6ae 100644 --- a/src/StaticPHP/Package/PackageBuilder.php +++ b/src/StaticPHP/Package/PackageBuilder.php @@ -15,6 +15,7 @@ use StaticPHP\Util\FileSystem; use StaticPHP\Util\GlobalPathTrait; use StaticPHP\Util\InteractiveTerm; use StaticPHP\Util\System\LinuxUtil; +use StaticPHP\Util\System\UnixUtil; class PackageBuilder { @@ -178,14 +179,15 @@ class PackageBuilder if (SystemTarget::getTargetOS() === 'Darwin') { shell()->exec("dsymutil -f {$binary_path} -o {$debug_file}"); } elseif (SystemTarget::getTargetOS() === 'Linux') { + $objcopy = LinuxUtil::findCommand('llvm-objcopy') ?: 'objcopy'; if ($eu_strip = LinuxUtil::findCommand('eu-strip')) { shell() ->exec("{$eu_strip} -f {$debug_file} {$binary_path}") - ->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}"); + ->exec("{$objcopy} --add-gnu-debuglink={$debug_file} {$binary_path}"); } else { shell() - ->exec("objcopy --only-keep-debug {$binary_path} {$debug_file}") - ->exec("objcopy --add-gnu-debuglink={$debug_file} {$binary_path}"); + ->exec("{$objcopy} --only-keep-debug {$binary_path} {$debug_file}") + ->exec("{$objcopy} --add-gnu-debuglink={$debug_file} {$binary_path}"); } } else { logger()->debug('extractDebugInfo is only supported on Linux and macOS'); @@ -199,9 +201,10 @@ class PackageBuilder */ public function stripBinary(string $binary_path): void { + $strip = UnixUtil::findCommand('llvm-strip') ?: 'strip'; shell()->exec(match (SystemTarget::getTargetOS()) { - 'Darwin' => "strip -S {$binary_path}", - 'Linux' => "strip --strip-unneeded {$binary_path}", + 'Darwin' => "{$strip} -S {$binary_path}", + 'Linux' => "{$strip} --strip-unneeded {$binary_path}", 'Windows' => 'echo "Skip strip on Windows"', // Windows strip is not available for now default => throw new SPCInternalException('stripBinary is only supported on Linux and macOS'), }); diff --git a/src/StaticPHP/Runtime/Executor/UnixAutoconfExecutor.php b/src/StaticPHP/Runtime/Executor/UnixAutoconfExecutor.php index c59859cf..b206fee1 100644 --- a/src/StaticPHP/Runtime/Executor/UnixAutoconfExecutor.php +++ b/src/StaticPHP/Runtime/Executor/UnixAutoconfExecutor.php @@ -11,6 +11,7 @@ use StaticPHP\Package\LibraryPackage; use StaticPHP\Package\PackageBuilder; use StaticPHP\Package\PackageInstaller; use StaticPHP\Runtime\Shell\UnixShell; +use StaticPHP\Runtime\SystemTarget; use StaticPHP\Util\InteractiveTerm; use ZM\Logger\ConsoleColor; @@ -149,13 +150,17 @@ class UnixAutoconfExecutor extends Executor */ private function getDefaultConfigureArgs(): array { - return [ + $args = [ '--disable-shared', '--enable-static', "--prefix={$this->package->getBuildRootPath()}", '--with-pic', '--enable-pic', ]; + if ($host_triple = SystemTarget::getAutoconfHostTriple()) { + $args[] = "--host={$host_triple}"; + } + return $args; } /** diff --git a/src/StaticPHP/Runtime/SystemTarget.php b/src/StaticPHP/Runtime/SystemTarget.php index 489f8438..b1f086c1 100644 --- a/src/StaticPHP/Runtime/SystemTarget.php +++ b/src/StaticPHP/Runtime/SystemTarget.php @@ -127,4 +127,35 @@ class SystemTarget { return in_array(self::getTargetOS(), ['Linux', 'Darwin', 'BSD']); } + + /** + * Returns a GNU host triple for autoconf --host= when SPC_TARGET names an + * architecture different from the build host (true cross-compile). + * Returns null for same-arch builds. + * Strips libc version suffix (-gnu.2.17 → -gnu) and trailing flags (e.g. ' -dynamic'). + */ + public static function getAutoconfHostTriple(): ?string + { + $target = (string) getenv('SPC_TARGET'); + if ($target === '' || str_contains($target, 'native')) { + return null; + } + $cleaned = preg_split('/\s+/', trim((string) preg_replace('/(-gnu|-musl)\.[\d.]+/', '$1', $target)))[0]; + if ($cleaned === '') { + return null; + } + // Only emit --host for true cross-arch builds; same-arch (incl. cross-libc) lets autoconf detect. + $target_arch_token = explode('-', $cleaned)[0]; + $arch_aliases = [ + 'x86_64' => ['x86_64', 'amd64'], + 'aarch64' => ['aarch64', 'arm64'], + 'arm' => ['arm', 'armv6', 'armv7', 'armhf', 'armel'], + 'i386' => ['i386', 'i486', 'i586', 'i686'], + ]; + $host_arch = GNU_ARCH; + if (array_any($arch_aliases, fn ($aliases) => in_array($target_arch_token, $aliases, true) && in_array($host_arch, $aliases, true))) { + return null; + } + return $cleaned; + } }