diff --git a/.github/workflows/build-unix.yml b/.github/workflows/build-unix.yml index 7a745048..16ad76e0 100644 --- a/.github/workflows/build-unix.yml +++ b/.github/workflows/build-unix.yml @@ -230,12 +230,12 @@ jobs: - uses: actions/upload-artifact@v4 name: "Upload License Files" with: - name: license-files + name: license-files-${{ inputs.php-version }}-${{ inputs.os }} path: buildroot/license/ - uses: actions/upload-artifact@v4 name: "Upload Build Metadata" with: - name: build-meta + name: build-meta-${{ inputs.php-version }}-${{ inputs.os }} path: | buildroot/build-extensions.json buildroot/build-libraries.json diff --git a/bin/spc-gnu-docker b/bin/spc-gnu-docker index 164697f1..1c033134 100755 --- a/bin/spc-gnu-docker +++ b/bin/spc-gnu-docker @@ -87,7 +87,7 @@ RUN sed -i 's/^#.*baseurl=http/baseurl=http/g' /etc/yum.repos.d/*.repo && \ sed -i 's|http://|https://|g' /etc/yum.repos.d/*.repo RUN yum update -y && \ - yum install -y devtoolset-10-gcc-* + yum install -y devtoolset-10-gcc-* devtoolset-10-libatomic-devel RUN echo "source scl_source enable devtoolset-10" >> /etc/bashrc RUN source /etc/bashrc RUN yum install -y which diff --git a/config/lib.json b/config/lib.json index 1a195f66..28775535 100644 --- a/config/lib.json +++ b/config/lib.json @@ -228,8 +228,9 @@ ], "lib-depends": [ "zlib", - "libpng", "libjpeg", + "libjxl", + "libpng", "libwebp", "freetype", "libtiff", @@ -252,6 +253,18 @@ "openssl" ] }, + "jbig": { + "source": "jbig", + "static-libs-unix": [ + "libjbig.a", + "libjbig85.a" + ], + "headers": [ + "jbig.h", + "jbig85.h", + "jbig_ar.h" + ] + }, "ldap": { "source": "ldap", "static-libs-unix": [ @@ -265,6 +278,13 @@ "libsodium" ] }, + "lerc": { + "source": "lerc", + "static-libs-unix": [ + "libLerc.a" + ], + "cpp-library": true + }, "libacl": { "source": "libacl", "static-libs-unix": [ @@ -400,6 +420,21 @@ "zlib" ] }, + "libjxl": { + "source": "libjxl", + "static-libs-unix": [ + "libjxl.a", + "libjxl_cms.a", + "libjxl_threads.a", + "libhwy.a" + ], + "lib-depends": [ + "brotli", + "libjpeg", + "libpng", + "libwebp" + ] + }, "liblz4": { "source": "liblz4", "static-libs-unix": [ @@ -485,9 +520,6 @@ ], "lib-depends": [ "openssl" - ], - "lib-suggests": [ - "zlib" ] }, "libtiff": { @@ -498,6 +530,13 @@ "lib-depends": [ "zlib", "libjpeg" + ], + "lib-suggests-unix": [ + "lerc", + "libwebp", + "jbig", + "xz", + "zstd" ] }, "libuuid": { @@ -813,6 +852,15 @@ "libiconv" ] }, + "watcher": { + "source": "watcher", + "static-libs-unix": [ + "libwatcher-c.a" + ], + "headers": [ + "wtr/watcher-c.h" + ] + }, "xz": { "source": "xz", "static-libs-unix": [ @@ -866,14 +914,5 @@ "zstd.h", "zstd_errors.h" ] - }, - "watcher": { - "source": "watcher", - "static-libs-unix": [ - "libwatcher-c.a" - ], - "headers": [ - "wtr/watcher-c.h" - ] } } diff --git a/config/source.json b/config/source.json index bfd330bb..c6343683 100644 --- a/config/source.json +++ b/config/source.json @@ -388,6 +388,19 @@ "path": "LICENSE" } }, + "jbig": { + "type": "url", + "url": "https://dl.static-php.dev/static-php-cli/deps/jbig/jbigkit-2.1.tar.gz", + "provide-pre-built": true, + "alt": { + "type": "url", + "url": "https://www.cl.cam.ac.uk/~mgk25/jbigkit/download/jbigkit-2.1.tar.gz" + }, + "license": { + "type": "file", + "path": "COPYING" + } + }, "ldap": { "type": "filelist", "url": "https://www.openldap.org/software/download/OpenLDAP/openldap-release/", @@ -397,6 +410,16 @@ "path": "LICENSE" } }, + "lerc": { + "type": "ghtar", + "repo": "Esri/lerc", + "prefer-stable": true, + "provide-pre-built": true, + "license": { + "type": "file", + "path": "LICENSE" + } + }, "libacl": { "alt": { "type": "url", @@ -534,6 +557,21 @@ "path": "LICENSE.md" } }, + "libjxl": { + "type": "git", + "url": "https://github.com/libjxl/libjxl", + "rev": "main", + "submodules": [ + "third_party/highway", + "third_party/libjpeg-turbo", + "third_party/sjpeg", + "third_party/skcms" + ], + "license": { + "type": "file", + "path": "LICENSE" + } + }, "liblz4": { "type": "ghrel", "repo": "lz4/lz4", @@ -597,6 +635,7 @@ "repo": "libssh2/libssh2", "match": "libssh2.+\\.tar\\.gz", "prefer-stable": true, + "provide-pre-built": true, "license": { "type": "file", "path": "COPYING" @@ -606,7 +645,6 @@ "type": "filelist", "url": "https://download.osgeo.org/libtiff/", "regex": "/href=\"(?tiff-(?[^\"]+)\\.tar\\.xz)\"/", - "provide-pre-built": true, "license": { "type": "file", "path": "LICENSE.md" @@ -994,6 +1032,15 @@ "path": "COPYING" } }, + "watcher": { + "type": "ghtar", + "repo": "e-dant/watcher", + "prefer-stable": true, + "license": { + "type": "file", + "path": "license" + } + }, "xdebug": { "type": "url", "url": "https://pecl.php.net/get/xdebug", @@ -1074,14 +1121,5 @@ "type": "file", "path": "LICENSE" } - }, - "watcher": { - "type": "ghtar", - "repo": "e-dant/watcher", - "prefer-stable": true, - "license": { - "type": "file", - "path": "license" - } } } diff --git a/src/SPC/builder/Extension.php b/src/SPC/builder/Extension.php index 6a702416..e321b0a8 100644 --- a/src/SPC/builder/Extension.php +++ b/src/SPC/builder/Extension.php @@ -10,7 +10,6 @@ use SPC\exception\WrongUsageException; use SPC\store\Config; use SPC\store\FileSystem; use SPC\util\SPCConfigUtil; -use SPC\util\SPCTarget; class Extension { @@ -550,6 +549,11 @@ class Extension $sharedLibString .= '-l' . $lib . ' '; } } + // move -lstdc++ to static libraries because centos 7 the shared libstdc++ is incomplete + if (str_contains((string) getenv('PATH'), 'rh/devtoolset-10')) { + $staticLibString .= ' -lstdc++'; + $sharedLibString = str_replace('-lstdc++', '', $sharedLibString); + } return [trim($staticLibString), trim($sharedLibString)]; } diff --git a/src/SPC/builder/linux/library/jbig.php b/src/SPC/builder/linux/library/jbig.php new file mode 100644 index 00000000..e47e21f4 --- /dev/null +++ b/src/SPC/builder/linux/library/jbig.php @@ -0,0 +1,12 @@ +optionalLib('zstd', ...ac_with_args('zstd')) ->optionalLib('freetype', ...ac_with_args('freetype')) ->optionalLib('bzip2', ...ac_with_args('bzlib')) + ->optionalLib('libjxl', ...ac_with_args('jxl')) + ->optionalLib('jbig', ...ac_with_args('jbig')) ->addConfigureArgs( '--disable-openmp', - '--without-jbig', - '--without-jxl', '--without-x', ); diff --git a/src/SPC/builder/unix/library/jbig.php b/src/SPC/builder/unix/library/jbig.php new file mode 100644 index 00000000..85e24748 --- /dev/null +++ b/src/SPC/builder/unix/library/jbig.php @@ -0,0 +1,35 @@ +source_dir . '/Makefile', 'CFLAGS = -O2 -W -Wno-unused-result', 'CFLAGS = -O2 -W -Wno-unused-result -fPIC'); + return true; + } + + /** + * @throws RuntimeException + */ + protected function build(): void + { + shell()->cd($this->source_dir)->initializeEnv($this) + ->exec("make -j{$this->builder->concurrency} {$this->builder->getEnvString()} lib") + ->exec('cp libjbig/libjbig.a ' . BUILD_LIB_PATH) + ->exec('cp libjbig/libjbig85.a ' . BUILD_LIB_PATH) + ->exec('cp libjbig/jbig.h ' . BUILD_INCLUDE_PATH) + ->exec('cp libjbig/jbig85.h ' . BUILD_INCLUDE_PATH) + ->exec('cp libjbig/jbig_ar.h ' . BUILD_INCLUDE_PATH); + } +} diff --git a/src/SPC/builder/unix/library/lerc.php b/src/SPC/builder/unix/library/lerc.php new file mode 100644 index 00000000..290c0f61 --- /dev/null +++ b/src/SPC/builder/unix/library/lerc.php @@ -0,0 +1,22 @@ +build(); + } +} diff --git a/src/SPC/builder/unix/library/libjxl.php b/src/SPC/builder/unix/library/libjxl.php new file mode 100644 index 00000000..871477b9 --- /dev/null +++ b/src/SPC/builder/unix/library/libjxl.php @@ -0,0 +1,28 @@ +addConfigureArgs('-DJPEGXL_ENABLE_TOOLS=OFF') + ->addConfigureArgs('-DJPEGXL_ENABLE_EXAMPLES=OFF') + ->addConfigureArgs('-DJPEGXL_ENABLE_MANPAGES=OFF') + ->addConfigureArgs('-DJPEGXL_ENABLE_BENCHMARK=OFF') + ->addConfigureArgs('-DJPEGXL_ENABLE_PLUGINS=OFF') + ->addConfigureArgs('-DJPEGXL_ENABLE_SJPOEG=ON') + ->addConfigureArgs('-DJPEGXL_ENABLE_JNI=OFF') + ->addConfigureArgs('-DJPEGXL_ENABLE_TRANSCODE_JPEG=ON') + ->addConfigureArgs('-DJPEGXL_STATIC=' . (SPCTarget::isStatic() ? 'ON' : 'OFF')) + ->addConfigureArgs('-DJPEGXL_FORCE_SYSTEM_BROTLI=ON') + ->addConfigureArgs('-DBUILD_TESTING=OFF') + ->build(); + } +} diff --git a/src/SPC/builder/unix/library/libtiff.php b/src/SPC/builder/unix/library/libtiff.php index f615019a..b4afdd7f 100644 --- a/src/SPC/builder/unix/library/libtiff.php +++ b/src/SPC/builder/unix/library/libtiff.php @@ -6,7 +6,9 @@ namespace SPC\builder\unix\library; use SPC\exception\FileSystemException; use SPC\exception\RuntimeException; +use SPC\store\FileSystem; use SPC\util\executor\UnixAutoconfExecutor; +use SPC\util\SPCTarget; trait libtiff { @@ -16,7 +18,15 @@ trait libtiff */ protected function build(): void { + $libcpp = SPCTarget::getTargetOS() === 'Linux' ? '-lstdc++' : '-lc++'; + FileSystem::replaceFileStr($this->source_dir . '/configure', '-lwebp', '-lwebp -lsharpyuv'); + FileSystem::replaceFileStr($this->source_dir . '/configure', '-l"$lerc_lib_name"', '-l"$lerc_lib_name" ' . $libcpp); UnixAutoconfExecutor::create($this) + ->optionalLib('lerc', '--enable-lerc', '--disable-lerc') + ->optionalLib('zstd', '--enable-zstd', '--disable-zstd') + ->optionalLib('libwebp', '--enable-webp', '--disable-webp') + ->optionalLib('xz', '--enable-lzma', '--disable-lzma') + ->optionalLib('jbig', '--enable-jbig', '--disable-jbig') ->configure( // zlib deps '--enable-zlib', @@ -24,16 +34,15 @@ trait libtiff "--with-zlib-lib-dir={$this->getLibDir()}", // libjpeg deps '--enable-jpeg', - '--disable-old-jpeg', - '--disable-jpeg12', "--with-jpeg-include-dir={$this->getIncludeDir()}", "--with-jpeg-lib-dir={$this->getLibDir()}", - // We disabled lzma, zstd, webp, libdeflate by default to reduce the size of the binary - '--disable-lzma', - '--disable-zstd', - '--disable-webp', + '--disable-old-jpeg', + '--disable-jpeg12', '--disable-libdeflate', + '--disable-tools', + '--disable-contrib', '--disable-cxx', + '--without-x', ) ->make(); $this->patchPkgconfPrefix(['libtiff-4.pc']); diff --git a/src/SPC/store/Downloader.php b/src/SPC/store/Downloader.php index b02d2073..4bdb75fc 100644 --- a/src/SPC/store/Downloader.php +++ b/src/SPC/store/Downloader.php @@ -219,34 +219,41 @@ class Downloader * @throws RuntimeException * @throws WrongUsageException */ - public static function downloadGit(string $name, string $url, string $branch, ?string $move_path = null, int $retries = 0, int $lock_as = SPC_DOWNLOAD_SOURCE): void + public static function downloadGit(string $name, string $url, string $branch, ?array $submodules = null, ?string $move_path = null, int $retries = 0, int $lock_as = SPC_DOWNLOAD_SOURCE): void { $download_path = FileSystem::convertPath(DOWNLOAD_PATH . "/{$name}"); if (file_exists($download_path)) { FileSystem::removeDir($download_path); } logger()->debug("cloning {$name} source"); - $check = !defined('DEBUG_MODE') ? ' -q' : ''; - $cancel_func = function () use ($download_path) { + + $quiet = !defined('DEBUG_MODE') ? '-q --quiet' : ''; + $git = SPC_GIT_EXEC; + $shallow = defined('GIT_SHALLOW_CLONE') ? '--depth 1 --single-branch' : ''; + $recursive = ($submodules === null) ? '--recursive' : ''; + + try { + self::registerCancelEvent(function () use ($download_path) { + if (is_dir($download_path)) { + logger()->warning('Removing path ' . $download_path); + FileSystem::removeDir($download_path); + } + }); + f_passthru("{$git} clone {$quiet} --config core.autocrlf=false --branch \"{$branch}\" {$shallow} {$recursive} \"{$url}\" \"{$download_path}\""); + if ($submodules !== null) { + foreach ($submodules as $submodule) { + f_passthru("cd \"{$download_path}\" && {$git} submodule update --init " . escapeshellarg($submodule)); + } + } + } catch (RuntimeException $e) { if (is_dir($download_path)) { - logger()->warning('Removing path ' . $download_path); FileSystem::removeDir($download_path); } - }; - try { - self::registerCancelEvent($cancel_func); - f_passthru( - SPC_GIT_EXEC . ' clone' . $check . - (defined('DEBUG_MODE') ? '' : ' --quiet') . - ' --config core.autocrlf=false ' . - "--branch \"{$branch}\" " . (defined('GIT_SHALLOW_CLONE') ? '--depth 1 --single-branch' : '') . " --recursive \"{$url}\" \"{$download_path}\"" - ); - } catch (RuntimeException $e) { if ($e->getCode() === 2 || $e->getCode() === -1073741510) { throw new WrongUsageException('Keyboard interrupted, download failed !'); } if ($retries > 0) { - self::downloadGit($name, $url, $branch, $move_path, $retries - 1); + self::downloadGit($name, $url, $branch, $submodules, $move_path, $retries - 1, $lock_as); return; } throw $e; @@ -343,6 +350,7 @@ class Downloader $name, $pkg['url'], $pkg['rev'], + $pkg['submodules'] ?? null, $pkg['extract'] ?? null, self::getRetryAttempts(), SPC_DOWNLOAD_PRE_BUILT @@ -462,6 +470,7 @@ class Downloader $name, $source['url'], $source['rev'], + $source['submodules'] ?? null, $source['path'] ?? null, self::getRetryAttempts(), $download_as diff --git a/src/globals/ext-tests/imagick.php b/src/globals/ext-tests/imagick.php index 5fac8dcc..49f41fbe 100644 --- a/src/globals/ext-tests/imagick.php +++ b/src/globals/ext-tests/imagick.php @@ -10,3 +10,4 @@ assert(Imagick::queryFormats('WEBP') !== []); assert(Imagick::queryFormats('JPEG') !== []); assert(Imagick::queryFormats('PNG') !== []); assert(Imagick::queryFormats('TIFF') !== []); +assert(Imagick::queryFormats('JXL') !== []); diff --git a/src/globals/test-extensions.php b/src/globals/test-extensions.php index 092552be..945a204d 100644 --- a/src/globals/test-extensions.php +++ b/src/globals/test-extensions.php @@ -29,7 +29,7 @@ $test_os = [ 'ubuntu-24.04', // bin/spc for x86_64 'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64 'ubuntu-24.04-arm', // bin/spc for arm64 - 'windows-latest', // .\bin\spc.ps1 + // 'windows-latest', // .\bin\spc.ps1 ]; // whether enable thread safe @@ -60,7 +60,7 @@ $shared_extensions = match (PHP_OS_FAMILY) { }; // If you want to test lib-suggests for all extensions and libraries, set it to true. -$with_suggested_libs = false; +$with_suggested_libs = true; // If you want to test extra libs for extensions, add them below (comma separated, example `libwebp,libavif`). Unnecessary, when $with_suggested_libs is true. $with_libs = match (PHP_OS_FAMILY) {