Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
263 dpurdie 1
########################################################################
2
# Copyright (C) 2008 ERG Limited, All rights reserved
227 dpurdie 3
#
4
# Module name   : makeif.pl
263 dpurdie 5
# Module type   : JATS Internal
6
# Compiler(s)   : Perl
7
# Environment(s): JATS
227 dpurdie 8
#
263 dpurdie 9
# Description   : This modules builds the interface object
10
#
227 dpurdie 11
#                       *** DO NOT DETAB ***
12
#
263 dpurdie 13
#......................................................................#
14
 
15
use strict;
16
use warnings;
17
 
227 dpurdie 18
#
263 dpurdie 19
#   System Globals
20
#   Declared to avoid compile errors
227 dpurdie 21
#
263 dpurdie 22
our $ScmVersion;
23
our $ScmTargetHost;
24
our @TESTPROJECT_TO_ARUN;
25
our @TESTPROJECT_TO_URUN;
26
our $ToolsetPROJECT_type;
227 dpurdie 27
 
28
###############################################################################
29
#   MakeInterface ---
30
#       Interface framework
31
#
32
#   Push                Push a package into the interface stack.
33
#   Factory             Build a interface.
34
#   Load                Loads the specified interface
35
#...
36
 
37
package MakeIf;
38
 
39
use strict;
40
use warnings;
41
 
42
our (@IfStack)              = ();               # interface stack
43
 
44
 
45
sub Push
46
{
47
    ::Debug( "MakeIf::Push( @_ )" );
48
    push (@IfStack, @_);                        # push onto stack
49
}
50
 
51
 
52
sub Factory
53
{
54
    sub Unroll
55
    {
56
        my ($stack) = @_;                       # current
57
        my ($package, $base, $self);
58
 
59
        $package = shift(@$stack);              # base class
60
        ::Error( "Interface -- base-class $package cannot Spawn." )
61
            unless( $package->can( "Spawn" ));
62
 
63
        $self = $package->Spawn();
64
 
65
        while (scalar(@$stack))
66
        {                                       # child
67
            my ($has_constructor);
68
 
69
            $base = $package;
70
            $package = shift(@$stack);
71
 
72
            no strict 'refs';
73
 
74
            ::Warning( "Interface --- base package $base is empty." )
75
                unless (%{"$base\::"});
76
 
77
            $has_constructor = $package->can( "Constructor" );
78
 
79
            push @{"$package\::ISA"}, $base;    # inherit class(es)
80
            bless ($self, $package);            # consecrate
81
 
82
            $self->Constructor()                # 'local' constructor
83
                if ($has_constructor);
84
        }
85
 
86
        return ($self);
87
    }
88
 
89
    my (@stack) = @IfStack;                     # clone stack
90
    my ($self);
91
 
92
    ::Error( "Interface -- object stack empty." )
93
        if ( ! scalar (@stack) );
94
    $self = Unroll( \@stack) ||
95
        ::Error( "Interface --- cannot build interface object." );
96
    return $self;
97
}
98
 
99
 
100
sub Load
101
{
102
    my ($dpackage, $dir, $root, $project) = @_;
103
    my ($package, $template, $cfgfile, $pkgfile, $code);
104
 
105
    #
106
    #   The code will not work if dpackage has a "-" in it
107
    #   Replace nasty characters with nice ones
108
    #
109
    $project = '' unless ( $project );
110
    $dpackage =~ s~-~_~g;
111
    $package = $dpackage . "_" . $project . "_DPACKAGE";
112
    $pkgfile = $dir . "/DPACKAGE";
113
    $cfgfile = $dir . "/DPACKAGE.CFG";
114
 
115
    $template = (<< '__END_OF_DPACKAGE_TEMPLATE__');
116
########################################################################
117
#
118
#   DPACKAGE Template -- version (1.x)
119
#
120
#       Version         State interface version requirements.
121
#       Using           Using statement.
122
#       Needs           Pre-req
123
#       Interface       Push onto the interface stack.
124
#       Self            Our reference.
125
#       Package         Package name.
126
#       Name            Name of perl package.
127
#       Root            Root directory of our installation.
128
#       Debug           General purpose debug output.
129
#..
130
package __PACKAGE__;
131
 
132
use strict;
133
use warnings;
134
 
135
our $VERSION='1.00';                            # Template version
136
our $SelfReference;
137
 
138
DPACKAGE_Initialise();
139
 
140
sub DPACKAGE_Initialise {
141
    my $self = {
142
            PACKAGE     => "__DPACKAGE__",
143
            NAME        => "__PACKAGE__",
144
            ROOT        => "__ROOT__"
145
        };
146
    $SelfReference = bless $self, "__PACKAGE__";
147
}
148
 
149
sub Self                { return $SelfReference; }
150
sub Package             { $SelfReference->{PACKAGE}; }
151
sub Name                { $SelfReference->{NAME}; }
152
sub Root                { $SelfReference->{ROOT}; }
153
sub Interface           { MakeIf::Push( "__PACKAGE__" ); }
154
sub Debug               { ::Debug @_; }
155
sub Debug2              { ::Debug2 @_; }
156
sub Debug3              { ::Debug3 @_; }
157
 
158
 
159
sub Version
160
{
161
    my ($major, $minor) = @_;
162
 
163
    ::Error( "DPACKAGE $SelfReference->{PACKAGE} requires Version($major,$minor)" )
164
        if ($major != 1 || $minor != 0);
165
}
166
 
167
 
168
sub Using
169
{
170
    my ($using) = @_;
171
    $SelfReference->{USING} = $using;
172
}
173
 
174
 
175
sub Needs
176
{
177
    my ($name, $version) = @_;
178
 
179
    #   TODO - statement of DPACKAGE prereqs.
180
    #
181
    #   name                Package name
182
    #
183
    #   Version [optional]
184
    #       =xx.xx.xx       Absolute
185
    #       >=xx.xx.xx      Greater or equal.  Where xx respresents
186
    #                       either, * or missing.
187
    #...
188
}
189
 
190
 
191
sub IncDir
192
{
193
    #TODO
194
}
195
 
196
 
197
sub LibDir
198
{
199
    #TODO
200
}
201
 
202
 
203
sub Libraries
204
{
205
    my ($caller, $file, $line) = caller();
206
 
207
    ::Error( "$SelfReference->{PACKAGE} ($line) requires Using()" )
208
        if ( ! defined( $SelfReference->{USING} ) );
209
 
210
    MakeIf::Libaries( $SelfReference->{USING}, @_ );
211
}
212
 
213
###########################################################################
214
#   -END-
215
#
216
__END_OF_DPACKAGE_TEMPLATE__
217
 
218
    $template =~ s/__PACKAGE__/$package/g;      # preprocess template
219
    $template =~ s/__DPACKAGE__/$dpackage/g;
220
    $template =~ s/__ROOT__/$root/g;
221
 
222
    if ( -e $cfgfile )
223
    {
224
        open(CFGFILE, $cfgfile) ||
225
            ::Error( "cannot open '$cfgfile'" );
226
        $code .= "# line 1 ".$cfgfile."\n";     # name the image
227
        while (<CFGFILE>) {
228
            $code .= $_;                        # slurp text
229
        }
230
        close (CFGFILE);
231
    }
232
 
233
    open(PKGFILE, $pkgfile) ||
234
        ::Error( "cannot open '$pkgfile'" );
235
    $code .= "# line 1 ".$pkgfile."\n";         # name the image
236
    while (<PKGFILE>) {
237
        $code .= $_;                            # slurp text
238
    }
239
    close (PKGFILE);
240
 
241
    eval "# line 1 \"DPACKAGE_TEMPLATE\"\n".    # name the image
242
         "$template";                           # .. template code
243
    die $@ if ($@);
244
 
245
    eval "package $package;\n".
246
         "use strict;\n".
247
         "use warnings;\n".
248
         "$code";                               # .. user code
249
    die $@ if ($@);
250
}
251
 
