Radix cross Linux Build System

Cross-platform build system is designed to build distributions of different operating systems for a set of target devices

39 Commits   2 Branches   2 Tags
     5         kx #!/bin/env 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 .$(HARDWARE)_requires file for current directory
     5         kx #
     5         kx # usage:
     5         kx #   $0 [options] topdir toolchain hardware
     5         kx #
     5         kx # where:
     5         kx #      'topdir' - is a absolute path to the top directory of checked out branch
     5         kx #   'toolchain' - is a TOOLCHAIN name
     5         kx #    'hardware' - is a HARDWARE  name
     5         kx #     'flavour' - is a HARDWARE  variant
     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 ($toolchain, $hardware, $flavour, $target_build_dir);
     5         kx 
     5         kx 
     5         kx sub usage
     5         kx {
     5         kx   print <<EOF;
     5         kx 
     5         kx Usage: build_requires [options] topdir toolchain hardware [flavour]
     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        toolchain - is a TOOLCHAIN name;
     5         kx         hardware - is a HARDWARE name.
     5         kx          flavour - is a HARDWARE variant.
     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_requires
     5         kx {
     5         kx   my $makefile = shift;
     5         kx   my $flavour  = shift;
     5         kx 
     5         kx   # Add a dependency to the Makefile
     5         kx   requires_depend( $makefile );
     5         kx 
     5         kx   my $cdir = dirname( $makefile );
     5         kx 
     5         kx   my %requires;
     5         kx 
     5         kx   #
     5         kx   # We read the head of Makefile until '__END_OF_REQUIRES__' keyword.
     5         kx   # The 'build-system/constants.mk' should be included before requires.
     5         kx   #
     5         kx   my $shell_output = <<`SHELL`;
     5         kx cd $cdir
     5         kx head -n `cat Makefile | grep -n "__END_OF_REQUIRES__" | cut -f 1 -d ':'` Makefile | \
     5         kx   make TOOLCHAIN=$toolchain HARDWARE=$hardware FLAVOUR=$flavour -f - -p __build_requires__ 2>/dev/null | grep "REQUIRES"
     5         kx exit 0
     5         kx SHELL
     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, $f);
     5         kx 
     5         kx       $d = `echo $req | cut -f 1 -d '^'`;
     5         kx       $d =~ s/^\s+|\s+$//;
     5         kx       if( $req =~ m/\^/ )
     5         kx       {
     5         kx         $f = `echo $req | cut -f 2 -d '^'`;
     5         kx         $f =~ s/^\s+|\s+$//;
     5         kx       }
     5         kx       else
     5         kx       {
     5         kx         $f = "";
     5         kx       }
     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_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 REQUIRES statement points to a missing directory
     5         kx         _kxLab::error( "build_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           if( $f eq "" ) { $requires{$d} = "";            }
     5         kx           else           { $requires{$d . "^" . $f} = ""; }
     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, $f);
     5         kx 
     5         kx     $d = `echo $req | cut -f 1 -d '^'`;
     5         kx     $d =~ s/^\s+|\s+$//;
     5         kx     if( $req =~ m/\^/ )
     5         kx     {
     5         kx       $f = `echo $req | cut -f 2 -d '^'`;
     5         kx       $f =~ s/^\s+|\s+$//;
     5         kx     }
     5         kx     else
     5         kx     {
     5         kx       $f = "";
     5         kx     }
     5         kx 
     5         kx     # Read sub requires
     5         kx     my $makefile = "$top_dir/$d/Makefile";
     5         kx     my %sub_requires = read_requires( $makefile, $f );
     5         kx     if( scalar(%sub_requires) )
     5         kx     {
     5         kx       my @sorted_sub_requires = sort(keys %sub_requires);
     5         kx 
     5         kx       # Build dependencies for sub requires
     5         kx       if( $f eq "" ) { start_depend( $d );            }
     5         kx       else           { start_depend( $d . "^" . $f ); }
     5         kx       foreach my $sub_req ( @sorted_sub_requires )
     5         kx       {
     5         kx         depend( $sub_req );
     5         kx       }
     5         kx       end_depend();
     5         kx 
     5         kx       # Make sub 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 $toolchain = shift;
     5         kx $hardware  = shift;
     5         kx $flavour   = shift;
     5         kx 
     5         kx my $makefile = "Makefile";
     5         kx 
     5         kx if( ! defined $topdir    or $topdir eq "" )    { usage; }
     5         kx if( ! defined $toolchain or $toolchain eq "" ) { usage; }
     5         kx if( ! defined $hardware  or $hardware eq "" )  { usage; }
     5         kx if( ! defined $flavour   or $flavour eq "" )
     5         kx {
     5         kx   $flavour = "";
     5         kx   $target_build_dir = "." . $toolchain . "/" . $hardware;
     5         kx }
     5         kx else
     5         kx {
     5         kx   $target_build_dir = "." . $toolchain . "/" . $hardware . "/" . $flavour;
     5         kx }
     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 my $build_system = $top_dir . "/build-system";
     5         kx 
     5         kx _kxLab::system( "mkdir -p $target_build_dir" );
     5         kx 
     5         kx $requires_file = $target_build_dir . "/" . ".requires";
     5         kx my $requires_depend_file = $requires_file . "_depend";
     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 my %requires = read_requires( "$pwd/$makefile", $flavour );
     5         kx 
     5         kx #$requires{"build-system"} = "";
     5         kx # ignore the "build-system" dependency (if any), since this dependency is implicit
     5         kx delete $requires{"build-system"};
     5         kx 
     5         kx my @sorted_requires = sort(keys %requires);
     5         kx 
     5         kx # build the all: rule
     5         kx start_depend( "all" );
     5         kx foreach my $req ( @sorted_requires )
     5         kx {
     5         kx   depend( $req );
     5         kx }
     5         kx end_depend();
     5         kx 
     5         kx # build sub dependencies
     5         kx foreach my $req ( @sorted_requires )
     5         kx {
     5         kx   make_sub_requires( $req );
     5         kx }
     5         kx 
     5         kx # Finish by including tree.mk
     5         kx print REQUIRES_FILE "TREEDIRS = ", join(" ", sort(keys %all_requires)), "\n\n";
     5         kx if( $pwd =~ m/$build_system/ )
     5         kx {
     5         kx   print REQUIRES_FILE "include \$(BUILDSYSTEM)/tree-bs.mk\n";
     5         kx }
     5         kx else
     5         kx {
     5         kx   print REQUIRES_FILE "include \$(BUILDSYSTEM)/tree.mk\n";
     5         kx }
     5         kx 
     5         kx 
     5         kx # close output files
     5         kx close REQUIRES_FILE;
     5         kx close REQUIRES_DEPEND_FILE;