Use existing pkg-config builds and pre-built contents for packages

This commit is contained in:
crazywhalecc 2025-08-31 15:04:34 +08:00
parent f2c131a2cc
commit 0fa38bad6d
No known key found for this signature in database
GPG Key ID: 1F4BDD59391F2680
14 changed files with 157 additions and 145 deletions

View File

@ -19,6 +19,13 @@
"watcher"
]
},
"pkg-config": {
"type": "package",
"source": "pkg-config",
"bin-unix": [
"pkg-config"
]
},
"micro": {
"type": "target",
"source": "micro"

View File

@ -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"
}
}
}

View File

@ -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",

View File

@ -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'));

View File

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

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

@ -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

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace SPC\builder\unix\library;
use SPC\util\executor\UnixAutoconfExecutor;
use SPC\util\SPCTarget;
trait pkgconfig
{
protected function build(): void
{
UnixAutoconfExecutor::create($this)
->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');
}
}

View File

@ -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;
}
}

View File

@ -1,111 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\store\pkg;
use SPC\store\Downloader;
use SPC\store\FileSystem;
use SPC\store\LockFile;
use SPC\util\SPCTarget;
class PkgConfig extends CustomPackage
{
public static function isInstalled(): bool
{
$arch = arch2gnu(php_uname('m'));
$os = match (PHP_OS_FAMILY) {
'Darwin' => '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",
];
}
}

View File

@ -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();

View File

@ -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

View File

@ -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.

View File

@ -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)