add brotli,bzip2,curl,zlib for linux

This commit is contained in:
crazywhalecc
2023-03-21 00:25:46 +08:00
parent 79efecb5a9
commit 063b55ae0d
10 changed files with 1038 additions and 9 deletions

View File

@@ -0,0 +1,135 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\builder\BuilderBase;
use SPC\builder\LibraryBase;
use SPC\builder\linux\LinuxBuilder;
use SPC\builder\linux\SystemUtil;
use SPC\builder\traits\UnixLibraryTrait;
use SPC\exception\RuntimeException;
use SPC\store\FileSystem;
use SPC\util\Patcher;
abstract class LinuxLibraryBase extends LibraryBase
{
use UnixLibraryTrait;
protected array $static_libs = [];
protected array $headers;
protected array $pkgconfs;
/**
* 依赖的名字及是否可选例如curl => true代表依赖 curl 但可选
*/
protected array $dep_names;
public function __construct(protected LinuxBuilder $builder)
{
parent::__construct();
}
public function getBuilder(): BuilderBase
{
return $this->builder;
}
/**
* @throws RuntimeException
*/
public function tryBuild(bool $force_build = false): int
{
// 传入 true表明直接编译
if ($force_build) {
$this->build();
return BUILD_STATUS_OK;
}
// 看看这些库是不是存在,如果不存在,则调用编译并返回结果状态
foreach ($this->getStaticLibs() as $name) {
if (!file_exists(BUILD_LIB_PATH . "/{$name}")) {
$this->tryBuild(true);
return BUILD_STATUS_OK;
}
}
// 头文件同理
foreach ($this->getHeaders() as $name) {
if (!file_exists(BUILD_INCLUDE_PATH . "/{$name}")) {
$this->tryBuild(true);
return BUILD_STATUS_OK;
}
}
// 到这里说明所有的文件都存在,就跳过编译
return BUILD_STATUS_ALREADY;
}
protected function makeFakePkgconfs()
{
$workspace = BUILD_ROOT_PATH;
if ($workspace === '/') {
$workspace = '';
}
foreach ($this->pkgconfs as $name => $content) {
file_put_contents(BUILD_LIB_PATH . "/pkgconfig/{$name}", "prefix={$workspace}\n" . $content);
}
}
/**
* @throws RuntimeException
*/
private function _make(bool $forceBuild = false, bool $fresh = false)
{
if ($forceBuild || php_uname('m') !== $this->builder->arch) {
$this->build();
return;
}
$static_lib_patches = SystemUtil::findStaticLibs($this->static_libs);
$header_patches = SystemUtil::findHeaders($this->headers);
if (!$static_lib_patches || !$header_patches) {
$this->build();
} else {
if ($this->builder->libc === 'musl_wrapper') {
logger()->warning('libc type may not match, this may cause strange symbol missing');
}
$this->copyExist($static_lib_patches, $header_patches);
}
$this->fixPkgConfigs();
}
private function fixPkgConfigs()
{
foreach ($this->pkgconfs as $name => $_) {
Patcher::patchLinuxPkgConfig(BUILD_LIB_PATH . "/pkgconfig/{$name}");
}
}
/**
* @throws RuntimeException
*/
private function copyExist(array $static_lib_patches, array $header_patches): void
{
if (!$static_lib_patches || !$header_patches) {
throw new RuntimeException('??? staticLibPathes or headerPathes is null');
}
logger()->info('using system ' . static::NAME);
foreach ($static_lib_patches as [$path, $staticLib]) {
@f_mkdir(BUILD_LIB_PATH . '/' . dirname($staticLib), recursive: true);
logger()->info("copy {$path}/{$staticLib} to " . BUILD_LIB_PATH . "/{$staticLib}");
copy("{$path}/{$staticLib}", BUILD_LIB_PATH . '/' . $staticLib);
}
foreach ($header_patches as [$path, $header]) {
@f_mkdir(BUILD_INCLUDE_PATH . '/' . dirname($header), recursive: true);
logger()->info("copy {$path}/{$header} to " . BUILD_INCLUDE_PATH . "/{$header}");
if (is_dir("{$path}/{$header}")) {
FileSystem::copyDir("{$path}/{$header}", BUILD_INCLUDE_PATH . "/{$header}");
} else {
copy("{$path}/{$header}", BUILD_INCLUDE_PATH . "/{$header}");
}
}
$this->makeFakePkgconfs();
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\RuntimeException;
class brotli extends LinuxLibraryBase
{
public const NAME = 'brotli';
/**
* @throws RuntimeException
*/
public function build()
{
[$lib, $include, $destdir] = SEPARATED_PATH;
f_passthru(
"{$this->builder->set_x} && " .
"cd {$this->source_dir} && " .
'rm -rf build && ' .
'mkdir -p build && ' .
'cd build && ' .
"{$this->builder->configure_env} " . ' cmake ' .
// '--debug-find ' .
'-DCMAKE_BUILD_TYPE=Release ' .
'-DBUILD_SHARED_LIBS=OFF ' .
'-DCMAKE_INSTALL_PREFIX=/ ' .
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'.. && ' .
"cmake --build . -j {$this->builder->concurrency} --target brotlicommon-static && " .
"cmake --build . -j {$this->builder->concurrency} --target brotlidec-static && " .
"cmake --build . -j {$this->builder->concurrency} --target brotlienc-static && " .
'cp libbrotlidec-static.a ' . BUILD_LIB_PATH . ' && ' .
'cp libbrotlienc-static.a ' . BUILD_LIB_PATH . ' && ' .
'cp libbrotlicommon-static.a ' . BUILD_LIB_PATH . ' && ' .
'cp -r ../c/include/brotli ' . BUILD_INCLUDE_PATH
);
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\RuntimeException;
class bzip2 extends LinuxLibraryBase
{
public const NAME = 'bzip2';
protected array $dep_names = [];
/**
* @throws RuntimeException
*/
public function build()
{
f_passthru(
$this->builder->set_x . ' && ' .
"cd {$this->source_dir} && " .
"make {$this->builder->configure_env} PREFIX='" . BUILD_ROOT_PATH . "' clean" . ' && ' .
"make -j{$this->builder->concurrency} {$this->builder->configure_env} PREFIX='" . BUILD_ROOT_PATH . "' libbz2.a" . ' && ' .
// make install may fail when cross-compiling, so we copy files.
'cp libbz2.a ' . BUILD_LIB_PATH . ' && ' .
'cp bzlib.h ' . BUILD_INCLUDE_PATH
);
$this->makeFakePkgconfs();
}
}

View File

@@ -0,0 +1,163 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\RuntimeException;
class curl extends LinuxLibraryBase
{
public const NAME = 'curl';
protected array $static_libs = ['libcurl.a'];
protected array $headers = ['curl'];
protected array $pkgconfs = [
'libcurl.pc' => <<<'EOF'
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
supported_protocols="DICT FILE FTP FTPS GOPHER GOPHERS HTTP HTTPS IMAP IMAPS MQTT POP3 POP3S RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP"
supported_features="AsynchDNS GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets alt-svc brotli libz zstd"
Name: libcurl
URL: https://curl.se/
Description: Library to transfer files with ftp, http, etc.
Version: 7.83.0
Libs: -L${libdir} -lcurl
Libs.private: -lnghttp2 -lidn2 -lssh2 -lssh2 -lpsl -lssl -lcrypto -lssl -lcrypto -lgssapi_krb5 -lzstd -lbrotlidec -lz
Cflags: -I${includedir}
EOF
];
protected array $dep_names = [
'zlib' => false,
'libssh2' => true,
'brotli' => true,
'nghttp2' => true,
'zstd' => true,
'openssl' => true,
'idn2' => true,
'psl' => true,
];
public function getStaticLibFiles(string $style = 'autoconf', bool $recursive = true): string
{
$libs = parent::getStaticLibFiles($style, $recursive);
if ($this->builder->getLib('openssl')) {
$libs .= ' -ldl -lpthread';
}
return $libs;
}
/**
* @throws RuntimeException
*/
public function build()
{
$extra = '';
// lib:openssl
$openssl = $this->builder->getLib('openssl');
if ($openssl instanceof LinuxLibraryBase) {
$extra .= '-DCURL_USE_OPENSSL=ON ';
} else {
$extra .= '-DCURL_USE_OPENSSL=OFF -DCURL_ENABLE_SSL=OFF ';
}
// lib:zlib
$zlib = $this->builder->getLib('zlib');
if ($zlib instanceof LinuxLibraryBase) {
$extra .= '-DZLIB_LIBRARY="' . $zlib->getStaticLibFiles(style: 'cmake') . '" ' .
'-DZLIB_INCLUDE_DIR=' . BUILD_INCLUDE_PATH . ' ';
}
// lib:libssh2
$libssh2 = $this->builder->getLib('libssh2');
if ($libssh2 instanceof LinuxLibraryBase) {
$extra .= '-DLIBSSH2_LIBRARY="' . $libssh2->getStaticLibFiles(style: 'cmake') . '" ' .
'-DLIBSSH2_INCLUDE_DIR="' . BUILD_INCLUDE_PATH . '" ';
} else {
$extra .= '-DCURL_USE_LIBSSH2=OFF ';
}
// lib:brotli
$brotli = $this->builder->getLib('brotli');
if ($brotli) {
$extra .= '-DCURL_BROTLI=ON ' .
'-DBROTLIDEC_LIBRARY="' . realpath(BUILD_LIB_PATH . '/libbrotlidec-static.a') . ';' . realpath(BUILD_LIB_PATH . '/libbrotlicommon-static.a') . '" ' .
'-DBROTLICOMMON_LIBRARY="' . realpath(BUILD_LIB_PATH . '/libbrotlicommon-static.a') . '" ' .
'-DBROTLI_INCLUDE_DIR="' . BUILD_INCLUDE_PATH . '" ';
} else {
$extra .= '-DCURL_BROTLI=OFF ';
}
// lib:nghttp2
$nghttp2 = $this->builder->getLib('nghttp2');
if ($nghttp2 instanceof LinuxLibraryBase) {
$extra .= '-DUSE_NGHTTP2=ON ' .
'-DNGHTTP2_LIBRARY="' . $nghttp2->getStaticLibFiles(style: 'cmake') . '" ' .
'-DNGHTTP2_INCLUDE_DIR="' . BUILD_INCLUDE_PATH . '" ';
} else {
$extra .= '-DUSE_NGHTTP2=OFF ';
}
// lib:ldap
$ldap = $this->builder->getLib('ldap');
if ($ldap instanceof LinuxLibraryBase) {
// $extra .= '-DCURL_DISABLE_LDAP=OFF ';
// TODO: LDAP support
throw new RuntimeException('LDAP support is not implemented yet');
}
$extra .= '-DCURL_DISABLE_LDAP=ON ';
// lib:zstd
$zstd = $this->builder->getLib('zstd');
if ($zstd instanceof LinuxLibraryBase) {
$extra .= '-DCURL_ZSTD=ON ' .
'-DZstd_LIBRARY="' . $zstd->getStaticLibFiles(style: 'cmake') . '" ' .
'-DZstd_INCLUDE_DIR="' . BUILD_INCLUDE_PATH . '" ';
} else {
$extra .= '-DCURL_ZSTD=OFF ';
}
// lib:idn2
$idn2 = $this->builder->getLib('idn2');
$extra .= $idn2 instanceof LinuxLibraryBase ? '-DUSE_LIBIDN2=ON ' : '-DUSE_LIBIDN2=OFF ';
// lib:psl
$libpsl = $this->builder->getLib('psl');
$extra .= $libpsl instanceof LinuxLibraryBase ? '-DCURL_USE_LIBPSL=ON ' : '-DCURL_USE_LIBPSL=OFF ';
[$lib, $include, $destdir] = SEPARATED_PATH;
// compile
f_passthru(
$this->builder->set_x . ' && ' .
"cd {$this->source_dir} && " .
'rm -rf build && ' .
'mkdir -p build && ' .
'cd build && ' .
"{$this->builder->configure_env} " . ' cmake ' .
// '--debug-find ' .
'-DCMAKE_BUILD_TYPE=Release ' .
'-DBUILD_SHARED_LIBS=OFF ' .
$extra .
'-DCMAKE_INSTALL_PREFIX=/ ' .
"-DCMAKE_INSTALL_LIBDIR={$lib} " .
"-DCMAKE_INSTALL_INCLUDEDIR={$include} " .
"-DCMAKE_TOOLCHAIN_FILE={$this->builder->cmake_toolchain_file} " .
'.. && ' .
"make -j{$this->builder->concurrency} && " .
'make install DESTDIR="' . $destdir . '"'
);
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Copyright (c) 2022 Yun Dou <dixyes@gmail.com>
*
* lwmbs is licensed under Mulan PSL v2. You can use this
* software according to the terms and conditions of the
* Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
*/
declare(strict_types=1);
namespace SPC\builder\linux\library;
use SPC\exception\RuntimeException;
class zlib extends LinuxLibraryBase
{
public const NAME = 'zlib';
/**
* @throws RuntimeException
*/
public function build()
{
[,,$destdir] = SEPARATED_PATH;
f_passthru(
$this->builder->set_x . ' && ' .
"cd {$this->source_dir} && " .
"{$this->builder->configure_env} ./configure " .
'--static ' .
'--prefix= && ' . // use prefix=/
'make clean && ' .
"make -j{$this->builder->concurrency} && " .
'make install DESTDIR=' . $destdir
);
}
}