Subversion Repositories DevTools

Rev

Rev 299 | Go to most recent revision | Details | 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
#
147
# Inputs          : $dpackage       - Name of the Package containg file to load
148
#                   $dir            - Config directory within the package
149
#                   $root           - Base directory of the package
150
#                   $project        - Package project suffix (optional)
151
#
152
# Returns         : Nothing
153
#
154
sub Load
155
{
156
    my ($dpackage, $dir, $root, $project) = @_;
157
    my ($package, $template, $cfgfile, $pkgfile, $code);
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);
169
    $if->ReadFiles( $dir . "/DPACKAGE.CFG", $dir . "/DPACKAGE" );
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);
316
        }
317
    }
318
 
319
    #
320
    #   Evaluate the code
321
    #
322
    eval "$code";
323
    Error("DPACKAGE Syntax. Package: $SelfReference->{ROOT}", "Err: $@" ) if ($@);
324
}
325
 
326
sub EvaluateText
327
{
328
    my $this = shift;
329
    eval "@_";
330
    Error("DPACKAGE Syntax. Package: $SelfReference->{ROOT}", "Err: $@" ) if ($@);
331
}
332
 
333
###########################################################################
334
#   -END-
335
#
336
__END_OF_DPACKAGE_TEMPLATE__
337
 
338
    $template =~ s/__PACKAGE__/$package/g;      # preprocess template
339
    $template =~ s/__DPACKAGE__/$dpackage/g;
340
 
341
    #
342
    #   Have the template for the class in a text string
343
    #   Create it at run-time
344
    #
345
    my $if = eval "# line 1 \"DPACKAGE_TEMPLATE\"\n".   # name the image
346
         "$template";                                   # .. template code
347
    ::Error("JATS INTERNAL. MakeIf Template", "Err: $@" )
348
        if ($@);
349
    return $if;
350
}
351
 
352
###############################################################################
353
#   DPACKAGE Interface
354
#
355
#       PackageLoad     Load the DPACKAGES for soecified platform(s).
356
#
357
#       PackageDirs     Retrieve the search path for package configuration.
358
#
359
#       LibUsing        Processing Using(XXX) library recipes
360
#
361
#       LibProcess      Apply library ordering rules.
362
#
363
#       ExportDepend    Export a local package dependency list.
364
#..
365
 
366
our %IfPkgLibaries        = ();
367
our %IfPkgOrdering        =
368
        (
369
            'User'      => '0',                 # User (default)
370
 
371
            'App'       => '3',                 # Application common
372
            'App2'      => '3a',
373
            'App3'      => '3b',
374
            'App4'      => '3c',
375
 
376
            'If'        => '5',                 # Interface
377
            'If2'       => '5a',
378
            'If3'       => '5b',
379
            'If4'       => '5c',
380
 
381
            'Kern'      => '7',                 # Kernel (ie MOS, LMOS)
382
            'Kern2'     => '7a',
383
            'Kern3'     => '7b',
384
            'Kern4'     => '7c',
385
 
386
            'Sys'       => '9',                 # System (ie WIN32, Linux)
387
            'Sys2'      => '9a',
388
            'Sys3'      => '9b',
389
            'Sys4'      => '9c'
390
        );
391
 
392
#
393
#   Provide reverse lookup of the %IfPkgOrdering for error reporting purposes
394
#   It may be slow, but its not used (Often).
395
#
396
sub ClassNumToText
397
{
398
    my (@classes) = @_;
399
    my @result;
400
 
401
    foreach my $class ( @classes )
402
    {
403
        my $result = "Unknown Class($class)";
404
        foreach ( keys %IfPkgOrdering )
405
        {
406
            if ( $IfPkgOrdering{$_} eq $class )
407
            {
408
                $result = $_;
409
                last;
410
            }
411
        }
412
        push @result, $result;
413
    }
414
    return @result;
415
}
416
 
417
#-------------------------------------------------------------------------------
418
# Function        : PackageLoad
419
#
420
# Description     : Scan all external packages and locate DPACKAGE files
421
#                   This will (must) be in the JATS config directory (gbe)
422
#
423
#                   Once found they will be loaded into the system
424
#                   This will effectivly extend the base toolset
425
#
426
# Inputs          : $platform               - target platform
427
#                                             Only used to locate packages
428
#                                             Not 'really' used
429
#
430
# Returns         : Nothing
431
#
432
sub PackageLoad
433
{
434
    my ($platform) = @_;
435
    ::Debug ("PackageLoad", @_);
436
 
437
    return if ( !defined(%::ScmBuildPkgRules) );# configuration available
438
 
439
    my $pPlatform = $::ScmBuildPkgRules{$platform};
440
    foreach my $package ( @{$pPlatform} )
441
    {
442
        if ( defined( $package->{'CFGDIR'} ) )
443
        {
444
            my ($dir) = $package->{'ROOT'}.$package->{'CFGDIR'};
445
 
446
            ::Debug( "Examine $dir/DPACKAGE" );
447
            if ( -e "$dir/DPACKAGE" )
448
            {                                   # .. load interface
449
                ::Debug( "Loading $dir/DPACKAGE ($package->{'NAME'}) ..." );
450
 
451
                MakeIf::Load( $package->{'NAME'}, $dir, $package->{'ROOT'}, $package->{'DPROJ'} );
452
            }
453
        }
454
    }
455
}
456
 
