Skip to content

Commit 4f76942

Browse files
committed
toolchain fixes forward port from v2-pgo
1 parent ca8a28a commit 4f76942

11 files changed

Lines changed: 260 additions & 35 deletions

File tree

config/env.ini

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ SPC_TARGET=${GNU_ARCH}-linux-musl
100100
CC=${SPC_DEFAULT_CC}
101101
CXX=${SPC_DEFAULT_CXX}
102102
AR=${SPC_DEFAULT_AR}
103+
RANLIB=${SPC_DEFAULT_RANLIB}
103104
LD=${SPC_DEFAULT_LD}
104105
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
105106
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"
@@ -125,6 +126,8 @@ SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE
125126
SPC_CMD_VAR_PHP_MAKE_EXTRA_CXXFLAGS="-g -fstack-protector-strong -fno-ident -fPIE -fvisibility=hidden -fvisibility-inlines-hidden ${SPC_DEFAULT_CXXFLAGS}"
126127
; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so
127128
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=""
129+
; EXTRA_LDFLAGS_PROGRAM for `make` php; appended only to SAPI executable links (cli/fpm/cgi/micro/embed). Used by PGO to inject -fprofile-use= without polluting libphp.{a,so}.
130+
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM=""
128131

129132
; optional, path to openssl conf. This affects where openssl will look for the default CA.
130133
; default on Debian/Alpine: /etc/ssl, default on RHEL: /etc/pki/tls
@@ -140,6 +143,7 @@ SPC_USE_LLVM=system
140143
CC=${SPC_DEFAULT_CC}
141144
CXX=${SPC_DEFAULT_CXX}
142145
AR=${SPC_DEFAULT_AR}
146+
RANLIB=${SPC_DEFAULT_RANLIB}
143147
LD=${SPC_DEFAULT_LD}
144148
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
145149
SPC_DEFAULT_CFLAGS="--target=${MAC_ARCH}-apple-darwin -O3 -fno-plt -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffunction-sections -fdata-sections"
@@ -163,5 +167,7 @@ SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fpic -fpie -fvis
163167
SPC_CMD_VAR_PHP_MAKE_EXTRA_CXXFLAGS="-g -fstack-protector-strong -fno-ident -fpie -fvisibility=hidden -fvisibility-inlines-hidden -Werror=unknown-warning-option ${SPC_DEFAULT_CXXFLAGS}"
164168
; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.dylib
165169
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS=""
170+
; EXTRA_LDFLAGS_PROGRAM for `make` php; appended only to SAPI executable links (cli/fpm/cgi/micro/embed). Used by PGO to inject -fprofile-use= without polluting libphp.{a,dylib}.
171+
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS_PROGRAM=""
166172
; minimum compatible macOS version (LLVM vars, availability not guaranteed)
167173
MACOSX_DEPLOYMENT_TARGET=12.0

src/Package/Artifact/go_xcaddy.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public function afterExtract(string $target_path): void
109109
'GOROOT' => "{$target_path}",
110110
'GOBIN' => "{$target_path}/bin",
111111
'GOPATH' => "{$target_path}/go",
112-
])->exec('CC=cc go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest');
112+
])->exec('CGO_ENABLED=0 go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest');
113113
GlobalEnvManager::addPathIfNotExists("{$target_path}/bin");
114114
}
115115
}

src/Package/Artifact/zig.php

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use StaticPHP\Attribute\Artifact\CustomBinaryCheckUpdate;
1313
use StaticPHP\Exception\DownloaderException;
1414
use StaticPHP\Runtime\SystemTarget;
15+
use StaticPHP\Util\FileSystem;
1516

