add imagemagick (imagick) for macos, pkg-config for unix.=

This commit is contained in:
crazywhalecc 2023-05-10 02:04:08 +08:00
parent 9daa10e939
commit 7527f9f099
No known key found for this signature in database
GPG Key ID: 1F4BDD59391F2680
24 changed files with 229 additions and 11 deletions

View File

@ -107,11 +107,11 @@
"zlib",
"libpng",
"libjpeg",
"bzip2"
"bzip2",
"libwebp",
"freetype"
],
"lib-suggests": [
"libwebp",
"freetype",
"zstd",
"xz",
"libzip",

View File

@ -26,6 +26,7 @@
| gettext | | | |
| gmp | yes | yes | |
| iconv | yes | yes | |
| imagick | | yes | |
| inotify | yes | yes | |
| mbstring | yes | yes | |
| mbregex | yes | yes | |
@ -56,7 +57,7 @@
| xml | yes | yes | |
| xmlreader | yes, untested | yes, untested | |
| xmlwriter | yes, untested | yes, untested | |
| zip | yes, untested | yes | |
| zip | yes, untested | yes, untested | |
| zlib | yes | yes | |
| zstd | yes | yes | |

View File

@ -63,6 +63,9 @@ abstract class BuilderBase
if ($libraries === [] && $this->isLibsOnly()) {
$libraries = array_keys($support_lib_list);
}
if (!in_array('pkg-config', $libraries)) {
array_unshift($libraries, 'pkg-config');
}
// 排序 libs根据依赖计算一个新的列表出来
$libraries = DependencyUtil::getLibsByDeps($libraries);

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace SPC\builder;
use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
use SPC\store\Config;
@ -152,6 +153,11 @@ abstract class LibraryBase
return BUILD_STATUS_OK;
}
}
// pkg-config 做特殊处理,如果是 pkg-config 就检查有没有 pkg-config 二进制
if ($this instanceof MacOSLibraryBase && static::NAME === 'pkg-config' && !file_exists(BUILD_ROOT_PATH . '/bin/pkg-config')) {
$this->tryBuild(true);
return BUILD_STATUS_OK;
}
// 到这里说明所有的文件都存在,就跳过编译
return BUILD_STATUS_ALREADY;
}

View File

@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace SPC\builder\extension;
use SPC\builder\Extension;
use SPC\util\CustomExt;
#[CustomExt('imagick')]
class imagick extends Extension
{
public function getUnixConfigureArg(): string
{
return '--with-imagick=' . BUILD_ROOT_PATH;
}
}

View File

@ -70,7 +70,7 @@ class LinuxBuilder extends BuilderBase
cxx: $this->cxx
);
// 设置 pkgconfig
$this->pkgconf_env = 'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig"';
$this->pkgconf_env = 'PKG_CONFIG="' . BUILD_ROOT_PATH . '/bin/pkg-config" PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig"';
// 设置 configure 依赖的环境变量
$this->configure_env =
$this->pkgconf_env . ' ' .
@ -141,6 +141,9 @@ class LinuxBuilder extends BuilderBase
if ($this->getExt('swoole')) {
$extra_libs .= ' -lstdc++';
}
if ($this->getExt('imagick')) {
$extra_libs .= ' /usr/lib/libMagick++-7.Q16HDRI.a /usr/lib/libMagickCore-7.Q16HDRI.a /usr/lib/libMagickWand-7.Q16HDRI.a';
}
$envs = $this->pkgconf_env . ' ' .
"CC='{$this->cc}' " .
@ -169,7 +172,7 @@ class LinuxBuilder extends BuilderBase
shell()->cd(SOURCE_PATH . '/php-src')->exec('./buildconf --force');
SourcePatcher::patchPHPConfigure($this);
if ($this->getPHPVersionID() < 80000) {
$json_74 = '--enable-json ';
} else {

View File

@ -149,7 +149,7 @@ class SystemUtil
{
$paths = getenv('LIBPATH');
if (!$paths) {
$paths = '/lib:/lib64:/usr/lib:/usr/lib64:/usr/local/lib:/usr/local/lib64';
$paths = '/lib:/lib64:/usr/lib:/usr/lib64:/usr/local/lib:/usr/local/lib64:';
}
foreach (explode(':', $paths) as $path) {
if (file_exists("{$path}/{$name}")) {

View File

@ -61,6 +61,11 @@ abstract class LinuxLibraryBase extends LibraryBase
return BUILD_STATUS_OK;
}
}
// pkg-config 做特殊处理,如果是 pkg-config 就检查有没有 pkg-config 二进制
if (static::NAME === 'pkg-config' && !file_exists(BUILD_ROOT_PATH . '/bin/pkg-config')) {
$this->tryBuild(true);
return BUILD_STATUS_OK;
}
// 到这里说明所有的文件都存在,就跳过编译
return BUILD_STATUS_ALREADY;
}

View File

@ -61,5 +61,6 @@ class libpng extends LinuxLibraryBase
->cd(BUILD_LIB_PATH)
->exec('ln -sf libpng16.a libpng.a');
$this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX);
$this->cleanLaFiles();
}
}