457
#-------------------------------------------------------------------------------
458
# Function        : PackageDirs
459
#
460
# Description     : Extend an array of 'search' directories to include
461
#                   'gbe' extension directories located with external toolsets
462
#
463
#                   Scan the package information held in ScmBuildPkgRules
464
#                   and locate 'gbe' directories.
465
#
466
# Inputs          : $dirs       - Ref to an array to extend
467
#                   @platforms  - A list of platforms to scan
468
#
469
# Returns         : Nothing
470
#
471
sub PackageDirs
472
{
473
    my ($dirs, @platforms) = @_;
474
 
475
    if ( defined(%::ScmBuildPkgRules) )
476
    {
477
        for my $platform (@platforms)
478
        {
479
            my $pPlatform = $::ScmBuildPkgRules{$platform};
480
 
481
            foreach my $package ( @$pPlatform )
482
            {
483
                push @$dirs, $package->{'ROOT'}.$package->{'CFGDIR'}
484
                    if ( defined( $package->{'CFGDIR'} ) );
485
            }
486
        }
487
    }
488
}
489
 
490
#-------------------------------------------------------------------------------
491
# Function        : MakeIf::Libaries
492
#
493
# Description     : Maintain a data structure for the --Using() expansion
494
#
495
# Inputs          : $using              - Name of the Macro
496
#                   $platform           - Active platform predicate
497
#                   @libs               - List of Libraries
498
#
499
# Returns         : Nothing
500
#
501
sub Libaries
502
{
503
    my ($using, $platforms, @libs) = @_;
504
    my $recipe;
505
 
506
    ::Debug2( "Makeif::Libraries($using, $platforms, @libs)" );
507
    return if ( ! ::ActivePlatform($platforms) );
508
 
509
    push @{$IfPkgLibaries{$using}{LIBS}}, @libs;
510
}
511
 
512
 
513
#private
514
sub LibUsing
515
{
516
    my ($caller, $args, $libs) = @_;
517
    my ($using, @args) = split( ',', $args );
518
 
519
    ::Debug2( "Makeif::LibUsing($caller->$args)" );
520
 
521
    # Global arguments (if any)
522
    #
523
    #   ie. --Using(XXX)[,--NoWarn][,--ifdef USING_XXX]
524
    #
525
    my ($x_nowarn, $x_conds) = (0, 0);
526
 
527
    foreach (@args) {
528
        if ( /^--NoWarn$/ ) {                   # .. disable warnings
529
            $x_nowarn = 1;
530
 
531
        } elsif ( /^--if(.*)$/ ) {              # .. conditional(s)
532
            $x_conds .= "," if ($x_conds);
533
            $x_conds .= $_;
534
 
535
        } else {
536
            ::Warning( "$caller->Using($using), unknown option '$_'" );
537
        }
538
    }
539
 
540
 
541
    # Sanity test
542
    #   Recipe Entry Must Exist
543
    #   Detect recursive invocation
544
    #
545
    my $recipe = $IfPkgLibaries{$using};
546
    unless ( $recipe )
547
    {
548
        ::Warning( "$caller->Using($using), module not found" )
549
            unless ( $x_nowarn );
550
        return;
551
    }
552
 
553
    if ( $recipe->{COOKED} ) {
554
        ::Warning( "$caller->Using($using) causes loop, ignored" )
555
            unless ($recipe->{COOKED_ERR} );
556
        $recipe->{COOKED_ERR}++;
557
        return;
558
    }
559
 
560
    # Parse Using arguments
561
    my ($arg, $deforder, $defallowdup, $defnowarn, @defconds);
562
    $deforder = "User";                 # default "class"
563
    $defallowdup = 0;
564
    $defnowarn = 0;
565
 
566
    foreach (@{$recipe->{LIBS}})
567
    {
568
        # Locally processed switches (global/default settings)
569
        #
570
        if ( /^--DefOrder=(.*)$/ ) {
571
            $deforder = $1;             # Sort using name
572
            next;
573
        }
574
        if ( /^--DefAllowDup$/ ) {
575
            $defallowdup = 1;
576
            next;
577
        }
578
        if ( /^--DefNoWarn$/ ) {
579
            $defnowarn = 1;
580
            next;
581
        }
582
 
583
        if ( /^--DefCond\((.*)\)$/ ) {
584
            my (@conds) = split( ',', $1 );
585
 
586
            @defconds = ();
587
            foreach (@conds) {
588
                Error( "Invalid --DeCond argument '$_' " )
589
                    if ( ! /^--if/ );
590
                push @defconds, $_;
591
            }
592
            next;
593
        }
594
 
595
        # Handle indirections
596
        #
597
        if ( /^--Using\((.*)\)(.*)$/ )
598
        {                               # recurse
599
            my ($x_using);
600
 
601
            $x_using  = "$1";
602
            $x_using .= ",$x_conds"     if ( $x_conds );
603
            $x_using .= "$2";
604
 
605
            $recipe->{COOKED}++;
606
            LibUsing( $using, $x_using, $libs );
607
            $recipe->{COOKED}--;
608
            next;
609
        }
610
 
611
        # Libraries and arguments
612
        #
613
        if ( /^-[lL].*/ )
614
        {                               # Library
615
            my ($order, $allowdup, $nowarn, @conds) =
616
                ($deforder, $defallowdup, $defnowarn, @defconds);
617
            my (@args) = split( ',', $_ );
618
 
619
            foreach (@args) {
620
                if ( /^-([lL])(.*)/ ) {
621
                    $arg = $_;
622
                } elsif ( /^--Order=(.*)/ ) {
623
                    $order = $1;
624
                } elsif ( /^--AllowDup$/ ) {
625
                    $allowdup = 1;
626
                } elsif ( /^--NoAllowDup$/ ) {
627
                    $allowdup = 0;
628
                } elsif ( /^--NoWarn$/ ) {
629
                    $nowarn = 1;
630
                } elsif ( /^--Warn$/ ) {
631
                    $nowarn = 0;
632
                } elsif ( /^--if/ ) {
633
                    push @conds, $_;
634
                } else {
635
                    $arg .= $_;         # unknown
636
                }
637
            }
638
 
639
            $arg .= ",--Order=$order"       if ( $order );
640
            $arg .= ",--NoWarn"             if ( $nowarn );
641
            $arg .= ",--AllowDup"           if ( $allowdup );
642
            $arg .= ",$x_conds"             if ( $x_conds );
643
            $arg .= ",". join(',', @conds)  if ( @conds );
644
        }
645
        else
646
        {                               # other options etc
647
            $arg = $_;
648
        }
649
 
650
        push @$libs, $arg;              # push cooked argument
651
    }
652
}
653
 
