Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
227 dpurdie 1
########################################################################
7300 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
227 dpurdie 3
#
4
# Module name   : jats.sh
5
# Module type   : Makefile system
6
# Compiler(s)   : n/a
7
# Environment(s): jats build system
8
#
9
# Description   : Provide access to information from the build.pl file as parsed
10
#                 by JATS. This is more complete than the parser in the
11
#                 "BuildFile.pm"
12
#
13
#                 The purpose of this module is to provide an interface
14
#                 between (essentially) internal data structures and user
15
#                 scripts that need to access the data. These are primarily
16
#                 deployment scripts.
17
#
18
#                 The 'All' tag is used for backward compatabilty. It simply
19
#                 exports all the known data structures. NOT to be used by new
20
#                 code.
21
#
22
#
23
#
24
# Interface     : ReadBuildConfig           - Initialise module
25
#                 getPlatformParts          - Get a list of Platform parts
6133 dpurdie 26
#                 
27
#                 PackageEntry - Internal class
28
#                   getUnifiedName
29
#                   getBase
30
#                   getName
31
#                   getVersion
32
#                   getType
33
#                   getDir
34
#                   getLibDirs
35
#                   getIncDirs
227 dpurdie 36
#
37
#......................................................................#
38
 
255 dpurdie 39
require 5.006_001;
227 dpurdie 40
use strict;
41
use warnings;
42
 
43
#===============================================================================
44
package ReadBuildConfig;
45
use JatsError;
46
use JatsMakeInfo qw(:basic);
4324 dpurdie 47
use FileUtils;
227 dpurdie 48
 
49
# automatically export what we need into namespace of caller.
50
use Exporter();
51
our (@ISA, @EXPORT, %EXPORT_TAGS, @EXPORT_OK);
52
@ISA         = qw(Exporter);
53
@EXPORT      = qw(  ReadBuildConfig
54
                    getPlatformParts
55
                    getPackagePaths
271 dpurdie 56
                    getPackageList
4324 dpurdie 57
                    getToolInfo
7300 dpurdie 58
                    testToolInfo
6133 dpurdie 59
                    getAliases
7320 dpurdie 60
                    isGenericBuild
227 dpurdie 61
                );
62
@EXPORT_OK =  qw(   $InterfaceVersion
63
                    $ScmBuildMachType
64
                    $ScmInterfaceVersion
65
                    $ScmBuildName
66
                    $ScmBuildPackage
67
                    $ScmBuildVersion
68
                    $ScmBuildProject
69
                    $ScmBuildVersionFull
70
                    $ScmBuildPreviousVersion
71
                    $ScmSrcDir
72
                    $ScmLocal
73
                    $ScmDeploymentPatch
74
                    $ScmBuildSrc
75
                    $ScmExpert
261 dpurdie 76
                    $ScmAll
4003 dpurdie 77
                    $ScmNoBuild
7300 dpurdie 78
                    $ScmBuildUuid
227 dpurdie 79
                    %ScmBuildAliases
80
                    %ScmBuildProducts
81
                    %ScmBuildPlatforms
7310 dpurdie 82
                    %ScmBuildMatrix
227 dpurdie 83
                    %ScmBuildPkgRules
84
                    @BUILDPLATFORMS
85
                    @DEFBUILDPLATFORMS
86
                    @BUILDTOOLSPATH
87
                    %BUILDPLATFORM_PARTS
88
                    %BUILDINFO
247 dpurdie 89
                    %BUILD_KNOWNFILES
227 dpurdie 90
                );
91
 
92
%EXPORT_TAGS = (All => [@EXPORT, @EXPORT_OK]);
93
 
94
#-------------------------------------------------------------------------------
95
#   Global variables
96
#
97
 
98
my $interface;
99
my $platform;
100
 
101
#
102
#   The $InterfaceVersion value is manually maintained
103
#   The integer part should be changed to indicate a incompatible change
104
#   to the JATS files created within the interface directory
105
#
106
#   $InterfaceVersion is treated as a float. The fractional part can be
107
#   used to indicate minor changes to the file format.
108
#
109
our $InterfaceVersion       = "2.0";            # Change will issue error message
110
 
