Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

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