mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-13 20:05:35 +08:00
use arch-linux-musl toolchains
This commit is contained in:
@@ -18,9 +18,6 @@ class LinuxBuilder extends BuilderBase
|
|||||||
/** Unix compatible builder methods */
|
/** Unix compatible builder methods */
|
||||||
use UnixBuilderTrait;
|
use UnixBuilderTrait;
|
||||||
|
|
||||||
/** @var string Using libc [musl,glibc] */
|
|
||||||
public string $libc;
|
|
||||||
|
|
||||||
/** @var array Tune cflags */
|
/** @var array Tune cflags */
|
||||||
public array $tune_c_flags;
|
public array $tune_c_flags;
|
||||||
|
|
||||||
@@ -40,20 +37,19 @@ class LinuxBuilder extends BuilderBase
|
|||||||
$this->options = $options;
|
$this->options = $options;
|
||||||
|
|
||||||
// ---------- set necessary options ----------
|
// ---------- set necessary options ----------
|
||||||
// set C Compiler (default: alpine: gcc, others: musl-gcc)
|
// set C/C++ compilers (default: alpine: gcc, others: musl-cross-make)
|
||||||
$this->setOptionIfNotExist('cc', match (SystemUtil::getOSRelease()['dist']) {
|
if (SystemUtil::isMuslDist()) {
|
||||||
'alpine' => 'gcc',
|
$this->setOptionIfNotExist('cc', 'gcc');
|
||||||
default => 'musl-gcc'
|
$this->setOptionIfNotExist('cxx', 'g++');
|
||||||
});
|
} else {
|
||||||
// set C++ Compiler (default: g++)
|
$arch = arch2gnu(php_uname('m'));
|
||||||
$this->setOptionIfNotExist('cxx', 'g++');
|
$this->setOptionIfNotExist('cc', "{$arch}-linux-musl-gcc");
|
||||||
|
$this->setOptionIfNotExist('cxx', "{$arch}-linux-musl-g++");
|
||||||
|
}
|
||||||
// set arch (default: current)
|
// set arch (default: current)
|
||||||
$this->setOptionIfNotExist('arch', php_uname('m'));
|
$this->setOptionIfNotExist('arch', php_uname('m'));
|
||||||
$this->setOptionIfNotExist('gnu-arch', arch2gnu($this->getOption('arch')));
|
$this->setOptionIfNotExist('gnu-arch', arch2gnu($this->getOption('arch')));
|
||||||
|
|
||||||
// ---------- set necessary compile environments ----------
|
|
||||||
// set libc
|
|
||||||
$this->libc = $this->getOption('cc', 'gcc') === 'musl-gcc' ? 'musl_wrapper' : 'musl'; // SystemUtil::selectLibc($this->cc);
|
|
||||||
// concurrency
|
// concurrency
|
||||||
$this->concurrency = SystemUtil::getCpuCount();
|
$this->concurrency = SystemUtil::getCpuCount();
|
||||||
// cflags
|
// cflags
|
||||||
@@ -81,7 +77,7 @@ class LinuxBuilder extends BuilderBase
|
|||||||
'CXX' => $this->getOption('cxx'),
|
'CXX' => $this->getOption('cxx'),
|
||||||
'PATH' => BUILD_ROOT_PATH . '/bin:' . getenv('PATH'),
|
'PATH' => BUILD_ROOT_PATH . '/bin:' . getenv('PATH'),
|
||||||
]);
|
]);
|
||||||
// cross-compile does not support yet
|
// cross-compiling is not supported yet
|
||||||
/*if (php_uname('m') !== $this->arch) {
|
/*if (php_uname('m') !== $this->arch) {
|
||||||
$this->cross_compile_prefix = SystemUtil::getCrossCompilePrefix($this->cc, $this->arch);
|
$this->cross_compile_prefix = SystemUtil::getCrossCompilePrefix($this->cc, $this->arch);
|
||||||
logger()->info('using cross compile prefix: ' . $this->cross_compile_prefix);
|
logger()->info('using cross compile prefix: ' . $this->cross_compile_prefix);
|
||||||
@@ -134,7 +130,7 @@ class LinuxBuilder extends BuilderBase
|
|||||||
} else {
|
} else {
|
||||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", array_filter($this->getAllStaticLibFiles())));
|
$extra_libs .= (empty($extra_libs) ? '' : ' ') . implode(' ', array_map(fn ($x) => "-Xcompiler {$x}", array_filter($this->getAllStaticLibFiles())));
|
||||||
}
|
}
|
||||||
// add libstdc++, some extensions or libraries need it (C++ cannot be linked statically)
|
// add libstdc++, some extensions or libraries need it
|
||||||
$extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCppExtension() ? '-lstdc++ ' : '');
|
$extra_libs .= (empty($extra_libs) ? '' : ' ') . ($this->hasCppExtension() ? '-lstdc++ ' : '');
|
||||||
$this->setOption('extra-libs', $extra_libs);
|
$this->setOption('extra-libs', $extra_libs);
|
||||||
|
|
||||||
@@ -174,9 +170,11 @@ class LinuxBuilder extends BuilderBase
|
|||||||
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
|
$enableFpm = ($build_target & BUILD_TARGET_FPM) === BUILD_TARGET_FPM;
|
||||||
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
|
$enableMicro = ($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO;
|
||||||
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
|
$enableEmbed = ($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED;
|
||||||
|
$arch = arch2gnu(php_uname('m'));
|
||||||
|
|
||||||
shell()->cd(SOURCE_PATH . '/php-src')
|
shell()->cd(SOURCE_PATH . '/php-src')
|
||||||
->exec(
|
->exec(
|
||||||
|
(!SystemUtil::isMuslDist() ? "LD_LIBRARY_PATH=/usr/local/musl/{$arch}-linux-musl/lib " : '') .
|
||||||
'./configure ' .
|
'./configure ' .
|
||||||
'--prefix= ' .
|
'--prefix= ' .
|
||||||
'--with-valgrind=no ' .
|
'--with-valgrind=no ' .
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ class SystemUtil
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function isMuslDist(): bool
|
||||||
|
{
|
||||||
|
return static::getOSRelease()['dist'] === 'alpine';
|
||||||
|
}
|
||||||
|
|
||||||
public static function getCpuCount(): int
|
public static function getCpuCount(): int
|
||||||
{
|
{
|
||||||
$ncpu = 1;
|
$ncpu = 1;
|
||||||
|
|||||||
@@ -8,57 +8,122 @@ use SPC\builder\linux\SystemUtil;
|
|||||||
use SPC\doctor\AsCheckItem;
|
use SPC\doctor\AsCheckItem;
|
||||||
use SPC\doctor\AsFixItem;
|
use SPC\doctor\AsFixItem;
|
||||||
use SPC\doctor\CheckResult;
|
use SPC\doctor\CheckResult;
|
||||||
|
use SPC\exception\DownloaderException;
|
||||||
|
use SPC\exception\FileSystemException;
|
||||||
use SPC\exception\RuntimeException;
|
use SPC\exception\RuntimeException;
|
||||||
|
use SPC\exception\WrongUsageException;
|
||||||
|
use SPC\store\Downloader;
|
||||||
|
use SPC\store\FileSystem;
|
||||||
|
|
||||||
class LinuxMuslCheck
|
class LinuxMuslCheck
|
||||||
{
|
{
|
||||||
/** @noinspection PhpUnused */
|
/** @noinspection PhpUnused */
|
||||||
|
/**
|
||||||
|
* @throws WrongUsageException
|
||||||
|
*/
|
||||||
#[AsCheckItem('if musl-libc is installed', limit_os: 'Linux')]
|
#[AsCheckItem('if musl-libc is installed', limit_os: 'Linux')]
|
||||||
public function checkMusl(): ?CheckResult
|
public function checkMusl(): CheckResult
|
||||||
{
|
{
|
||||||
$file = sprintf('/lib/ld-musl-%s.so.1', php_uname('m'));
|
if (SystemUtil::isMuslDist()) {
|
||||||
if (file_exists($file)) {
|
|
||||||
return CheckResult::ok();
|
return CheckResult::ok();
|
||||||
}
|
}
|
||||||
|
$arch = arch2gnu(php_uname('m'));
|
||||||
// non-exist, need to recognize distro
|
$cross_compile_lib = "/usr/local/musl/{$arch}-linux-musl/lib/libc.a";
|
||||||
$distro = SystemUtil::getOSRelease();
|
$cross_compile_gcc = "/usr/local/musl/bin/{$arch}-linux-musl-gcc";
|
||||||
return match ($distro['dist']) {
|
$musl_wrapper_lib = sprintf('/lib/ld-musl-%s.so.1', php_uname('m'));
|
||||||
'ubuntu', 'alpine', 'debian', 'rhel', 'almalinux' => CheckResult::fail('musl-libc is not installed on your system', 'fix-musl', [$distro]),
|
if (file_exists($musl_wrapper_lib) && file_exists($cross_compile_lib) && file_exists($cross_compile_gcc)) {
|
||||||
default => CheckResult::fail('musl-libc is not installed on your system'),
|
return CheckResult::ok();
|
||||||
};
|
}
|
||||||
|
return CheckResult::fail('musl-libc is not installed on your system', 'fix-musl');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @noinspection PhpUnused */
|
||||||
/**
|
/**
|
||||||
* @throws RuntimeException
|
* @throws DownloaderException
|
||||||
* @noinspection PhpUnused
|
* @throws FileSystemException
|
||||||
|
* @throws WrongUsageException
|
||||||
*/
|
*/
|
||||||
#[AsFixItem('fix-musl')]
|
#[AsFixItem('fix-musl')]
|
||||||
public function fixMusl(array $distro): bool
|
public function fixMusl(): bool
|
||||||
{
|
{
|
||||||
$rhel_install = 'wget https://musl.libc.org/releases/musl-1.2.4.tar.gz && tar -zxvf musl-1.2.4.tar.gz && \
|
$arch = arch2gnu(php_uname('m'));
|
||||||
rm -f musl-1.2.4.tar.gz && cd musl-1.2.4 &&
|
$musl_wrapper_lib = sprintf('/lib/ld-musl-%s.so.1', php_uname('m'));
|
||||||
if [[ ! "$PATH" =~ (^|:)"/usr/local/musl/bin"(:|$) ]]; then echo "export PATH=/usr/local/musl/bin:$PATH" >> ~/.bash_profile
|
$cross_compile_lib = "/usr/local/musl/{$arch}-linux-musl/lib/libc.a";
|
||||||
fi && \
|
$cross_compile_gcc = "/usr/local/musl/bin/{$arch}-linux-musl-gcc";
|
||||||
./configure --enable-wrapper=gcc && \
|
|
||||||
make -j && make install && cd .. && rm -rf musl-1.2.4';
|
|
||||||
$install_cmd = match ($distro['dist']) {
|
|
||||||
'ubuntu', 'debian' => 'apt-get install musl musl-tools -y',
|
|
||||||
'alpine' => 'apk add musl musl-utils musl-dev',
|
|
||||||
'rhel' => $rhel_install,
|
|
||||||
'almalinux' => $rhel_install,
|
|
||||||
default => throw new RuntimeException('Current linux distro does not have an auto-install script for musl packages yet.'),
|
|
||||||
};
|
|
||||||
$prefix = '';
|
|
||||||
if (get_current_user() !== 'root') {
|
|
||||||
$prefix = 'sudo ';
|
|
||||||
logger()->warning('Current user is not root, using sudo for running command');
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
shell(true)->exec($prefix . $install_cmd);
|
if (!file_exists(DOWNLOAD_PATH)) {
|
||||||
|
FileSystem::createDir(DOWNLOAD_PATH);
|
||||||
|
}
|
||||||
|
if (!file_exists($musl_wrapper_lib)) {
|
||||||
|
$this->installMuslWrapper();
|
||||||
|
}
|
||||||
|
if (!file_exists($cross_compile_lib) || !file_exists($cross_compile_gcc)) {
|
||||||
|
$this->installMuslCrossMake();
|
||||||
|
}
|
||||||
|
|
||||||
|
$prefix = '';
|
||||||
|
if (get_current_user() !== 'root') {
|
||||||
|
$prefix = 'sudo ';
|
||||||
|
logger()->warning('Current user is not root, using sudo for running command');
|
||||||
|
}
|
||||||
|
$profile = '/etc/profile';
|
||||||
|
if (file_exists('~/.bash_profile')) {
|
||||||
|
$profile = '~/.bash_profile';
|
||||||
|
} elseif (file_exists('~/.profile')) {
|
||||||
|
$profile = '~/.profile';
|
||||||
|
}
|
||||||
|
if (!file_exists($profile)) {
|
||||||
|
shell(true)->exec($prefix . 'touch ' . $profile);
|
||||||
|
}
|
||||||
|
if (!getenv('PATH') || !str_contains(getenv('PATH'), '/usr/local/musl/bin')) {
|
||||||
|
$fix_path = 'echo "export PATH=/usr/local/musl/bin:$PATH" >> ' . $profile . ' && export PATH=/usr/local/musl/bin:$PATH';
|
||||||
|
shell(true)->exec($prefix . $fix_path);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (RuntimeException) {
|
} catch (RuntimeException) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws DownloaderException
|
||||||
|
* @throws RuntimeException
|
||||||
|
* @throws FileSystemException
|
||||||
|
*/
|
||||||
|
public function installMuslWrapper(): void
|
||||||
|
{
|
||||||
|
$prefix = '';
|
||||||
|
if (get_current_user() !== 'root') {
|
||||||
|
$prefix = 'sudo ';
|
||||||
|
logger()->warning('Current user is not root, using sudo for running command');
|
||||||
|
}
|
||||||
|
$musl_source = [
|
||||||
|
'type' => 'url',
|
||||||
|
'url' => 'https://musl.libc.org/releases/musl-1.2.4.tar.gz',
|
||||||
|
];
|
||||||
|
Downloader::downloadSource('musl-1.2.4', $musl_source);
|
||||||
|
FileSystem::extractSource('musl-1.2.4', DOWNLOAD_PATH . '/musl-1.2.4.tar.gz');
|
||||||
|
$musl_gcc_install_cmd = 'cd ' . SOURCE_PATH . '/musl-1.2.4 && \
|
||||||
|
./configure --enable-wrapper=gcc && \
|
||||||
|
make -j && make install';
|
||||||
|
shell(true)->exec($prefix . $musl_gcc_install_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws DownloaderException
|
||||||
|
* @throws RuntimeException
|
||||||
|
* @throws FileSystemException
|
||||||
|
*/
|
||||||
|
public function installMuslCrossMake(): void
|
||||||
|
{
|
||||||
|
$arch = arch2gnu(php_uname('m'));
|
||||||
|
$musl_compile_source = [
|
||||||
|
'type' => 'url',
|
||||||
|
'url' => "https://musl.cc/{$arch}-linux-musl-cross.tgz",
|
||||||
|
];
|
||||||
|
Downloader::downloadSource('musl-compile', $musl_compile_source);
|
||||||
|
FileSystem::extractSource('musl-compile', DOWNLOAD_PATH . "/{$arch}-linux-musl-cross.tgz");
|
||||||
|
shell(true)->exec('cp -rf ' . SOURCE_PATH . '/musl-compile/* /usr/local/musl');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user