111
#
112
#   The following varaibles are "read" in from the build.cfg file
113
#   In order to access simply access we need to declare them
114
#
115
our %BUILDINFO;
116
our %BUILDPLATFORM_PARTS;
117
our $ScmInterfaceVersion;
118
our %ScmBuildPkgRules;
119
our $ScmBuildMachType;
7320 dpurdie 120
our %ScmBuildMatrix; 
227 dpurdie 121
 
122
#-------------------------------------------------------------------------------
123
# Function        : ReadBuildConfig
124
#
125
# Description     : Read in the build config information
126
#                   Read in build.cfg
127
#
128
# Inputs          : $interface              - Path to the interface directory
129
#                   $platform               - Platform being processed
130
#
7320 dpurdie 131
# Returns         : True - data has been loaded
227 dpurdie 132
#
133
sub ReadBuildConfig
134
{
135
    $interface = shift;
136
    $platform = shift;
137
 
138
    my $no_test;
7320 dpurdie 139
    my $no_error;
227 dpurdie 140
    foreach  ( @_ )
141
    {
142
        if ( m/^--NoTest/i ) {
143
            $no_test = 1;
7320 dpurdie 144
        } elsif ( m/^--NoError/i ) {
145
             $no_error = 1;
227 dpurdie 146
        } else {
147
            Warning ("ReadBuildConfig, Unknown option: $_");
148
        }
149
    }
150
 
7320 dpurdie 151
    unless ($interface) {
152
        WarnError (!$no_error, "ReadBuildConfig. Interface directory is not defined");
153
        return 0;
154
    }
155
 
227 dpurdie 156
    Debug("BuildConfig::Reading config, $interface");
157
    my $cfgfile = "$interface/build.cfg";
7320 dpurdie 158
    unless ( -f $cfgfile ) {
159
        WarnError (!$no_error, "JATS internal file missing. Rebuild required",
160
                                "BuildConfig: Cannot find file: $cfgfile" ) ;
161
        return 0;
162
    }
227 dpurdie 163
 
164
    #
165
    #   Include the build.cfg data
166
    #
167
    require ( $cfgfile );
168
 
169
    #
170
    #   Ensure that the version of the interface files can be consumed
171
    #   The $ScmInterfaceVersion is a written copy of $InterfaceVersion
172
    #
173
    #   Allow build.cfg files that do not have a ScmInterfaceVersion
174
    #   Assume that these are at version 1.0.
175
    #
176
    $ScmInterfaceVersion = '1.0' unless ( $ScmInterfaceVersion );
177
    Debug ("ReadBuildConfig: Version: $ScmInterfaceVersion, Need: $InterfaceVersion");
178
    if ( int($ScmInterfaceVersion) != int($InterfaceVersion)  )
179
    {
7320 dpurdie 180
        WarnError (!$no_error, "JATS interface files are not compatible with this version of JATS",
227 dpurdie 181
               "Rebuild required.",
182
               "Current Interface Version: $ScmInterfaceVersion",
183
               "JATS Interface Version   : $InterfaceVersion" );
7320 dpurdie 184
        return 0;
227 dpurdie 185
    }
186
 
187
    #
188
    #   Ensure that this config file is designed for this machine type
189
    #   At make-time this test may not be valid. It should have been
190
    #   validated before make-time.
191
    #
192
    TestMachType ($ScmBuildMachType, "build.cfg") unless $no_test;
193
 
194
    #
195
    #   Remove some unused data
196
    #   Reduces the size of Makefile.cfg. Speeds up writting
197
    #
198
    if ( $platform )
199
    {
200
        for (keys %::ScmBuildPlatforms)
201
        {
202
            next if ($_ eq $platform );
203
            delete ($::BUILDPLATFORM_PARTS{$_} );
204
            delete ($::BUILDINFO{$_} );
205
            delete ($::ScmBuildPkgRules{$_} );
206
        }
207
    }
208
 
209
    #   dump
210
    #
211
    Debug( "Aliases:" );
369 dpurdie 212
    if ( ! (%::ScmBuildAliases) ) {
227 dpurdie 213
        Debug( "  undefined" );
214
 
215
    } else {
216
        foreach my $key (keys %::ScmBuildAliases) {
217
            my( @value ) = split( ' ', $::ScmBuildAliases{ $key } );
218
            Debug( " $key\t= @value" );
219
        }
220
    }
221
 
222
    Debug( "Products:" );
369 dpurdie 223
    if ( ! (%::ScmBuildProducts) ) {
227 dpurdie 224
        Debug( "  undefined" );
225
 
226
    } else {
227
        foreach my $key (keys %::ScmBuildProducts) {
228
            my( @value ) = split( ',', $::ScmBuildProducts{ $key } );
229
            Debug( " $key\t= @value" );
230
        }
231
    }
232
 
233
    Debug( "Platforms:" );
369 dpurdie 234
    if ( ! (%::ScmBuildPlatforms) ) {
227 dpurdie 235
        Debug( "  undefined" );
236
 
237
    } else {
238
        foreach my $key (keys %::ScmBuildPlatforms) {
239
            my( @args ) = split( /$;/, $::ScmBuildPlatforms{ $key } );
240
            Debug( " $key\t= @args" );
241
        }
242
    }
7320 dpurdie 243
 
244
    return 1;
227 dpurdie 245
}
246
 