252
 
253
###############################################################################
254
#   DPACKAGE Interface
255
#
256
#       PackageLoad     Load the DPACKAGES for soecified platform(s).
257
#
258
#       PackageDirs     Retrieve the search path for package configuration.
259
#
260
#       LibUsing        Processing Using(XXX) library recipes
261
#
262
#       LibProcess      Apply library ordering rules.
263
#
264
#       ExportDepend    Export a local package dependency list.
265
#..
266
 
267
our (@IfPkgLibaries)        = ();
268
our (%IfPkgOrdering)        =
269
        (
270
            'User'      => '0',                 # User (default)
271
 
272
            'App'       => '3',                 # Application common
273
            'App2'      => '3a',
274
            'App3'      => '3b',
275
            'App4'      => '3c',
276
 
277
            'If'        => '5',                 # Interface
278
            'If2'       => '5a',
279
            'If3'       => '5b',
280
            'If4'       => '5c',
281
 
282
            'Kern'      => '7',                 # Kernel (ie MOS, LMOS)
283
            'Kern2'     => '7a',
284
            'Kern3'     => '7b',
285
            'Kern4'     => '7c',
286
 
287
            'Sys'       => '9',                 # System (ie WIN32, Linux)
288
            'Sys2'      => '9a',
289
            'Sys3'      => '9b',
290
            'Sys4'      => '9c'
291
        );
292
 
293
#
294
#   Provide reverse lookup of the %IfPkgOrdering for error reporting purposes
295
#   It may be slow, but its not used (Often).
296
#
297
sub ClassNumToText
298
{
299
    my (@classes) = @_;
300
    my @result;
301
 
302
    foreach my $class ( @classes )
303
    {
304
        my $result = "Unknown Class($class)";
305
        foreach ( keys %IfPkgOrdering )
306
        {
307
            if ( $IfPkgOrdering{$_} eq $class )
308
            {
309
                $result = $_;
310
                last;
311
            }
312
        }
313
        push @result, $result;
314
    }
315
    return @result;
316
}
317
 
318
 
319
sub PackageLoad
320
{
321
    my ($platform) = @_;
322
 
323
    return if ( !defined(%::ScmBuildPkgRules) );# configuration available
324
 
325
    my $pPlatform = $::ScmBuildPkgRules{$platform};
326
 
327
    foreach my $package ( @{$pPlatform} )
328
    {
329
        if ( defined( $package->{'CFGDIR'} ) )
330
        {
331
            my ($dir) = $package->{'ROOT'}.$package->{'CFGDIR'};
332
 
333
            if ( -e "$dir/DPACKAGE" )
334
            {                                   # .. load interface
335
                ::Debug( "Loading $dir/DPACKAGE ($package->{'NAME'}) ..." );
336
 
337
                MakeIf::Load( $package->{'NAME'}, $dir, $package->{'ROOT'}, $package->{'DPROJ'} );
338
            }
339
        }
340
    }
341
}
342
 
343
#-------------------------------------------------------------------------------
344
# Function        : PackageDirs
345
#
346
# Description     : Extend an array of 'search' directories to include
347
#                   'gbe' extension directories located with external toolsets
348
#
349
#                   Scan the package information held in ScmBuildPkgRules
350
#                   and locate 'gbe' directories.
351
#
352
# Inputs          : $dirs       - Ref to an array to extend
353
#                   @platforms  - A list of platforms to scan
354
#
355
# Returns         : Nothing
356
#
357
sub PackageDirs
358
{
359
    my ($dirs, @platforms) = @_;
360
 
361
    if ( defined(%::ScmBuildPkgRules) )
362
    {
363
        for my $platform (@platforms)
364
        {
365
            my $pPlatform = $::ScmBuildPkgRules{$platform};
366
 
367
            foreach my $package ( @$pPlatform )
368
            {
369
                push @$dirs, $package->{'ROOT'}.$package->{'CFGDIR'}
370
                    if ( defined( $package->{'CFGDIR'} ) );
371
            }
372
        }
373
    }
374
}
375
 
376
 
