Merge branch 'refs/heads/main' into php-85

# Conflicts:
#	src/globals/test-extensions.php
This commit is contained in:
crazywhalecc
2025-07-28 10:12:13 +08:00
69 changed files with 1183 additions and 729 deletions

View File

@@ -18,7 +18,6 @@ abstract class BuildCommand extends BaseCommand
}
$this->addOption('with-clean', null, null, 'fresh build, remove `source` and `buildroot` dir before build');
$this->addOption('bloat', null, null, 'add all libraries into binary');
$this->addOption('rebuild', 'r', null, 'Delete old build and rebuild');
$this->addOption('enable-zts', null, null, 'enable ZTS support');
}

View File

@@ -245,11 +245,14 @@ class DownloadCommand extends BaseCommand
}
// if download failed, we will try to download alternative sources
logger()->warning("Download failed: {$e->getMessage()}");
logger()->notice("Trying to download alternative sources for {$source}");
$alt_sources = Config::getSource($source)['alt'] ?? null;
if ($alt_sources === null) {
$alt_config = array_merge($config, $this->getDefaultAlternativeSource($source));
logger()->warning("No alternative sources found for {$source}, using default alternative source");
$alt_config = array_merge($config, Downloader::getDefaultAlternativeSource($source));
} elseif ($alt_sources === false) {
throw new DownloaderException("No alternative sources found for {$source}, skipping alternative download");
} else {
logger()->notice("Trying to download alternative sources for {$source}");
$alt_config = array_merge($config, $alt_sources);
}
Downloader::downloadSource($source, $alt_config, $force_all || in_array($source, $force_list));
@@ -395,27 +398,4 @@ class DownloadCommand extends BaseCommand
}
return static::FAILURE;
}
private function getDefaultAlternativeSource(string $source_name): array
{
return [
'type' => 'custom',
'func' => function (bool $force, array $source, int $download_as) use ($source_name) {
logger()->debug("Fetching alternative source for {$source_name}");
// get from dl.static-php.dev
$url = "https://dl.static-php.dev/static-php-cli/deps/spc-download-mirror/{$source_name}/?format=json";
$json = json_decode(Downloader::curlExec(url: $url, retries: intval(getenv('SPC_DOWNLOAD_RETRIES') ?: 0)), true);
if (!is_array($json)) {
throw new RuntimeException('failed http fetch');
}
$item = $json[0] ?? null;
if ($item === null) {
throw new RuntimeException('failed to parse json');
}
$full_url = 'https://dl.static-php.dev' . $item['full_path'];
$filename = basename($item['full_path']);
Downloader::downloadFile($source_name, $full_url, $filename, $source['path'] ?? null, $download_as);
},
];
}
}

View File