1617
class zig
1718
{
@@ -131,5 +132,151 @@ public function postExtractZig(string $target_path): void
131132
chmod("{$target_path}/zig-ld.lld", 0755);
132133
chmod("{$target_path}/zig-ranlib", 0755);
133134
chmod("{$target_path}/zig-objcopy", 0755);
135+
136+
// Build the clang runtime bits zig 0.15+ doesn't ship: profile runtime
137+
// (so -fprofile-generate actually emits .profraw) and crtbegin/crtend
138+
// (so shared libs get __dso_handle and the __cxa_finalize atexit hook).
139+
// These get auto-linked by the zig-cc wrapper when the right flags fly past.
140+
$this->buildClangRuntimeBits($target_path);
141+
}
142+
143+
/**
144+
* Detect the bundled clang version and build the missing clang runtime
145+
* archives into `<zig>/lib/`. Compiles from a 2 MB compiler-rt-<llvm>.src
146+
* tarball — far cheaper than fetching the 2 GB prebuilt LLVM tarball.
147+
*/
148+
private function buildClangRuntimeBits(string $zig_bin_dir): void
149+
{
150+
if (PHP_OS_FAMILY !== 'Linux') {
151+
return;
152+
}
153+
$libDir = "{$zig_bin_dir}/lib";
154+
$profileLib = "{$libDir}/libclang_rt.profile.a";
155+
$crtBegin = "{$libDir}/clang_rt.crtbegin.o";
156+
$crtEnd = "{$libDir}/clang_rt.crtend.o";
157+
if (file_exists($profileLib) && file_exists($crtBegin) && file_exists($crtEnd)) {
158+
return;
159+
}
160+
161+
$zig = "{$zig_bin_dir}/zig";
162+
$verLine = trim((string) shell_exec(escapeshellarg($zig) . ' cc --version 2>/dev/null'));
163+
if (!preg_match('/clang version (\d+\.\d+\.\d+)/', $verLine, $m)) {
164+
logger()->warning('[zig] could not detect bundled clang version; skipping runtime bit build (PGO + shared libs without __dso_handle will fail to link)');
165+
return;
166+
}
167+
$llvmVersion = $m[1];
168+
logger()->info("Building clang runtime bits for LLVM {$llvmVersion} (zig's bundled clang)");
169+
170+
$srcRoot = $this->fetchCompilerRtSource($llvmVersion);
171+
if ($srcRoot === null) {
172+
return;
173+
}
174+
175+
f_mkdir($libDir, recursive: true);
176+
if (!file_exists($profileLib)) {
177+
$this->buildProfileRuntime($zig, $srcRoot, $profileLib);
178+
}
179+
if (!file_exists($crtBegin) || !file_exists($crtEnd)) {
180+
$this->buildCrtObjects($zig, $srcRoot, $crtBegin, $crtEnd);
181+
}
182+
FileSystem::removeDir($srcRoot);
183+
}
184+
185+
private function fetchCompilerRtSource(string $llvmVersion): ?string
186+
{
187+
$tarball = "compiler-rt-{$llvmVersion}.src.tar.xz";
188+
$url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-{$llvmVersion}/{$tarball}";
189+
$tarballPath = DOWNLOAD_PATH . '/' . $tarball;
190+
if (!file_exists($tarballPath)) {
191+
try {
192+
default_shell()->executeCurlDownload($url, $tarballPath);
193+
} catch (\Throwable $e) {
194+
logger()->warning("[zig] failed to download {$tarball}: {$e->getMessage()}");
195+
return null;
196+
}
197+
}
198+
$srcRoot = PKG_ROOT_PATH . "/compiler-rt-src-{$llvmVersion}";
199+
FileSystem::removeDir($srcRoot);
200+
FileSystem::createDir($srcRoot);
201+
try {
202+
default_shell()->executeTarExtract($tarballPath, $srcRoot, 'xz');
203+
} catch (\Throwable $e) {
204+
logger()->warning("[zig] failed to extract {$tarball}: {$e->getMessage()}");
205+
return null;
206+
}
207+
return $srcRoot;
208+
}
209+
210+
private function buildProfileRuntime(string $zig, string $srcRoot, string $libPath): void
211+
{
212+
$profileSrc = "{$srcRoot}/lib/profile";
213+
$profileInc = "{$srcRoot}/include";
214+
if (!is_dir($profileSrc)) {
215+
logger()->warning("[zig] profile src dir missing at {$profileSrc} — PGO will not work");
216+
return;
217+
}
218+
$sources = array_merge(
219+
glob("{$profileSrc}/*.c") ?: [],
220+
glob("{$profileSrc}/*.cpp") ?: []
221+
);
222+
// Keep Linux-only compilation units; the others bring in OS-specific headers
223+
// we can't satisfy without their respective SDKs.
224+
$skip = ['/PlatformAIX', '/PlatformDarwin', '/PlatformFuchsia', '/PlatformOther', '/PlatformWindows', '/WindowsMMap'];
225+
$sources = array_filter($sources, function ($f) use ($skip) {
226+
foreach ($skip as $s) {
227+
if (str_contains($f, $s)) {
228+
return false;
229+
}
230+
}
231+
return true;
232+
});
233+
234+
$objDir = "{$srcRoot}/obj-profile";
235+
f_mkdir($objDir, recursive: true);
236+
$cflags = '-c -O2 -fPIC -fvisibility=hidden ' .
237+
'-I' . escapeshellarg($profileInc) . ' ' .
238+
'-DCOMPILER_RT_HAS_ATOMICS=1 -DCOMPILER_RT_HAS_FCNTL_LCK=1 -DCOMPILER_RT_HAS_UNAME=1';
239+
$objs = [];
240+
foreach ($sources as $src) {
241+
$obj = $objDir . '/' . pathinfo($src, PATHINFO_FILENAME) . '.o';
242+
$cmd = escapeshellarg($zig) . ' cc ' . $cflags . ' -o ' . escapeshellarg($obj) . ' ' . escapeshellarg($src) . ' 2>&1';
243+
if (!$this->runZigCmd($cmd, $obj, "failed to compile {$src}")) {
244+
return;
245+
}
246+
$objs[] = $obj;
247+
}
248+
$arCmd = escapeshellarg($zig) . ' ar rcs ' . escapeshellarg($libPath) . ' ' . implode(' ', array_map('escapeshellarg', $objs)) . ' 2>&1';
249+
if (!$this->runZigCmd($arCmd, $libPath, 'zig ar failed')) {
250+
return;
251+
}
252+
logger()->info('[zig] libclang_rt.profile.a installed (' . filesize($libPath) . ' bytes)');
253+
}
254+
255+
private function buildCrtObjects(string $zig, string $srcRoot, string $crtBegin, string $crtEnd): void
256+
{
257+
$beginSrc = "{$srcRoot}/lib/builtins/crtbegin.c";
258+
$endSrc = "{$srcRoot}/lib/builtins/crtend.c";
259+
if (!is_file($beginSrc) || !is_file($endSrc)) {
260+
logger()->error("[zig] crtbegin/crtend source missing under {$srcRoot}/lib/builtins — shared libs will lack __dso_handle");
261+
return;
262+
}
263+
$cflags = '-c -O2 -fPIC -fvisibility=hidden -DCRT_HAS_INITFINI_ARRAY';
264+
foreach ([[$beginSrc, $crtBegin], [$endSrc, $crtEnd]] as [$src, $dst]) {
265+
$cmd = escapeshellarg($zig) . ' cc ' . $cflags . ' -o ' . escapeshellarg($dst) . ' ' . escapeshellarg($src) . ' 2>&1';
266+
if (!$this->runZigCmd($cmd, $dst, "failed to compile {$src}")) {
267+
return;
268+
}
269+
}
270+
logger()->info('[zig] clang_rt.crtbegin.o + clang_rt.crtend.o installed (' . filesize($crtBegin) . ' + ' . filesize($crtEnd) . ' bytes)');
271+
}
272+
273+
private function runZigCmd(string $cmd, string $dst, string $errPrefix): bool
274+
{
275+
exec($cmd, $out, $rc);
276+
if ($rc !== 0 || !is_file($dst)) {
277+
logger()->warning("[zig] {$errPrefix}: " . implode("\n", $out));
278+
return false;
279+
}
280+
return true;
134281
}
135282
}