377
sub Libaries
378
{
379
    my ($using, $platforms, @libs) = @_;
380
    my ($recipe) =
381
        {
382
            USING   => "$using",
383
            LIBS    => [ @libs ],
384
        };
385
 
386
    ::Debug2( "Makeif::Libraries($using, $platforms, @libs)" );
387
 
388
    return if ( ! ::ActivePlatform($platforms) );
389
 
390
    push @IfPkgLibaries, $recipe;
391
}
392
 
393
 
394
#private
395
sub LibUsing
396
{
397
    my ($caller, $args, $libs) = @_;
398
    my ($using, @args) = split( ',', $args );
399
 
400
    ::Debug2( "Makeif::LibUsing($caller->$args)" );
401
 
402
# Global arguments (if any)
403
#
404
#   ie. --Using(XXX)[,--NoWarn][,--ifdef USING_XXX]
405
#
406
    my ($x_nowarn, $x_conds) = (0, 0);
407
 
408
    foreach (@args) {
409
        if ( /^--NoWarn$/ ) {                   # .. disable warnings
410
            $x_nowarn = 1;
411
 
412
        } elsif ( /^--if(.*)$/ ) {              # .. conditional(s)
413
            $x_conds .= "," if ($x_conds);
414
            $x_conds .= $_;
415
 
416
        } else {
417
            ::Warning( "$caller->Using($using), unknown option '$_'" );
418
        }
419
    }
420
 
421
# Library list
422
#
423
    my ($found) = 0;
424
 
425
    foreach my $recipe (@IfPkgLibaries)
426
    {
427
        if ( $recipe->{USING} eq $using )
428
        {
429
            my ($arg, $deforder, $defallowdup, $defnowarn, @defconds);
430
 
431
        # Record matchs and then stop any loop conditions
432
            $found++;
433
 
434
            if ( $recipe->{COOKED} ) {
435
                ::Warning( "$caller->Using($using) causes loop, ignored" );
436
                next;
437
            }
438
 
439
        # Parse Using arguments
440
            $deforder = "User";                 # default "class"
441
            $defallowdup = 0;
442
            $defnowarn = 0;
443
 
444
            foreach (@{$recipe->{LIBS}})
445
            {
446
            # Locally processed switches (global/default settings)
447
            #
448
                if ( /^--DefOrder=(.*)$/ ) {
449
                    $deforder = $1;             # Sort using name
450
                    next;
451
                }
452
                if ( /^--DefAllowDup$/ ) {
453
                    $defallowdup = 1;
454
                    next;
455
                }
456
                if ( /^--DefNoWarn$/ ) {
457
                    $defnowarn = 1;
458
                    next;
459
                }
460
 
461
                if ( /^--DefCond\((.*)\)$/ ) {
462
                    my (@conds) = split( ',', $1 );
463
 
464
                    @defconds = ();
465
                    foreach (@conds) {
466
                        Error( "Invalid --DeCond argument '$_' " )
467
                            if ( ! /^--if/ );
468
                        push @defconds, $_;
469
                    }
470
                    next;
471
                }
472
 
473
            # Handle indirections
474
            #
475
                if ( /^--Using\((.*)\)(.*)$/ )
476
                {                               # recurse
477
                    my ($x_using);
478
 
479
                    $x_using  = "$1";
480
                    $x_using .= ",$x_conds"     if ( $x_conds );
481
                    $x_using .= "$2";
482
 
483
                    $recipe->{COOKED}++;
484
                    LibUsing( $using, $x_using, $libs );
485
                    $recipe->{COOKED}--;
486
                    next;
487
                }
488
 
489
            # Libraries and arguments
490
            #
491
                if ( /^-[lL].*/ )
492
                {                               # Library
493
                    my ($order, $allowdup, $nowarn, @conds) =
494
                        ($deforder, $defallowdup, $defnowarn, @defconds);
495
                    my (@args) = split( ',', $_ );
496
 
497
                    foreach (@args) {
498
                        if ( /^-([lL])(.*)/ ) {
499
                            $arg = $_;
500
                        } elsif ( /^--Order=(.*)/ ) {
501
                            $order = $1;
502
                        } elsif ( /^--AllowDup$/ ) {
503
                            $allowdup = 1;
504
                        } elsif ( /^--NoAllowDup$/ ) {
505
                            $allowdup = 0;
506
                        } elsif ( /^--NoWarn$/ ) {
507
                            $nowarn = 1;
508
                        } elsif ( /^--Warn$/ ) {
509
                            $nowarn = 0;
510
                        } elsif ( /^--if/ ) {
511
                            push @conds, $_;
512
                        } else {
513
                            $arg .= $_;         # unknown
514
                        }
515
                    }
516
 
517
                    $arg .= ",--Order=$order"       if ( $order );
518
                    $arg .= ",--NoWarn"             if ( $nowarn );
519
                    $arg .= ",--AllowDup"           if ( $allowdup );
520
                    $arg .= ",$x_conds"             if ( $x_conds );
521
                    $arg .= ",". join(',', @conds)  if ( @conds );
522
                }
523
                else
524
                {                               # other options etc
525
                    $arg = $_;
526
                }
527
 
528
                push @$libs, $arg;              # push cooked argument
529
            }
530
        }
531
    }
532
 
533
    ::Warning( "$caller->Using($using), module not found" )
534
        unless ( $found || $x_nowarn );
535
}
536
 
537
 
