From 0fa38bad6d85de6b86a0b2a00aedb3f8c68079de Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Sun, 31 Aug 2025 15:04:34 +0800 Subject: [PATCH] Use existing pkg-config builds and pre-built contents for packages --- config/lib.json | 7 ++ config/pkg.json | 28 ++++- config/source.json | 9 ++ src/SPC/builder/freebsd/BSDBuilder.php | 5 - src/SPC/builder/freebsd/library/pkgconfig.php | 15 +++ src/SPC/builder/linux/library/pkgconfig.php | 15 +++ src/SPC/builder/macos/library/pkgconfig.php | 15 +++ src/SPC/builder/unix/library/pkgconfig.php | 31 +++++ src/SPC/doctor/item/PkgConfigCheck.php | 21 ++-- src/SPC/store/pkg/PkgConfig.php | 111 ------------------ src/SPC/toolchain/ToolchainManager.php | 6 - src/SPC/util/GlobalEnvManager.php | 11 +- src/SPC/util/PkgConfigUtil.php | 22 ++++ src/SPC/util/executor/UnixCMakeExecutor.php | 6 +- 14 files changed, 157 insertions(+), 145 deletions(-) create mode 100644 src/SPC/builder/freebsd/library/pkgconfig.php create mode 100644 src/SPC/builder/linux/library/pkgconfig.php create mode 100644 src/SPC/builder/macos/library/pkgconfig.php create mode 100644 src/SPC/builder/unix/library/pkgconfig.php delete mode 100644 src/SPC/store/pkg/PkgConfig.php diff --git a/config/lib.json b/config/lib.json index ead0ecc6..6d414b9f 100644 --- a/config/lib.json +++ b/config/lib.json @@ -19,6 +19,13 @@ "watcher" ] }, + "pkg-config": { + "type": "package", + "source": "pkg-config", + "bin-unix": [ + "pkg-config" + ] + }, "micro": { "type": "target", "source": "micro" diff --git a/config/pkg.json b/config/pkg.json index ce4d6546..942b1dbd 100644 --- a/config/pkg.json +++ b/config/pkg.json @@ -71,15 +71,35 @@ "type": "custom" }, "pkg-config-x86_64-linux": { - "type": "custom" + "type": "ghrel", + "repo": "static-php/static-php-cli-hosted", + "match": "pkg-config-x86_64-linux-musl-1.2.5.txz", + "extract-files": { + "bin/pkg-config": "{pkg_root_path}/bin/pkg-config" + } }, "pkg-config-aarch64-linux": { - "type": "custom" + "type": "ghrel", + "repo": "static-php/static-php-cli-hosted", + "match": "pkg-config-aarch64-linux-musl-1.2.5.txz", + "extract-files": { + "bin/pkg-config": "{pkg_root_path}/bin/pkg-config" + } }, "pkg-config-x86_64-macos": { - "type": "custom" + "type": "ghrel", + "repo": "static-php/static-php-cli-hosted", + "match": "pkg-config-x86_64-darwin.txz", + "extract-files": { + "bin/pkg-config": "{pkg_root_path}/bin/pkg-config" + } }, "pkg-config-aarch64-macos": { - "type": "custom" + "type": "ghrel", + "repo": "static-php/static-php-cli-hosted", + "match": "pkg-config-aarch64-darwin.txz", + "extract-files": { + "bin/pkg-config": "{pkg_root_path}/bin/pkg-config" + } } } diff --git a/config/source.json b/config/source.json index 9ab020a3..565d95fd 100644 --- a/config/source.json +++ b/config/source.json @@ -7,6 +7,15 @@ }, "alt": false }, + "pkg-config": { + "type": "url", + "url": "https://dl.static-php.dev/static-php-cli/deps/pkg-config/pkg-config-0.29.2.tar.gz", + "provide-pre-built": true, + "license": { + "type": "file", + "path": "COPYING" + } + }, "amqp": { "type": "url", "url": "https://pecl.php.net/get/amqp", diff --git a/src/SPC/builder/freebsd/BSDBuilder.php b/src/SPC/builder/freebsd/BSDBuilder.php index 09f31c9a..985de5d2 100644 --- a/src/SPC/builder/freebsd/BSDBuilder.php +++ b/src/SPC/builder/freebsd/BSDBuilder.php @@ -7,7 +7,6 @@ namespace SPC\builder\freebsd; use SPC\builder\unix\UnixBuilderBase; use SPC\exception\WrongUsageException; use SPC\store\FileSystem; -use SPC\store\pkg\PkgConfig; use SPC\store\SourcePatcher; class BSDBuilder extends UnixBuilderBase @@ -26,10 +25,6 @@ class BSDBuilder extends UnixBuilderBase f_putenv('CXX=' . $this->getOption('cxx', 'clang++')); // set PATH f_putenv('PATH=' . BUILD_ROOT_PATH . '/bin:' . getenv('PATH')); - // set PKG_CONFIG - f_putenv('PKG_CONFIG=' . PkgConfig::getEnvironment()['PATH'] . '/bin/pkg-config'); - // set PKG_CONFIG_PATH - f_putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig/'); // set arch (default: current) $this->setOptionIfNotExist('arch', php_uname('m')); diff --git a/src/SPC/builder/freebsd/library/pkgconfig.php b/src/SPC/builder/freebsd/library/pkgconfig.php new file mode 100644 index 00000000..62bd8ace --- /dev/null +++ b/src/SPC/builder/freebsd/library/pkgconfig.php @@ -0,0 +1,15 @@ +appendEnv([ + 'CFLAGS' => '-Wimplicit-function-declaration -Wno-int-conversion', + 'LDFLAGS' => SPCTarget::isStatic() ? '--static' : '', + ]) + ->configure( + '--with-internal-glib', + '--disable-host-tool', + '--without-sysroot', + '--without-system-include-path', + '--without-system-library-path', + '--without-pc-path', + ) + ->make(with_install: 'install-exec'); + + shell()->exec('strip ' . BUILD_ROOT_PATH . '/bin/pkg-config'); + } +} diff --git a/src/SPC/doctor/item/PkgConfigCheck.php b/src/SPC/doctor/item/PkgConfigCheck.php index 8ca1c83e..0936a606 100644 --- a/src/SPC/doctor/item/PkgConfigCheck.php +++ b/src/SPC/doctor/item/PkgConfigCheck.php @@ -9,7 +9,7 @@ use SPC\doctor\AsFixItem; use SPC\doctor\CheckResult; use SPC\doctor\OptionalCheck; use SPC\store\PackageManager; -use SPC\store\pkg\PkgConfig; +use SPC\util\PkgConfigUtil; #[OptionalCheck([self::class, 'optionalCheck'])] class PkgConfigCheck @@ -20,26 +20,19 @@ class PkgConfigCheck } /** @noinspection PhpUnused */ - #[AsCheckItem('if pkg-config is installed', level: 800)] + #[AsCheckItem('if pkg-config is installed or built', level: 800)] public function checkPkgConfig(): CheckResult { - if (PkgConfig::isInstalled()) { - return CheckResult::ok(); + if (!($pkgconf = PkgConfigUtil::findPkgConfig())) { + return CheckResult::fail('pkg-config is not installed', 'install-pkgconfig'); } - return CheckResult::fail('pkg-config is not installed', 'install-pkgconfig'); + return CheckResult::ok($pkgconf); } #[AsFixItem('install-pkgconfig')] public function installPkgConfig(): bool { - $arch = arch2gnu(php_uname('m')); - $os = match (PHP_OS_FAMILY) { - 'Windows' => 'win', - 'Darwin' => 'macos', - 'BSD' => 'freebsd', - default => 'linux', - }; - PackageManager::installPackage("pkg-config-{$arch}-{$os}"); - return PkgConfig::isInstalled(); + PackageManager::installPackage('pkg-config'); + return true; } } diff --git a/src/SPC/store/pkg/PkgConfig.php b/src/SPC/store/pkg/PkgConfig.php deleted file mode 100644 index cc5d3dcd..00000000 --- a/src/SPC/store/pkg/PkgConfig.php +++ /dev/null @@ -1,111 +0,0 @@ - 'macos', - default => 'linux', - }; - $name = "pkg-config-{$arch}-{$os}"; - return is_file(PKG_ROOT_PATH . "/{$name}/bin/pkg-config"); - } - - public function getSupportName(): array - { - return [ - 'pkg-config-x86_64-linux', - 'pkg-config-aarch64-linux', - 'pkg-config-x86_64-macos', - 'pkg-config-aarch64-macos', - ]; - } - - public function fetch(string $name, bool $force = false, ?array $config = null): void - { - $pkgroot = PKG_ROOT_PATH; - $bin = "{$pkgroot}/{$name}/bin/pkg-config"; - if ($force) { - FileSystem::removeDir("{$pkgroot}/{$name}"); - } - if (file_exists($bin)) { - return; - } - // Use known stable pkg-config source tarball (same as config/source.json) - $pkg = [ - 'type' => 'url', - 'url' => 'https://dl.static-php.dev/static-php-cli/deps/pkg-config/pkg-config-0.29.2.tar.gz', - 'filename' => 'pkg-config-0.29.2.tar.gz', - ]; - Downloader::downloadPackage($name, $pkg, $force); - } - - public function extract(string $name): void - { - $pkgroot = PKG_ROOT_PATH; - $prefix = "{$pkgroot}/{$name}"; - $bin = "{$prefix}/bin/pkg-config"; - if (file_exists($bin)) { - return; - } - $lock = json_decode(FileSystem::readFile(LockFile::LOCK_FILE), true); - $source_type = $lock[$name]['source_type']; - $filename = DOWNLOAD_PATH . '/' . ($lock[$name]['filename'] ?? $lock[$name]['dirname']); - $srcdir = "{$pkgroot}/{$name}/src"; - FileSystem::extractPackage($name, $source_type, $filename, $srcdir); - - // build from source into package prefix - $env = [ - 'CFLAGS' => '-Wno-int-conversion ' . (getenv('SPC_DEFAULT_C_FLAGS') ?: '-Os'), - 'LDFLAGS' => (SPCTarget::isStatic() ? '--static' : ''), - 'PKG_CONFIG' => 'pkg-config', - 'PKG_CONFIG_PATH' => BUILD_ROOT_PATH . '/lib/pkgconfig', - ]; - $shell = shell() - ->setEnv([ - 'CC' => 'cc', - 'CXX' => 'c++', - 'AR' => 'ar', - 'LD' => 'ld', - ]) - ->appendEnv($env)->cd($srcdir); - $shell->exec( - "./configure --prefix='{$prefix}' " . - '--with-internal-glib ' . - '--disable-host-tool ' . - '--without-sysroot ' . - '--without-system-include-path ' . - '--without-system-library-path ' . - '--without-pc-path', - ); - $shell->exec('make -j' . (getenv('SPC_CONCURRENCY') ?: '1')); - $shell->exec('make install-exec'); - if (is_file($bin)) { - @shell()->exec('strip ' . $bin); - } - } - - public static function getEnvironment(): array - { - $arch = arch2gnu(php_uname('m')); - $os = match (PHP_OS_FAMILY) { - 'Darwin' => 'macos', - default => 'linux', - }; - $name = "pkg-config-{$arch}-{$os}"; - return [ - 'PATH' => PKG_ROOT_PATH . "/{$name}/bin", - ]; - } -} diff --git a/src/SPC/toolchain/ToolchainManager.php b/src/SPC/toolchain/ToolchainManager.php index 819bdb64..3fe48ae1 100644 --- a/src/SPC/toolchain/ToolchainManager.php +++ b/src/SPC/toolchain/ToolchainManager.php @@ -5,9 +5,7 @@ declare(strict_types=1); namespace SPC\toolchain; use SPC\builder\linux\SystemUtil; -use SPC\exception\EnvironmentException; use SPC\exception\WrongUsageException; -use SPC\store\pkg\PkgConfig; use SPC\util\GlobalEnvManager; use SPC\util\SPCTarget; @@ -58,10 +56,6 @@ class ToolchainManager if (SPCTarget::getLibc() === 'glibc' && SystemUtil::isMuslDist()) { throw new WrongUsageException('You are linking against glibc dynamically, which is only supported on glibc distros.'); } - if (!is_dir(PkgConfig::getEnvironment()['PATH'])) { - throw new EnvironmentException('Please install pkg-config first. (You can use `doctor` command to install it)'); - } - GlobalEnvManager::addPathIfNotExists(PkgConfig::getEnvironment()['PATH']); $toolchain = getenv('SPC_TOOLCHAIN'); /* @var ToolchainInterface $toolchain */ $instance = new $toolchain(); diff --git a/src/SPC/util/GlobalEnvManager.php b/src/SPC/util/GlobalEnvManager.php index c979ca2c..f3af8971 100644 --- a/src/SPC/util/GlobalEnvManager.php +++ b/src/SPC/util/GlobalEnvManager.php @@ -7,7 +7,6 @@ namespace SPC\util; use SPC\builder\macos\SystemUtil; use SPC\exception\SPCInternalException; use SPC\exception\WrongUsageException; -use SPC\store\pkg\PkgConfig; use SPC\toolchain\ToolchainManager; /** @@ -40,7 +39,7 @@ class GlobalEnvManager // Define env vars for unix if (is_unix()) { self::addPathIfNotExists(BUILD_BIN_PATH); - self::putenv('PKG_CONFIG=' . PkgConfig::getEnvironment()['PATH'] . '/pkg-config'); + self::addPathIfNotExists(PKG_ROOT_PATH . '/bin'); self::putenv('PKG_CONFIG_PATH=' . BUILD_LIB_PATH . '/pkgconfig'); } @@ -123,6 +122,14 @@ class GlobalEnvManager self::putenv("YACC={$yacc}"); } } + + // init pkg-config for unix + if (is_unix()) { + if (($found = PkgConfigUtil::findPkgConfig()) === null) { + throw new WrongUsageException('Cannot find pkg-config executable. Please run `doctor` to fix this.'); + } + self::putenv("PKG_CONFIG={$found}"); + } } private static function readIniFile(): array diff --git a/src/SPC/util/PkgConfigUtil.php b/src/SPC/util/PkgConfigUtil.php index 41a3b6e2..25e0e1f2 100644 --- a/src/SPC/util/PkgConfigUtil.php +++ b/src/SPC/util/PkgConfigUtil.php @@ -14,6 +14,28 @@ use SPC\exception\ExecutionException; */ class PkgConfigUtil { + /** + * Find the pkg-config executable which is compatible with static builds. + * + * @return null|string Path to pkg-config executable, or null if not found + */ + public static function findPkgConfig(): ?string + { + // Find pkg-config executable + $find_list = [ + PKG_ROOT_PATH . '/bin/pkg-config', + BUILD_BIN_PATH . '/pkg-config', + ]; + $found = null; + foreach ($find_list as $file) { + if (file_exists($file) && is_executable($file)) { + $found = $file; + break; + } + } + return $found; + } + /** * Returns the version of a module. * This method uses `pkg-config --modversion` to get the version of the specified module. diff --git a/src/SPC/util/executor/UnixCMakeExecutor.php b/src/SPC/util/executor/UnixCMakeExecutor.php index abcfe392..3e29addf 100644 --- a/src/SPC/util/executor/UnixCMakeExecutor.php +++ b/src/SPC/util/executor/UnixCMakeExecutor.php @@ -8,7 +8,7 @@ use SPC\builder\freebsd\library\BSDLibraryBase; use SPC\builder\linux\library\LinuxLibraryBase; use SPC\builder\macos\library\MacOSLibraryBase; use SPC\store\FileSystem; -use SPC\store\pkg\PkgConfig; +use SPC\util\PkgConfigUtil; use SPC\util\shell\UnixShell; /** @@ -185,7 +185,7 @@ class UnixCMakeExecutor extends Executor $cxx = getenv('CCX'); logger()->debug("making cmake tool chain file for {$os} {$target_arch} with CFLAGS='{$cflags}'"); $root = BUILD_ROOT_PATH; - $pkgConfig = PkgConfig::getEnvironment()['PATH']; + $pkgConfigExecutable = PkgConfigUtil::findPkgConfig(); $ccLine = ''; if ($cc) { $ccLine = 'SET(CMAKE_C_COMPILER ' . $cc . ')'; @@ -204,7 +204,7 @@ SET(CMAKE_PREFIX_PATH "{$root}") SET(CMAKE_INSTALL_PREFIX "{$root}") SET(CMAKE_INSTALL_LIBDIR "lib") -set(PKG_CONFIG_EXECUTABLE "{$pkgConfig}/pkg-config") +set(PKG_CONFIG_EXECUTABLE "{$pkgConfigExecutable}") list(APPEND PKG_CONFIG_EXECUTABLE "--static") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)