src/StaticPHP/Doctor/Item/LinuxMuslCheck.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,20 @@ public function fixMusl(): bool
7373
$prefix = 'sudo ';
7474
logger()->warning('Current user is not root, using sudo for running command');
7575
}
76+
$sysEnv = ['CC' => 'gcc', 'CXX' => 'g++', 'AR' => 'ar', 'LD' => 'ld', 'RANLIB' => 'ranlib'];
77+
$envFlags = '';
78+
foreach ($sysEnv as $k => $v) {
79+
$envFlags .= "{$k}={$v} ";
80+
}
81+
$envFlags = rtrim($envFlags);
7682
$shell = shell()->cd(SOURCE_PATH . '/musl-wrapper')
77-
->exec('CC=gcc CXX=g++ AR=ar LD=ld ./configure --disable-gcc-wrapper')
78-
->exec('CC=gcc CXX=g++ AR=ar LD=ld make -j');
83+
->setEnv($sysEnv)
84+
->exec('./configure --disable-gcc-wrapper')
85+
->exec('make -j');
7986
if ($prefix !== '') {
80-
f_passthru('cd ' . SOURCE_PATH . "/musl-wrapper && CC=gcc CXX=g++ AR=ar LD=ld {$prefix}make install");
87+
f_passthru('cd ' . SOURCE_PATH . "/musl-wrapper && {$envFlags} {$prefix}make install");
8188
} else {
82-
$shell->exec("CC=gcc CXX=g++ AR=ar LD=ld {$prefix}make install");
89+
$shell->exec("{$prefix}make install");
8390
}
8491
return true;
8592
}