538
sub LibProcess
539
{
540
    my ($libs) = @_;
541
    my (@newlibs, @ordered_newlibs);
542
    my ($order, @cond, %librecipes, %libstatus);
543
 
544
    #
545
    #   Only process the library specification if arguments/attributes
546
    #   are encountered .. compat with older makefile's.
547
    #
548
    my ($attrs) = 0;
549
 
550
    #   use Data::Dumper;
551
    #   $Data::Dumper::Purity = 1;
552
    #   ::Debug "# Uncooked library list";
553
    #   ::Debug Dumper( $libs );
554
 
555
    $order = 1;                                 # physical order start @ 1
556
    @cond = ();
557
 
558
    foreach (@$libs)
559
    {
560
        my ($libname, $class, $fdup, $fnowarn, @params);
561
 
562
        $libname = "";                          # library name and class
563
        $class = "User";                        # deafult class
564
        $fdup = 0;                              # default, remove duplicates
565
        $fnowarn = 0;
566
 
567
        if ( /^--if(.*)/ )
568
        {                                       # Conditional (for next)
569
            ::Warning( "Stray --if '$1' within library specification -- ignored" )
570
                if ( @cond );
571
            @cond = ( $_ );
572
            $attrs++;
573
            next;
574
        }
575
 
576
        if ( /^-[lL].*/ )
577
        {                                       # Library
578
            my (@args) = split( ',', $_ );      # split specification
579
 
580
            foreach (@args) {
581
                if ( /^-([lL])(.*)/ ) {         # Library
582
                    if ( $::ScmTargetHost eq "Unix" ) {
583
                        $libname = "lib$2";     # .. prefix lib
584
                        $libname =~ s/^liblib/lib/;
585
                    } else {
586
                        $libname = $2;          # .. just stripped name
587
                    }
588
                    $libname .= "\$(GBE_TYPE)"  # .. append GBE_TYPE
589
                        if ( $1 eq "l" );
590
 
591
                    push @params, $libname;
592
 
593
                } else {                        # Attribute/options
594
                    if ( /^--Order=(.*)/ ) {    # .. sort using 'class'
595
                        if ( exists $IfPkgOrdering{$1} )
596
                        {
597
                            $class = $1;
598
                        }
599
                        else
600
                        {
601
                            ::Warning( "Lib '$libname' has unknown class '$1'" );
602
                        }
603
 
604
 
605
                    } elsif ( /^--AllowDup$/ ) {# .. allow duplicate images
606
                        $fdup = 1;
607
 
608
                    } elsif ( /^--NoWarn$/ ) {  # .. disable warnings
609
                        $fnowarn = 1;
610
 
611
                    } elsif ( /^--if(.*)/ ) {   # .. conditional(s)
612
                        push @cond, $_;
613
 
614
                    } else {                    # .. other "parameters"
615
                        push @params, $_;
616
                    }
617
 
618
                    $attrs++;
619
                }
620
            }
621
 
622
            #
623
            #   Convert text class name to an ordered number to assist in sorting
624
            #
625
            $class = $IfPkgOrdering{ $class };
626
        }
627
        else
628
        {                                       # Anything else
629
            push @params, $_;
630
        }
631
 
632
        my ($recipe) = {
633
                CLASS   => $class,              # logical class, prim key
634
                ORDER   => $order,              # physical order, 2nd key
635
                LIBNAME => $libname,            # library name (if any)
636
                FDUP    => $fdup,               # duplicate flag
637
                FNOWARN => $fnowarn,            # no-warning flag
638
                CONDS   => [ @cond ],           # optional conditional(s)
639
                PARAMS  => [ @params ],         # parameters
640
            };
641
 
642
        push @newlibs, $recipe;                 # push recipe
643
        push @{$librecipes{$libname}}, $recipe  # plus index using $name
644
            if ( $libname ne "" );
645
 
646
        @cond = ();
647
        $order++;
648
    }
649
 
650
    #   ::Debug3 "# Cooked library list";
651
    #   ::Debug3 Dumper( @newlibs );
652
 
653
#   Parse the library list and determine the status and correct
654
#   handling of any duplicate images.
655
#..
656
    foreach my $name (keys %librecipes)
657
    {
658
        if ( scalar( @{$librecipes{$name}} ) > 1 )
659
        {
660
            my ($class, $classerr, $dup, $nowarn);
661
 
662
            foreach my $recipe (@{$librecipes{$name}})
663
            {
664
                $classerr = 1                   # test for conflicts
665
                    if ( defined($class) && $class ne $recipe->{CLASS} );
666
 
667
                $class = $recipe->{CLASS};
668
 
669
                $dup = $recipe->{FDUP}          # accumulate
670
                    if ( !defined($dup) || $recipe->{FDUP} );
671
 
672
                $nowarn = $recipe->{FNOWARN}    # accumulate
673
                    if ( !defined($nowarn) || $recipe->{FNOWARN} );
674
            }
675
 
676
            my ($stat) = {};
677
 
678
            $stat->{SEEN} = 0;
679
            $stat->{DUP} = $dup;
680
            $stat->{NOWARN} = $nowarn;
681
            $stat->{CLASSERR} = 1 if (defined($classerr));
682
            $libstatus{$name} = $stat;
683
        }
684
    }
685
 
686
#   Sort the library list
687
#
688
    @ordered_newlibs =                          # sort by class/order
689
        sort {
690
            ($a->{CLASS} ne "" && $b->{CLASS} ne "" &&
691
                    $a->{CLASS} cmp $b->{CLASS}) ||
692
            $a->{ORDER} <=> $b->{ORDER}
693
        } @newlibs;
694
 
695
    #   ::Debug3 "# Sorted library list";
696
    #   ::Debug3 Dumper( @ordered_newlibs );
697
 
698
#   Now built the final list, removing duplicates (if required)
699
#
700
    @$libs = ();                                # zap libraries
701
 
702
    foreach my $newlib (@ordered_newlibs)
703
    {
704
        my ($name) = $newlib->{LIBNAME};
705
 
706
        if ($attrs && defined($libstatus{$name}))
707
        {                                       # two or more entries
708
            my ($stat) = $libstatus{$name};
709
 
710
            if ( $stat->{SEEN}++ == 0 )
711
            {                                   # first image
712
                if ( ! $stat->{NOWARN} )
713
                {                               # .. warnings ?
714
                    if ( defined($stat->{CLASSERR}) )
715
                    {                           # .. class conflict
716
                        my (@classes);
717
 
718
                        foreach my $recipe (@{$librecipes{$name}}) {
719
                            ::UniquePush( \@classes, $recipe->{CLASS} );
720
                        }
721
                        ::Warning( "Lib '$name' has multiple classes\n\t" .
722
                            ::CommifySeries( ClassNumToText(@classes) ) );
723
                    }
724
 
725
                    my ($count) = scalar( @{$librecipes{$name}} );
726
 
727
                    ::Warning( "Lib '$name' appeared $count times, ".
728
                               "duplicate" . ($count > 2 ? "s":""). " removed" )
729
                        if ($stat->{DUP} == 0);
730
                }
731
            }
732
            else
733
            {                                   # remove duplicate(s) ?
734
                next if ($stat->{DUP} == 0);
735
            }
736
        }
737
 
738
        my ($spec);
739
 
740
        $spec = join( ',', @{$newlib->{PARAMS}} );
741
        $spec .= "\n\t\t" . join( "\n\t\t", @{$newlib->{CONDS}} )
742
            if ( @{$newlib->{CONDS}} );
743
 
744
        push @$libs, $spec;
745
    }
746
 
747
    #   ::Debug "# Final library list";
748
    #   ::Debug Dumper( $libs );
749
}
750
 
