2009-05-20 10:59:36 +02:00
|
|
|
#!/usr/bin/perl
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
use File::Copy;
|
2009-05-22 16:27:46 +02:00
|
|
|
use Getopt::Long;
|
2009-05-20 10:59:36 +02:00
|
|
|
|
|
|
|
my $dir = ".";
|
2009-05-22 16:27:46 +02:00
|
|
|
my $rpmrelease;
|
|
|
|
my $patches="";
|
|
|
|
|
|
|
|
GetOptions(
|
|
|
|
"patches=s" => \$patches,
|
|
|
|
"release=s" => \$rpmrelease
|
|
|
|
) or die "Usage: $0 [--release <release>] [--patches <dir>]\n";
|
2009-05-20 10:59:36 +02:00
|
|
|
|
|
|
|
# flavor -> [supported archs]
|
|
|
|
my %flavor_archs = parse_config_conf();
|
|
|
|
|
|
|
|
# template name -> template body
|
|
|
|
my %templates = read_spec_templates();
|
|
|
|
|
|
|
|
# config.sh variables
|
|
|
|
my %vars = parse_config_sh();
|
|
|
|
my ($srcversion, $variant) = ($vars{'SRCVERSION'}, $vars{'VARIANT'});
|
|
|
|
|
|
|
|
# rpm changelog
|
|
|
|
my $changelog = convert_changes();
|
|
|
|
|
|
|
|
# package name -> [summary, description]
|
|
|
|
my %binary_descriptions = parse_descriptions();
|
|
|
|
|
2009-05-22 16:27:46 +02:00
|
|
|
$patches="--patches $patches" if $patches;
|
|
|
|
my $patchversion = `$dir/compute-PATCHVERSION.sh $patches`;
|
2009-05-20 10:59:36 +02:00
|
|
|
chomp $patchversion;
|
2009-05-22 16:27:46 +02:00
|
|
|
my $rpmversion;
|
2009-05-20 10:59:36 +02:00
|
|
|
if (defined($rpmrelease)) {
|
2009-05-22 16:27:46 +02:00
|
|
|
($rpmversion = $patchversion) =~ s/-.*//;
|
2009-05-20 10:59:36 +02:00
|
|
|
} else {
|
2009-05-22 16:27:46 +02:00
|
|
|
($rpmversion, $rpmrelease) = (split(/-/, $patchversion, 2), "");
|
2009-05-20 10:59:36 +02:00
|
|
|
}
|
2009-05-22 16:27:46 +02:00
|
|
|
$rpmrelease =~ s/[^.]$/$&./;
|
|
|
|
$rpmrelease =~ s/-/./g;
|
2009-05-20 10:59:36 +02:00
|
|
|
|
|
|
|
my %macros = (
|
|
|
|
VARIANT => $variant,
|
|
|
|
SRCVERSION => $srcversion,
|
|
|
|
PATCHVERSION => $patchversion,
|
|
|
|
RPMVERSION => $rpmversion,
|
|
|
|
RELEASE_PREFIX => $rpmrelease,
|
|
|
|
);
|
|
|
|
|
|
|
|
# binary spec files
|
|
|
|
for my $flavor (sort keys(%flavor_archs)) {
|
|
|
|
$flavor_archs{$flavor} = [sort @{$flavor_archs{$flavor}}];
|
|
|
|
my ($summary, $description);
|
|
|
|
if (!exists($binary_descriptions{"kernel-$flavor"})) {
|
|
|
|
print STDERR "warning: no description for kernel-$flavor found\n";
|
|
|
|
$summary = "The Linux Kernel";
|
|
|
|
$description = "The Linux Kernel.";
|
|
|
|
} else {
|
|
|
|
$summary = $binary_descriptions{"kernel-$flavor"}->[0];
|
|
|
|
$description = $binary_descriptions{"kernel-$flavor"}->[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
do_spec('binary', "kernel-$flavor.spec", %macros,
|
|
|
|
FLAVOR => $flavor,
|
|
|
|
SUMMARY => $summary,
|
|
|
|
DESCRIPTION => $description,
|
|
|
|
ARCHS => join(" ", arch2rpm(@{$flavor_archs{$flavor}})),
|
|
|
|
PROVIDES_OBSOLETES => provides_obsoletes($flavor, @{$flavor_archs{$flavor}}),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
# kernel-source.spec
|
|
|
|
do_spec('source', "kernel-source$variant.spec", %macros);
|
|
|
|
|
|
|
|
# kernel-syms.spec
|
|
|
|
{
|
|
|
|
my $requires = "";
|
|
|
|
for my $flavor (sort keys(%flavor_archs)) {
|
|
|
|
next if $flavor eq "vanilla";
|
|
|
|
my @archs = arch2rpm(@{$flavor_archs{$flavor}});
|
|
|
|
$requires .= "%ifarch @archs\n";
|
|
|
|
$requires .= "Requires: kernel-$flavor-devel = \%version-\%source_rel\n";
|
|
|
|
$requires .= "%endif\n";
|
|
|
|
}
|
|
|
|
chomp $requires;
|
|
|
|
do_spec('syms', "kernel-syms$variant.spec", %macros,
|
|
|
|
REQUIRES => $requires);
|
|
|
|
}
|
|
|
|
|
|
|
|
exit 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub parse_config_conf {
|
|
|
|
my %res;
|
|
|
|
|
|
|
|
for my $arch (split(/\s+/, `$dir/arch-symbols --list`)) {
|
|
|
|
my @flavors = `$dir/guards $arch < $dir/config.conf`;
|
|
|
|
next if @flavors == 0;
|
|
|
|
chomp @flavors;
|
|
|
|
@flavors = map { s/.*\///; $_ } @flavors;
|
|
|
|
for my $flavor (@flavors) {
|
|
|
|
$res{$flavor} ||= [];
|
|
|
|
push(@{$res{$flavor}}, $arch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return %res;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_spec_templates {
|
|
|
|
my %res;
|
|
|
|
|
|
|
|
for my $template qw(binary source syms) {
|
|
|
|
xopen(my $fh, '<', "$dir/kernel-$template.spec.in");
|
|
|
|
my @lines = <$fh>;
|
|
|
|
$res{$template} = join("", @lines);
|
|
|
|
close($fh);
|
|
|
|
}
|
|
|
|
return %res;
|
|
|
|
}
|
|
|
|
|
|
|
|
# return a hash of config.sh variables
|
|
|
|
sub parse_config_sh {
|
|
|
|
my %res;
|
|
|
|
|
|
|
|
xopen(my $fh, '<', "$dir/config.sh");
|
|
|
|
while (<$fh>) {
|
|
|
|
chomp;
|
|
|
|
if (/^\s*([A-Z_]+)=(.*)/) {
|
|
|
|
$res{$1} = $2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close($fh);
|
|
|
|
return %res;
|
|
|
|
}
|
|
|
|
|
|
|
|
# convert kernel-source.changes to rpm changelog
|
|
|
|
sub convert_changes {
|
|
|
|
my $res = "\%changelog\n";
|
|
|
|
my @progs = qw(/usr/lib/build/changelog2spec
|
|
|
|
/work/src/bin/tools/convert_changes_to_rpm_changelog);
|
|
|
|
|
|
|
|
my $changesfile = "$dir/kernel-source$variant.changes";
|
|
|
|
if (-e $changesfile) {
|
|
|
|
for my $prog (@progs) {
|
|
|
|
if (-x $prog) {
|
|
|
|
$res .= `$prog $changesfile`;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
chomp $res;
|
|
|
|
return $res;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub parse_descriptions {
|
|
|
|
my %res;
|
|
|
|
my $current;
|
|
|
|
my $blank = "";
|
|
|
|
# 0 - expect summary, 1 - eating blank lines, 2 - reading description
|
|
|
|
my $state = 0;
|
|
|
|
|
|
|
|
xopen(my $fh, '<', "$dir/package-descriptions");
|
|
|
|
while (<$fh>) {
|
|
|
|
next if /^\s*#/;
|
|
|
|
|
|
|
|
if (/^==+\s+([^\s]+)\s+==+\s*$/) {
|
|
|
|
my $package = $1;
|
|
|
|
if ($current) {
|
|
|
|
chomp $current->[1];
|
|
|
|
}
|
|
|
|
$current = ["", ""];
|
|
|
|
$res{$package} = $current;
|
|
|
|
$state = 0;
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
if (/^$/) {
|
|
|
|
if ($state == 2) {
|
|
|
|
$blank .= $_;
|
|
|
|
}
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
# non-blank line and not === package ===
|
|
|
|
if ($state == 0) {
|
|
|
|
chomp;
|
|
|
|
$current->[0] = $_;
|
|
|
|
$state = 1;
|
|
|
|
} elsif ($state == 1) {
|
|
|
|
$current->[1] = $_;
|
|
|
|
$blank = "";
|
|
|
|
$state = 2;
|
|
|
|
} else {
|
|
|
|
$current->[1] .= $blank;
|
|
|
|
$blank = "";
|
|
|
|
$current->[1] .= $_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($current) {
|
|
|
|
chomp $current->[1];
|
|
|
|
}
|
|
|
|
close($fh);
|
|
|
|
return %res;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub arch2rpm {
|
|
|
|
if (wantarray) {
|
|
|
|
return map { _arch2rpm($_) } @_;
|
|
|
|
}
|
|
|
|
return _arch2rpm($_[0]);
|
|
|
|
}
|
|
|
|
sub _arch2rpm {
|
|
|
|
my $arch = shift;
|
|
|
|
return "\%ix86" if $arch eq "i386";
|
|
|
|
return $arch;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub append_changelog {
|
|
|
|
my $changelog = $_[1];
|
|
|
|
if ($_[0] =~ s/\%changelog$/$changelog/) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
$_[0] .= $changelog;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub provides_obsoletes {
|
|
|
|
my $flavor = shift;
|
|
|
|
my @archs = @_;
|
|
|
|
my $res = "";
|
|
|
|
|
|
|
|
for my $arch (@archs) {
|
|
|
|
my @packs = `$dir/guards $arch $flavor <$dir/old-packages.conf`;
|
|
|
|
chomp @packs;
|
|
|
|
next if (!@packs);
|
|
|
|
my $rpmarch = arch2rpm($arch);
|
|
|
|
chomp $rpmarch;
|
|
|
|
$res .= "\%ifarch $rpmarch\n";
|
|
|
|
$res .= "Provides: @packs\n";
|
|
|
|
$res .= "Obsoletes: @packs\n";
|
|
|
|
$res .= "\%endif\n";
|
|
|
|
}
|
|
|
|
chomp $res;
|
|
|
|
return $res;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub do_spec {
|
|
|
|
my $template = shift;
|
|
|
|
my $specfile = shift;
|
|
|
|
my %macros = @_;
|
|
|
|
|
|
|
|
my $text = $templates{$template};
|
|
|
|
for my $m (keys %macros) {
|
|
|
|
$text =~ s/\@$m\@/$macros{$m}/g;
|
|
|
|
}
|
|
|
|
append_changelog($text, $changelog);
|
|
|
|
print "$specfile\n";
|
|
|
|
xopen(my $fh, '>', "$dir/$specfile");
|
|
|
|
print $fh $text;
|
|
|
|
close($fh);
|
|
|
|
|
|
|
|
return if $specfile eq "kernel-source$variant.spec";
|
|
|
|
my $changesfile = $specfile;
|
|
|
|
$changesfile =~ s/\.spec$//;
|
|
|
|
$changesfile .= ".changes";
|
|
|
|
copy("$dir/kernel-source$variant.changes", $changesfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub xopen {
|
|
|
|
open($_[0], $_[1], $_[2]) or die "$_[2]: $!\n";
|
|
|
|
}
|
|
|
|
|