src/StaticPHP/Package/PhpExtensionPackage.php

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,14 +274,20 @@ public function getSharedExtensionEnv(): array
274274
$compiler_extra = trim($compiler_extra . ' -lcompiler_rt');
275275
GlobalEnvManager::putenv("SPC_COMPILER_EXTRA={$compiler_extra}");
276276
}
277-
$config = (new SPCConfigUtil())->getExtensionConfig($this);
277+
// include_suggests so transitive optional libs (e.g. librdkafka → lz4/zstd/ssl) are in the link line
278+
$config = (new SPCConfigUtil())->getExtensionConfig($this, include_suggests: true);
278279
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
279280
$preStatic = PHP_OS_FAMILY === 'Darwin' ? '' : '-Wl,--start-group ';
280281
$postStatic = PHP_OS_FAMILY === 'Darwin' ? '' : ' -Wl,--end-group ';
282+
// -Wl,-Bsymbolic: bind zend_* refs to the .so's own copies, not via global lookup
283+
$ldflags = (string) $config['ldflags'];
284+
if (PHP_OS_FAMILY !== 'Darwin' && !str_contains($ldflags, '-Wl,-Bsymbolic')) {
285+
$ldflags = clean_spaces($ldflags . ' -Wl,-Bsymbolic');
286+
}
281287
return [
282288
'CFLAGS' => $config['cflags'],
283289
'CXXFLAGS' => $config['cflags'],
284-
'LDFLAGS' => $config['ldflags'],
290+
'LDFLAGS' => $ldflags,
285291
'LIBS' => clean_spaces("{$preStatic} {$staticLibs} {$postStatic} {$sharedLibs}"),
286292
'LD_LIBRARY_PATH' => BUILD_LIB_PATH,
287293
];
@@ -303,10 +309,11 @@ public function phpizeForUnix(array $env, PhpExtensionPackage $package): void
303309
public function configureForUnix(array $env, PhpExtensionPackage $package): void
304310
{
305311
$phpvars = getenv('SPC_EXTRA_PHP_VARS') ?: '';
312+
// CustomPhpConfigureArg keys are OS names ('Linux'/'Darwin'), not platform strings
306313
shell()->cd($package->getSourceDir())
307314
->setEnv($env)
308315
->exec(
309-
'./configure ' . $this->getPhpConfigureArg(SystemTarget::getCurrentPlatformString(), true) .
316+
'./configure ' . $this->getPhpConfigureArg(SystemTarget::getTargetOS(), true) .
310317
' --with-php-config=' . BUILD_BIN_PATH . '/php-config ' .
311318
"--enable-shared --disable-static {$phpvars}"
312319
);
@@ -318,13 +325,43 @@ public function configureForUnix(array $env, PhpExtensionPackage $package): void
318325
#[Stage]
319326
public function makeForUnix(array $env, PhpExtensionPackage $package, PackageBuilder $builder): void
320327
{
328+
// phpize Makefile's _SHARED_LIBADD line misses our static archives — splice them in
329+
$package->patchSharedLibAdd();
321330
shell()->cd($package->getSourceDir())
322331
->setEnv($env)
323332
->exec('make clean')
324333
->exec("make -j{$builder->concurrency}")
325334
->exec('make install');
326335
}
327336

337+
public function patchSharedLibAdd(): void
338+
{
339+
// include_suggests so transitive optional libs (e.g. librdkafka → lz4/zstd/ssl) are in the link line
340+
$config = (new SPCConfigUtil())->getExtensionConfig($this, include_suggests: true);
341+
[$staticLibs, $sharedLibs] = $this->splitLibsIntoStaticAndShared($config['libs']);
342+
$lstdcpp = str_contains($sharedLibs, '-l:libstdc++.a')
343+
? '-l:libstdc++.a'
344+
: (str_contains($sharedLibs, '-lstdc++') ? '-lstdc++' : '');
345+
346+
$makefile = $this->getSourceDir() . '/Makefile';
347+
if (!is_file($makefile)) {
348+
return;
349+
}
350+
$content = (string) file_get_contents($makefile);
351+
if (!preg_match('/^(.*_SHARED_LIBADD\s*=\s*)(.*)$/m', $content, $m)) {
352+
return;
353+
}
354+
$prefix = $m[1];
355+
$current = trim($m[2]);
356+
$merged = clean_spaces("{$current} {$staticLibs} {$lstdcpp}");
357+
$merged = deduplicate_flags($merged);
358+
\StaticPHP\Util\FileSystem::replaceFileRegex(
359+
$makefile,
360+
'/^(.*_SHARED_LIBADD\s*=.*)$/m',
361+
$prefix . $merged
362+
);
363+
}
364+
328365
/**
329366
* Build shared extension on Unix-like systems.
330367
* Only for internal calling. For external use, call buildShared() instead.
@@ -333,6 +370,21 @@ public function makeForUnix(array $env, PhpExtensionPackage $package, PackageBui
333370
*/
334371
public function buildSharedForUnix(PackageBuilder $builder): void
335372
{
373+
// skip virtual addons (arg-type=none + display-name → owning ext); the parent ext built it
374+
$argType = $this->extension_config['arg-type'] ?? null;
375+
$displayName = $this->extension_config['display-name'] ?? null;
376+
if ($argType === 'none' && $displayName !== null && $displayName !== $this->getExtensionName()) {
377+
logger()->info("Skipping virtual extension [{$this->getName()}] — it's part of [{$displayName}].");
378+
return;
379+
}
380+
381+
if (!is_dir($this->getSourceDir())) {
382+
throw new ValidationException(
383+
"Extension source directory not found: {$this->getSourceDir()}",
384+
validation_module: "Extension {$this->getName()} source"
385+
);
386+
}
387+
336388
$env = $this->getSharedExtensionEnv();
337389

338390
$this->runStage([$this, 'phpizeForUnix'], ['env' => $env]);

src/StaticPHP/Runtime/Executor/UnixCMakeExecutor.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ private function getDefaultCMakeArgs(): array
230230

231231
// EXE linker flags: base system libs + framework flags for target packages
232232
$exeLinkerFlags = SystemTarget::getRuntimeLibs();
233-
if ($this->package instanceof TargetPackage) {
233+
if ($this->package instanceof TargetPackage && SystemTarget::getTargetOS() === 'Darwin') {
234234
$resolvedNames = array_keys($this->installer->getResolvedPackages());
235235
$resolvedNames[] = $this->package->getName();
236236
$fwFlags = new SPCConfigUtil()->getFrameworksString($resolvedNames);
@@ -302,9 +302,12 @@ private function makeCmakeToolchainFile(): string
302302
set(CMAKE_C_STANDARD_INCLUDE_DIRECTORIES "{$include}")
303303
set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES "{$include}")
304304
CMAKE;
305-
// Whoops, linux may need CMAKE_AR sometimes
305+
// pin AR/RANLIB so cmake uses zig-ar/zig-ranlib instead of system /usr/bin/ranlib (zig archives need it)
306306
if (PHP_OS_FAMILY === 'Linux') {
307-
$toolchain .= "\nSET(CMAKE_AR \"ar\")";
307+
$ar = getenv('SPC_DEFAULT_AR') ?: getenv('AR') ?: 'ar';
308+
$ranlib = getenv('SPC_DEFAULT_RANLIB') ?: (getenv('RANLIB') ?: 'ranlib');
309+
$toolchain .= "\nSET(CMAKE_AR \"{$ar}\")";
310+
$toolchain .= "\nSET(CMAKE_RANLIB \"{$ranlib}\")";
308311
}
309312
FileSystem::writeFile(SOURCE_PATH . '/toolchain.cmake', $toolchain);
310313
return $created = realpath(SOURCE_PATH . '/toolchain.cmake');

src/StaticPHP/Toolchain/ClangBrewToolchain.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public function initEnv(): void
1515
GlobalEnvManager::putenv("SPC_DEFAULT_CC={$homebrew_prefix}/opt/llvm/bin/clang");
1616
GlobalEnvManager::putenv("SPC_DEFAULT_CXX={$homebrew_prefix}/opt/llvm/bin/clang++");
1717
GlobalEnvManager::putenv("SPC_DEFAULT_AR={$homebrew_prefix}/opt/llvm/bin/llvm-ar");
18+
GlobalEnvManager::putenv("SPC_DEFAULT_RANLIB={$homebrew_prefix}/opt/llvm/bin/llvm-ranlib");
1819
GlobalEnvManager::putenv('SPC_DEFAULT_LD=ld');
1920
GlobalEnvManager::addPathIfNotExists("{$homebrew_prefix}/opt/llvm/bin");
2021
}

src/StaticPHP/Toolchain/ClangNativeToolchain.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public function initEnv(): void
2121
GlobalEnvManager::putenv('SPC_DEFAULT_CC=clang');
2222
GlobalEnvManager::putenv('SPC_DEFAULT_CXX=clang++');
2323
GlobalEnvManager::putenv('SPC_DEFAULT_AR=ar');
24+
GlobalEnvManager::putenv('SPC_DEFAULT_RANLIB=ranlib');
2425
GlobalEnvManager::putenv('SPC_DEFAULT_LD=ld');
2526
}
2627

src/StaticPHP/Toolchain/GccNativeToolchain.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public function initEnv(): void
1818
GlobalEnvManager::putenv('SPC_DEFAULT_CC=gcc');
1919
GlobalEnvManager::putenv('SPC_DEFAULT_CXX=g++');
2020
GlobalEnvManager::putenv('SPC_DEFAULT_AR=ar');
21+
GlobalEnvManager::putenv('SPC_DEFAULT_RANLIB=ranlib');
2122
GlobalEnvManager::putenv('SPC_DEFAULT_LD=ld');
2223
}
2324

0 commit comments

Comments
 (0)