PKGBUILDs/devel/generator/generate.pl

269 lines
12 KiB
Perl
Raw Permalink Normal View History

#!/usr/bin/perl
use FindBin;
use Mojolicious;
use Mojo::File 'path';
use Mojo::Log;
use Mojo::Util;
use warnings;
use strict;
use utf8;
my @vcs_0_variant_suffixes = (qw(git svn hg));
my @cfg_0_variant_suffixes = (qw(static static-compat));
my @cfg_1_variant_suffixes = (qw(doc test cli angle dynamic opengl noopengl));
my @variant_suffixes = (\@vcs_0_variant_suffixes, \@cfg_0_variant_suffixes, \@cfg_1_variant_suffixes);
sub is_outdated {
my ($source_path, $target_path) = @_;
my $source_last_modified = (stat($source_path))[9];
my $target_last_modified = (stat($target_path))[9];
return !defined $target_last_modified || $source_last_modified > $target_last_modified;
}
my $log = Mojo::Log->new;
my $mojolicious = Mojolicious->new;
my $renderer = $mojolicious->renderer;
my $pkgbuilds_dir = path($FindBin::Bin, '..', '..')->realpath;
my @template_paths = ("$FindBin::Bin/templates", $pkgbuilds_dir);
$log->level($ENV{LOG_LEVEL} // 'info');
$mojolicious->log($log);
$renderer->paths(\@template_paths);
$log->debug("Template paths:\n" . join("\n", @template_paths));
2020-10-27 12:33:18 +01:00
my $filter_regex = $ARGV[0];
my $install_directory = $ARGV[1] // $pkgbuilds_dir;
unless (-d $install_directory) {
$log->error("Output directory '$install_directory' does not exist.");
exit(-1);
}
2020-10-08 17:50:23 +02:00
# add helper to render Qt dependencies
sub _render_deps {
my ($package_prefix, $controller, @d) = @_;
my $prefix = $controller->stash('package_name_prefix');
my $suffix = $controller->stash('package_name_suffix');
2024-06-09 21:26:35 +02:00
my $quote = $prefix =~ qr/^(mingw-w64|android|wasm)/ ? "'" : '';
return join(' ', map { "${quote}${prefix}${package_prefix}-${_}${suffix}${quote}" } @d);
2020-10-08 17:50:23 +02:00
}
sub _render_optdeps {
my ($package_prefix, $controller, %d) = @_;
my $prefix = $controller->stash('package_name_prefix');
my $suffix = $controller->stash('package_name_suffix');
return join(' ', map { "'${prefix}${package_prefix}-${_}${suffix}: $d{$_}'" } sort keys %d);
}
for my $qt_version (qw(qt5 qt6)) {
$mojolicious->helper("${qt_version}deps" => sub { _render_deps($qt_version, @_) });
$mojolicious->helper("${qt_version}optdeps" => sub { _render_optdeps($qt_version, @_) });
}
# add helper to expand pkg-config style libraries into full paths for use with CMake
# example: "-lfoo -lbar" => "/usr/lib/foo.a;/usr/lib/bar.a"
$mojolicious->helper(expand_libs => sub {
my $controller = shift;
my $prefix = $controller->stash('install_prefix');
my $extension = $controller->stash('library_extension');
return join(';', map {
my $library_name = $_;
$library_name = $1 if $library_name =~ qr/\w*-l(.*)\w*/;
"$prefix/lib/lib$library_name.$extension";
} @_);
});
2021-04-13 12:24:25 +02:00
# define revisions of Qt modules from KDE fork
my %kde_fork_revisions = (
2022-05-16 20:00:12 +02:00
# module => [rev, 'commit on KDE fork', 'version bump to be reverted'],
2024-05-28 21:14:37 +02:00
activeqt => [0, '91bfd21f86c450b129ac2dde9d33b32e140d8a0c'],
winextras => [0, '907009a4f7e5d2b99805547caf4b901bdbb0d4d6'],
'3d' => [0, '9bf4d03e2515f7c454647d54542330b6e90f8191'],
base => [140, '1c13ef067ea3c97342f98039931ea18b3992014f'],
charts => [0, '7315c48bcec88014e78165bbda54abfcd557e0af'],
connectivity => [3, '99f30db37c63447c59d5fac15bc8feb832a7fd04'],
datavis3d => [0, '79cd0fb6cafcd42e4037ae1363fda3bc2cec934a'],
declarative => [28, '50c8def854806485d66aabcf6918e8b987032e55'],
gamepad => [0, 'b1c2f272f69e222a532485e6f820776c220b3535'],
graphicaleffects => [0, '2c39e673d6c15a84dcc7882d3772fa04cc79f9ed'],
imageformats => [7, '4e4f5fc6bdac96f5281a3ebeb0fee78df7b1a498'],
location => [7, '3beb9c810611337fde61d89aa981e9f177a9ede9'],
lottie => [0, 'b8c1fa109dce6f8bff9f55738d2f1e21ff677796'],
multimedia => [2, '53069c9c6eb52b744333812f42aed36c3db6e752'],
networkauth => [1, '28180f28c98e329676463e24cef0097cba45bc00'],
purchasing => [0, 'd4903bf08c576a6c085278c1960a2676cd83dca7'],
quick3d => [1, 'ad229f0c135f74801fba2bcd22c78abc0e3cf1d2'],
quickcontrols => [0, '9325659ec390eda5b160736a926ba58ccb445cce'],
quickcontrols2 => [5, '69fea340f8f4c483a9b2889e4e24a4b1b52ebc87'],
quicktimeline => [0, 'bf6c73064c82b07fcb1f7e72c263b249e137e224'],
remoteobjects => [0, '3873bdc809ca8d58d91968cb0de34da26646bc79'],
scxml => [0, '6834b183966d08d9f061642ee7ea2d482cbbf073'],
sensors => [0, 'bf0b718cd0b6c7823e9d2037d3bdece44185f444'],
serialbus => [0, '616bc5b962cdcacb1c1ba985d7236392e9cadb8c'],
serialport => [0, '34c19c6441cd440dc65b59ae7670eadf099d51f8'],
speech => [1, '8ad0f08ad7e2a8d27dc5e69806812c6a3f298946'],
svg => [5, '690128b2b8fb6d6fbdc43b2b2633f0f1de3f0638'],
tools => [4, 'f82ed367d1b80b69d738cfcde534b75854a45476'],
translations => [0, 'c601106c8b5d5495f951c8ea0ad6a9e171416ae0'],
virtualkeyboard => [0, '7389450a5de5fdd210f1459abcf73621ec0496bd'],
wayland => [57, '75f434f14499eb47ede2cb66f0946527bf555791'],
webchannel => [3, 'fca83088ef430f96257d2014e77d08bd350259af'],
webglplugin => [0, '3681356904277e055759693551357e7e488d1be9'],
websockets => [2, 'dbbdc64b804f7c4d0ed92198aaab49b07fa15e7f'],
webview => [0, 'bbb1891595aba23ff3c6d137aa74442f9e54479b'],
x11extras => [0, '6c3605fcb3b34e55951f597e06c135d97dfa6cd7'],
xmlpatterns => [0, '087f6f35bd027f940818b1696d0aad822e034377'],
2021-04-13 12:24:25 +02:00
);
2022-01-02 13:29:53 +01:00
# $rev := git rev-list --count v5.15.2..$commit_on_kde_fork
2021-04-13 12:24:25 +02:00
# find templates; populate "pages" array
my @pages;
my $template_file_name = 'PKGBUILD.sh.ep';
my $top_level_dirs = $pkgbuilds_dir->list({dir => 1});
for my $top_level_dir (@$top_level_dirs) {
next unless -d $top_level_dir;
next unless $top_level_dir ne 'devel';
my $default_package_name = $top_level_dir->basename;
2020-10-06 17:49:34 +02:00
my ($qt_module, $qt_major_version);
if ($default_package_name =~ qr/qt(5|6)-(.*)/) {
$qt_major_version = $1;
$qt_module = $2;
}
2021-04-13 12:24:25 +02:00
my $kde_fork_revision;
if ($qt_major_version && $qt_major_version eq '5' && $qt_module) {
$kde_fork_revision = $kde_fork_revisions{$qt_module};
}
my $variant_dirs = $top_level_dir->list({dir => 1});
for my $variant_dir (@$variant_dirs) {
next unless -d $variant_dir;
my $variant = $variant_dir->basename;
my $template_file = $variant_dir->child($template_file_name);
if (!-f $template_file) {
# print warning; all additional Qt repos for mingw-w64 should be converted to use templates now
$log->warn("No template $template_file_name present for Qt module $qt_module and variant $variant")
if defined $qt_module && index($variant, 'mingw-w64') == 0 && $variant !~ qr/.*-test$/;
next;
}
# determine files
my $files = $variant_dir->list;
my $patch_files = $files->grep(qr/.*\.patch/);
2020-10-06 17:49:34 +02:00
my $qt_module_sha256_file_name = "qt$qt_module-sha256.txt";
my $qt_module_sha256_file = defined $qt_module
2020-10-06 17:49:34 +02:00
? $variant_dir->child($qt_module_sha256_file_name)
: undef;
my $qt_module_sha256 = defined $qt_module_sha256_file && -f $qt_module_sha256_file
? Mojo::Util::trim($qt_module_sha256_file->slurp)
2020-10-06 17:49:34 +02:00
: "$qt_module_sha256_file_name missing";
# determine variant parts
my $variant_prefix_part = $variant;
my $variant_suffix_part = '';
if ($variant) {
for my $variant_suffixes (@variant_suffixes) {
for my $variant_suffix (@$variant_suffixes) {
next unless $variant =~ qr/.*-$variant_suffix$/;
$variant_prefix_part = substr($variant, 0, length($variant) - length($variant_suffix) - 1);
$variant_suffix_part = $variant_suffix_part ? "$variant_suffix-$variant_suffix_part" : $variant_suffix;
last;
}
}
}
my $package_name_prefix = $variant_prefix_part ? "$variant_prefix_part-" : "";
my $package_name_suffix = $variant_suffix_part ? "-$variant_suffix_part" : "";
my $is_static_variant = $variant_suffix_part =~ qr/static/;
my $has_static_variant = $is_static_variant || -d "$default_package_name/$variant-static";
my $is_mingw = $package_name_prefix eq 'mingw-w64-';
2020-10-27 12:33:18 +01:00
my $package_name = "$package_name_prefix$default_package_name$package_name_suffix";
next if defined $filter_regex && $package_name !~ $filter_regex;
push(@pages, {
install_path => "$default_package_name/$variant/PKGBUILD",
template_params => [
template => "$default_package_name/$variant/PKGBUILD",
stash_variables => {
variant => $variant,
variant_prefix_part => $variant_prefix_part,
variant_suffix_part => $variant_suffix_part,
default_package_name => $default_package_name,
package_name_prefix => $package_name_prefix,
package_name_suffix => $package_name_suffix,
2020-10-27 12:33:18 +01:00
package_name => $package_name,
files => $files,
patch_files => $patch_files,
2020-10-06 17:49:34 +02:00
qt_major_version => $qt_major_version,
qt_module => $qt_module,
qt_module_sha256 => $qt_module_sha256,
2021-04-13 12:24:25 +02:00
kde_fork_revision => $kde_fork_revision,
static_variant => $is_static_variant,
static_suffix => $is_static_variant ? '-static' : '',
static_deps => undef,
static_makedeps => undef,
is_mingw => $is_mingw,
library_extension => $is_static_variant ? 'a' : ($is_mingw ? 'dll.a' : 'so'),
install_prefix => $is_mingw ? '/usr/$_arch' : '/usr',
shared_config => !$is_static_variant,
static_config => $is_static_variant || !$has_static_variant,
2020-01-28 21:12:38 +01:00
no_libraries => 0,
},
]
});
}
}
# render "pages"
for my $page (@pages) {
# process template params
my $template_params = $page->{template_params};
my $template_source_path;
my $template_target_path;
my $template_stash_variables;
if (defined $template_params) {
my ($template_name, $template_args) = (@$template_params % 2 ? shift @$template_params : undef, {@$template_params});
my $template_format = ($template_args->{format} //= 'sh');
my $template_handler = $template_args->{handler} // 'ep';
$template_name //= $template_args->{template};
$template_stash_variables = delete $template_args->{stash_variables};
$template_source_path = "$template_name.$template_format.$template_handler";
$template_target_path = "$template_name.$template_format";
$template_params = $template_args;
$template_params->{template} = $template_name;
}
# determine source path and target path
my $source_path = $page->{source_path} // $template_source_path;
if (!$template_params && !$source_path) {
die 'page needs either template_params or source_path';
}
my $output_file = path($install_directory, $page->{install_path} // $template_target_path // $source_path);
# ensure output directory exists
$output_file->dirname->make_path unless -f $output_file;
# skip unless the target is outdated
# note: Can not skip templates that easy because that would require tracking includes.
if (!defined $template_params && !is_outdated($source_path, $output_file)) {
$log->info("Skipping '$source_path' -> '$output_file' (target up-to-date)");
next;
}
# do a simple copy
if (!defined $template_params) {
$log->info("Copying '$source_path' -> '$output_file'");
Mojo::File->new($source_path)->copy_to($output_file);
next;
}
# render template
$log->info("Rendering '$source_path' -> '$output_file'");
my $controller = $mojolicious->build_controller;
$controller->stash($template_stash_variables) if defined $template_stash_variables;
my $output = $controller->render_to_string(%$template_params);
$log->debug($output);
$output_file->spew($output, 'UTF-8');
}