Subversion Repositories DevTools

Rev

Rev 7302 | Rev 7319 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
#! perl
2
########################################################################
7300 dpurdie 3
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
227 dpurdie 4
#
5
# Module name   : jats.sh
6
# Module type   : Makefile system
7
# Compiler(s)   : n/a
8
# Environment(s): jats
9
#
10
# Description   : Package Entry
11
#
12
#       New         Create a new package entry instance.
13
#
14
#       RuleInc     Check whether the specific 'include' path should
15
#                   be included within the PINCDIRS list.
16
#
17
#       RuleLib     Check whether the specific 'lib' path should
18
#                   be included within the PLIBDIRS list.
19
#
20
#       Cleanup     Performs any record cleanup required prior to the
21
#                   entry being published.
22
#
23
# Usage:
24
#
25
# Version   Who      Date        Description
26
#
27
#......................................................................#
28
 
255 dpurdie 29
require 5.006_001;
227 dpurdie 30
use strict;
31
use warnings;
32
 
33
use DescPkg;
34
use JatsError;
35
 
36
 
37
our $BUILDNAME_PACKAGE;
38
our $BUILDNAME_VERSION;
39
our $BUILDNAME_PROJECT;
40
our $BUILDINTERFACE;
41
our @BUILDTOOLS;
42
 
43
 
44
package PackageEntry;
45
 
46
our %DescPkgCache           = ();           # Hash of known packages
47
our %PackageDefined         = ();           # Quick defined package test
48
our @PackageList            = ();           # Ordered array of packages
49
 
311 dpurdie 50
 
51
#-------------------------------------------------------------------------------
52
# Function        : EmptyEntry
53
#
54
# Description     : Create an empty class element
55
#                   Populated with the basic items
56
#
57
# Inputs          : None
58
#
59
# Returns         : New, empty entry
60
#
61
sub EmptyEntry
227 dpurdie 62
{
63
    my ($self) = {
64
            PINCDIRS        => [],
65
            PLIBDIRS        => [],
66
            LIBEXAMINED     => {},
67
            INCEXAMINED     => {},
68
            TOOLDIRS        => [],
69
            THXDIRS         => [],
70
        };
311 dpurdie 71
    return bless $self, __PACKAGE__;
72
}
227 dpurdie 73
 