751
 
752
sub ExportDepend
753
{
754
    #
755
    #   Create the dependancy data structure
756
    #   Its easier to dump a complete structure
757
    #
758
    my %ScmBuildPkgDepend;
759
    foreach my $platform ( keys %::ScmBuildPkgRules )
760
    {
761
        foreach my $package ( @{$::ScmBuildPkgRules{$platform}} )
762
        {
763
            my %entry;
764
            $entry{NAME}        = $package->{'NAME'};
765
            $entry{VERSION}     = $package->{'VERSION'};
766
            $entry{DNAME}       = $package->{'DNAME'};
767
            $entry{DVERSION}    = $package->{'DVERSION'};
768
            $entry{DPROJ}       = $package->{'DPROJ'};
769
 
770
            push @{$ScmBuildPkgDepend{$platform}}, \%entry;
771
        }
772
    }
773
 
774
 
775
    my $fh = ::ConfigurationFile::New( "DPACKAGE.CFG" );
776
    $fh->Header( "makelib (Version $::ScmVersion)",
777
                                "DPACKAGE configuration file" );
778
    $fh->DumpData(
779
        "# Dependancy list.\n#\n",
780
        "ScmBuildPkgDepend", \%ScmBuildPkgDepend );
781
 
782
    $fh->Close(1);
783
}
784
 
785
 
786
###############################################################################
787
#   BASE_Toolset ---
788
#       Default interface.
789
#
790
#..
791
 
792
package BASE_Toolset;
793
 
794
MakeIf::Push( "BASE_Toolset" );                 # root of object stack
795
 
796
sub Spawn
797
{
798
    my ($obclass) = shift;
799
    my ($class) = ref($obclass) || $obclass;
800
    my ($self) = {};
801
 
802
    ::Debug2( "\tBASE_Toolset->Spawn()" );
803
    bless($self, $class);
804
    return ($self);
805
}
806
 
807
 
808
sub Preprocess
809
{
810
    my ($self) = shift;
811
 
812
    ::Debug2( "BASE_Toolset->Preprocess()" );
813
    ::ToolsetPreprocess()                       # optional toolset interface
814
        if ( defined &::ToolsetPreprocess );
815
}
816
 
817
 
818
sub Postprocess
819
{
820
    my ($self) = shift;
821
 
822
    ::Debug2( "BASE_Toolset->Postprocess()" );
823
    ::ToolsetPostprocess()                      # optional toolset interface
824
        if ( defined &::ToolsetPostprocess );
825
}
826
 
827
 
828
sub CTAGS
829
{
830
    ::ToolsetCTAGS()                            # optional toolset interface
831
        if ( defined &::ToolsetCTAGS );
832
}
833
 
834
 
835
sub CCDepend
836
{
837
    my ($self) = shift;
838
 
839
    ::Debug2( "BASE_Toolset->CCDepend()" );
840
    ::Error ("BASE_Toolset does not support C file dependency generation" )
841
        unless ( defined &::ToolsetCCDepend );
842
    ::ToolsetCCDepend( @_ );                    # toolset
843
}
844
 
845
 
846
sub CXXDepend
847
{
848
    my ($self) = shift;
849
 
850
    ::Debug2( "BASE_Toolset->CXXDepend()" );
851
    ::Error ("BASE_Toolset does not support C++ dependency generation" )
852
        unless ( defined &::ToolsetCXXDepend );
853
    ::ToolsetCXXDepend( @_ );                   # toolset
854
}
855
 
856
 
857
sub CC
858
{
859
    my ($self) = shift;
860
    my ($source, $obj, $pArgs) = @_;
861
 
862
    ::Debug2( "BASE_Toolset->CC($source)" );
863
    ::Error ("BASE_Toolset does not support C compilation" )
864
        unless ( defined &::ToolsetCC );
865
    ::ToolsetCC( @_ );                          # toolset
866
}
867
 
868
 
869
sub CXX
870
{
871
    my ($self) = shift;
872
    my ($source, $obj, $pArgs) = @_;
873
 
874
    ::Debug2( "BASE_Toolset->CXX($source)" );
875
    ::Error ("BASE_Toolset does not support C++ compilation" )
876
        unless ( defined &::ToolsetCXX );
877
    ::ToolsetCXX( @_ );                         # toolset
878
}
879
 
880
 
881
sub AS
882
{
883
    my ($self) = shift;
884
    my ($source, $obj, $pArgs) = @_;
885
 
886
    ::Debug2( "BASE_Toolset->AS($source)" );
887
    ::Error ("BASE_Toolset does not support assembler files" )
888
        unless ( defined &::ToolsetAS );
889
    ::ToolsetAS( @_ );                          # toolset
890
}
891
 
892
 
893
sub EXT
894
{
895
    my ($self) = shift;
896
 
897
    ::Debug2( "BASE_Toolset->EXT()" );
898
    return ::ToolsetEXT( @_ )                   # optional toolset interface
899
        if ( defined &::ToolsetEXT );
900
    return 0;                                   # default not supppored
901
}
902
 
903
 
904
sub AR
905
{
906
    my ($self) = shift;
907
    my ($name, $pArgs, $pObjs) = @_;
908
 
909
    ::Debug2( "BASE_Toolset->AR($name)" );
910
    ::Error ("BASE_Toolset does not support library files" )
911
        unless ( defined &::ToolsetAR );
912
 
913
    ProcessArgs ( "", @_ );                     # Proccess arguments
914
    ::ToolsetAR( @_ );                          # toolset
915
}
916
 