247
#-------------------------------------------------------------------------------
7320 dpurdie 248
# Function        : isGenericBuild 
249
#
250
# Description     : Determine if this is a 'GENERIC' build
251
#                   ie: can be built on ANY build machine
252
#
253
# Inputs          : 
254
#
255
# Returns         : TRUE - Is generic
256
#
257
sub isGenericBuild
258
{
259
    return exists $ScmBuildMatrix{'GENERIC'} ? 1 : 0;
260
}
261
 
262
#-------------------------------------------------------------------------------
6133 dpurdie 263
# Function        : getAliases 
264
#
265
# Description     : Return a list of aliases for the current platform
266
#
267
# Inputs          : 
268
#
269
# Returns         : A list of aliases
270
#
271
sub getAliases
272
{
273
    Error ("BuildConfig:getAliases. Not initialised") unless ( $platform );
274
    #
275
    #   Determine the aliases for this target
276
    #       The alias list includes the actual target too
277
    #
278
    my @AliasList;
279
    push @AliasList, $platform;
280
 
281
    if ( exists( $BUILDINFO{$platform}{'ALIAS'} ))
282
    {
283
        push @AliasList, $BUILDINFO{$platform}{'ALIAS'};
284
    }
285
 
286
    if ( exists( $BUILDINFO{$platform}{'USERALIAS'} ))
287
    {
288
        push @AliasList, @{$BUILDINFO{$platform}{'USERALIAS'}};
289
    }
290
 
291
    return @AliasList;
292
}
293
 
294
 
295
#-------------------------------------------------------------------------------
227 dpurdie 296
# Function        : getPlatformParts
297
#
298
# Description     : return a list of platform parts
299
#
300
# Inputs          : None
301
#
302
# Returns         : A list of platform parts to search in the interface
303
#                   directory, local directory or other
304
#
305
sub getPlatformParts
306
{
307
    Error ("BuildConfig. Not initialised") unless ( $platform );
308
    return @{$BUILDINFO{$platform}{PARTS}};
309
}
310
 
