Skip to content

Commit 0a33fba

Browse files
committed
zig toolchain stuff
1 parent 5370af4 commit 0a33fba

File tree

10 files changed

+147
-36
lines changed

10 files changed

+147
-36
lines changed

config/env.ini

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,21 +65,23 @@ UPX_EXEC="${PKG_ROOT_PATH}\bin\upx.exe"
6565
SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime140,win32,zend_stream,cli_static
6666

6767
[linux]
68-
; Linux can use different build toolchain, but the toolchain can not be changed in this file:
69-
; - musl (default): used for general linux distros, can build `musl-static` target only.
70-
; - zig (WIP): used for general linux distros, can build `musl` and `glibc` targets.
71-
; - musl-native: used for alpine linux, can build `musl-static` and `musl`(WIP) target.
72-
; - gnu-native (assume): used for general linux distros, can build `glibc` target only and have portability issues.
68+
; Linux can use different build toolchains.
69+
; - musl (default, when SPC_LIBC=musl): used for general linux distros, can build `musl` (statically linked) only.
70+
; - zig (will become default): usable on all Linux distros, can build `-musl`, `arch-linux-musl -dynamic` and `arch-linux-gnu` targets. Can specify version such as `x86_64-linux-gnu.2.17`.
71+
; - musl-native: used for alpine linux, can build `musl` and `musl -dynamic` target.
72+
; - gnu-native: used for general linux distros, can build gnu target for the installed glibc version only.
7373

74-
; build target:
75-
; - musl-static (default): pure static linking, using musl-libc, can run on any linux distro.
76-
; - musl: static linking with dynamic linking to musl-libc, can run on musl-based linux distro.
77-
; - glibc: static linking with dynamic linking to glibc, can run on glibc-based linux distro.
78-
79-
; include PATH for musl libc.
74+
; LEGACY option to specify the target, switch to SPC_TARGET with zig toolchain instead
8075
SPC_LIBC=musl
81-
SPC_LIBC_VERSION=
82-
SPC_LIBC_LINKAGE=-static
76+
77+
; Recommended: specify your target here. Zig toolchain will be used.
78+
; examples:
79+
; `native-native-gnu` - links against glibc, version 2.17
80+
; `native-native-gnu.2.17` - links against glibc, version 2.17
81+
; `native-native` - static linking against musl
82+
; `native-native-musl -dynamic` - links against musl libc
83+
; SPC_TARGET=
84+
8385
; compiler environments
8486
CC=${SPC_LINUX_DEFAULT_CC}
8587
CXX=${SPC_LINUX_DEFAULT_CXX}

docs/en/guide/extension-notes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ and this extension cannot be compiled into php by static linking, so it cannot b
8282

8383
## xdebug
8484

85-
1. Xdebug is only buildable as a shared extension. You need to use a build target other than `musl-static` for SPC_TARGET.
85+
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`.
8686
2. When using Linux/glibc or macOS, you can compile Xdebug as a shared extension using --build-shared="xdebug".
8787
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`.
8888

src/SPC/builder/linux/LinuxBuilder.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use SPC\exception\WrongUsageException;
1111
use SPC\store\FileSystem;
1212
use SPC\store\SourcePatcher;
13+
use SPC\toolchain\ToolchainManager;
14+
use SPC\toolchain\ZigToolchain;
1315
use SPC\util\GlobalEnvManager;
1416

1517
class LinuxBuilder extends UnixBuilderBase
@@ -66,7 +68,7 @@ public function buildPHP(int $build_target = BUILD_TARGET_NONE): void
6668
}
6769
// add libstdc++, some extensions or libraries need it
6870
$extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCpp() ? '-lstdc++ ' : '');
69-
$extra_libs .= (SystemUtil::getCCType() === 'clang' ? ' -lunwind' : '');
71+
$extra_libs .= (ToolchainManager::getToolchainClass() === ZigToolchain::class ? ' -lunwind' : '');
7072
f_putenv('SPC_EXTRA_LIBS=' . $extra_libs);
7173
$cflags = $this->arch_c_flags;
7274
f_putenv('CFLAGS=' . $cflags);