654
 
655
sub LibProcess
656
{
657
    my ($libs) = @_;
658
    my (@newlibs, @ordered_newlibs);
659
    my ($order, @cond, %librecipes, %libstatus);
660
 
661
    #
662
    #   Only process the library specification if arguments/attributes
663
    #   are encountered .. compat with older makefile's.
664
    #
665
    my ($attrs) = 0;
666
 
667
    #   use Data::Dumper;
668
    #   $Data::Dumper::Purity = 1;
669
    #   ::Debug "# Uncooked library list";
670
    #   ::Debug Dumper( $libs );
671
 
672
    $order = 1;                                 # physical order start @ 1
673
    @cond = ();
674
 
675
    foreach (@$libs)
676
    {
677
        my ($libname, $class, $fdup, $fnowarn, @params);
678
 
679
        $libname = "";                          # library name and class
680
        $class = "User";                        # deafult class
681
        $fdup = 0;                              # default, remove duplicates
682
        $fnowarn = 0;
683
 
684
        if ( /^--if(.*)/ )
685
        {                                       # Conditional (for next)
686
            ::Warning( "Stray --if '$1' within library specification -- ignored" )
687
                if ( @cond );
688
            @cond = ( $_ );
689
            $attrs++;
690
            next;
691
        }
692
 
693
        if ( /^-[lL].*/ )
694
        {                                       # Library
695
            my (@args) = split( ',', $_ );      # split specification
696
 
697
            foreach (@args) {
698
                if ( /^-([lL])(.*)/ ) {         # Library
699
                    if ( $::ScmTargetHost eq "Unix" ) {
700
                        $libname = "lib$2";     # .. prefix lib
701
                        $libname =~ s/^liblib/lib/;
702
                    } else {
703
                        $libname = $2;          # .. just stripped name
704
                    }
705
                    $libname .= "\$(GBE_TYPE)"  # .. append GBE_TYPE
706
                        if ( $1 eq "l" );
707
 
708
                    push @params, $libname;
709
 
710
                } else {                        # Attribute/options
711
                    if ( /^--Order=(.*)/ ) {    # .. sort using 'class'
712
                        if ( exists $IfPkgOrdering{$1} )
713
                        {
714
                            $class = $1;
715
                        }
716
                        else
717
                        {
718
                            ::Warning( "Lib '$libname' has unknown class '$1'" );
719
                        }
720
 
721
 
722
                    } elsif ( /^--AllowDup$/ ) {# .. allow duplicate images
723
                        $fdup = 1;
724
 
725
                    } elsif ( /^--NoWarn$/ ) {  # .. disable warnings
726
                        $fnowarn = 1;
727
 
728
                    } elsif ( /^--if(.*)/ ) {   # .. conditional(s)
729
                        push @cond, $_;
730
 
731
                    } else {                    # .. other "parameters"
732
                        push @params, $_;
733
                    }
734
 
735
                    $attrs++;
736
                }
737
            }
738
 
739
            #
740
            #   Convert text class name to an ordered number to assist in sorting
741
            #
742
            $class = $IfPkgOrdering{ $class };
743
        }
744
        else
745
        {                                       # Anything else
746
            push @params, $_;
747
        }
748
 
749
        my ($recipe) = {
750
                CLASS   => $class,              # logical class, prim key
751
                ORDER   => $order,              # physical order, 2nd key
752
                LIBNAME => $libname,            # library name (if any)
753
                FDUP    => $fdup,               # duplicate flag
754
                FNOWARN => $fnowarn,            # no-warning flag
755
                CONDS   => [ @cond ],           # optional conditional(s)
756
                PARAMS  => [ @params ],         # parameters
757
            };
758
 
759
        push @newlibs, $recipe;                 # push recipe
760
        push @{$librecipes{$libname}}, $recipe  # plus index using $name
761
            if ( $libname ne "" );
762
 
763
        @cond = ();
764
        $order++;
765
    }
766
 
767
    #   ::Debug3 "# Cooked library list";
768
    #   ::Debug3 Dumper( @newlibs );
769
 
770
#   Parse the library list and determine the status and correct
771
#   handling of any duplicate images.
772
#..
773
    foreach my $name (keys %librecipes)
774
    {
775
        if ( scalar( @{$librecipes{$name}} ) > 1 )
776
        {
777
            my ($class, $classerr, $dup, $nowarn);
778
 
779
            foreach my $recipe (@{$librecipes{$name}})
780
            {
781
                $classerr = 1                   # test for conflicts
782
                    if ( defined($class) && $class ne $recipe->{CLASS} );
783
 
784
                $class = $recipe->{CLASS};
785
 
786
                $dup = $recipe->{FDUP}          # accumulate
787
                    if ( !defined($dup) || $recipe->{FDUP} );
788
 
789
                $nowarn = $recipe->{FNOWARN}    # accumulate
790
                    if ( !defined($nowarn) || $recipe->{FNOWARN} );
791
            }
792
 
793
            my ($stat) = {};
794
 
795
            $stat->{SEEN} = 0;
796
            $stat->{DUP} = $dup;
797
            $stat->{NOWARN} = $nowarn;
798
            $stat->{CLASSERR} = 1 if (defined($classerr));
799
            $libstatus{$name} = $stat;
800
        }
801
    }
802
 
803
#   Sort the library list
804
#
805
    @ordered_newlibs =                          # sort by class/order
806
        sort {
807
            ($a->{CLASS} ne "" && $b->{CLASS} ne "" &&
808
                    $a->{CLASS} cmp $b->{CLASS}) ||
809
            $a->{ORDER} <=> $b->{ORDER}
810
        } @newlibs;
811
 
812
    #   ::Debug3 "# Sorted library list";
813
    #   ::Debug3 Dumper( @ordered_newlibs );
814
 
815
#   Now built the final list, removing duplicates (if required)
816
#
817
    @$libs = ();                                # zap libraries
818
 
819
    foreach my $newlib (@ordered_newlibs)
820
    {
821
        my ($name) = $newlib->{LIBNAME};
822
 
823
        if ($attrs && defined($libstatus{$name}))
824
        {                                       # two or more entries
825
            my ($stat) = $libstatus{$name};
826
 
827
            if ( $stat->{SEEN}++ == 0 )
828
            {                                   # first image
829
                if ( ! $stat->{NOWARN} )
830
                {                               # .. warnings ?
831
                    if ( defined($stat->{CLASSERR}) )
832
                    {                           # .. class conflict
833
                        my (@classes);
834
 
835
                        foreach my $recipe (@{$librecipes{$name}}) {
836
                            ::UniquePush( \@classes, $recipe->{CLASS} );
837
                        }
838
                        ::Warning( "Lib '$name' has multiple classes\n\t" .
839
                            ::CommifySeries( ClassNumToText(@classes) ) );
840
                    }
841
 
842
                    my ($count) = scalar( @{$librecipes{$name}} );
843
 
844
                    ::Warning( "Lib '$name' appeared $count times, ".
845
                               "duplicate" . ($count > 2 ? "s":""). " removed" )
846
                        if ($stat->{DUP} == 0);
847
                }
848
            }
849
            else
850
            {                                   # remove duplicate(s) ?
851
                next if ($stat->{DUP} == 0);
852
            }
853
        }
854
 
855
        my ($spec);
856
 
857
        $spec = join( ',', @{$newlib->{PARAMS}} );
858
        $spec .= "\n\t\t" . join( "\n\t\t", @{$newlib->{CONDS}} )
859
            if ( @{$newlib->{CONDS}} );
860
 
861
        push @$libs, $spec;
862
    }
863
 
864
    #   ::Debug "# Final library list";
865
    #   ::Debug Dumper( $libs );
866
}
867
 
