From 2f0763fcd78154fc3af918f52a471e70073bc43f Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Sun, 1 Oct 2023 20:35:25 +0200 Subject: [PATCH] add c++ support for linux systems --- composer.json | 1 + src/SPC/builder/linux/LinuxBuilder.php | 13 ++++--- src/SPC/builder/linux/library/icu.php | 3 +- src/SPC/builder/unix/library/ldap.php | 3 +- src/SPC/builder/unix/library/snappy.php | 3 +- src/SPC/command/DownloadCommand.php | 2 +- src/SPC/doctor/item/LinuxMuslCheck.php | 43 ++++++++++++++++------ src/SPC/doctor/item/LinuxToolCheckList.php | 9 +++-- src/SPC/store/SourceExtractor.php | 2 +- 9 files changed, 52 insertions(+), 27 deletions(-) diff --git a/composer.json b/composer.json index 706f8d646..4a7fedde8 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,7 @@ "php": ">= 8.1", "ext-mbstring": "*", "ext-pcntl": "*", + "ext-zip": "*", "laravel/prompts": "^0.1.3", "symfony/console": "^5.4 || ^6 || ^7", "zhamao/logger": "^1.0" diff --git a/src/SPC/builder/linux/LinuxBuilder.php b/src/SPC/builder/linux/LinuxBuilder.php index bae677651..225377e39 100644 --- a/src/SPC/builder/linux/LinuxBuilder.php +++ b/src/SPC/builder/linux/LinuxBuilder.php @@ -40,12 +40,14 @@ public function __construct(array $options = []) // ---------- set necessary options ---------- // set C Compiler (default: alpine: gcc, others: musl-gcc) - $this->setOptionIfNotExist('cc', match (SystemUtil::getOSRelease()['dist']) { - 'alpine' => 'gcc', - default => 'musl-gcc' - }); + $compiler_prefix = match (arch2gnu(php_uname('m'))) { + 'x86_64' => 'x86_64-linux-musl-', + 'aarch64' => 'aarch64-linux-musl-', + }; + $this->setOptionIfNotExist('library_path', '/usr/local/musl/lib:/usr/local/musl/' . substr($compiler_prefix, 0, -1) . '/lib'); + $this->setOptionIfNotExist('cc', "{$compiler_prefix}gcc"); // set C++ Compiler (default: g++) - $this->setOptionIfNotExist('cxx', 'g++'); + $this->setOptionIfNotExist('cxx', "{$compiler_prefix}g++"); // set arch (default: current) $this->setOptionIfNotExist('arch', php_uname('m')); $this->setOptionIfNotExist('gnu-arch', arch2gnu($this->getOption('arch'))); @@ -260,6 +262,7 @@ public function buildCli(string $extra_libs, string $use_lld): void * * @throws RuntimeException * @throws FileSystemException + * @throws WrongUsageException */ public function buildMicro(string $extra_libs, string $use_lld, string $cflags): void { diff --git a/src/SPC/builder/linux/library/icu.php b/src/SPC/builder/linux/library/icu.php index 39125675b..bc7a3b53e 100644 --- a/src/SPC/builder/linux/library/icu.php +++ b/src/SPC/builder/linux/library/icu.php @@ -11,6 +11,7 @@ class icu extends LinuxLibraryBase protected function build(): void { $root = BUILD_ROOT_PATH; + $arch = arch2gnu(php_uname('m')) === 'x86_64' ? 'x86_64-linux-musl' : 'aarch64-linux-musl'; $cppflag = 'CPPFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=1 -DU_STATIC_IMPLEMENTATION=1"'; shell()->cd($this->source_dir . '/source') ->exec( @@ -28,7 +29,7 @@ protected function build(): void "--prefix={$root}" ) ->exec('make clean') - ->exec("make -j{$this->builder->concurrency}") + ->exec("LD_LIBRARY_PATH=/usr/local/musl/{$arch}/lib make -j{$this->builder->concurrency}") ->exec('make install'); } } diff --git a/src/SPC/builder/unix/library/ldap.php b/src/SPC/builder/unix/library/ldap.php index d1ffcbd78..0753b76ca 100644 --- a/src/SPC/builder/unix/library/ldap.php +++ b/src/SPC/builder/unix/library/ldap.php @@ -10,7 +10,7 @@ protected function build(): void { $alt = ''; // openssl support - $alt .= $this->builder->getLib('openssl') && $this->builder->getExt('zlib') ? '--with-tls=openssl ' : ''; + $alt .= $this->builder->getLib('openssl') ? '--with-tls=openssl ' : ''; // gmp support $alt .= $this->builder->getLib('gmp') ? '--with-mp=gmp ' : ''; // libsodium support @@ -23,7 +23,6 @@ protected function build(): void '--enable-static ' . '--disable-shared ' . '--disable-slapd ' . - '--disable-slurpd ' . '--without-systemd ' . '--without-cyrus-sasl ' . $alt . diff --git a/src/SPC/builder/unix/library/snappy.php b/src/SPC/builder/unix/library/snappy.php index 112cf5ede..1738ef192 100644 --- a/src/SPC/builder/unix/library/snappy.php +++ b/src/SPC/builder/unix/library/snappy.php @@ -29,6 +29,7 @@ protected function build(): void '../..' ) ->exec("cmake --build . -j {$this->builder->concurrency}") - ->exec('make install'); + ->exec('make install') + ->exec('mv ' . BUILD_ROOT_PATH . '/lib64/libsnappy.a ' . BUILD_ROOT_PATH . '/lib/libsnappy.a'); } } diff --git a/src/SPC/command/DownloadCommand.php b/src/SPC/command/DownloadCommand.php index b1977459c..e6588a415 100644 --- a/src/SPC/command/DownloadCommand.php +++ b/src/SPC/command/DownloadCommand.php @@ -28,7 +28,7 @@ public function configure(): void $this->addArgument('sources', InputArgument::REQUIRED, 'The sources will be compiled, comma separated'); $this->addOption('shallow-clone', null, null, 'Clone shallow'); $this->addOption('with-openssl11', null, null, 'Use openssl 1.1'); - $this->addOption('with-php', null, InputOption::VALUE_REQUIRED, 'version in major.minor format like 8.1', '8.1'); + $this->addOption('with-php', null, InputOption::VALUE_REQUIRED, 'version in major.minor format (default 8.2)', '8.2'); $this->addOption('clean', null, null, 'Clean old download cache and source before fetch'); $this->addOption('all', 'A', null, 'Fetch all sources that static-php-cli needed'); $this->addOption('custom-url', 'U', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Specify custom source download url, e.g "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"'); diff --git a/src/SPC/doctor/item/LinuxMuslCheck.php b/src/SPC/doctor/item/LinuxMuslCheck.php index 3e5cb75a1..267a0dbf1 100644 --- a/src/SPC/doctor/item/LinuxMuslCheck.php +++ b/src/SPC/doctor/item/LinuxMuslCheck.php @@ -8,34 +8,51 @@ use SPC\doctor\AsCheckItem; use SPC\doctor\AsFixItem; use SPC\doctor\CheckResult; +use SPC\exception\DownloaderException; +use SPC\exception\FileSystemException; use SPC\exception\RuntimeException; +use SPC\exception\WrongUsageException; +use SPC\store\Downloader; class LinuxMuslCheck { /** @noinspection PhpUnused */ + /** + * @throws WrongUsageException + */ #[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')); + $arch = arch2gnu(php_uname('m')) === 'x86_64' ? 'x86_64-linux-musl' : 'aarch64-linux-musl'; + $file = "/usr/local/musl/{$arch}/lib/libc.a"; if (file_exists($file)) { return CheckResult::ok(); } - - // non-exist, need to recognize distro - $distro = SystemUtil::getOSRelease(); - return match ($distro['dist']) { - 'ubuntu', 'alpine', 'debian', 'rhel', 'almalinux' => CheckResult::fail('musl-libc is not installed on your system', 'fix-musl', [$distro]), - default => CheckResult::fail('musl-libc is not installed on your system'), - }; + return CheckResult::fail('musl-libc is not installed on your system', 'fix-musl'); } /** * @throws RuntimeException - * @noinspection PhpUnused + * @throws DownloaderException + * @throws FileSystemException + * @throws WrongUsageException */ #[AsFixItem('fix-musl')] - public function fixMusl(array $distro): bool + public function fixMusl(): bool { + $distro = SystemUtil::getOSRelease(); + $source = [ + 'type' => 'git', + 'url' => 'https://github.com/richfelker/musl-cross-make', + 'rev' => 'master', + ]; + Downloader::downloadSource('musl-cross-make', $source); + $arch = arch2gnu(php_uname('m')) === 'x86_64' ? 'x86_64-linux-musl' : 'aarch64-linux-musl'; + $install_musl_wrapper_cmd = 'cd ' . DOWNLOAD_PATH . '/musl-cross-make && \ + make install TARGET=' . $arch . ' OUTPUT=/usr/local/musl -j && \ + if [[ ! "$PATH" =~ (^|:)"/usr/local/musl/bin"(:|$) ]]; then echo "export PATH=/usr/local/musl/bin:$PATH" >> ~/.bash_profile + fi && \ + source ~/.bash_profile'; $rhel_install = 'wget https://musl.libc.org/releases/musl-1.2.4.tar.gz && tar -zxvf musl-1.2.4.tar.gz && \ rm -f musl-1.2.4.tar.gz && cd musl-1.2.4 && if [[ ! "$PATH" =~ (^|:)"/usr/local/musl/bin"(:|$) ]]; then echo "export PATH=/usr/local/musl/bin:$PATH" >> ~/.bash_profile @@ -55,7 +72,9 @@ public function fixMusl(array $distro): bool logger()->warning('Current user is not root, using sudo for running command'); } try { - shell(true)->exec($prefix . $install_cmd); + shell(true) + ->exec($prefix . $install_cmd) + ->exec($install_musl_wrapper_cmd); return true; } catch (RuntimeException) { return false; diff --git a/src/SPC/doctor/item/LinuxToolCheckList.php b/src/SPC/doctor/item/LinuxToolCheckList.php index 4ff16dcca..b99eaa964 100644 --- a/src/SPC/doctor/item/LinuxToolCheckList.php +++ b/src/SPC/doctor/item/LinuxToolCheckList.php @@ -36,7 +36,8 @@ class LinuxToolCheckList 'git', 'autoconf', 'automake', 'tar', 'unzip', 'gzip', 'gcc', 'bzip2', 'cmake', 'patch', - 'xz', + 'xz', 'g++', 'libtool', + 'curl', // needed to download openssl 'wget', // to get musl ]; @@ -50,15 +51,15 @@ class LinuxToolCheckList 'libxml2-utils', 'make', 'pkg-config', 'sed', 'w3m', 'xsltproc', 'xz-utils', ]; - + // todo: require those public const PAM_TOOLS_RHEL = [ 'autoconf', 'automake', 'bison', 'bzip2', 'flex', 'make', 'gettext', 'pkg-config', 'sed', 'w3m', 'xz', 'libdb-devel', 'libselinux-devel', - 'openssl-devel', 'libtool', 'libxml2', - 'docbook-xsl-ns', 'libxslt' + 'openssl-devel', 'libtool', 'libxml2', + 'docbook-xsl-ns', 'libxslt', ]; /** @noinspection PhpUnused */ diff --git a/src/SPC/store/SourceExtractor.php b/src/SPC/store/SourceExtractor.php index 4a68bef8a..fd8f1e549 100644 --- a/src/SPC/store/SourceExtractor.php +++ b/src/SPC/store/SourceExtractor.php @@ -52,7 +52,7 @@ public static function initSource(?array $sources = null, ?array $libs = null, ? // start check foreach ($sources_extracted as $source => $item) { if (Config::getSource($source) === null) { - throw new WrongUsageException("Source [{$source}] not exists, please check name and correct it !"); + throw new WrongUsageException("Source [{$source}] does not exist, please check the name and correct it !"); } if (!isset($lock[$source])) { throw new WrongUsageException('Source [' . $source . '] not downloaded or not locked, you should download it first !');