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
24 changed files with 229 additions and 11 deletions

View File

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

View File

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

View File

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

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace SPC\builder; namespace SPC\builder;
use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
use SPC\store\Config; use SPC\store\Config;
@@ -152,6 +153,11 @@ abstract class LibraryBase
return BUILD_STATUS_OK; 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; 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 cxx: $this->cxx
); );
// 设置 pkgconfig // 设置 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 依赖的环境变量 // 设置 configure 依赖的环境变量
$this->configure_env = $this->configure_env =
$this->pkgconf_env . ' ' . $this->pkgconf_env . ' ' .
@@ -141,6 +141,9 @@ class LinuxBuilder extends BuilderBase
if ($this->getExt('swoole')) { if ($this->getExt('swoole')) {
$extra_libs .= ' -lstdc++'; $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 . ' ' . $envs = $this->pkgconf_env . ' ' .
"CC='{$this->cc}' " . "CC='{$this->cc}' " .
@@ -169,7 +172,7 @@ class LinuxBuilder extends BuilderBase
shell()->cd(SOURCE_PATH . '/php-src')->exec('./buildconf --force'); shell()->cd(SOURCE_PATH . '/php-src')->exec('./buildconf --force');
SourcePatcher::patchPHPConfigure($this); SourcePatcher::patchPHPConfigure($this);
if ($this->getPHPVersionID() < 80000) { if ($this->getPHPVersionID() < 80000) {
$json_74 = '--enable-json '; $json_74 = '--enable-json ';
} else { } else {

View File

@@ -149,7 +149,7 @@ class SystemUtil
{ {
$paths = getenv('LIBPATH'); $paths = getenv('LIBPATH');
if (!$paths) { 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) { foreach (explode(':', $paths) as $path) {
if (file_exists("{$path}/{$name}")) { if (file_exists("{$path}/{$name}")) {

View File

@@ -61,6 +61,11 @@ abstract class LinuxLibraryBase extends LibraryBase
return BUILD_STATUS_OK; 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; return BUILD_STATUS_ALREADY;
} }

View File

@@ -61,5 +61,6 @@ class libpng extends LinuxLibraryBase
->cd(BUILD_LIB_PATH) ->cd(BUILD_LIB_PATH)
->exec('ln -sf libpng16.a libpng.a'); ->exec('ln -sf libpng16.a libpng.a');
$this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX); $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); $this->cmake_toolchain_file = SystemUtil::makeCmakeToolchainFile('Darwin', $this->arch, $this->arch_c_flags);
// 设置 configure 依赖的环境变量 // 设置 configure 依赖的环境变量
$this->configure_env = $this->configure_env =
'PKG_CONFIG="' . BUILD_ROOT_PATH . '/bin/pkg-config" ' .
'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig/" ' . 'PKG_CONFIG_PATH="' . BUILD_LIB_PATH . '/pkgconfig/" ' .
"CC='{$this->cc}' " . "CC='{$this->cc}' " .
"CXX='{$this->cxx}' " . "CXX='{$this->cxx}' " .
@@ -145,7 +146,7 @@ class MacOSBuilder extends BuilderBase
if ($this->getLib('libxml2') || $this->getExt('iconv')) { if ($this->getLib('libxml2') || $this->getExt('iconv')) {
$extra_libs .= ' -liconv'; $extra_libs .= ' -liconv';
} }
if ($this->getPHPVersionID() < 80000) { if ($this->getPHPVersionID() < 80000) {
$json_74 = '--enable-json '; $json_74 = '--enable-json ';
} else { } 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) ->cd(BUILD_LIB_PATH)
->exec('ln -sf libpng16.a libpng.a'); ->exec('ln -sf libpng16.a libpng.a');
$this->patchPkgconfPrefix(['libpng16.pc'], PKGCONF_PATCH_PREFIX); $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); 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_FIND_ROOT_PATH "{$root}")
SET(CMAKE_PREFIX_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_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

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

View File

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

View File

@@ -28,5 +28,6 @@ trait libwebp
->exec("make -j{$this->builder->concurrency}") ->exec("make -j{$this->builder->concurrency}")
->exec('make install DESTDIR=' . $destdir); ->exec('make install DESTDIR=' . $destdir);
$this->patchPkgconfPrefix(['libsharpyuv.pc', 'libwebp.pc', 'libwebpdecoder.pc', 'libwebpdemux.pc', 'libwebpmux.pc'], PKGCONF_PATCH_PREFIX); $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 '; $extra .= $this->builder->getLib('bzip2') ? '-DENABLE_BZIP2=ON ' : '-DENABLE_BZIP2=OFF ';
// lib:xz // lib:xz
$extra .= $this->builder->getLib('xz') ? '-DENABLE_LZMA=ON ' : '-DENABLE_LZMA=OFF '; $extra .= $this->builder->getLib('xz') ? '-DENABLE_LZMA=ON ' : '-DENABLE_LZMA=OFF ';
// lib:zstd // lib:zstd (disabled due to imagemagick link issue
$extra .= $this->builder->getLib('zstd') ? '-DENABLE_ZSTD=ON ' : '-DENABLE_ZSTD=OFF '; $extra .= /* $this->builder->getLib('zstd') ? '-DENABLE_ZSTD=ON ' : */ '-DENABLE_ZSTD=OFF ';
// lib:openssl // lib:openssl
$extra .= $this->builder->getLib('openssl') ? '-DENABLE_OPENSSL=ON ' : '-DENABLE_OPENSSL=OFF '; $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\BuilderBase;
use SPC\builder\linux\LinuxBuilder; use SPC\builder\linux\LinuxBuilder;
use SPC\builder\linux\SystemUtil;
use SPC\builder\macos\MacOSBuilder; use SPC\builder\macos\MacOSBuilder;
use SPC\exception\FileSystemException; use SPC\exception\FileSystemException;
use SPC\exception\RuntimeException; use SPC\exception\RuntimeException;
@@ -99,6 +100,14 @@ class SourcePatcher
'-lz', '-lz',
BUILD_LIB_PATH . '/libz.a' 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 public static function patchCurlMacOS(): void

View File

@@ -66,6 +66,8 @@ function osfamily2dir(): string
} }
/** /**
* 执行shell直接输出在终端出现错误抛出异常
*
* @throws \SPC\exception\RuntimeException * @throws \SPC\exception\RuntimeException
*/ */
function f_passthru(string $cmd): ?bool function f_passthru(string $cmd): ?bool
@@ -89,7 +91,13 @@ function f_passthru(string $cmd): ?bool
return $ret; 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); logger()->debug('Running command (no output) : ' . $command);
return exec($command, $output, $result_code); return exec($command, $output, $result_code);