src/SPC/builder/unix/library/libxslt.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ protected function build(): void
3333
'--without-debugger',
3434
"--with-libxml-prefix={$this->getBuildRootPath()}",
3535
);
36-
if (getenv('SPC_LINUX_DEFAULT_LD_LIBRARY_PATH') && getenv('SPC_LINUX_DEFAULT_LIBRARY_PATH')) {
36+
if (getenv('SPC_LD_LIBRARY_PATH') && getenv('SPC_LIBRARY_PATH')) {
3737
$ac->appendEnv([
38-
'LD_LIBRARY_PATH' => getenv('SPC_LINUX_DEFAULT_LD_LIBRARY_PATH'),
39-
'LIBRARY_PATH' => getenv('SPC_LINUX_DEFAULT_LIBRARY_PATH'),
38+
'LD_LIBRARY_PATH' => getenv('SPC_LD_LIBRARY_PATH'),
39+
'LIBRARY_PATH' => getenv('SPC_LIBRARY_PATH'),
4040
]);
4141
}
4242
$ac->configure()->make();

src/SPC/doctor/item/ZigCheck.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SPC\doctor\item;
6+
7+
use SPC\doctor\AsCheckItem;
8+
use SPC\doctor\AsFixItem;
9+
use SPC\doctor\CheckResult;
10+
use SPC\doctor\OptionalCheck;
11+
use SPC\exception\DownloaderException;
12+
use SPC\exception\FileSystemException;
13+
use SPC\exception\RuntimeException;
14+
use SPC\exception\WrongUsageException;
15+
use SPC\store\Downloader;
16+
use SPC\store\FileSystem;
17+
use SPC\store\PackageManager;
18+
use SPC\store\pkg\Zig;
19+
use SPC\store\SourcePatcher;
20+
use SPC\toolchain\MuslToolchain;
21+
use SPC\toolchain\ZigToolchain;
22+
23+
#[OptionalCheck([self::class, 'optionalCheck'])]
24+
class ZigCheck
25+
{
26+
public static function optionalCheck(): bool
27+
{
28+
return getenv('SPC_TOOLCHAIN') === ZigToolchain::class;
29+
}
30+
31+
/** @noinspection PhpUnused */
32+
#[AsCheckItem('if zig is installed', level: 800)]
33+
public function checkZig(): CheckResult
34+
{
35+
if (Zig::isInstalled()) {
36+
return CheckResult::ok();
37+
}
38+
return CheckResult::fail('zig is not installed', 'install-zig');
39+
}
40+
41+
/** @noinspection PhpUnused */
42+
/**
43+
* @throws FileSystemException
44+
* @throws WrongUsageException
45+
*/
46+
#[AsFixItem('install-zig')]
47+
public function fixMuslCrossMake(): bool
48+
{
49+
$arch = arch2gnu(php_uname('m'));
50+
$os = match (PHP_OS_FAMILY) {
51+
'Windows' => 'win',
52+
'Darwin' => 'macos',
53+
'BSD' => 'freebsd',
54+
default => 'linux',
55+
};
56+
PackageManager::installPackage("musl-toolchain-{$arch}-{$os}");
57+
return Zig::isInstalled();
58+
}
59+
}

src/SPC/store/pkg/CustomPackage.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@ abstract public function fetch(string $name, bool $force = false, ?array $config
1313
abstract public function extract(string $name): void;
1414

1515
abstract public static function getEnvironment(): array;
16+
17+
abstract public static function isInstalled(): bool;
1618
}

src/SPC/store/pkg/Zig.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,27 @@
1111

1212
class Zig extends CustomPackage
1313
{
14+
private static function getPath(): string
15+
{
16+
$arch = arch2gnu(php_uname('m'));
17+
$os = match (PHP_OS_FAMILY) {
18+
'Linux' => 'linux',
19+
'Windows' => 'win',
20+
'Darwin' => 'macos',
21+
'BSD' => 'freebsd',
22+
default => 'linux',
23+
};
24+
25+
$packageName = "zig-{$arch}-{$os}";
26+
return PKG_ROOT_PATH . "/{$packageName}";
27+
}
28+
29+
public static function isInstalled(): bool
30+
{
31+
$path = self::getPath();
32+
return file_exists("$path/zig") && file_exists("$path/zig-cc") && file_exists("$path/zig-c++");
33+
}
34+
1435
public function getSupportName(): array
1536
{
1637
return [

src/SPC/toolchain/MuslToolchain.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@ public function initEnv(): void
2020
GlobalEnvManager::addPathIfNotExists('/usr/local/musl/bin');
2121
GlobalEnvManager::addPathIfNotExists("/usr/local/musl/{$arch}-linux-musl/bin");
2222

23-
GlobalEnvManager::putenv("SPC_LINUX_DEFAULT_LD_LIBRARY_PATH=/usr/local/musl/lib:/usr/local/musl/{$arch}-linux-musl/lib");
24-
GlobalEnvManager::putenv("SPC_LINUX_DEFAULT_LIBRARY_PATH=/usr/local/musl/lib:/usr/local/musl/{$arch}-linux-musl/lib");
23+
GlobalEnvManager::putenv("SPC_LD_LIBRARY_PATH=/usr/local/musl/lib:/usr/local/musl/{$arch}-linux-musl/lib");
24+
GlobalEnvManager::putenv("SPC_LIBRARY_PATH=/usr/local/musl/lib:/usr/local/musl/{$arch}-linux-musl/lib");
2525
}
2626

2727
public function afterInit(): void
2828
{
2929
$arch = getenv('GNU_ARCH');
3030
// append LD_LIBRARY_PATH to $configure = getenv('SPC_CMD_PREFIX_PHP_CONFIGURE');
3131
$configure = getenv('SPC_CMD_PREFIX_PHP_CONFIGURE');
32-
$ld_library_path = getenv('SPC_LINUX_DEFAULT_LD_LIBRARY_PATH');
32+
$ld_library_path = getenv('SPC_LD_LIBRARY_PATH');
3333
GlobalEnvManager::putenv("SPC_CMD_PREFIX_PHP_CONFIGURE=LD_LIBRARY_PATH=\"{$ld_library_path}\" {$configure}");
3434

3535
if (!file_exists("/usr/local/musl/{$arch}-linux-musl/lib/libc.a")) {

src/SPC/toolchain/ToolchainManager.php

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,36 @@
1111
class ToolchainManager
1212
{
1313
public const array OS_DEFAULT_TOOLCHAIN = [
14-
'Linux' => MuslToolchain::class, // use musl toolchain by default, after zig pr merged, change this to ZigToolchain::class
14+
'Linux' => ZigToolchain::class,
1515
'Windows' => MSVCToolchain::class,
1616
'Darwin' => ClangNativeToolchain::class,
1717
'BSD' => ClangNativeToolchain::class,
1818
];
1919

20-
/**
21-
* @throws WrongUsageException
22-
*/
23-
public static function initToolchain(): void
20+
public static function getToolchainClass(): string
2421
{
2522
$libc = getenv('SPC_LIBC');
2623
if ($libc !== false) {
27-
// uncomment this when zig pr is merged
28-
// logger()->warning('SPC_LIBC is deprecated, please use SPC_TARGET instead.');
29-
$toolchain = match ($libc) {
24+
logger()->warning('SPC_LIBC is deprecated, please use SPC_TARGET instead.');
25+
return match ($libc) {
3026
'musl' => SystemUtil::isMuslDist() ? GccNativeToolchain::class : MuslToolchain::class,
31-
'glibc' => !SystemUtil::isMuslDist() ? GccNativeToolchain::class : throw new WrongUsageException('SPC_TARGET must be musl-static or musl for musl dist.'),
27+
'glibc' => !SystemUtil::isMuslDist() ? GccNativeToolchain::class : throw new WrongUsageException('SPC_TARGET must be musl for musl dist.'),
3228
default => throw new WrongUsageException('Unsupported SPC_LIBC value: ' . $libc),
3329
};
34-
} else {
35-
$toolchain = self::OS_DEFAULT_TOOLCHAIN[PHP_OS_FAMILY];
3630
}
37-
$toolchainClass = $toolchain;
31+
32+
return self::OS_DEFAULT_TOOLCHAIN[PHP_OS_FAMILY];
33+
}
34+
35+
/**
36+
* @throws WrongUsageException
37+
*/
38+
public static function initToolchain(): void
39+
{
40+
$toolchainClass = self::getToolchainClass();
3841
/* @var ToolchainInterface $toolchainClass */
3942
(new $toolchainClass())->initEnv();
40-
GlobalEnvManager::putenv("SPC_TOOLCHAIN={$toolchain}");
43+
GlobalEnvManager::putenv("SPC_TOOLCHAIN={$toolchainClass}");
4144
}
4245

4346
public static function afterInitToolchain(): void

src/SPC/toolchain/ZigToolchain.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,31 @@
44

55
namespace SPC\toolchain;
66

7+
use SPC\exception\WrongUsageException;
8+
use SPC\store\pkg\Zig;
9+
use SPC\util\GlobalEnvManager;
10+
711
class ZigToolchain implements ToolchainInterface
812
{
9-
public function initEnv(): void {}
13+
public function initEnv(): void
14+
{
15+
$arch = getenv('GNU_ARCH');
16+
// Set environment variables for musl toolchain
17+
GlobalEnvManager::putenv("SPC_LINUX_DEFAULT_CC=zig-cc");
18+
GlobalEnvManager::putenv("SPC_LINUX_DEFAULT_CXX=zig-c++");
19+
GlobalEnvManager::putenv("SPC_LINUX_DEFAULT_AR=ar");
20+
GlobalEnvManager::putenv("SPC_LINUX_DEFAULT_LD=ld");
21+
GlobalEnvManager::addPathIfNotExists('/usr/local/musl/bin');
22+
GlobalEnvManager::addPathIfNotExists("/usr/local/musl/{$arch}-linux-musl/bin");
23+
24+
GlobalEnvManager::putenv("SPC_LD_LIBRARY_PATH=/usr/local/musl/lib:/usr/local/musl/{$arch}-linux-musl/lib");
25+
GlobalEnvManager::putenv("SPC_LIBRARY_PATH=/usr/local/musl/lib:/usr/local/musl/{$arch}-linux-musl/lib");
26+
}
1027

11-
public function afterInit(): void {}
28+
public function afterInit(): void
29+
{
30+
if (!is_dir(Zig::getEnvironment()['PATH'])) {
31+
throw new WrongUsageException('You are building with zig, but zig is not installed, please install zig first. (You can use `doctor` command to install it)');
32+
}
33+
}
1234
}

0 commit comments

Comments
 (0)