311
#-------------------------------------------------------------------------------
312
# Function        : getPackagePaths
313
#
314
# Description     : Return a list of all packages
315
#                   LinkPkgarchive packages will be provided as is
316
#                   BuildPkgArchive packages will be provided as a single
317
#                   reference to the interface directory
318
#
319
# Inputs          : Options
320
#                       --Interface=xxxx            Path to the interface dir
321
#                                                   If provided, then the path
322
#                                                   will be used for the first
323
#                                                   BuildPkgArchive
324
#                       --All                       All paths
325
#                       --Tools                     All Tools Paths
326
#                       --Gbe                       All Gbe paths
327
#
328
# Returns         : An array of paths
329
#
330
sub getPackagePaths
331
{
332
    Error ("BuildConfig. Not initialised") unless ( $platform );
333
 
334
    my $interface;
335
    my $all;
336
    my $need;
337
    my @result;
338
 
339
    #
340
    #   Parse Options
341
    #
342
    foreach ( @_ )
343
    {
344
        if ( m~^--Interface=(.+)~ ) {
345
            $interface = $1;
346
        } elsif ( m~^--All~ ) {
347
            $all = 1;
348
        } elsif ( m~^--Tools~ ) {
349
            $need = 'TOOLDIRS';
350
        } elsif ( m~^--Gbe~ ) {
351
            $need = 'CFGDIR';
352
        } else {
353
            Error ("BuildConfig. Unknown Option: $_");
354
        }
355
    }
356
 
357
    #
311 dpurdie 358
    #   Locate required entries
227 dpurdie 359
    #
360
    for my $entry (@{$ScmBuildPkgRules{$platform} })
361
    {
362
        #
363
        #   Do we need this entry
364
        #   Select tools and gbe entries
365
        #
366
        my @subdirs = '/';
367
        if ( $need )
368
        {
369
            next unless ( exists ($entry->{$need} ) );
370
            my $subdir = $entry->{$need};
371
            if ( ref($subdir) eq 'ARRAY' ) {
372
                @subdirs = @{$subdir};
373
            } else {
374
                @subdirs = $subdir;
375
            }
376
        }
377
 
378
        #
311 dpurdie 379
        #   Skip the Pseudo INTERFACE package if we are processing all packages
380
        #   Skip BuildPkgArchives if we aren't processing all
227 dpurdie 381
        #
311 dpurdie 382
        next if ( ($entry->{'TYPE'} eq 'interface') && $all );
383
        next if ( ($entry->{'TYPE'} eq 'build') && !$all );
384
 
385
        #
386
        #   Select appropriate root
387
        #       Use provided interface path - not too sure why
388
        #       Should be able to simplify this
389
        #
390
        my $dir = $entry->{'ROOT'};
391
        $dir = $interface if ( $entry->{'TYPE'} eq 'interface' );
392
 
393
        foreach my $subdir ( @subdirs )
227 dpurdie 394
        {
311 dpurdie 395
            my $dir = $entry->{'ROOT'} . $subdir;
396
            $dir =~ s~/+~/~g;
397
            $dir =~ s~/+$~~g;
398
            push @result, $dir;
227 dpurdie 399
        }
400
    }
401
 
402
    return @result;
403
}
404
 
271 dpurdie 405
#-------------------------------------------------------------------------------
406
# Function        : getPackageList
407
#
408
# Description     : Returns a list of package entries
4324 dpurdie 409
#                   Only real use of the returned values is to iterate over it
410
#                   and pass the values into other functions within this
271 dpurdie 411
#                   class.
412
#
413
# Inputs          : Nothing
414
#
415
# Returns         : A list of refs to package data
416
#
417
sub getPackageList
418
{
419
    Error ("BuildConfig. Not initialised") unless ( $platform );
420
    my @result;
421
 
422
    foreach ( @ {$ScmBuildPkgRules{$platform} } )
423
    {
424
#        my %self;
425
#        $self{DATA} = $_;
426
        push @result, bless $_, "PackageEntry";
427
    }
428
    return ( @result );
429
}
430
 
4324 dpurdie 431
#-------------------------------------------------------------------------------
7300 dpurdie 432
# Function        : testToolInfo 
4324 dpurdie 433
#
7300 dpurdie 434
# Description     : Test to see if suitable toolInfo exists
435
#                   May be used if the need for the toolInfo is optional
4324 dpurdie 436
#
7300 dpurdie 437
# Inputs          : $toolname       - Tool to locate
438
#                   $error          - True: Error on not found
4324 dpurdie 439
#
7300 dpurdie 440
# Returns         : undefined       - No tool located
441
#                   refToToolEntry  - Used internally
4324 dpurdie 442
#
7300 dpurdie 443
sub testToolInfo
4324 dpurdie 444
{
7300 dpurdie 445
    my ($toolname, $error) = @_;
4324 dpurdie 446
    my $toolroot;
447
    my $toolinfo;
448
    my $pentry;
449
    my @searchPath;
450
 
451
    foreach my $entry ( getPackageList() )
452
    {
453
        my $path = $entry->getBase(2);
454
        Verbose("getToolInfo: $path");
455
        #   Generic
456
        $toolinfo = catdir($path, 'gbe', 'INFO', 'info.' . $toolname . '.generic');
457
        push @searchPath, $toolinfo;
458
        if ( -f $toolinfo )
459
        {
460
            $toolroot = $path;
461
            $pentry = $entry;
462
            last;
463
        }
464
        #   Machine specific
465
        $toolinfo = catdir($path, 'gbe', 'INFO', 'info.' . $toolname . '.'. $ENV{GBE_HOSTMACH});
466
        push @searchPath, $toolinfo;
467
        if ( -f $toolinfo )
468
        {
469
            $toolroot = $path;
470
            $pentry = $entry;
471
            last;
472
        }
473
    }
7300 dpurdie 474
 
475
    unless (defined $toolroot)
4324 dpurdie 476
    {
7300 dpurdie 477
        #   Didn't find the required tool
478
        Error ("Cannot find required tool in any package: $toolname", "Search Path:", @searchPath) if ($error );
479
        return undef ;
480
    }
481
 
482
    #
483
    #   Return user info
484
    #
485
    return ($pentry, $toolroot, $toolinfo) if (wantarray);
486
    return $pentry;
487
}
488
 