917
 
918
sub ARLINT
919
{
920
    my ($self) = shift;
921
    my ($name, $pArgs, $pObjs) = @_;
922
 
923
    my ($lname) = "\$(LIBDIR)/$name\$(GBE_TYPE)";
924
    my ($ltarget) = "lib_$name\_lint";
925
    my (@LIBCSRC, @LIBCXXSRC) = ();
926
    my ($srcfile) = "";
927
 
928
    ::Debug2( "BASE_Toolset->ARLINT($name)" );
929
    ::Error ("BASE_Toolset does not support library files" )
930
        unless ( defined &::ToolsetAR );
931
 
932
    foreach (@$pObjs) {
933
        $_ =~ s/^\$\(OBJDIR\)\///g;             # remmove OBJDIR
934
 
935
        if ( ($srcfile = $::OBJSOURCE{ $_ }) )
936
        {
937
            my( $quoted_srcfile ) = quotemeta( $srcfile );
938
 
939
            if ( grep /^$quoted_srcfile$/, @::CSRCS ) {
940
                push( @LIBCSRC, $srcfile );
941
 
942
            } elsif ( grep /^$quoted_srcfile$/, @::CXXSRC ) {
943
                push( @LIBCXXSRC, $srcfile );
944
 
945
            }
946
        }
947
    }
948
 
949
    ::MakePrint(  "
950
#.. Lint library ($name)
951
 
952
.PHONY:		$ltarget
953
$ltarget:	LIBBASE = $name
954
$ltarget:	LIBNAME = $lname
955
" );
956
 
957
    ::MakeDefEntry ( "$ltarget:","LIBCSRC =", \@LIBCSRC );
958
    ::MakeDefEntry ( "$ltarget:","LIBCXXSRC =", \@LIBCXXSRC );
959
 
960
    if ( defined ( &::ToolsetARLINT ) ) {
961
        ::MakePrint( "$ltarget:" );
962
        ::ToolsetARLINT( $name, $pArgs, $pObjs, $ltarget, \@LIBCSRC, \@LIBCXXSRC );
963
 
964
    } else {
965
        ::MakePrint( "$ltarget:	\
966
	\@echo [\$(LIBNAME)] linting not supported..\n" );
967
    }
968
 
969
    ::MakePrint( "\n" );
970
}
971
 
972
 
973
sub ARMerge
974
{
975
    my ($self) = shift;
976
    my ($name, $pArgs, $pLibs) = @_;
977
 
978
    ::Debug2( "BASE_Toolset->ARMERGE($name)" );
979
    ::Error ("BASE_Toolset does not support library file merging" )
980
        unless ( defined &::ToolsetARMerge );
981
    ::ToolsetARMerge( @_ );                     # toolset
982
}
983
 
984
 
985
sub SHLD
986
{
987
    my ($self) = shift;
988
    my ($name, $pArgs, $pObjs, $pLibs) = @_;
989
    my ($i);
990
 
991
    ::Debug2( "BASE_Toolset->SHLD($name)" );
992
    ::Error ("BASE_Toolset does not support shared libraries" )
993
        unless ( defined &::ToolsetSHLD );
994
 
995
    ProcessArgs ( 'Using', @_ );                # Proccess arguments
996
 
997
    MakeIf::LibProcess( $pLibs );               # cook libraries
998
 
999
    ::Debug3( " args: @$pArgs" );
1000
    ::Debug3( " objs: @$pObjs" );
1001
    ::Debug3( " libs: @$pLibs" );
1002
 
1003
    ::ToolsetSHLD( @_ );                        # toolset
1004
}
1005
 
1006
 
1007
sub SHLDLINT
1008
{
1009
    my ($self) = shift;
1010
    my ($name, $pArgs, $pObjs, $pLibs) = @_;
1011
 
1012
    my ($lname) = "\$(LIBDIR)/$name\$(GBE_TYPE)";
1013
    my ($ltarget) = "shlib_$name\_lint";
1014
    my (@SHLIBCSRC, @SHLIBCXXSRC) = ();
1015
    my ($srcfile) = "";
1016
 
1017
    ::Debug2( "BASE_Toolset->SHLDLINT($name)" );
1018
    ::Error ("BASE_Toolset does not support shared libraries" )
1019
        unless ( defined &::ToolsetSHLD );
1020
 
1021
    foreach (@$pObjs) {
1022
        $_ =~ s/^\$\(OBJDIR\)\///g;             # remmove OBJDIR
1023
 
1024
        if ( ($srcfile = $::OBJSOURCE{ $_ }) )
1025
        {
1026
            my( $quoted_srcfile ) = quotemeta( $srcfile );
1027
 
1028
            if ( grep /^$quoted_srcfile$/, @::CSRCS ) {
1029
                push( @SHLIBCSRC, $srcfile );
1030
 
1031
            } elsif ( grep /^$quoted_srcfile$/, @::CXXSRC ) {
1032
                push( @SHLIBCXXSRC, $srcfile );
1033
 
1034
            }
1035
        }
1036
    }
1037
 
1038
    ::MakePrint(  "
1039
#.. Lint shared library ($name)
1040
 
1041
.PHONY:		$ltarget
1042
$ltarget:	SHLIBBASE = $name
1043
$ltarget:	SHLIBNAME = $lname
1044
" );
1045
 
1046
    ::MakeDefEntry ( "$ltarget:","SHLIBCSRC =", \@SHLIBCSRC );
1047
    ::MakeDefEntry ( "$ltarget:","SHLIBCXXSRC =", \@SHLIBCXXSRC );
1048
 
1049
    if ( defined ( &::ToolsetSHLDLINT ) ) {
1050
        ::MakePrint( "$ltarget:" );
1051
        ::ToolsetSHLDLINT( $name, $pArgs, $pObjs, $pLibs, $ltarget, \@SHLIBCSRC, \@SHLIBCXXSRC );
1052
 
1053
    } else {
1054
        ::MakePrint( "$ltarget:	\
1055
	\@echo [\$(SHLIBNAME)] linting not supported..\n" );
1056
    }
1057
 
1058
    ::MakePrint( "\n" );
1059
}
1060
 
1061
 
1062
sub LD
1063
{
1064
    my ($self) = shift;
1065
    my ($name, $pArgs, $pObjs, $pLibs) = @_;
1066
    my ($i);
1067
 
1068
    ::Debug2( "BASE_Toolset->LD($name)" );
1069
    ::Error ("BASE_Toolset does not support program generation" )
1070
        unless ( defined &::ToolsetLD );
1071
 
1072
    ProcessArgs ( 'Using', @_ );                 # Proccess arguments
1073
 
1074
    MakeIf::LibProcess( $pLibs );               # cook libraries
1075
 
1076
    ::Debug3( " args: @$pArgs" );
1077
    ::Debug3( " objs: @$pObjs" );
1078
    ::Debug3( " libs: @$pLibs" );
1079
 
1080
    ::ToolsetLD( @_ );                          # toolset
1081
}
1082
 
1083
 
1084
sub LDLINT
1085
{
1086
    my ($self) = shift;
1087
    my ($name, $pArgs, $pObjs, $pLibs) = @_;
1088
 
1089
    my ($pname) = "\$(BINDIR)/$name";
1090
    my ($ptarget) = "prog_$name\_lint";
1091
    my (@PROGCSRC, @PROGCXXSRC) = ();
1092
    my ($srcfile) = "";
1093
 
1094
    ::Debug2( "BASE_Toolset->LDLINT($name)" );
1095
    ::Error ("BASE_Toolset does not support program generation" )
1096
        unless ( defined &::ToolsetLD );
1097
 
1098
    foreach (@$pObjs) {
1099
        $_ =~ s/^\$\(OBJDIR\)\///g;             # remmove OBJDIR
1100
 
1101
        if ( ($srcfile = $::OBJSOURCE{ $_ }) )
1102
        {
1103
            my( $quoted_srcfile ) = quotemeta( $srcfile );
1104
 
1105
            if ( grep /^$quoted_srcfile$/, @::CSRCS ) {
1106
                push( @PROGCSRC, $srcfile );
1107
 
1108
            } elsif ( grep /^$quoted_srcfile$/, @::CXXSRC ) {
1109
                push( @PROGCXXSRC, $srcfile );
1110
 
1111
            }
1112
        }
1113
    }
1114
 
1115
    ::MakePrint(  "
1116
#.. Lint program ($name)
1117
 
1118
.PHONY:		$ptarget
1119
$ptarget:	PROGBASE = $name
1120
$ptarget:	PROGNAME = $pname
1121
" );
1122
 
1123
    ::MakeDefEntry ( "$ptarget:","PROGCSRC =", \@PROGCSRC );
1124
    ::MakeDefEntry ( "$ptarget:","PROGCXXSRC =", \@PROGCXXSRC );
1125
 
1126
    if ( defined ( &::ToolsetLDLINT ) ) {
1127
        ::MakePrint( "$ptarget:" );
1128
        ::ToolsetLDLINT( $name, $pArgs, $pObjs, $pLibs, $ptarget, \@PROGCSRC, \@PROGCXXSRC );
1129
 
1130
    } else {
1131
        ::MakePrint( "$ptarget:	\
1132
	\@echo [\$(PROGNAME)] linting not supported..\n" );
1133
    }
1134
 
1135
    ::MakePrint( "\n" );
1136
}
1137
 
1138
#-------------------------------------------------------------------------------
1139
# Function        : PROJECT
1140
#
1141
# Description     : Invoke the underlying toolset functions to construct a
1142
#                   project
1143
#
1144
# Inputs          : $pProject       - Reference to the project data
1145
#
1146
# Returns         :
1147
#
1148
sub PROJECT
1149
{
1150
    my( $self, $pProject) = @_;
1151
    my $name = $pProject->{name};
1152
 
1153
    ::Debug2( "BASE_Toolset->PROJECT($name)" );
1154
    ::Error ("BASE_Toolset does not support Project generation" )
1155
        unless ( defined &::ToolsetPROJECT );
1156
 
1157
    #
1158
    #   Sanity test the Toolset PROJECT
1159
    #   Only the JAVA toolset will handle ANT projects
1160
    #
1161
    my $ptype = $pProject->{type} ;
1162
    if ( $ptype )
1163
    {
1164
        my $type = $::ToolsetPROJECT_type || '';
1165
        ::Error ("BASE_Toolset does not support Project generation of type: $ptype " )
1166
            unless ( $type eq $ptype );
1167
    }
1168
 
1169
    #
1170
    #   Generate Phony target names
1171
    #   The toolset MUST provide the targets
1172
    #
1173
    ::MakePrint( "PHONY:\tProjectClean_$name\n" );
1174
    ::MakePrint( "PHONY:\tProject_$name\n" );
1175
    ::MakePrint( "PHONY:\tProjectATest_$name\n" ) if ($pProject->{'autotest'});
1176
    ::MakePrint( "PHONY:\tProjectUTest_$name\n" ) if ($pProject->{'unittest'});
1177
    ::MakePrint( "\n" );
1178
 
1179
    #
1180
    #   Projects may be specific to debug or production
1181
    #
1182
    my $conditional;
1183
    $conditional = 'ifeq'  if ($pProject->{'Debug'});
1184
    $conditional = 'ifneq' if ($pProject->{'Prod'});
1185
    if ( $conditional )
1186
    {
1187
        ::MakePrint( "$conditional \"\$(DEBUG)\" \"1\"\n" );
1188
    }
1189
 
1190
    #
1191
    #   Invoke toolset specific function to create the desired targets
1192
    #
1193
    ::ToolsetPROJECT( $pProject->{name},
1194
                      $pProject->{project},
1195
                      $pProject->{options},
1196
                      $pProject->{'autotest'},
1197
                      $pProject->{'unittest'},
1198
                      $pProject->{'generated'}
1199
                       );
1200
 
1201
    #
1202
    #   Complete any conditional process
1203
    #
1204
    if ( $conditional )
1205
    {
1206
        ::MakePrint( "else\n\n" );
1207
        ::MakePrint( "ProjectClean_$name:\n" );
1208
        ::MakePrint( "Project_$name:\n" );
1209
        ::MakePrint( "ProjectATest_$name:\n" ) if ($pProject->{'autotest'});
1210
        ::MakePrint( "ProjectUTest_$name:\n" ) if ($pProject->{'unittest'});
1211
        ::MakePrint( "\nendif\n" );
1212
    }
1213
 
1214
    #
1215
    #   If this project does contain a unit test, then the name of the target
1216
    #   that will run the unit test must be added to a list
1217
    #
1218
    push @::TESTPROJECT_TO_ARUN, "ProjectATest_$name" if ($pProject->{'autotest'});
1219
    push @::TESTPROJECT_TO_URUN, "ProjectUTest_$name" if ($pProject->{'unittest'});
1220
}
1221
 
1222
 
1223
#-------------------------------------------------------------------------------
1224
# Function        : TESTFRAMEWORK
1225
#
1226
# Description     : Invoke the underlying toolset functions to construct a
1227
#                   Test Frame Work
1228
#
1229
#                   Done by manipulating entries in the HASH that is passed
1230
#                   into the FrameWork Support functionn
1231
#
1232
# Inputs          : $pEntry       - Reference to the test data
1233
#
1234
# Returns         :
1235
#
1236
sub TESTFRAMEWORK
1237
{
1238
    my( $self, $pEntry, @args) = @_;
1239
    my $name = $pEntry->{framework};
1240
    my $fnc = 'ToolsetTESTFRAMEWORK_'. uc($name);
1241
    my $fref = UNIVERSAL::can ( '::main', $fnc );
1242
    ::Debug2( "BASE_Toolset->TestFrameWork($name)" );
1243
    ::Error ("BASE_Toolset does not support Test Frame Work generation: $name" )
1244
        unless ( $fref );
1245
 
1246
    &$fref( $pEntry, @args );          # Invoke the Function
1247
}
1248
 
1249
#sub LDUsing
1250
#{
1251
#    my ($self) = shift;
1252
#    my ($using, $name, $isshared, $pObjs, $pLibs) = @_;
1253
#
1254
#    ::Debug2( "BASE_Toolset->LDUsing($using, $isshared, $name)" );
1255
#
1256
#    MakeIf::LibUsing( $name, $using, $pLibs );
1257
#}
1258
 
1259
#-------------------------------------------------------------------------------
1260
# Function        : ProcessArgs
1261
#
1262
# Description     : Process arguments for the program and library building commands
1263
#                   Processes options:
1264
#                       --Using(XXX),[options]
1265
#                       --Exclude(XXX,XXX,XXX)
1266
#                       --ExcludeLIB(XXX,XXX,XXX)
1267
#
1268
# Inputs          : $mode       - Using == Allow 'Using'
1269
#                   $name       - Name of the program/library
1270
#                   $pArgs      - Ref to an array of arguments
1271
#                   $pObjs      - Ref to an array of objects
1272
#                   $pLibs      - Ref to an array of libraries (Optional)
1273
#
1274
#                   Note: Argument order to assist caller
1275
#
1276
# Returns         : Nothing directly
1277
#                   Massages arrays directly
1278
#
1279
sub ProcessArgs
1280
{
1281
    my ($mode, $name, $pArgs, $pObjs, $pLibs) = @_;
1282
    ::Debug2( "BASE_Toolset->ProcessArgs(@$pArgs)" );
1283
 
1284
    my @rArgs;
1285
 
1286
    my $i;
1287
    for ($i = 0; $i < scalar @$pArgs; $i++)
1288
    {
1289
        $_ = $pArgs->[$i];
1290
 
1291
        if ( $mode && /^--Using\((.*)\)(.*)$/)  # --Using(XXX)[,options]
1292
        {
1293
            MakeIf::LibUsing( $name, "$1$2", $pLibs );
1294
 
1295
#::DebugDumpData("IfPkgLibaries",\@IfPkgLibaries );
1296
#::DebugDumpData("pLibs",\$pLibs );
1297
        }
1298
        elsif (/^--Exclude\((.*)\)$/)           # --Exclude(Obj,Obj...)
1299
        {
1300
            #
1301
            #   Exclude specified object files
1302
            #   Note: Maintain the order of the object files
1303
            #
1304
            my %exclude;
1305
            my @retain = ();
1306
 
1307
            @exclude{split( ',', $1 )} = ();
1308
 
1309
            foreach (@$pObjs)
1310
            {
1311
                (my $objfile = $_) =~ s~.*/~~;  # Remove Shared lib object directory
1312
 
1313
                push @retain, $_
1314
                    unless (exists $exclude{$objfile} );
1315
            }
1316
            @$pObjs = @retain;
1317
            ::Debug3( "BASE_Toolset->ProcessArgs. OBJS: @retain)" );
1318
        }
1319
        elsif (/^--ExcludeLib\((.*)\)$/)        # --ExcludeLib(Lib,Lib...)
1320
        {
1321
            #
1322
            #   Exclude specified library files
1323
            #   Note: Maintain the order of the library files
1324
            #
1325
            my %exclude;
1326
            my @retain_libs = ();
1327
 
1328
            @exclude{split( ',', $1 )} = ();
1329
 
1330
            foreach (@$pLibs)
1331
            {
1332
                m~-[Ll]([^,]*)~;                # Extract library name
1333
                my $libfile = $1;
1334
                push @retain_libs, $_
1335
                    unless (exists $exclude{$libfile} );
1336
            }
1337
            @$pLibs = @retain_libs;
1338
            ::Debug3( "BASE_Toolset->ProcessArgs. LIBS: @retain_libs)" );
1339
        }
1340
        else
1341
        {
1342
            #
1343
            #   Unknown option
1344
            #   Retain to be processed later
1345
            #
1346
            push @rArgs, $_;
1347
        }
1348
    }
1349
 
1350
    #
1351
    #   Pass unprocessed arguments back to the user
1352
    #
1353
    @$pArgs = @rArgs;
1354
}
1355
 
1356
1;
1357