Blame | Last modification | View Log | RSS feed
######################################################################### Copyright (c) VIX TECHNOLOGY (AUST) LTD## Module name : JatsLocatePkgFile.pm# Module type : Makefile system# Compiler(s) : Perl# Environment(s): jats## Description : Package to simplify the process of locating one or more# files with the JATS build environment.## Specifically designed to assist in the creation of:# Day0 file systems# Debian Packages# Deployable packages## Intended to locate files in dependent packages# Supports LinkPkgArchive and BuildPkgArchive## Knows about the construction of programs and shared# libraries as well as other special file types.## Uses a set of options to identify the file# The file specifier is of the form# Name[,--Option]+## Available Options are:# --prog - Name is a program# Search where programs are stored# Append the target specific suffix# --bin - Similar to --prog, but does not modify# the provided name.# --deb - Name is the base of a Debian Package# Searchs in BIN directories# --lib - Name is the base of a Shared Library# Searchs in LIB directories# --dir=SubDir - Search for Name in a subdir of the# dependent packages# --pkg - Search for Name in a pkg subdir# Limited by the current target# --etc - Same as --dir=etc# --jar - Same as --dir=jar# --scripts - Same as --dir=scripts## --AllowMultiple - Allow multiple files## Usage:## $Locator = JatsLocatePkgFile::New( Platform, 'P' );# $result = $Locator->LocateFile ('busybox,--prog');###......................................................................#require 5.008_002;use strict;use warnings;package JatsLocatePkgFile;use JatsError;use JatsMakeConfig;# automatically export what we need into namespace of caller.use Exporter();our (@ISA, @EXPORT);@ISA = qw(Exporter);@EXPORT = qw(FileSet);## Hash of known file location specifications# Only allowed to have one in any one definition#my %LocSpec = ('prog' => { code => \&searchProg },'bin' => { code => \&searchBin },'deb' => { code => \&searchDeb },'dir' => { code => \&searchDir },'pkg' => { code => \&searchPkg },'lib' => { code => \&searchLib },'etc' => { code => \&searchSimple, dir => 'etc' },'jar' => { code => \&searchSimple, dir => 'jar'},'scripts' => { code => \&searchSimple, dir => 'scripts'},# 'thx' => 1,# 'jar' => 1,# 'local' => 1,# 'interface' => 1,);#-------------------------------------------------------------------------------# Function : FileSet## Description : Create a new instance of a File Locator# Used to provide the basic configuration of the target# system## Inputs : None# Useful information is prsent in the environment### Returns : Class Ref#sub FileSet{Debug ("New JatsLocatePkgFile");my $self;## Load all the MakeFile generate information and data structures#my $mi = JatsMakeConfigLoader::Load();## Document Class Variables#$self->{'platform'} = $mi->{'PLATFORM'};$self->{'type'} = $mi->{'TYPE'};$self->{'cache'} = undef;## Create a class# Bless my self#bless ($self, __PACKAGE__);## Locate required entries#my @result;for my $entry ( @{$mi->GetDataItem('%ScmBuildPkgRules')} ){## If a BuildPkgArchive, then skip as its data will be embedded# in the pseudo INTERFACE package#next if ( ($entry->{'TYPE'} eq 'build' ) );push @result, $entry->{'ROOT'};}$self->{'BuildPaths'} = \@result;$self->{'BuildParts'} = $mi->GetDataItem('%BUILDPLATFORM_PARTS');$self->{'a'} = $mi->GetDataItem('$a');$self->{'exe'} = $mi->GetDataItem('$exe');$self->{'so'} = $mi->GetDataItem('$so');# DebugDumpData(__PACKAGE__, $self );return $self;}#-------------------------------------------------------------------------------# Function : LocateFile## Description : Locate a file as specified by a user description## Inputs : $self - Instance Data# $fspec - A file specification## Returns : A list of files that match# May not return on error#sub LocateFile{my $self = shift;my ($fspec) = @_;my $opts;my $mode;## Split the file spec into bits# Extract options and the base file name# Create a hash of options# Convert options to lowercase# Extract any assignments# Treat --Flag as --Flag=1#$self->{'uspec'} = $fspec;while ( $fspec =~ m~^(.*),--(.*?)(=(.*?))?,*$~ ){$fspec = $1;my $opt = lc($2);$opts->{$opt} = defined($3) ? $4 : 1;$mode = $LocSpec{$opt}if ( exists $LocSpec{$opt} )}## Save the remainder as the filename# It may not exist#$opts->{'file'} = $fspec;$opts->{'Mode'} = $mode;# DebugDumpData("File", $opts);## Dispatch to a suitable processing routine#if ( $mode ){if ( $mode->{'code'} ){my @result = ( $mode->{'code'}( $self, $opts ) );print "-----Files found: $#result\n";if ( ! $opts->{'allowmultiple'} ){Error ("Mutliple Files found: $self->{'uspec'}" )if ( $#result > 1 );}return wantarray ? @result : $result[0];}DebugDumpData("File", $opts);Error ("Unknown search method: @_");}else{## No Mode specified# Must be a local file#my $ufile = $opts->{'file'};return $ufileif ( -f $ufile );return undef;}}#-------------------------------------------------------------------------------# Function : searchLib## Description : The user is looking for a shared library file# It will have a specific extension# It will be in one of the 'lib' directories known to JATS## Current Limitations:# Does not perform Unix Lib Prefix# Does not handle Name.version.so# Does not handle 'so' Name and 'real' name pairs### Inputs : $self - Instance Data# $opts - Options Hash## Returns :#sub searchLib{my ($self, $opts) = @_;my $ufile = $opts->{'file'};my $ext = $self->{so} ? '.' . $self->{a} : '';my @results;foreach my $dir ( @{ LibDirs($self) } ){foreach ( glob ( "$dir/*") ){foreach my $type ( $self->{'type'}, '' ){push @results, $_ if ( $_ =~ "/$ufile$type$ext\$" );}}# foreach my $type ( $self->{'type'}, '' )# {# my $file = "$dir/$ufile" . $type . $ext;# push @results, $file# if ( -f $file );# }}return @results;}#-------------------------------------------------------------------------------# Function : searchProg## Description : The user is looking for a program file# It will have a specific extension# It will be in one of the 'Bin' directories known to JATS## Inputs : $self - Instance Data# $opts - Options Hash## Returns :#sub searchProg{my ($self, $opts) = @_;my $ufile = $opts->{'file'} . $self->{exe};my @results;foreach my $dir ( @{ BinDirs($self) } ){foreach ( glob ( "$dir/*") ){push @results, $_ if ( $_ =~ "/$ufile\$" );}}return @results;# my $ufile = $opts->{'file'} . $self->{exe};# foreach my $dir ( @{ BinDirs($self) } )# {# my $file = "$dir/$ufile";# return $file# if ( -f $file );# }# return undef;}#-------------------------------------------------------------------------------# Function : searchBin## Description : The user is looking for a program file# It will be in one of the 'Bin' directories known to JATS## Inputs : $self - Instance Data# $opts - Options Hash## Returns :#sub searchBin{my ($self, $opts) = @_;my $ufile = $opts->{'file'};my @results;foreach my $dir ( @{ BinDirs($self) } ){foreach ( glob ( "$dir/*") ){push @results, $_ if ( $_ =~ "/$ufile\$" );}}return @results;}#-------------------------------------------------------------------------------# Function : searchDeb## Description : The user is looking for a Debian Package# It will have a specific extension# It will be in one of the 'Bin' directories known to JATS## Inputs : $self - Instance Data# $opts - Options Hash## Returns :#sub searchDeb{my ($self, $opts) = @_;foreach my $dir ( @{ BinDirs($self) } ){if ( my @files = glob ( "$dir/$opts->{file}_*.deb" ) ){return $files[0];}}return undef;}#-------------------------------------------------------------------------------# Function : searchDir## Description : The user is looking for a file in a package subdir# It will be in one of the package directories## Inputs : $self - Instance Data# $opts - Options Hash## Returns :#sub searchDir{my ($self, $opts) = @_;my $ufile = $opts->{'file'};foreach my $dir ( @{ MiscDirs($self, $opts->{'dir'}) } ){my $file = "$dir/$ufile";return $fileif ( -f $file );}return undef;}#-------------------------------------------------------------------------------# Function : searchSimple## Description : The user is looking for a file in known subdir subdir# It will be in one of the package directories## Inputs : $self - Instance Data# $opts - Options Hash## Returns :#sub searchSimple{my ($self, $opts) = @_;my $mode = $opts->{'Mode'}{'dir'};Error ("JatsLocatePkgFile. searchSimple. Internal Error. No 'dir' configured'","Entry: $self->{'uspec'}") unless ( $mode );$opts->{'dir'} = $mode;return searchDir( $self, $opts );}#-------------------------------------------------------------------------------# Function : searchPkg## Description : The user is looking for a file in a package pkg subdir# It will be in one of the package directories## Inputs : $self - Instance Data# $opts - Options Hash## Returns :#sub searchPkg{my ($self, $opts) = @_;my $ufile = $opts->{'file'};foreach my $dir ( @{ PkgDirs($self) } ){my $file = "$dir/$ufile";return $fileif ( -f $file );}return undef;}#-------------------------------------------------------------------------------# Function : BinDirs## Description : Return an array of directories to search for Bin files# Cache results for future use## Bin dirs are used to hold:# Programs# Debian Packages# File System Images## The directory is named after a platform and will have# a P or D suffix## Template: {BASE}/bin/{PLATFORM}{TYPE}# Compatability: {BASE}/bin.{PLATFORM}{TYPE}# {BASE}/bin/bin.{PLATFORM}{TYPE}## Inputs : $self - Instance Data## Returns : An Array#sub BinDirs{my $self = shift;## Return cached results#unless ( $self->{'cache'}{'bin'} ){## Create an array of location to search#my @dirs;foreach my $base ( @{$self->{'BuildPaths'}} ){foreach my $type ( $self->{'type'}, '' ){foreach my $subdir ( @{$self->{'BuildParts'}} ){my $dir = "$base/bin/$subdir$type";#print "----Try : $dir\n";push @dirs, $dir if ( -d $dir );}}}$self->{'cache'}{'bin'} = \@dirs;}return $self->{'cache'}{'bin'}}#-------------------------------------------------------------------------------# Function : LibDirs## Description : Return an array of directories to search for Lib files# Cache results for future use## Lib dirs are used to hold:# Shared Libraries# Static Libraries## The file name should have an embedded type (P or D)## Template: {BASE}/lib/{PLATFORM}# Compatability: {BASE}/lib/{PLATFORM}{TYPE}# {BASE}/lib.{PLATFORM}{TYPE}# {BASE}/lib/lib.{PLATFORM}{TYPE}## Inputs : $self - Instance Data## Returns : An Array#sub LibDirs{my $self = shift;## Return cached results#unless ( $self->{'cache'}{'lib'} ){## Create an array of location to search#my @dirs;foreach my $base ( @{$self->{'BuildPaths'}} ){foreach my $type ( $self->{'type'}, '' ){foreach my $subdir ( @{$self->{'BuildParts'}}){my $dir = "$base/lib/$subdir$type";#print "----Try : $dir\n";push @dirs, $dir if ( -d $dir );}}}$self->{'cache'}{'lib'} = \@dirs;}return $self->{'cache'}{'lib'}}#-------------------------------------------------------------------------------# Function : PkgDirs## Description : Return an array of directories to search for Pkg files# Cache results for future use## pkg dirs are used to contain foreign subdirectory trees# Typically used to transparently transfer 3rd parts software## There are two forms of pkg dir# Both are not supported within the same package## Form-1# Template: {BASE}/pkg## Form-2# Template: {BASE}/pkg.{PLATFORM}# Template: {BASE}/pkg.{MACHTYPE}## Currently NOT a very good pkg searcher# It does not handle pkg/pkg.MACHTYPE dirs## Inputs : $self - Instance Data## Returns : An Array#sub PkgDirs{my $self = shift;## Return cached results#unless ( $self->{'cache'}{'pkg'} ){## Create an array of location to search#my @dirs;foreach my $base ( @{$self->{'BuildPaths'}} ){next unless ( -d "$base/pkg" );foreach my $subdir ( @{$self->{'BuildParts'}} ){my $dir = "$base/pkg/$subdir";#print "----Try : $dir\n";push @dirs, $dir if ( -d $dir );}unless ( @dirs ){push @dirs, $base;}}$self->{'cache'}{'pkg'} = \@dirs;}return $self->{'cache'}{'pkg'}}#-------------------------------------------------------------------------------# Function : MiscDirs## Description : Return an array of directories to search for Misc files# Cache results for future use## Misc dirs are used to contains files of known types# Normally a flat directory structure# No 'type' information## Template: {BASE}/{DIR}## Used for dirs that are not special, like the Bin and Lib## Inputs : $self - Instance Data# $root - Base of the section## Returns : An Array#sub MiscDirs{my ($self, $root) = @_;## Clean up the user path# Remove leading, trailing and multiple /#$root =~ s~/+~/~g;$root =~ s~^/~~;$root =~ s~/$~~;## Return cached results#unless ( $self->{'cache'}{$root} ){## Create an array of location to search#my @dirs;foreach my $base ( @{$self->{'BuildPaths'}} ){my $dir = "$base/$root";#print "----Try : $dir\n";push @dirs, $dir if ( -d $dir );}$self->{'cache'}{$root} = \@dirs;}return $self->{'cache'}{$root}}#sub DESTROY#{# DebugDumpData(__PACKAGE__, @_);#}1;