311 dpurdie 74
sub New
75
{
7301 dpurdie 76
    my ($base, $name, $version, $sandbox, $type, $local, $pkgSig) = @_;
311 dpurdie 77
    my $self = EmptyEntry();
78
 
79
    #   Load package description ...
80
    #
81
    #       If a sandbox link, parse the build.pl and retrieve the BuildName()
82
    #       otherwise, load the description from the 'descpkg'.
83
    #
84
    #   Note:   The results are cached within DescPkgCache
85
    #..
227 dpurdie 86
    if ( ! exists( $DescPkgCache{$base} ) )
87
    {
88
        my ($rec);
89
        my ($desc) = "";
90
 
91
        if ( $sandbox )
92
        {
93
            open (BUILDPL, "$base/build.pl") ||
94
                ::Error( "cannot open '$base/build.pl'" );
95
            while (<BUILDPL>) {
96
                if ( $_ =~ /^\s*BuildName\s*\(\s*[\"\'](.*)[\'\"]\s*\)/ ) {
97
                    $desc = $1;                 # BuildName() argument
98
                    ($rec->{NAME}, $rec->{VERSION}, $rec->{PROJ}) = split( ' ', $desc );
99
                    last;
100
                }
101
            }
102
            close (BUILDPL);
103
        }
104
        elsif ( -f "$base/descpkg" )
105
        {
106
            $rec = ::ReadDescpkg( "$base/descpkg", 1 );
107
        }
108
        else
109
        {                                       # doesn't exist
110
            ::Error( "Package description does not exist",
111
                     "Package Location: $base" )
112
        }
113
 
114
        ::Error("Cannot determine package description",
115
                "Package Location: $base" )
116
            unless ( $rec );
117
 
118
        ::Warning( "Package names do not match: $rec->{NAME}, $name" )
119
            if ( $rec->{NAME} ne $name );
120
 
7301 dpurdie 121
        if ( $local )
227 dpurdie 122
        {                                       # display results
331 dpurdie 123
            my $logPrefix = "               ->";
124
            if ( $local ) {
125
                ::Log( "$logPrefix $base" );
126
            } elsif ($rec->{NAME} eq "") {
127
                ::Log( "$logPrefix n/a" );
227 dpurdie 128
            } else {
331 dpurdie 129
                ::Log( "$logPrefix $rec->{NAME} $rec->{VERSION} $rec->{PROJ}" );
227 dpurdie 130
            }
131
        }
132
        elsif ( $rec->{VERSION_FULL} ne $version )
133
        {
134
            ::Warning( "Package versions do not match: $name : $rec->{VERSION_FULL}, $version" );
135
        }
136
 
137
        #
7300 dpurdie 138
        #   Extend the package information to contain sufficient data
227 dpurdie 139
        #   for general use. Information will be retained to allow the
140
        #   user to extact specific package information
141
        #
142
        $version =~ m~(\d+\.\d+\.\d+)\.(\w+)~ ;
143
        my $vnum = $1 || $version;
144
        my $proj = $2 || '';
145
 
146
        $rec->{UNAME}    = $name;
147
        $rec->{UVERSION} = $version;
148
        $rec->{UVNUM}    = $vnum;
149
        $rec->{UPROJ}    = $proj;
150
        $rec->{type}     = $type;
7301 dpurdie 151
        $rec->{PKGSIG}   = $pkgSig;
227 dpurdie 152
 
153
        $PackageDefined{$name}{$proj}{$vnum} = $base;
154
        push @PackageList, $base;
155
 
156
        $DescPkgCache{$base} = $rec;                  # cache result
157
    }
158
 
159
#   Build the package entry record
160
#..
161
    my ($descpkg) = $DescPkgCache{$base};       # descpkg details
162
 
163
    $self->{'base'}         = $base;
164
    $self->{'base'}         .= "/local"
165
        if ( $sandbox );
166
 
167
    $self->{'name'}         = $name;
168
    $self->{'version'}      = $version;
169
    $self->{'sandbox'}      = $sandbox;
170
    $self->{'dname'}        = $descpkg->{NAME};
171
    $self->{'dversion'}     = $descpkg->{VERSION};
172
    $self->{'dproj'}        = $descpkg->{PROJ} || $descpkg->{UPROJ} || '';
173
    $self->{'packages'}     = $descpkg->{PACKAGES};
174
    $self->{'type'}         = $type;
175
    $self->{'cfgdir'}       = "/gbe"
176
        if ( $sandbox || -d $base."/gbe" );
7301 dpurdie 177
#    $self->{pkgsig}         = $descpkg->{PKGSIG};
227 dpurdie 178
 
311 dpurdie 179
    return $self;
227 dpurdie 180
}
181
 
311 dpurdie 182
#-------------------------------------------------------------------------------
183
# Function        : Interface
184
#
185
# Description     : Create a specialised 'interface' entry
186
#
187
# Inputs          : $base           - Path to the Interface directory
188
#
189
# Returns         : Ref to this class
190
#
191
sub Interface
192
{
193
    my ($base) = @_;
194
    my $self = EmptyEntry();
195
 
196
    $self->{'base'}         = $base;
197
    $self->{'name'}         = 'INTERFACE';
198
    $self->{'version'}      = '0.0.0';
199
    $self->{'sandbox'}      = 0;
200
    $self->{'dname'}        = $self->{'name'};
201
    $self->{'dversion'}     = $self->{'version'};
202
    $self->{'dproj'}        = '';
203
    $self->{'packages'}     = '';
204
    $self->{'type'}         = 'interface';
205
    $self->{'cfgdir'}       = '/gbe';
206
 
207
    return $self;
208
 
209
}
210
 
227 dpurdie 211
sub RuleInc
212
{
213
    my( $self ) = shift;
214
    my( $path ) = @_;
215
    my( $examined ) = $self->{INCEXAMINED};
216
    my( $list ) = $self->{PINCDIRS};
217
 
218
    return if ( $$examined{$path} );
219
    $$examined{$path} = 1;
220
 
221
    push @$list, $path      if ( $self->{'sandbox'} || -d $self->{'base'}.$path );
222
}
223
 
224
#
225
#   Examine Path to ensure that it is a directory and that it contains files
226
#   Simplify Lib Path searching by removing useless paths.
227
#
228
#   If there are ANY files then the directory is useful
229
#   If there are no files ( only subdirectories ) then the directory is not useful
230
#
231
sub isUsefulDir
232
{
233
    my ($path) = @_;
234
 
235
    if ( -d $path )
236
    {
237
        opendir (USEFUL, $path) or ::Error ("Cannot open $path");
238
        my @dirlist = readdir USEFUL;
285 dpurdie 239
        closedir USEFUL;
227 dpurdie 240
 
241
        foreach ( @dirlist )
242
        {
243
            return 1 if ( -f "$path/$_" );
244
        }
245
    }
246
    return 0;
247
}
248
 
249
sub RuleLib
250
{
251
    my( $self ) = shift;
252
    my( $path ) = @_;
253
    my( $examined ) = $self->{LIBEXAMINED};
254
    my( $list ) = $self->{PLIBDIRS};
255
 
256
    return if ( $$examined{$path} );
257
    $$examined{$path} = 1;
258
 
259
    push @$list, $path."D"  if ( $self->{'sandbox'} || isUsefulDir($self->{'base'}.$path."D") );
260
    push @$list, $path."P"  if ( $self->{'sandbox'} || isUsefulDir($self->{'base'}.$path."P") );
261
    push @$list, $path      if ( $self->{'sandbox'} || isUsefulDir($self->{'base'}.$path) );
262
}
263
 
264
#-------------------------------------------------------------------------------
265
# Function        : ExamineToolPath
266
#
267
# Description     : Given the root of a package, locate any
268
#                   toolset extension paths within the tree. These will be
269
#                   saved and later used when user tools and scripts are
270
#                   invoked.
271
#
272
#   Examine:
273
#       - tools/bin/GBE_MACHTYPE    - Hardware specfic tools
274
#       - tools/bin                 - Hardware independent tools - scripts
275
#       - tools/scripts/GBE_MACHINE - Hardware specific scripts
276
#       - tools/scripts             - Hardware independent scripts (too)
277
#
278
# Inputs          : self
279
#
280
# Returns         : Nothing
281
#
282
sub ExamineToolPath
283
{
284
    my( $self ) = shift;
285
 
286
    #
287
    #   Determine base dir
288
    #       LinkPkgArchive  : From the package
289
    #       BuildPkgArchive : From the interface directory
290
    #
291
    my $base_dir = $self->{'base'};
292
    $base_dir = "$::Cwd/$BUILDINTERFACE"
293
        if ( $self->{'type'} eq 'build' );
294
 
295
    for my $path ("/tools/bin", "/tools/scripts" )
296
    {
297
        foreach my $suffix ( "/$::GBE_MACHTYPE", "" )
298
        {
299
            my $dir = $base_dir . $path . $suffix;
300
            if ( isUsefulDir( $dir ) )
301
            {
302
                ::UniquePush( \@{$self->{'TOOLDIRS'}}, $dir );
303
                ::UniquePush( \@BUILDTOOLS, $dir );
304
            }
305
        }
306
    }
307
}
308
 
309
#-------------------------------------------------------------------------------
310
# Function        : ExamineThxPath
311
#
312
# Description     : Given the root of a package, locate some well known
313
#                   packaging directories for later use.
314
#
315
#                   Examine:
316
#                       /thx/$platform
317
#                       /thx
318
#
319
# Inputs          : self
320
#                   platform        - Current build platform
321
#
322
# Returns         : nothing
323
#
324
sub ExamineThxPath
325
{
326
    my( $self, $platform ) = @_;
327
 
328
    my $dir = $self->{'base'} . '/thx';
329
    if ( -d $dir )
330
    {
331
        push @{$self->{'THXDIRS'}}, "/thx/$platform" if isUsefulDir( "$dir/$platform" );
332
        push @{$self->{'THXDIRS'}}, "/thx" if isUsefulDir( $dir );
333
    }
334
}
335
 
336
sub Cleanup
337
{
338
    my ($self) = shift;
339
 
340
    delete $self->{LIBEXAMINED};
341
    delete $self->{INCEXAMINED};
342
}
343
 
344
 
345
#-------------------------------------------------------------------------------
346
# Function        : GetBaseDir
347
#
348
# Description     : Return the base directory of a given package
349
#                   Simple getter function
350
#
351
# Inputs          : self
352
#                   path    - Optional path within package
353
#
354
# Returns         : The base directory of the package
355
#
356
sub GetBaseDir
357
{
358
    my ($self, $path) = @_;
359
    my $dir = $self->{'base'};
360
    $dir .= '/' . $path if ( $path );
361
    return $dir;
362
}
363
 
364
 
365
#-------------------------------------------------------------------------------
366
# Function        : SanityTest
367
#
368
# Description     : Examine all the packages used in the current build.pl
369
#                   and all the packages used to build them. Then generate
370
#                   warning if there are mismatches.
371
#
372
#                   All the data has been collected and stored within
373
#                   $DescPkgCache. This routine processes the data and
374
#                   constructs a data structure to locate packages with
375
#                   multiple versions.
376
#
377
#                   The project name is considered to be a part of the package
378
#                   name. Thus aaaa_11.22.33.mass is different to aaaa_11.22.33.syd
379
#
380
# Inputs          :
381
#
382
# Returns         :
383
#
384
my %package_list;
385
 
386
sub AddEntry
387
{
388
    my( $root, $rver, $rproj, $name, $version ) = @_;
389
    my $ver;
390
    my $proj;
391
 
392
    if ($version eq "!current") {
393
        $ver = "current";
394
        $proj = "";
395
    } else {
396
        $version =~ m~(.*)\.(.*?)$~;
397
        $ver = $1  || 'BadVer';
398
        $proj = $2 || 'BadProj';
399
    }
400
 
401
    ::UniquePush( \@{$package_list{"$name$;$proj"}{$ver}},  "${root}_${rver}.${rproj}");
402
}
403
 
404
sub SanityTest
405
{
406
    foreach my $package ( keys %DescPkgCache )
407
    {
408
        my $pptr = $DescPkgCache{$package};
409
        my $lver = $pptr->{'VERSION'};
410
           $lver .= '.' . $pptr->{'PROJ'} if ( $pptr->{'PROJ'} );
411
        AddEntry( $BUILDNAME_PACKAGE, $BUILDNAME_VERSION, $BUILDNAME_PROJECT, $pptr->{'NAME'}, $lver );
412
 
413
 
414
        foreach my $subpkg ( @{$pptr->{'PACKAGES'}} )
415
        {
416
            my $name = $subpkg->{name};
417
            my $ver = $subpkg->{version};
418
 
419
            AddEntry( $pptr->{'NAME'}, $pptr->{'VERSION'}, $pptr->{'PROJ'}, $name, $ver );
420
        }
421
    }
422
 
423
    #::DebugDumpData("XXX", \%package_list );
424
 
425
    #
426
    #   Detect and print warnings about multiple entries
427
    #
428
    my $first_found = 0;
429
    foreach my $pentry ( sort keys %package_list)
430
    {
431
        my @versions = keys %{$package_list{$pentry}};
432
 
433
        if ( $#versions > 0 )
434
        {
435
            ::Warning("Package mismatchs detected.") unless ( $first_found++ );
436
 
437
            my ($pname, $pproj) = split $;, $pentry ;
438
            foreach my $version ( @versions )
439
            {
440
                ::Warning("Package ${pname}_${version}.${pproj} used by:", @{$package_list{$pentry}{$version}});
441
            }
442
        }
443
 
444
    }
445
}
446
 
447
#-------------------------------------------------------------------------------
448
# Function        : Exists
449
#
450
# Description     : A class function to determine if a given package is known
451
#                   to the PackageEntry manager. Used to detect multiple package
452
#                   definitions.
453
#
454
#                   The test ignores package versions
455
#                   It is not possible to include different versions of the
456
#                   same package. The test ignores the project part of the
457
#                   version. This allows for
458
#                           sysbasetypes aa.bb.cc.mas and
459
#                           sysbasetypes xx.yy.zz.syd
460
#
461
# Inputs          : $name           - User package name
462
#                   $version        - User version ( with project )
463
#
464
# Returns         : True: Package exists
465
#
466
 
467
sub Exists
468
{
469
    my ($name, $version) = @_;
470
 
471
    $version =~ m~(\d+\.\d+\.\d+)\.(\w+)~ ;
472
    my $vnum = $1 || $version;
473
    my $proj = $2 || '';
474
 
475
    return exists( $PackageDefined{$name}{$proj} );
476
}
477
 
478
#-------------------------------------------------------------------------------
479
# Function        : GetPackageList
480
#
481
# Description     : A class function to return a list of packages
7300 dpurdie 482
#                   The list cannot be used directly. It is really a set of
227 dpurdie 483
#                   keys to an internal data structure.
484
#
485
#                   The result can be used to iterate over the list of packages
486
#                   using other functions.
487
#
488
# Inputs          : None
489
#
490
# Returns         : An array of package tags
491
#                   The array is ordered by package definition order
492
#
493
sub GetPackageList
494
{
495
    return @PackageList;
496
}
497
 
498
#-------------------------------------------------------------------------------
499
# Function        : GetPackageData
500
#
501
# Description     : A class function to return specific data for a given package
502
#
503
# Inputs          : $tag        - An iteration tag provided by GetPackageList()
504
#
505
# Returns         : A list of
506
#                       Package name
507
#                       Package version
508
#                       Package type : build or link
509
#
510
sub GetPackageData
511
{
512
    my ($tag) = @_;
513
    my $rec = $DescPkgCache{$tag};
514
    return $rec->{UNAME}, $rec->{UVERSION}, $rec->{type};
515
}
516
 
517
#-------------------------------------------------------------------------------
7302 dpurdie 518
# Function        : GetNameVersion
519
#
520
# Description     : Return a package name and version for display purposes
521
#
522
# Inputs          : $tag        - An iteration tag provided by GetPackageList()
523
#
524
# Returns         : A list of
525
#                       Package name
526
#                       Package version
527
#                       Package type : build or link
528
#
529
sub GetNameVersion
530
{
531
    my ($tag) = @_;
532
    my $rec = $DescPkgCache{$tag};
533
    return join( ' ', $rec->{NAME}, $rec->{VERSION_FULL} );
534
}
535
 
536
#-------------------------------------------------------------------------------
227 dpurdie 537
# Function        : GetPackageVersionList
538
#
539
# Description     : A class function to return a list of package names as used
540
#                   to generate version strings
541
#
542
#
543
# Inputs          : None
544
#
545
# Returns         : An array of version list entries
546
#                   Each element of the form: "name (version)"
547
#
548
sub GetPackageVersionList
549
{
550
    my @list;
551
    foreach my $tag ( @PackageList )
552
    {
553
        my $rec = $DescPkgCache{$tag};
554
        push @list, "$rec->{UNAME} ($rec->{UVERSION})";
555
    }
556
 
557
    return @list;
558
}
559
 
7301 dpurdie 560
#-------------------------------------------------------------------------------
561
# Function        : GetPackageSignature
562
#
563
# Description     : A class function to return a packages signature
564
#
565
#
566
# Inputs          : None
567
#
568
# Returns         : An array of version list entries
569
#                   Each element of the form: "name (version)"
570
#
571
sub GetPackageSignature
572
{
573
    my ($tag) = @_;
574
    my $rec = $DescPkgCache{$tag};
575
    return $rec->{PKGSIG};
576
}
577
 
7302 dpurdie 578
#-------------------------------------------------------------------------------
579
# Function        : Dump 
580
#
581
# Description     : Internal diagnostic tool
582
#                   Dumps internal data structures    
583
#
584
# Inputs          : None 
585
#
586
# Returns         : Nothing 
587
#
7301 dpurdie 588
 
7302 dpurdie 589
sub Dump
590
{
591
    ::DebugDumpData("PackageEntry",\%DescPkgCache);
592
}
593
 
227 dpurdie 594
### End of package: PackageEntry
595
 
596
1;
597