@@ -24,6 +24,8 @@ class InstallPkgCommand extends BaseCommand
$this->addArgument('packages', InputArgument::REQUIRED, 'The packages will be installed, comma separated');
$this->addOption('shallow-clone', null, null, 'Clone shallow');
$this->addOption('custom-url', 'U', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Specify custom source download url, e.g "php-src:https://downloads.php.net/~eric/php-8.3.0beta1.tar.gz"');
$this->addOption('no-alt', null, null, 'Do not download alternative packages');
$this->addOption('skip-extract', null, null, 'Skip package extraction, just download the package archive');
}
/**
@@ -66,10 +68,20 @@ class InstallPkgCommand extends BaseCommand
$new_config['filename'] = $config['filename'];
}
logger()->info("Installing source {$pkg} from custom url [{$ni}/{$cnt}]");
PackageManager::installPackage($pkg, $new_config);
PackageManager::installPackage(
$pkg,
$new_config,
allow_alt: false,
extract: !$this->getOption('skip-extract')
);
} else {
logger()->info("Fetching package {$pkg} [{$ni}/{$cnt}]");
PackageManager::installPackage($pkg, Config::getPkg($pkg));
PackageManager::installPackage(
$pkg,
Config::getPkg($pkg),
allow_alt: !$this->getOption('no-alt'),
extract: !$this->getOption('skip-extract')
);
}
}
$time = round(microtime(true) - START_TIME, 3);

View File

@@ -23,6 +23,9 @@ class SPCConfigCommand extends BaseCommand
$this->addOption('with-suggested-exts', 'E', null, 'Build with suggested extensions for selected exts');
$this->addOption('includes', null, null, 'Add additional include path');
$this->addOption('libs', null, null, 'Add additional libs path');
$this->addOption('libs-only-deps', null, null, 'Output dependent libraries with -l prefix');
$this->addOption('absolute-libs', null, null, 'Output absolute paths for libraries');
$this->addOption('no-php', null, null, 'Do not link to PHP library');
}
/**
@@ -37,16 +40,19 @@ class SPCConfigCommand extends BaseCommand
$include_suggest_ext = $this->getOption('with-suggested-exts');
$include_suggest_lib = $this->getOption('with-suggested-libs');
$util = new SPCConfigUtil();
$util = new SPCConfigUtil(options: [
'no_php' => $this->getOption('no-php'),
'libs_only_deps' => $this->getOption('libs-only-deps'),
'absolute_libs' => $this->getOption('absolute-libs'),
]);
$config = $util->config($extensions, $libraries, $include_suggest_ext, $include_suggest_lib);
if ($this->getOption('includes')) {
$this->output->writeln($config['cflags']);
} elseif ($this->getOption('libs')) {
$this->output->writeln("{$config['ldflags']} {$config['libs']}");
} else {
$this->output->writeln("{$config['cflags']} {$config['ldflags']} {$config['libs']}");
}
$this->output->writeln(match (true) {
$this->getOption('includes') => $config['cflags'],
$this->getOption('libs-only-deps') => $config['libs'],
$this->getOption('libs') => "{$config['ldflags']} {$config['libs']}",
default => "{$config['cflags']} {$config['ldflags']} {$config['libs']}",
});
return 0;
}

View File

@@ -42,6 +42,19 @@ class PackLibCommand extends BuildCommand
$builder->proveLibs($libraries);
$builder->validateLibsAndExts();
// before pack, check if the dependency tree contains lib-suggests
foreach ($libraries as $lib) {
if (Config::getLib($lib, 'lib-suggests', []) !== []) {
logger()->critical("The library {$lib} has lib-suggests, packing [{$lib_name}] is not safe, abort !");
return static::FAILURE;
}
}
$origin_files = [];
// get pack placehoder defines
$placehoder = get_pack_replace();
foreach ($builder->getLibs() as $lib) {
if ($lib->getName() !== $lib_name) {
// other dependencies: install or build, both ok
@@ -64,6 +77,27 @@ class PackLibCommand extends BuildCommand
// After build: load buildroot/ directory, and calculate increase files
$after_buildroot = FileSystem::scanDirFiles(BUILD_ROOT_PATH, relative: true);
$increase_files = array_diff($after_buildroot, $before_buildroot);
// patch pkg-config and la files with absolute path
foreach ($increase_files as $file) {
if (str_ends_with($file, '.pc') || str_ends_with($file, '.la')) {
$content = FileSystem::readFile(BUILD_ROOT_PATH . '/' . $file);
$origin_files[$file] = $content;
// replace relative paths with absolute paths
$content = str_replace(
array_keys($placehoder),
array_values($placehoder),
$content
);
FileSystem::writeFile(BUILD_ROOT_PATH . '/' . $file, $content);
}
}
// add .spc-extract-placeholder.json in BUILD_ROOT_PATH
$placeholder_file = BUILD_ROOT_PATH . '/.spc-extract-placeholder.json';
file_put_contents($placeholder_file, json_encode(array_keys($origin_files), JSON_PRETTY_PRINT));
$increase_files[] = '.spc-extract-placeholder.json';
// every file mapped with BUILD_ROOT_PATH
// get BUILD_ROOT_PATH last dir part
$buildroot_part = basename(BUILD_ROOT_PATH);
@@ -85,6 +119,16 @@ class PackLibCommand extends BuildCommand
$filename = WORKING_DIR . '/dist/' . $filename;
f_passthru("tar {$tar_option} {$filename} -T " . WORKING_DIR . '/packlib_files.txt');
logger()->info('Pack library ' . $lib->getName() . ' to ' . $filename . ' complete.');
// remove temp files
unlink($placeholder_file);
}
}
foreach ($origin_files as $file => $content) {
// restore original files
if (file_exists(BUILD_ROOT_PATH . '/' . $file)) {
FileSystem::writeFile(BUILD_ROOT_PATH . '/' . $file, $content);
}
}