868
 
869
sub ExportDepend
870
{
871
    #
872
    #   Create the dependancy data structure
873
    #   Its easier to dump a complete structure
874
    #
875
    my %ScmBuildPkgDepend;
876
    foreach my $platform ( keys %::ScmBuildPkgRules )
877
    {
878
        foreach my $package ( @{$::ScmBuildPkgRules{$platform}} )
879
        {
880
            my %entry;
881
            $entry{NAME}        = $package->{'NAME'};
882
            $entry{VERSION}     = $package->{'VERSION'};
883
            $entry{DNAME}       = $package->{'DNAME'};
884
            $entry{DVERSION}    = $package->{'DVERSION'};
885
            $entry{DPROJ}       = $package->{'DPROJ'};
886
 
887
            push @{$ScmBuildPkgDepend{$platform}}, \%entry;
888
        }
889
    }
890
 
891
 
892
    my $fh = ::ConfigurationFile::New( "DPACKAGE.CFG" );
893
    $fh->Header( "makelib (Version $::ScmVersion)",
894
                                "DPACKAGE configuration file" );
895
    $fh->DumpData(
896
        "# Dependancy list.\n#\n",
897
        "ScmBuildPkgDepend", \%ScmBuildPkgDepend );
898
 
899
    $fh->Close(1);
900
}
901
 
902
 
903
###############################################################################
904
#   BASE_Toolset ---
905
#       Default interface.
906
#
907
#..
908
 
909
package BASE_Toolset;
910
 
911
MakeIf::Push( "BASE_Toolset" );                 # root of object stack
912
 
913
sub Spawn
914
{
915
    my ($obclass) = shift;
916
    my ($class) = ref($obclass) || $obclass;
917
    my ($self) = {};
918
 
919
    ::Debug2( "\tBASE_Toolset->Spawn()" );
920
    bless($self, $class);
921
    return ($self);
922
}
923
 
924
 
925
sub Preprocess
926
{
927
    my ($self) = shift;
928
 
929
    ::Debug2( "BASE_Toolset->Preprocess()" );
930
    ::ToolsetPreprocess()                       # optional toolset interface
931
        if ( defined &::ToolsetPreprocess );
932
}
933
 