489
 
490
#-------------------------------------------------------------------------------
491
# Function        : getToolInfo 
492
#
493
# Description     : Locate and load the tool information for the named tool
494
#
495
# Inputs          : $toolname           - tool to locate
496
#                   ...                 - Optional,Names of fields to expect in the package
497
#                                         If any of the required fields ar missing an error
498
#                                         will be reported
499
#
500
# Returns         : A hash of Tool info
501
#
502
sub getToolInfo
503
{
504
    my ($toolname, @fnames) = @_;
505
    my %data;
506
 
507
    #
508
    #   Check existence and get essential information
509
    #       Will not return if not found
510
    #
511
    my ($pentry, $toolroot, $toolinfo) = testToolInfo ($toolname, 1);
512
 
513
    open (my $DATA, '<', $toolinfo ) || Error("Cannot open tool info file. $!", "File: $toolinfo");
514
    while ( <$DATA> )
515
    {
516
        $_ =~ s~\s+$~~;
517
        next if ( m~^#~ );
518
        next if length($_) < 1;
519
        m~(.*?)\s*=\s*(.*)~;
520
        $data{$1} = $2;
521
    }
522
    close $DATA;
523
    $data{PKGBASE} = $toolroot;
524
    $data{PKGENTRY} = $pentry;
4324 dpurdie 525
#DebugDumpData("Data", \%data);
526
 
7300 dpurdie 527
    #
528
    #   Ensure that the required fields are in the info file
529
    #   These will be a mix of mandatory and user fields
530
    #
531
    my @missing;
532
    for my $fname ('TOOLNAME','TOOLROOT', @fnames)
533
    {
534
        next if defined $data{$fname};
535
        push @missing, $fname;
4324 dpurdie 536
    }
7300 dpurdie 537
    if (@missing)
538
    {
539
        Error("Tool Package '$toolname' is missing required fields:", @missing);
540
    }
541
    return \%data;
4324 dpurdie 542
}
543
 
544
 
271 dpurdie 545
################################################################################
546
#   PackageEntry
547
################################################################################
548
#
549
#   A class to access the data embedded into $ScmBuildPkgRules
550
#   Use a class interface to abstract the data
551
#
552
package PackageEntry;
553
 
554
#-------------------------------------------------------------------------------
555
# Function        : dump
556
#
557
# Description     : Diagnostic Dump of the body of the package entry
558
#
559
# Inputs          : None
560
#
561
# Returns         : None
562
#
563
sub dump
564
{
565
    my $self = shift;
566
    ::DebugDumpData("PackageEntry", $self );
567
}
568
 
569
#-------------------------------------------------------------------------------
5411 dpurdie 570
# Function        : getUnifiedName 
571
#
572
# Description     : Return a Package Name based on PackageName and project suffix
573
#                   Package Name is cleaned up a bit
574
#                       Replace non-alphanumenrics with a '_'
575
#                       Converted to upper case 
576
#
577
# Inputs          : $self
578
#                   $prefix         - Optional Prefix 
579
#                   $suffix         - Optional Suffix 
580
#
581
# Returns         : String
582
#
583
sub getUnifiedName
584
{
585
    my ($self,$prefix,$suffix) = @_;
586
 
587
    my $name = $prefix || '';
588
    $name .= $self->{'DNAME'};
589
    $name .= '_' . $self->{'DPROJ'} if $self->{'DPROJ'};
590
    $name .= $suffix || '';
591
 
592
    $name =~ s~\W~_~g; 
593
    $name =~ s~-~_~g; 
594
    $name =~ tr~_~_~s;
595
    $name = uc $name;
596
    return $name;
597
}
598
 
599
 
600
#-------------------------------------------------------------------------------
271 dpurdie 601
# Function        : getBase
602
#
603
# Description     : Determine the base directory of the package
604
#
605
# Inputs          : $self                   - Class Ref
606
#                   $type                   - 0: Empty
607
#                                             1: abs dpkg_archive
608
#                                             2: May be in the interface
311 dpurdie 609
#                                             3: Interface, LinkPkgs
271 dpurdie 610
#
611
# Returns         : As above
612
#
613
sub getBase
614
{
615
    my ($self, $type ) = @_;
7300 dpurdie 616
    ::Error ("Internal: PackageEntry::getBase called without 'type' argument") unless defined $type;
371 dpurdie 617
 
271 dpurdie 618
    if ( $type == 1 ) {
619
        return $self->{ROOT};
620
    } elsif ( $type == 2 ) {
311 dpurdie 621
        if ( $self->{'TYPE'} eq 'build' ) {
622
            return $interface;
623
        } else {
271 dpurdie 624
            return $self->{ROOT};
625
        }
311 dpurdie 626
    } elsif ( $type == 3 ) {
627
        return if ( $self->{'TYPE'} eq 'build' );
371 dpurdie 628
        return $self->{ROOT};
271 dpurdie 629
    } else  {
630
        return '';
631
    }
632
}
633
 
634
#-------------------------------------------------------------------------------
6133 dpurdie 635
# Function        : getXxxx 
636
#
637
# Description     : Various getters
638
#
639
# Inputs          : $self - Reference to the class 
640
#
641
# Returns         : Value
642
#
643
 
644
sub getName
645
{
646
    my ($self) = @_;
647
    return $self->{NAME};
648
}
649
 
650
sub getVersion
651
{
652
    my ($self) = @_;
653
    return $self->{VERSION};
654
}
655
 
656
sub getType
657
{
658
    my ($self) = @_;
659
    return $self->{TYPE};
660
}
661
 
662
#
663
#   Returns the location of the package.
664
#       This will be a ref into the package store
665
#       Used only if access to dpkg_archive is needed
666
#       Only useful if TYPE is build or link
667
#
668
sub getDir
669
{
670
    my ($self) = @_;
671
    return $self->{ROOT};
672
}
673
 
674
#-------------------------------------------------------------------------------
271 dpurdie 675
# Function        : getLibDirs
676
#
677
# Description     : Return an array of library directories
678
#
679
# Inputs          : $self                   - Class ref
680
#                   $type                   - 0 : Relative to base of the package
681
#                                             1 : abs to the dpkg_archive package
682
#                                             2 : abs to the interface
6133 dpurdie 683
#                                             3 : Interface, LinkPkgs
271 dpurdie 684
#
685
# Returns         : An array
686
#
687
sub getLibDirs
688
{
689
    my ($self, $type ) = @_;
690
    my @result;
691
    my $prefix = getBase( $self, $type );
692
 
693
    foreach ( @{$self->{PLIBDIRS}} )
694
    {
695
        push @result, $prefix . $_;
696
    }
697
    return @result;
698
}
699
 
700
#-------------------------------------------------------------------------------
701
# Function        : getIncDirs
702
#
703
# Description     : Return an array of include directories
704
#
705
# Inputs          : $self                   - Class ref
706
#                   $type                   - 0 : Relative to base of the package
707
#                                             1 : abs to the dpkg_archive package
708
#                                             2 : abs to the interface
311 dpurdie 709
#                                             3: Interface, LinkPkgs
271 dpurdie 710
#
711
# Returns         : An array
712
#
713
sub getIncDirs
714
{
715
    my ($self, $type ) = @_;
716
    my @result;
717
    my $prefix = getBase( $self, $type );
718
 
719
    foreach ( @{$self->{PINCDIRS}} )
720
    {
721
        push @result, $prefix . $_;
722
    }
723
    return @result;
724
}
725
 
227 dpurdie 726
#------------------------------------------------------------------------------
727
1;