#!/bin/env perl
#
# Generate .REQUIRES file for package.
#
# usage:
# $0 [options] dir dir outfile
#
# where: 'dir' - is directory where made required package
# 'outfile' - output file with following format:
#
# _kxLibc=1.0.7
# pkgtool=0.0.1
#
# empty version is allowed:
#
# pkg=
#
my ($toolchain, $hardware, $flavour);
sub read_requires
{
my %requires;
my ( $name, $version, $group );
my ( $file_name, $makefile );
my $ptype = shift;
if( $ptype eq "bin" )
{
$name = "BIN_PKG_NAME";
$version = "BIN_PKG_VERSION";
$group = "BIN_PKG_GROUP";
}
elsif( $ptype eq "dev" )
{
$name = "DEV_PKG_NAME";
$version = "DEV_PKG_VERSION";
$group = "DEV_PKG_GROUP";
}
else
{
$name = "PKG_NAME";
$version = "PKG_VERSION";
$group = "PKG_GROUP";
}
foreach my $req ( reverse @_ )
{
my $d = `echo $req | cut -f 1 -d '^'`;
$d =~ s/^\s+|\s+$//;
$file_name = "${top_build_dir}/$d/Makefile";
$makefile = `cat $file_name`;
if( $makefile =~ m/^ *([_A-Za-z]*[_A-Za-z0-9]*)$name(.+= +)(.+)/gm )
{
my ( @p, @n, @v );
my ( $n, $v, $g );
my $prefix = $1;
my $cdir = "${top_build_dir}/$d";
my $shell_output = <<`SHELL`;
cd $cdir
make TOOLCHAIN=$toolchain HARDWARE=$hardware FLAVOUR=$flavour -f $file_name print-$prefix$name 2>/dev/null
exit 0
SHELL
while( $shell_output =~ m/^ *$prefix$name(.+= +)(.+)/gm ) { $n = $2; }
$shell_output = <<`SHELL`;
cd $cdir
make TOOLCHAIN=$toolchain HARDWARE=$hardware FLAVOUR=$flavour -f $file_name print-$prefix$version 2>/dev/null
exit 0
SHELL
while( $shell_output =~ m/^ *$prefix$version(.+= +)(.+)/gm ) { $v = $2; }
$shell_output = <<`SHELL`;
cd $cdir
make TOOLCHAIN=$toolchain HARDWARE=$hardware FLAVOUR=$flavour -f $file_name print-$prefix$group 2>/dev/null
exit 0
SHELL
while( $shell_output =~ m/^ *$prefix$group(.+= +)(.+)/gm ) { $g = $2; }
$requires{"$d"} = \@p;
if( $g ) { @n = split / +/, $g . '/' . $n; }
else { @n = split / +/, $n; }
push( @{ $requires{"$d"} }, @n );
@v = split / +/, $v;
if( $requires{"$d"} )
{
push( @{ $requires{"$d"} }, @v );
}
}
else
{
#
# The ..._PKG_NAME is not found in a Makefile then
# assume that this Makefile is a collection (depth=1):
# ---------------------------------------------------
# NOTE:
# ----
# We do not allow flavours in the package .REQUIRES file.
#
my $cdir = "${top_build_dir}/$d";
#
# We read the head of Makefile until '__END_OF_REQUIRES__' keyword.
# The 'build-system/constants.mk' should be included before requires.
#
my $requires_output = <<`SHELL`;
cd $cdir
head -n `cat Makefile | grep -n "__END_OF_REQUIRES__" | cut -f 1 -d ':'` Makefile | \
make TOOLCHAIN=$toolchain HARDWARE=$hardware FLAVOUR=$flavour -f - -p __build_requires__ 2>/dev/null | grep "REQUIRES"
exit 0
SHELL
while( $requires_output =~ m/^REQUIRES(.+= +)(.+)/gm )
{
my @r = split( " ", $2 );
foreach my $req ( reverse @r )
{
$d = `echo $req | cut -f 1 -d '^'`;
$d =~ s/^\s+|\s+$//;
$file_name = "${top_build_dir}/$d/Makefile";
$makefile = `cat $file_name`;
if( $makefile =~ m/^ *([_A-Za-z]*[_A-Za-z0-9]*)$name(.+= +)(.+)/gm )
{
my ( @p, @n, @v );
my ( $n, $v, $g );
my $prefix = $1;
my $cdir = "${top_build_dir}/$d";
my $shell_output = <<`SHELL`;
cd $cdir
make TOOLCHAIN=$toolchain HARDWARE=$hardware FLAVOUR=$flavour -f $file_name print-$prefix$name 2>/dev/null
exit 0
SHELL
while( $shell_output =~ m/^ *$prefix$name(.+= +)(.+)/gm ) { $n = $2; }
$shell_output = <<`SHELL`;
cd $cdir
make TOOLCHAIN=$toolchain HARDWARE=$hardware FLAVOUR=$flavour -f $file_name print-$prefix$version 2>/dev/null
exit 0
SHELL
while( $shell_output =~ m/^ *$prefix$version(.+= +)(.+)/gm ) { $v = $2; }
$shell_output = <<`SHELL`;
cd $cdir
make TOOLCHAIN=$toolchain HARDWARE=$hardware FLAVOUR=$flavour -f $file_name print-$prefix$group 2>/dev/null
exit 0
SHELL
while( $shell_output =~ m/^ *$prefix$group(.+= +)(.+)/gm ) { $g = $2; }
$requires{"$d"} = \@p;
if( $g ) { @n = split / +/, $g . '/' . $n; }
else { @n = split / +/, $n; }
push( @{ $requires{"$d"} }, @n );
@v = split / +/, $v;
if( $requires{"$d"} )
{
push( @{ $requires{"$d"} }, @v );
}
}
} # end of foreach ( req )
} # End of while ( shell_output )
}
}
return %requires;
}
sub usage
{
print <<EOF;
Usage: build_pkg_requires [options] dir ... dir output_file_name
Options:
--toolchain={TOOLCHAIN} - actual Toolchain name;
--hardware={HARDVARE} - actual Hardware name;
--flavour={FLAVOUR} - actual Flavour name;
--pkg-type={all|bin|dev} - find required packages of defined type only;
--all - find required packages of all types;
--bin - find binary packages only;
--dev - find development packages only.
EOF
exit;
}
my $pkg_type;
my @dirs;
foreach ( @ARGV )
{
if( /--toolchain=(\S*)/ )
{
$toolchain = $1;
}
elsif( /--hardware=(\S*)/ )
{
$hardware = $1;
}
elsif( /--flavour=(\S*)/ )
{
$flavour = $1;
}
elsif( /--pkg-type=(\S*)/ )
{
$pkg_type = $1;
}
elsif( /--all/ )
{
$pkg_type = "all";
}
elsif( /--bin/ )
{
$pkg_type = "bin";
}
elsif( /--dev/ )
{
$pkg_type = "dev";
}
elsif( /--help/ )
{
usage;
}
else
{
push @dirs, $_;
}
}
$reqfile = pop @dirs;
if( $pkg_type eq "" ) { $pkg_type = "all"; }
# Set up $top_build_dir
$pwd = `pwd`;
chomp $pwd;
if( $ENV{TOP_BUILD_DIR_ABS} eq "" )
{
$p = $pwd;
while( ! -f "$p/build-system/core.mk" )
{
$p =~ m!(.*)/(.*)!;
$p = $1;
}
$top_build_dir = $p;
}
else
{
$top_build_dir = $ENV{TOP_BUILD_DIR_ABS};
}
# Open the output file
open( REQUIRES_FILE, "> $reqfile" );
# Read package names and versions from required Makefiles
%requires = read_requires( $pkg_type, @dirs );
while( ($pkg, $nv) = each %requires )
{
print REQUIRES_FILE "${$nv}[0]=${$nv}[1]\n";
}
# Close output file
close REQUIRES_FILE;