Subversion Repositories DevTools

Rev

Rev 255 | Rev 311 | 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
########################################################################
3
# Copyright ( C ) 2004 ERG Limited, All rights reserved
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
 
50
sub New
51
{
52
    my ($base, $name, $version, $sandbox, $type) = @_;
53
    my ($self) = {
54
            PINCDIRS        => [],
55
            PLIBDIRS        => [],
56
            LIBEXAMINED     => {},
57
            INCEXAMINED     => {},
58
            TOOLDIRS        => [],
59
            THXDIRS         => [],
60
        };
61
    my ($ppkg);
62
 
63
#   Load package description ...
64
#
65
#       If a sandbox link, parse the build.pl and retrieve the BuildName()
66
#       otherwise, load the description from the 'descpkg'.
67
#
68
#   Note:   The results are cached within DescPkgCache
69
#..
70
    if ( ! exists( $DescPkgCache{$base} ) )
71
    {
72
        my ($rec);
73
        my ($desc) = "";
74
 
75
        if ( $sandbox )
76
        {
77
            open (BUILDPL, "$base/build.pl") ||
78
                ::Error( "cannot open '$base/build.pl'" );
79
            while (<BUILDPL>) {
80
                if ( $_ =~ /^\s*BuildName\s*\(\s*[\"\'](.*)[\'\"]\s*\)/ ) {
81
                    $desc = $1;                 # BuildName() argument
82
                    ($rec->{NAME}, $rec->{VERSION}, $rec->{PROJ}) = split( ' ', $desc );
83
                    last;
84
                }
85
            }
86
            close (BUILDPL);
87
        }
88
        elsif ( -f "$base/descpkg" )
89
        {
90
            $rec = ::ReadDescpkg( "$base/descpkg", 1 );
91
        }
92
        else
93
        {                                       # doesn't exist
94
            ::Error( "Package description does not exist",
95
                     "Package Location: $base" )
96
        }
97
 
98
        ::Error("Cannot determine package description",
99
                "Package Location: $base" )
100
            unless ( $rec );
101
 
102
        ::Warning( "Package names do not match: $rec->{NAME}, $name" )
103
            if ( $rec->{NAME} ne $name );
104
 
105
        if ( substr($version,0,8) eq '!current' ||
106
                substr($version,0,8) eq '!sandbox' )
107
        {                                       # display results
108
            ::Log( "          -> " );
109
            if ($rec->{NAME} eq "") {
110
                ::Log( "n/a\n" );
111
            } else {
112
                ::Log( "$rec->{NAME} $rec->{VERSION} $rec->{PROJ}\n" );
113
            }
114
        }
115
        elsif ( $rec->{VERSION_FULL} ne $version )
116
        {
117
            ::Warning( "Package versions do not match: $name : $rec->{VERSION_FULL}, $version" );
118
        }
119
 
120
        #
121
        #   Extend the package information to contain suffiecient data
122
        #   for general use. Information will be retained to allow the
123
        #   user to extact specific package information
124
        #
125
        $version =~ m~(\d+\.\d+\.\d+)\.(\w+)~ ;
126
        my $vnum = $1 || $version;
127
        my $proj = $2 || '';
128
 
129
        $rec->{UNAME}    = $name;
130
        $rec->{UVERSION} = $version;
131
        $rec->{UVNUM}    = $vnum;
132
        $rec->{UPROJ}    = $proj;
133
        $rec->{type}     = $type;
134
 
135
        $PackageDefined{$name}{$proj}{$vnum} = $base;
136
        push @PackageList, $base;
137
 
138
        $DescPkgCache{$base} = $rec;                  # cache result
139
    }
140
 
141
#   Build the package entry record
142
#..
143
    my ($descpkg) = $DescPkgCache{$base};       # descpkg details
144
 
145
    $self->{'base'}         = $base;
146
    $self->{'base'}         .= "/local"
147
        if ( $sandbox );
148
 
149
    $self->{'name'}         = $name;
150
    $self->{'version'}      = $version;
151
    $self->{'sandbox'}      = $sandbox;
152
    $self->{'dname'}        = $descpkg->{NAME};
153
    $self->{'dversion'}     = $descpkg->{VERSION};
154
    $self->{'dproj'}        = $descpkg->{PROJ} || $descpkg->{UPROJ} || '';
155
    $self->{'packages'}     = $descpkg->{PACKAGES};
156
    $self->{'type'}         = $type;
157
    $self->{'cfgdir'}       = "/gbe"
158
        if ( $sandbox || -d $base."/gbe" );
159
 
160
    return bless $self, __PACKAGE__;
161
}
162
 
163
sub RuleInc
164
{
165
    my( $self ) = shift;
166
    my( $path ) = @_;
167
    my( $examined ) = $self->{INCEXAMINED};
168
    my( $list ) = $self->{PINCDIRS};
169
 
170
    return if ( $$examined{$path} );
171
    $$examined{$path} = 1;
172
 
173
    push @$list, $path      if ( $self->{'sandbox'} || -d $self->{'base'}.$path );
174
}
175
 
176
#
177
#   Examine Path to ensure that it is a directory and that it contains files
178
#   Simplify Lib Path searching by removing useless paths.
179
#
180
#   If there are ANY files then the directory is useful
181
#   If there are no files ( only subdirectories ) then the directory is not useful
182
#
183
sub isUsefulDir
184
{
185
    my ($path) = @_;
186
 
187
    if ( -d $path )
188
    {
189
        opendir (USEFUL, $path) or ::Error ("Cannot open $path");
190
        my @dirlist = readdir USEFUL;
285 dpurdie 191
        closedir USEFUL;
227 dpurdie 192
 
193
        foreach ( @dirlist )
194
        {
195
            return 1 if ( -f "$path/$_" );
196
        }
197
    }
198
    return 0;
199
}
200
 
201
sub RuleLib
202
{
203
    my( $self ) = shift;
204
    my( $path ) = @_;
205
    my( $examined ) = $self->{LIBEXAMINED};
206
    my( $list ) = $self->{PLIBDIRS};
207
 
208
    return if ( $$examined{$path} );
209
    $$examined{$path} = 1;
210
 
211
    push @$list, $path."D"  if ( $self->{'sandbox'} || isUsefulDir($self->{'base'}.$path."D") );
212
    push @$list, $path."P"  if ( $self->{'sandbox'} || isUsefulDir($self->{'base'}.$path."P") );
213
    push @$list, $path      if ( $self->{'sandbox'} || isUsefulDir($self->{'base'}.$path) );
214
}
215
 
216
#-------------------------------------------------------------------------------
217
# Function        : ExamineToolPath
218
#
219
# Description     : Given the root of a package, locate any
220
#                   toolset extension paths within the tree. These will be
221
#                   saved and later used when user tools and scripts are
222
#                   invoked.
223
#
224
#   Examine:
225
#       - tools/bin/GBE_MACHTYPE    - Hardware specfic tools
226
#       - tools/bin                 - Hardware independent tools - scripts
227
#       - tools/scripts/GBE_MACHINE - Hardware specific scripts
228
#       - tools/scripts             - Hardware independent scripts (too)
229
#
230
# Inputs          : self
231
#
232
# Returns         : Nothing
233
#
234
sub ExamineToolPath
235
{
236
    my( $self ) = shift;
237
 
238
    #
239
    #   Determine base dir
240
    #       LinkPkgArchive  : From the package
241
    #       BuildPkgArchive : From the interface directory
242
    #
243
    my $base_dir = $self->{'base'};
244
    $base_dir = "$::Cwd/$BUILDINTERFACE"
245
        if ( $self->{'type'} eq 'build' );
246
 
247
    for my $path ("/tools/bin", "/tools/scripts" )
248
    {
249
        foreach my $suffix ( "/$::GBE_MACHTYPE", "" )
250
        {
251
            my $dir = $base_dir . $path . $suffix;
252
            if ( isUsefulDir( $dir ) )
253
            {
254
                ::UniquePush( \@{$self->{'TOOLDIRS'}}, $dir );
255
                ::UniquePush( \@BUILDTOOLS, $dir );
256
            }
257
        }
258
    }
259
}
260
 
261
#-------------------------------------------------------------------------------
262
# Function        : ExamineThxPath
263
#
264
# Description     : Given the root of a package, locate some well known
265
#                   packaging directories for later use.
266
#
267
#                   Examine:
268
#                       /thx/$platform
269
#                       /thx
270
#
271
# Inputs          : self
272
#                   platform        - Current build platform
273
#
274
# Returns         : nothing
275
#
276
sub ExamineThxPath
277
{
278
    my( $self, $platform ) = @_;
279
 
280
    my $dir = $self->{'base'} . '/thx';
281
    if ( -d $dir )
282
    {
283
        push @{$self->{'THXDIRS'}}, "/thx/$platform" if isUsefulDir( "$dir/$platform" );
284
        push @{$self->{'THXDIRS'}}, "/thx" if isUsefulDir( $dir );
285
    }
286
}
287
 
288
sub Cleanup
289
{
290
    my ($self) = shift;
291
 
292
    delete $self->{LIBEXAMINED};
293
    delete $self->{INCEXAMINED};
294
}
295
 
296
 
297
#-------------------------------------------------------------------------------
298
# Function        : GetBaseDir
299
#
300
# Description     : Return the base directory of a given package
301
#                   Simple getter function
302
#
303
# Inputs          : self
304
#                   path    - Optional path within package
305
#
306
# Returns         : The base directory of the package
307
#
308
sub GetBaseDir
309
{
310
    my ($self, $path) = @_;
311
    my $dir = $self->{'base'};
312
    $dir .= '/' . $path if ( $path );
313
    return $dir;
314
}
315
 
316
 
317
#-------------------------------------------------------------------------------
318
# Function        : SanityTest
319
#
320
# Description     : Examine all the packages used in the current build.pl
321
#                   and all the packages used to build them. Then generate
322
#                   warning if there are mismatches.
323
#
324
#                   All the data has been collected and stored within
325
#                   $DescPkgCache. This routine processes the data and
326
#                   constructs a data structure to locate packages with
327
#                   multiple versions.
328
#
329
#                   The project name is considered to be a part of the package
330
#                   name. Thus aaaa_11.22.33.mass is different to aaaa_11.22.33.syd
331
#
332
# Inputs          :
333
#
334
# Returns         :
335
#
336
my %package_list;
337
 
338
sub AddEntry
339
{
340
    my( $root, $rver, $rproj, $name, $version ) = @_;
341
    my $ver;
342
    my $proj;
343
 
344
    if ($version eq "!current") {
345
        $ver = "current";
346
        $proj = "";
347
    } else {
348
        $version =~ m~(.*)\.(.*?)$~;
349
        $ver = $1  || 'BadVer';
350
        $proj = $2 || 'BadProj';
351
    }
352
 
353
    ::UniquePush( \@{$package_list{"$name$;$proj"}{$ver}},  "${root}_${rver}.${rproj}");
354
}
355
 
356
sub SanityTest
357
{
358
    foreach my $package ( keys %DescPkgCache )
359
    {
360
        my $pptr = $DescPkgCache{$package};
361
        my $lver = $pptr->{'VERSION'};
362
           $lver .= '.' . $pptr->{'PROJ'} if ( $pptr->{'PROJ'} );
363
        AddEntry( $BUILDNAME_PACKAGE, $BUILDNAME_VERSION, $BUILDNAME_PROJECT, $pptr->{'NAME'}, $lver );
364
 
365
 
366
        foreach my $subpkg ( @{$pptr->{'PACKAGES'}} )
367
        {
368
            my $name = $subpkg->{name};
369
            my $ver = $subpkg->{version};
370
 
371
            AddEntry( $pptr->{'NAME'}, $pptr->{'VERSION'}, $pptr->{'PROJ'}, $name, $ver );
372
        }
373
    }
374
 
375
    #::DebugDumpData("XXX", \%package_list );
376
 
377
    #
378
    #   Detect and print warnings about multiple entries
379
    #
380
    my $first_found = 0;
381
    foreach my $pentry ( sort keys %package_list)
382
    {
383
        my @versions = keys %{$package_list{$pentry}};
384
 
385
        if ( $#versions > 0 )
386
        {
387
            ::Warning("Package mismatchs detected.") unless ( $first_found++ );
388
 
389
            my ($pname, $pproj) = split $;, $pentry ;
390
            foreach my $version ( @versions )
391
            {
392
                ::Warning("Package ${pname}_${version}.${pproj} used by:", @{$package_list{$pentry}{$version}});
393
            }
394
        }
395
 
396
    }
397
}
398
 
399
#-------------------------------------------------------------------------------
400
# Function        : Exists
401
#
402
# Description     : A class function to determine if a given package is known
403
#                   to the PackageEntry manager. Used to detect multiple package
404
#                   definitions.
405
#
406
#                   The test ignores package versions
407
#                   It is not possible to include different versions of the
408
#                   same package. The test ignores the project part of the
409
#                   version. This allows for
410
#                           sysbasetypes aa.bb.cc.mas and
411
#                           sysbasetypes xx.yy.zz.syd
412
#
413
# Inputs          : $name           - User package name
414
#                   $version        - User version ( with project )
415
#
416
# Returns         : True: Package exists
417
#
418
 
419
sub Exists
420
{
421
    my ($name, $version) = @_;
422
 
423
    $version =~ m~(\d+\.\d+\.\d+)\.(\w+)~ ;
424
    my $vnum = $1 || $version;
425
    my $proj = $2 || '';
426
 
427
    return exists( $PackageDefined{$name}{$proj} );
428
}
429
 
430
#-------------------------------------------------------------------------------
431
# Function        : GetPackageList
432
#
433
# Description     : A class function to return a list of packages
434
#                   The list cannot be used directory. It is really a set of
435
#                   keys to an internal data structure.
436
#
437
#                   The result can be used to iterate over the list of packages
438
#                   using other functions.
439
#
440
# Inputs          : None
441
#
442
# Returns         : An array of package tags
443
#                   The array is ordered by package definition order
444
#
445
sub GetPackageList
446
{
447
    return @PackageList;
448
}
449
 
450
#-------------------------------------------------------------------------------
451
# Function        : GetPackageData
452
#
453
# Description     : A class function to return specific data for a given package
454
#
455
# Inputs          : $tag        - An iteration tag provided by GetPackageList()
456
#
457
# Returns         : A list of
458
#                       Package name
459
#                       Package version
460
#                       Package type : build or link
461
#
462
sub GetPackageData
463
{
464
    my ($tag) = @_;
465
    my $rec = $DescPkgCache{$tag};
466
    return $rec->{UNAME}, $rec->{UVERSION}, $rec->{type};
467
}
468
 
469
#-------------------------------------------------------------------------------
470
# Function        : GetPackageVersionList
471
#
472
# Description     : A class function to return a list of package names as used
473
#                   to generate version strings
474
#
475
#
476
# Inputs          : None
477
#
478
# Returns         : An array of version list entries
479
#                   Each element of the form: "name (version)"
480
#
481
sub GetPackageVersionList
482
{
483
    my @list;
484
    foreach my $tag ( @PackageList )
485
    {
486
        my $rec = $DescPkgCache{$tag};
487
        push @list, "$rec->{UNAME} ($rec->{UVERSION})";
488
    }
489
 
490
    return @list;
491
}
492
 
493
### End of package: PackageEntry
494
 
495
1;
496