Subversion Repositories DevTools

Rev

Rev 4728 | Details | Compare with Previous | Last modification | View Log | RSS feed

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