View File

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace SPC\builder\linux\library;
/**
* gmp is a template library class for unix
*/
class pkgconfig extends LinuxLibraryBase
{
use \SPC\builder\unix\library\pkgconfig;
public const NAME = 'pkg-config';
}

View File

@ -49,6 +49,7 @@ class MacOSBuilder extends BuilderBase
$this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile('Darwin', $this->arch, $this->arch_c_flags);
// 设置 configure 依赖的环境变量
$this->configure_env =
'PKG_CONFIG="' . BUILD_ROOT_PATH . '/bin/pkg-config" ' .
'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig/" ' .
"CC='{$this->cc}' " .
"CXX='{$this->cxx}' " .
@ -145,7 +146,7 @@ class MacOSBuilder extends BuilderBase
if ($this->getLib('libxml2') || $this->getExt('iconv')) {
$extra_libs .= ' -liconv';
}
if ($this->getPHPVersionID() < 80000) {
$json_74 = '--enable-json ';
} else {

View File

@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace SPC\builder\macos\library;
use SPC\store\FileSystem;
/**
* gmp is a template library class for unix
*/
class imagemagick extends MacOSLibraryBase
{
public const NAME = 'imagemagick';
protected function build(): void
{
$extra = '--without-jxl --without-xml --without-zstd ';
// jpeg support
$extra .= $this->builder->getLib('libjpeg') ? '--with-jpeg ' : '';
// png support
$extra .= $this->builder->getLib('libpng') ? '--with-png ' : '';
// webp support
$extra .= $this->builder->getLib('libwebp') ? '--with-webp ' : '';
// zstd support
// $extra .= $this->builder->getLib('zstd') ? '--with-zstd ' : '--without-zstd ';
// freetype support
$extra .= $this->builder->getLib('freetype') ? '--with-freetype ' : '--without-freetype ';
shell()->cd($this->source_dir)
->exec(
"{$this->builder->configure_env} ./configure " .
'--enable-static --disable-shared ' .
$extra .
'--prefix='
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
$filelist = [
'ImageMagick.pc',
'ImageMagick-7.Q16HDRI.pc',
'Magick++.pc',
'Magick++-7.Q16HDRI.pc',
'MagickCore.pc',
'MagickCore-7.Q16HDRI.pc',
'MagickWand.pc',
'MagickWand-7.Q16HDRI.pc',
];
$this->patchPkgconfPrefix($filelist);
foreach ($filelist as $file) {
FileSystem::replaceFile(
BUILD_LIB_PATH . '/pkgconfig/' . $file,
REPLACE_FILE_PREG,
'#includearchdir=/include/ImageMagick-7#m',
'includearchdir=${prefix}/include/ImageMagick-7'
);
}
}
}

View File

@ -55,5 +55,6 @@ class libpng extends MacOSLibraryBase
->cd(BUILD_LIB_PATH)
->exec('ln -sf libpng16.a libpng.a');
$this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX);
$this->cleanLaFiles();
}
}

View File

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace SPC\builder\macos\library;
/**
* gmp is a template library class for unix
*/
class pkgconfig extends MacOSLibraryBase
{
use \SPC\builder\unix\library\pkgconfig;
public const NAME = 'pkg-config';
}

View File

@ -77,4 +77,20 @@ trait UnixLibraryTrait
FileSystem::writeFile($realpath, $file);
}
}
/**
* remove libtool archive files
*
* @throws FileSystemException
* @throws RuntimeException
*/
public function cleanLaFiles(): void
{
foreach ($this->getStaticLibs() as $lib) {
$filename = pathinfo($lib, PATHINFO_FILENAME) . '.la';
if (file_exists(BUILD_LIB_PATH . '/' . $filename)) {
unlink(BUILD_LIB_PATH . '/' . $filename);
}
}
}
}

View File

@ -47,6 +47,7 @@ SET(CMAKE_CXX_FLAGS "{$cflags}")
SET(CMAKE_FIND_ROOT_PATH "{$root}")
SET(CMAKE_PREFIX_PATH "{$root}")
set(PKG_CONFIG_EXECUTABLE "{$root}/bin/pkg-config")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@ -4,6 +4,8 @@ declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\store\FileSystem;
trait freetype
{
protected function build()
@ -25,5 +27,13 @@ trait freetype
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['freetype2.pc']);
FileSystem::replaceFile(
BUILD_ROOT_PATH . '/lib/pkgconfig/freetype2.pc',
REPLACE_FILE_STR,
' -L/lib ',
' -L' . BUILD_ROOT_PATH . '/lib '
);
$this->cleanLaFiles();
}
}