934
 
935
sub Postprocess
936
{
937
    my ($self) = shift;
938
 
939
    ::Debug2( "BASE_Toolset->Postprocess()" );
940
    ::ToolsetPostprocess()                      # optional toolset interface
941
        if ( defined &::ToolsetPostprocess );
942
}
943
 
944
 
945
sub CTAGS
946
{
947
    ::ToolsetCTAGS()                            # optional toolset interface
948
        if ( defined &::ToolsetCTAGS );
949
}
950
 
951
 
952
sub CCDepend
953
{
954
    my ($self) = shift;
955
 
956
    ::Debug2( "BASE_Toolset->CCDepend()" );
957
    ::Error ("BASE_Toolset does not support C file dependency generation" )
958
        unless ( defined &::ToolsetCCDepend );
959
    ::ToolsetCCDepend( @_ );                    # toolset
960
}
961
 
962
 
963
sub CXXDepend
964
{
965
    my ($self) = shift;
966
 
967
    ::Debug2( "BASE_Toolset->CXXDepend()" );
968
    ::Error ("BASE_Toolset does not support C++ dependency generation" )
969
        unless ( defined &::ToolsetCXXDepend );
970
    ::ToolsetCXXDepend( @_ );                   # toolset
971
}
972
 
973
 
974
sub CC
975
{
976
    my ($self) = shift;
977
    my ($source, $obj, $pArgs) = @_;
978
 
979
    ::Debug2( "BASE_Toolset->CC($source)" );
980
    ::Error ("BASE_Toolset does not support C compilation" )
981
        unless ( defined &::ToolsetCC );
982
    ::ToolsetCC( @_ );                          # toolset
983
}
984
 
985
 
986
sub CXX
987
{
988
    my ($self) = shift;
989
    my ($source, $obj, $pArgs) = @_;
990
 
991
    ::Debug2( "BASE_Toolset->CXX($source)" );
992
    ::Error ("BASE_Toolset does not support C++ compilation" )
993
        unless ( defined &::ToolsetCXX );
994
    ::ToolsetCXX( @_ );                         # toolset
995
}
996
 
997
 
998
sub AS
999
{
1000
    my ($self) = shift;
1001
    my ($source, $obj, $pArgs) = @_;
1002
 
1003
    ::Debug2( "BASE_Toolset->AS($source)" );
1004
    ::Error ("BASE_Toolset does not support assembler files" )
1005
        unless ( defined &::ToolsetAS );
1006
    ::ToolsetAS( @_ );                          # toolset
1007
}
1008
 
1009
 
1010
sub EXT
1011
{
1012
    my ($self) = shift;
1013
 
1014
    ::Debug2( "BASE_Toolset->EXT()" );
1015
    return ::ToolsetEXT( @_ )                   # optional toolset interface
1016
        if ( defined &::ToolsetEXT );
1017
    return 0;                                   # default not supppored
1018
}
1019
 
1020
 
1021
sub AR
1022
{
1023
    my ($self) = shift;
1024
    my ($name, $pArgs, $pObjs) = @_;
1025
 
1026
    ::Debug2( "BASE_Toolset->AR($name)" );
1027
    ::Error ("BASE_Toolset does not support library files" )
1028
        unless ( defined &::ToolsetAR );
1029
 
1030
    ProcessArgs ( "", @_ );                     # Proccess arguments
1031
    ::ToolsetAR( @_ );                          # toolset
1032
}
1033
 
1034
 
