5 kx #!/usr/bin/perl
5 kx
5 kx use FindBin;
5 kx use lib $FindBin::Bin;
5 kx
5 kx use strict;
5 kx use warnings FATAL => 'all';
5 kx
5 kx use IO::Handle;
5 kx use File::Basename;
5 kx use File::Temp;
5 kx use Getopt::Long;
5 kx
5 kx use _kxLab;
5 kx
5 kx #
5 kx # Generate .src_requires file for current directory
5 kx #
5 kx # usage:
5 kx # $0 [options] topdir
5 kx #
5 kx # where:
5 kx # 'topdir' - is a absolute path to the top directory of checked out branch
5 kx #
5 kx
5 kx
5 kx # global variables
5 kx my (%all_requires, $top_dir, $opt_max_depth, %requires_depend, $requires_file, %skip_dirs);
5 kx
5 kx my %all_src_requires;
5 kx
5 kx sub usage
5 kx {
5 kx print <<EOF;
5 kx
5 kx Usage: build_src_requires [options] topdir
5 kx Options:
5 kx --max-depth=i - where 'i' is a maximal directory depth for finding requires;
5 kx --skip-dir - directory to be skipped (such as dist or TARGET_BUILD_DIR);
5 kx topdir - is a absolute path to the top of checked out branch.
5 kx
5 kx EOF
5 kx exit;
5 kx }
5 kx
5 kx
5 kx sub requires_depend
5 kx {
5 kx my $makefile = shift;
5 kx
5 kx if( ! exists $requires_depend{$makefile} )
5 kx {
5 kx print REQUIRES_DEPEND_FILE "$requires_file: $makefile\n\n";
5 kx print REQUIRES_DEPEND_FILE "$makefile:\n\n";
5 kx $requires_depend{$makefile} = "";
5 kx }
5 kx }
5 kx
5 kx sub read_src_requires
5 kx {
5 kx my $makefile = shift;
5 kx
5 kx # add a dependency to the Makefile
5 kx requires_depend($makefile);
5 kx
5 kx my %requires;
5 kx
5 kx my $shell_output = `cat $makefile`;
5 kx
5 kx while( $shell_output =~ m/^SOURCE_REQUIRES(.+= +)(.+)/gm )
5 kx {
5 kx my @n = split( " ", $2 );
5 kx foreach my $d ( @n )
5 kx {
5 kx if( $d eq "ALL_DIRS" )
5 kx {
5 kx my $dirname = dirname($makefile);
5 kx
5 kx opendir( DIR, "$dirname" ) or
5 kx _kxLab::error( "build_src_requires: Could not open directory: $dirname: $!" );
5 kx my @dirs = grep { ! /^\./ && -d "$_" && -f "$_/Makefile" } readdir( DIR );
5 kx closedir DIR;
5 kx
5 kx foreach my $dir (@dirs)
5 kx {
5 kx requires_depend("$dirname/$dir/Makefile");
5 kx "$dirname/$dir" =~ m!$top_dir/(.+)!;
5 kx $requires{$1} = "";
5 kx }
5 kx }
5 kx else
5 kx {
5 kx # Print a nice error message if the SOURCE_REQUIRES statement points to a missing directory
5 kx _kxLab::error( "build_src_requires: SOURCE_REQUIRES '$d' in $makefile not found. Exit" ) if( ! -d "$top_dir/$d" );
5 kx
5 kx if( -f "$top_dir/$d/Makefile" )
5 kx {
5 kx $requires{$d} = "";
5 kx requires_depend("$top_dir/$d/Makefile");
5 kx }
5 kx }
5 kx }
5 kx }
5 kx return %requires;
5 kx }
5 kx
5 kx sub read_requires
5 kx {
5 kx my $makefile = shift;
5 kx
5 kx # add a dependency to the Makefile
5 kx requires_depend($makefile);
5 kx
5 kx my %requires;
5 kx
5 kx my $shell_output = `cat $makefile`;
5 kx
5 kx while( $shell_output =~ m/^REQUIRES(.+= +)(.+)/gm )
5 kx {
5 kx my @n = split( " ", $2 );
5 kx foreach my $req ( @n )
5 kx {
5 kx my $d = `echo $req | cut -f 1 -d '^'`;
5 kx $d =~ s/^\s+|\s+$//;
5 kx
5 kx if( $d eq "ALL_DIRS" )
5 kx {
5 kx my $dirname = dirname($makefile);
5 kx
5 kx opendir( DIR, "$dirname" ) or
5 kx _kxLab::error( "build_src_requires: Could not open directory: $dirname: $!" );
5 kx my @dirs = grep { ! /^\./ && -d "$_" && -f "$_/Makefile" } readdir( DIR );
5 kx closedir DIR;
5 kx
5 kx foreach my $dir (@dirs)
5 kx {
5 kx requires_depend( "$dirname/$dir/Makefile" );
5 kx "$dirname/$dir" =~ m!$top_dir/(.+)!;
5 kx $requires{$1} = "";
5 kx
5 kx my %src_requires = read_src_requires( "$dirname/$dir/Makefile" );
5 kx my @sort_src_requires = sort(keys %src_requires);
5 kx foreach my $req ( @sort_src_requires )
5 kx {
5 kx $all_src_requires{$req} = "";
5 kx }
5 kx }
5 kx }
5 kx else
5 kx {
5 kx # Print a nice error message if the REQUIRES statement points to a missing directory
5 kx _kxLab::error( "build_src_requires: REQUIRES '$d' in $makefile not found. Exit" ) if( ! -d "$top_dir/$d" );
5 kx
5 kx if( -f "$top_dir/$d/Makefile" )
5 kx {
5 kx $requires{$d} = "";
5 kx
5 kx my %src_requires = read_src_requires( "$top_dir/$d/Makefile" );
5 kx my @sort_src_requires = sort(keys %src_requires);
5 kx foreach my $req ( @sort_src_requires )
5 kx {
5 kx $all_src_requires{$req} = "";
5 kx }
5 kx }
5 kx }
5 kx }
5 kx }
5 kx return %requires;
5 kx }
5 kx
5 kx sub start_depend
5 kx {
5 kx my $req = shift;
5 kx
5 kx print REQUIRES_FILE "$req:";
5 kx }
5 kx
5 kx sub depend
5 kx {
5 kx my $req = shift;
5 kx
5 kx print REQUIRES_FILE " $req";
5 kx }
5 kx
5 kx sub end_depend
5 kx {
5 kx print REQUIRES_FILE "\n\n";
5 kx }
5 kx
5 kx sub make_sub_requires
5 kx {
5 kx my $req = shift;
5 kx
5 kx if( ! exists $all_requires{$req} )
5 kx {
5 kx $all_requires{$req} = "";
5 kx
5 kx my $d = `echo $req | cut -f 1 -d '^'`;
5 kx $d =~ s/^\s+|\s+$//;
5 kx
5 kx # Read sub requires
5 kx my $makefile = "$top_dir/$d/Makefile";
5 kx my %sub_requires = read_requires( $makefile );
5 kx if( scalar(%sub_requires) )
5 kx {
5 kx # Make sub sub requires
5 kx my @sorted_sub_requires = sort(keys %sub_requires);
5 kx foreach my $sub_req ( @sorted_sub_requires )
5 kx {
5 kx make_sub_requires( $sub_req );
5 kx }
5 kx }
5 kx }
5 kx }
5 kx
5 kx
5 kx #
5 kx # Parse the command line options
5 kx #
5 kx $opt_max_depth = 10;
5 kx my @opt_skip_dirs;
5 kx GetOptions( "max-depth=i" => \$opt_max_depth, "skip-dir=s" => \@opt_skip_dirs );
5 kx %skip_dirs = map { $_ => "" } @opt_skip_dirs;
5 kx
5 kx # get the rest of the command line
5 kx my $topdir = shift;
5 kx my $makefile = "Makefile";
5 kx
5 kx if( ! defined $topdir or $topdir eq "" ) { usage; }
5 kx
5 kx _kxLab::error( "build_requires: $topdir is not a directory" ) if( ! -d $topdir );
5 kx _kxLab::error( "build_requires: Makefile missing: $makefile" ) if ( ! -f $makefile );
5 kx
5 kx # setup $top_build_dir
5 kx $top_dir = $topdir;
5 kx
5 kx $requires_file = ".src_requires";
5 kx my $requires_depend_file = $requires_file . "_depend";
5 kx
5 kx
5 kx # open the output files
5 kx open(REQUIRES_FILE, "> $requires_file") or
5 kx _kxLab::error( "build_requires: Could not open $requires_file file: $!" );
5 kx open(REQUIRES_DEPEND_FILE, "> $requires_depend_file") or
5 kx _kxLab::error( "build_requires: Could not open $requires_depend_file file: $!" );
5 kx
5 kx
5 kx # root component
5 kx my $pwd = `pwd`;
5 kx chomp $pwd;
5 kx $pwd =~ m!$top_dir(.*)!;
5 kx my $root;
5 kx if( $1 eq "" )
5 kx {
5 kx $root = "all";
5 kx }
5 kx else
5 kx {
5 kx $1 =~ m!/(.+)!;
5 kx $root = $1;
5 kx }
5 kx
5 kx print REQUIRES_FILE "# ROOT=$root\n\n";
5 kx print REQUIRES_DEPEND_FILE "\n";
5 kx
5 kx # read the makefile
5 kx %all_src_requires = read_src_requires( "$pwd/$makefile" );
5 kx my %requires = read_requires( "$pwd/$makefile" );
5 kx
5 kx
5 kx # check the "build-system" sub dependencies implicitly (excluding sources directories)
5 kx #$requires{"build-system"} = "";
5 kx
5 kx
5 kx # build sub dependencies
5 kx my @sorted_requires = sort(keys %requires);
5 kx foreach my $req ( @sorted_requires )
5 kx {
5 kx make_sub_requires( $req );
5 kx }
5 kx
5 kx # build the all: rule
5 kx start_depend( "all" );
5 kx my @sorted_src_requires = sort(keys %all_src_requires);
5 kx foreach my $req ( @sorted_src_requires )
5 kx {
5 kx depend( $req );
5 kx }
5 kx end_depend();
5 kx
5 kx
5 kx # Finish by including tree.mk
5 kx print REQUIRES_FILE "TREEDIRS = ", join(" ", sort(keys %all_src_requires)), "\n\n";
5 kx print REQUIRES_FILE "include \$(BUILDSYSTEM)/tree-src.mk\n";
5 kx
5 kx
5 kx # close output files
5 kx close REQUIRES_FILE;
5 kx close REQUIRES_DEPEND_FILE;