View File

@ -24,5 +24,6 @@ trait libavif
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
// patch pkgconfig
$this->patchPkgconfPrefix(['libavif.pc']);
$this->cleanLaFiles();
}
}

View File

@ -24,5 +24,6 @@ trait libjpeg
->exec('make install DESTDIR=' . BUILD_ROOT_PATH);
// patch pkgconfig
$this->patchPkgconfPrefix(['libjpeg.pc', 'libturbojpeg.pc']);
$this->cleanLaFiles();
}
}

View File

@ -28,5 +28,6 @@ trait libwebp
->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . $destdir);
$this->patchPkgconfPrefix(['libsharpyuv.pc', 'libwebp.pc', 'libwebpdecoder.pc', 'libwebpdemux.pc', 'libwebpmux.pc'], PKGCONF_PATCH_PREFIX);
$this->cleanLaFiles();
}
}

View File

@ -15,8 +15,8 @@ trait libzip
$extra .= $this->builder->getLib('bzip2') ? '-DENABLE_BZIP2=ON ' : '-DENABLE_BZIP2=OFF ';
// lib:xz
$extra .= $this->builder->getLib('xz') ? '-DENABLE_LZMA=ON ' : '-DENABLE_LZMA=OFF ';
// lib:zstd
$extra .= $this->builder->getLib('zstd') ? '-DENABLE_ZSTD=ON ' : '-DENABLE_ZSTD=OFF ';
// lib:zstd (disabled due to imagemagick link issue
$extra .= /* $this->builder->getLib('zstd') ? '-DENABLE_ZSTD=ON ' : */ '-DENABLE_ZSTD=OFF ';
// lib:openssl
$extra .= $this->builder->getLib('openssl') ? '-DENABLE_OPENSSL=ON ' : '-DENABLE_OPENSSL=OFF ';

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
trait pkgconfig
{
protected function build()
{
$macos_env = 'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig/" ' .
"CC='{$this->builder->cc}' " .
"CXX='{$this->builder->cxx}' " .
"CFLAGS='{$this->builder->arch_c_flags} -Wimplicit-function-declaration' ";
$linux_env = 'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig" ' .
"CC='{$this->builder->cc}' " .
"CXX='{$this->builder->cxx}' ";
$extra = match (PHP_OS_FAMILY) {
'Darwin' => '',
default => '--with-internal-glib ',
};
shell()->cd($this->source_dir)
->exec(
match (PHP_OS_FAMILY) {
'Darwin' => $macos_env,
default => $linux_env,
} .
'./configure ' .
'--disable-shared ' .
'--enable-static ' .
$extra .
'--prefix=' . BUILD_ROOT_PATH . ' ' .
'--without-sysroot ' .
'--without-system-include-path ' .
'--without-system-library-path ' .
'--without-pc-path'
)
->exec('make clean')
->exec("make -j{$this->builder->concurrency}")
->exec('make install');
}
}

View File

@ -6,6 +6,7 @@ namespace SPC\store;
use SPC\builder\BuilderBase;
use SPC\builder\linux\LinuxBuilder;
use SPC\builder\linux\SystemUtil;
use SPC\builder\macos\MacOSBuilder;
use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException;
@ -99,6 +100,14 @@ class SourcePatcher
'-lz',
BUILD_LIB_PATH . '/libz.a'
);
if (SystemUtil::getOSRelease()['dist'] === 'alpine') {
FileSystem::replaceFile(
SOURCE_PATH . '/libpng/configure',
REPLACE_FILE_STR,
'-lm',
'/usr/lib/libm.a'
);
}
}
public static function patchCurlMacOS(): void

View File

@ -66,6 +66,8 @@ function osfamily2dir(): string
}
/**
* 执行shell直接输出在终端出现错误抛出异常
*
* @throws \SPC\exception\RuntimeException
*/
function f_passthru(string $cmd): ?bool
@ -89,7 +91,13 @@ function f_passthru(string $cmd): ?bool
return $ret;
}
function f_exec(string $command, &$output, &$result_code)
/**
* 执行命令,不输出内容,返回执行结果和内容
*
* @param mixed $output
* @param mixed $result_code
*/
function f_exec(string $command, &$output, &$result_code): bool|string
{
logger()->debug('Running command (no output) : ' . $command);
return exec($command, $output, $result_code);