1035
sub ARLINT
1036
{
1037
    my ($self) = shift;
1038
    my ($name, $pArgs, $pObjs) = @_;
1039
 
1040
    my ($lname) = "\$(LIBDIR)/$name\$(GBE_TYPE)";
1041
    my ($ltarget) = "lib_$name\_lint";
1042
    my (@LIBCSRC, @LIBCXXSRC) = ();
1043
    my ($srcfile) = "";
1044
 
1045
    ::Debug2( "BASE_Toolset->ARLINT($name)" );
1046
    ::Error ("BASE_Toolset does not support library files" )
1047
        unless ( defined &::ToolsetAR );
1048
 
1049
    foreach (@$pObjs) {
1050
        $_ =~ s/^\$\(OBJDIR\)\///g;             # remmove OBJDIR
1051
 
1052
        if ( ($srcfile = $::OBJSOURCE{ $_ }) )
1053
        {
1054
            my( $quoted_srcfile ) = quotemeta( $srcfile );
1055
 
1056
            if ( grep /^$quoted_srcfile$/, @::CSRCS ) {
1057
                push( @LIBCSRC, $srcfile );
1058
 
1059
            } elsif ( grep /^$quoted_srcfile$/, @::CXXSRC ) {
1060
                push( @LIBCXXSRC, $srcfile );
1061
 
1062
            }
1063
        }
1064
    }
1065
 
1066
    ::MakePrint(  "
1067
#.. Lint library ($name)
1068
 
1069
.PHONY:		$ltarget
1070
$ltarget:	LIBBASE = $name
1071
$ltarget:	LIBNAME = $lname
1072
" );
1073
 
1074
    ::MakeDefEntry ( "$ltarget:","LIBCSRC =", \@LIBCSRC );
1075
    ::MakeDefEntry ( "$ltarget:","LIBCXXSRC =", \@LIBCXXSRC );
1076
 
1077
    if ( defined ( &::ToolsetARLINT ) ) {
1078
        ::MakePrint( "$ltarget:" );
1079
        ::ToolsetARLINT( $name, $pArgs, $pObjs, $ltarget, \@LIBCSRC, \@LIBCXXSRC );
1080
 
1081
    } else {
1082
        ::MakePrint( "$ltarget:	\
1083
	\@echo [\$(LIBNAME)] linting not supported..\n" );
1084
    }
1085
 
1086
    ::MakePrint( "\n" );
1087
}
1088
 
1089
 
1090
sub ARMerge
1091
{
1092
    my ($self) = shift;
1093
    my ($name, $pArgs, $pLibs) = @_;
1094
 
1095
    ::Debug2( "BASE_Toolset->ARMERGE($name)" );
1096
    ::Error ("BASE_Toolset does not support library file merging" )
1097
        unless ( defined &::ToolsetARMerge );
1098
    ::ToolsetARMerge( @_ );                     # toolset
1099
}
1100
 
1101
 
1102
sub SHLD
1103
{
1104
    my ($self) = shift;
1105
    my ($name, $pArgs, $pObjs, $pLibs) = @_;
1106
    my ($i);
1107
 
1108
    ::Debug2( "BASE_Toolset->SHLD($name)" );
1109
    ::Error ("BASE_Toolset does not support shared libraries" )
1110
        unless ( defined &::ToolsetSHLD );
1111
 
1112
    ProcessArgs ( 'Using', @_ );                # Proccess arguments
1113
 
1114
    MakeIf::LibProcess( $pLibs );               # cook libraries
1115
 
1116
    ::Debug3( " args: @$pArgs" );
1117
    ::Debug3( " objs: @$pObjs" );
1118
    ::Debug3( " libs: @$pLibs" );
1119
 
1120
    ::ToolsetSHLD( @_ );                        # toolset
1121
}
1122
 
1123
 
1124
sub SHLDLINT
1125
{
1126
    my ($self) = shift;
1127
    my ($name, $pArgs, $pObjs, $pLibs) = @_;
1128
 
1129
    my ($lname) = "\$(LIBDIR)/$name\$(GBE_TYPE)";
1130
    my ($ltarget) = "shlib_$name\_lint";
1131
    my (@SHLIBCSRC, @SHLIBCXXSRC) = ();
1132
    my ($srcfile) = "";
1133
 
1134
    ::Debug2( "BASE_Toolset->SHLDLINT($name)" );
1135
    ::Error ("BASE_Toolset does not support shared libraries" )
1136
        unless ( defined &::ToolsetSHLD );
1137
 
1138
    foreach (@$pObjs) {
1139
        $_ =~ s/^\$\(OBJDIR\)\///g;             # remmove OBJDIR
1140
 
1141
        if ( ($srcfile = $::OBJSOURCE{ $_ }) )
1142
        {
1143
            my( $quoted_srcfile ) = quotemeta( $srcfile );
1144
 
1145
            if ( grep /^$quoted_srcfile$/, @::CSRCS ) {
1146
                push( @SHLIBCSRC, $srcfile );
1147
 
1148
            } elsif ( grep /^$quoted_srcfile$/, @::CXXSRC ) {
1149
                push( @SHLIBCXXSRC, $srcfile );
1150
 
1151
            }
1152
        }
1153
    }
1154
 
1155
    ::MakePrint(  "
1156
#.. Lint shared library ($name)
1157
 
1158
.PHONY:		$ltarget
1159
$ltarget:	SHLIBBASE = $name
1160
$ltarget:	SHLIBNAME = $lname
1161
" );
1162
 
1163
    ::MakeDefEntry ( "$ltarget:","SHLIBCSRC =", \@SHLIBCSRC );
1164
    ::MakeDefEntry ( "$ltarget:","SHLIBCXXSRC =", \@SHLIBCXXSRC );
1165
 
1166
    if ( defined ( &::ToolsetSHLDLINT ) ) {
1167
        ::MakePrint( "$ltarget:" );
1168
        ::ToolsetSHLDLINT( $name, $pArgs, $pObjs, $pLibs, $ltarget, \@SHLIBCSRC, \@SHLIBCXXSRC );
1169
 
1170
    } else {
1171
        ::MakePrint( "$ltarget:	\
1172
	\@echo [\$(SHLIBNAME)] linting not supported..\n" );
1173
    }
1174
 
1175
    ::MakePrint( "\n" );
1176
}
1177
 
1178
 
1179
sub LD
1180
{
1181
    my ($self) = shift;
1182
    my ($name, $pArgs, $pObjs, $pLibs) = @_;
1183
    my ($i);
1184
 
1185
    ::Debug2( "BASE_Toolset->LD($name)" );
1186
    ::Error ("BASE_Toolset does not support program generation" )
1187
        unless ( defined &::ToolsetLD );
1188
 
1189
    ProcessArgs ( 'Using', @_ );                 # Proccess arguments
1190
 
1191
    MakeIf::LibProcess( $pLibs );               # cook libraries
1192
 
1193
    ::Debug3( " args: @$pArgs" );
1194
    ::Debug3( " objs: @$pObjs" );
1195
    ::Debug3( " libs: @$pLibs" );
1196
 
1197
    ::ToolsetLD( @_ );                          # toolset
1198
}
1199
 
1200
 
1201
sub LDLINT
1202
{
1203
    my ($self) = shift;
1204
    my ($name, $pArgs, $pObjs, $pLibs) = @_;
1205
 
1206
    my ($pname) = "\$(BINDIR)/$name";
1207
    my ($ptarget) = "prog_$name\_lint";
1208
    my (@PROGCSRC, @PROGCXXSRC) = ();
1209
    my ($srcfile) = "";
1210
 
1211
    ::Debug2( "BASE_Toolset->LDLINT($name)" );
1212
    ::Error ("BASE_Toolset does not support program generation" )
1213
        unless ( defined &::ToolsetLD );
1214
 
1215
    foreach (@$pObjs) {
1216
        $_ =~ s/^\$\(OBJDIR\)\///g;             # remmove OBJDIR
1217
 
1218
        if ( ($srcfile = $::OBJSOURCE{ $_ }) )
1219
        {
1220
            my( $quoted_srcfile ) = quotemeta( $srcfile );
1221
 
1222
            if ( grep /^$quoted_srcfile$/, @::CSRCS ) {
1223
                push( @PROGCSRC, $srcfile );
1224
 
1225
            } elsif ( grep /^$quoted_srcfile$/, @::CXXSRC ) {
1226
                push( @PROGCXXSRC, $srcfile );
1227
 
1228
            }
1229
        }
1230
    }
1231
 
1232
    ::MakePrint(  "
1233
#.. Lint program ($name)
1234
 
1235
.PHONY:		$ptarget
1236
$ptarget:	PROGBASE = $name
1237
$ptarget:	PROGNAME = $pname
1238
" );
1239
 
1240
    ::MakeDefEntry ( "$ptarget:","PROGCSRC =", \@PROGCSRC );
1241
    ::MakeDefEntry ( "$ptarget:","PROGCXXSRC =", \@PROGCXXSRC );
1242
 
1243
    if ( defined ( &::ToolsetLDLINT ) ) {
1244
        ::MakePrint( "$ptarget:" );
1245
        ::ToolsetLDLINT( $name, $pArgs, $pObjs, $pLibs, $ptarget, \@PROGCSRC, \@PROGCXXSRC );
1246
 
1247
    } else {
1248
        ::MakePrint( "$ptarget:	\
1249
	\@echo [\$(PROGNAME)] linting not supported..\n" );
1250
    }
1251
 
1252
    ::MakePrint( "\n" );
1253
}
1254
 
1255
#-------------------------------------------------------------------------------
1256
# Function        : PROJECT
1257
#
1258
# Description     : Invoke the underlying toolset functions to construct a
1259
#                   project
1260
#
1261
# Inputs          : $pProject       - Reference to the project data
1262
#
1263
# Returns         :
1264
#
1265
sub PROJECT
1266
{
1267
    my( $self, $pProject) = @_;
1268
    my $name = $pProject->{name};
1269
 
1270
    ::Debug2( "BASE_Toolset->PROJECT($name)" );
1271
    ::Error ("BASE_Toolset does not support Project generation" )
1272
        unless ( defined &::ToolsetPROJECT );
1273
 
1274
    #
1275
    #   Sanity test the Toolset PROJECT
1276
    #   Only the JAVA toolset will handle ANT projects
1277
    #
1278
    my $ptype = $pProject->{type} ;
1279
    if ( $ptype )
1280
    {
1281
        my $type = $::ToolsetPROJECT_type || '';
1282
        ::Error ("BASE_Toolset does not support Project generation of type: $ptype " )
1283
            unless ( $type eq $ptype );
1284
    }
1285
 
1286
    #
1287
    #   Generate Phony target names
1288
    #   The toolset MUST provide the targets
1289
    #
1290
    ::MakePrint( "PHONY:\tProjectClean_$name\n" );
1291
    ::MakePrint( "PHONY:\tProject_$name\n" );
1292
    ::MakePrint( "PHONY:\tProjectATest_$name\n" ) if ($pProject->{'autotest'});
1293
    ::MakePrint( "PHONY:\tProjectUTest_$name\n" ) if ($pProject->{'unittest'});
1294
    ::MakePrint( "\n" );
1295
 
1296
    #
1297
    #   Projects may be specific to debug or production
1298
    #
1299
    my $conditional;
1300
    $conditional = 'ifeq'  if ($pProject->{'Debug'});
1301
    $conditional = 'ifneq' if ($pProject->{'Prod'});
1302
    if ( $conditional )
1303
    {
1304
        ::MakePrint( "$conditional \"\$(DEBUG)\" \"1\"\n" );
1305
    }
1306
 
1307
    #
1308
    #   Invoke toolset specific function to create the desired targets
1309
    #
1310
    ::ToolsetPROJECT( $pProject->{name},
1311
                      $pProject->{project},
1312
                      $pProject->{options},
1313
                      $pProject->{'autotest'},
1314
                      $pProject->{'unittest'},
1315
                      $pProject->{'generated'}
1316
                       );
1317
 
1318
    #
1319
    #   Complete any conditional process
1320
    #
1321
    if ( $conditional )
1322
    {
1323
        ::MakePrint( "else\n\n" );
1324
        ::MakePrint( "ProjectClean_$name:\n" );
1325
        ::MakePrint( "Project_$name:\n" );
1326
        ::MakePrint( "ProjectATest_$name:\n" ) if ($pProject->{'autotest'});
1327
        ::MakePrint( "ProjectUTest_$name:\n" ) if ($pProject->{'unittest'});
1328
        ::MakePrint( "\nendif\n" );
1329
    }
1330
 
1331
    #
1332
    #   If this project does contain a unit test, then the name of the target
1333
    #   that will run the unit test must be added to a list
1334
    #
1335
    push @::TESTPROJECT_TO_ARUN, "ProjectATest_$name" if ($pProject->{'autotest'});
1336
    push @::TESTPROJECT_TO_URUN, "ProjectUTest_$name" if ($pProject->{'unittest'});
1337
}
1338
 
1339
 
1340
#-------------------------------------------------------------------------------
1341
# Function        : TESTFRAMEWORK
1342
#
1343
# Description     : Invoke the underlying toolset functions to construct a
1344
#                   Test Frame Work
1345
#
1346
#                   Done by manipulating entries in the HASH that is passed
1347
#                   into the FrameWork Support functionn
1348
#
1349
# Inputs          : $pEntry       - Reference to the test data
1350
#
1351
# Returns         :
1352
#
1353
sub TESTFRAMEWORK
1354
{
1355
    my( $self, $pEntry, @args) = @_;
1356
    my $name = $pEntry->{framework};
1357
    my $fnc = 'ToolsetTESTFRAMEWORK_'. uc($name);
1358
    my $fref = UNIVERSAL::can ( '::main', $fnc );
1359
    ::Debug2( "BASE_Toolset->TestFrameWork($name)" );
1360
    ::Error ("BASE_Toolset does not support Test Frame Work generation: $name" )
1361
        unless ( $fref );
1362
 
1363
    &$fref( $pEntry, @args );          # Invoke the Function
1364
}
1365
 
1366
#sub LDUsing
1367
#{
1368
#    my ($self) = shift;
1369
#    my ($using, $name, $isshared, $pObjs, $pLibs) = @_;
1370
#
1371
#    ::Debug2( "BASE_Toolset->LDUsing($using, $isshared, $name)" );
1372
#
1373
#    MakeIf::LibUsing( $name, $using, $pLibs );
1374
#}
1375
 
1376
#-------------------------------------------------------------------------------
1377
# Function        : ProcessArgs
1378
#
1379
# Description     : Process arguments for the program and library building commands
1380
#                   Processes options:
1381
#                       --Using(XXX),[options]
1382
#                       --Exclude(XXX,XXX,XXX)
1383
#                       --ExcludeLIB(XXX,XXX,XXX)
1384
#
1385
# Inputs          : $mode       - Using == Allow 'Using'
1386
#                   $name       - Name of the program/library
1387
#                   $pArgs      - Ref to an array of arguments
1388
#                   $pObjs      - Ref to an array of objects
1389
#                   $pLibs      - Ref to an array of libraries (Optional)
1390
#
1391
#                   Note: Argument order to assist caller
1392
#
1393
# Returns         : Nothing directly
1394
#                   Massages arrays directly
1395
#
1396
sub ProcessArgs
1397
{
1398
    my ($mode, $name, $pArgs, $pObjs, $pLibs) = @_;
1399
    ::Debug2( "BASE_Toolset->ProcessArgs(@$pArgs)" );
1400
 
1401
    my @rArgs;
1402
 
1403
    my $i;
1404
    for ($i = 0; $i < scalar @$pArgs; $i++)
1405
    {
1406
        $_ = $pArgs->[$i];
1407
 
1408
        if ( $mode && /^--Using\((.*)\)(.*)$/)  # --Using(XXX)[,options]
1409
        {
1410
            MakeIf::LibUsing( $name, "$1$2", $pLibs );
1411
 
1412
#::DebugDumpData("IfPkgLibaries",\%IfPkgLibaries );
1413
#::DebugDumpData("pLibs",\$pLibs );
1414
        }
1415
        elsif (/^--Exclude\((.*)\)$/)           # --Exclude(Obj,Obj...)
1416
        {
1417
            #
1418
            #   Exclude specified object files
1419
            #   Note: Maintain the order of the object files
1420
            #
1421
            my %exclude;
1422
            my @retain = ();
1423
 
1424
            @exclude{split( ',', $1 )} = ();
1425
 
1426
            foreach (@$pObjs)
1427
            {
1428
                (my $objfile = $_) =~ s~.*/~~;  # Remove Shared lib object directory
1429
 
1430
                push @retain, $_
1431
                    unless (exists $exclude{$objfile} );
1432
            }
1433
            @$pObjs = @retain;
1434
            ::Debug3( "BASE_Toolset->ProcessArgs. OBJS: @retain)" );
1435
        }
1436
        elsif (/^--ExcludeLib\((.*)\)$/)        # --ExcludeLib(Lib,Lib...)
1437
        {
1438
            #
1439
            #   Exclude specified library files
1440
            #   Note: Maintain the order of the library files
1441
            #
1442
            my %exclude;
1443
            my @retain_libs = ();
1444
 
1445
            @exclude{split( ',', $1 )} = ();
1446
 
1447
            foreach (@$pLibs)
1448
            {
1449
                m~-[Ll]([^,]*)~;                # Extract library name
1450
                my $libfile = $1;
1451
                push @retain_libs, $_
1452
                    unless (exists $exclude{$libfile} );
1453
            }
1454
            @$pLibs = @retain_libs;
1455
            ::Debug3( "BASE_Toolset->ProcessArgs. LIBS: @retain_libs)" );
1456
        }
1457
        else
1458
        {
1459
            #
1460
            #   Unknown option
1461
            #   Retain to be processed later
1462
            #
1463
            push @rArgs, $_;
1464
        }
1465
    }
1466
 
1467
    #
1468
    #   Pass unprocessed arguments back to the user
1469
    #
1470
    @$pArgs = @rArgs;
1471
}
1472
 
1473
1;
1474