Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
261 dpurdie 1
########################################################################
2
# Copyright (C) 2008 ERG Limited, All rights reserved
227 dpurdie 3
#
261 dpurdie 4
# Module name   : ToolsetPrinter.pm
5
# Module type   : Perl Module
6
# Compiler(s)   : Perl
7
# Environment(s): jats
227 dpurdie 8
#
261 dpurdie 9
# Description   : Common toolset utils
10
#                 Toolset I/O stream for creating makefile rules and recipes
11
# Usage:
227 dpurdie 12
#
13
#       New         Create a new stream
14
#
15
#       Prt         Print a raw line
16
#
17
#       PrtLn       Print a raw line and a new line
18
#
19
#       Newline     Print a single new line
20
#
21
#       Tag         Tagged line print.
22
#
23
#       Cmd         Command line print, tagged with meta quoted and terminates.
24
#
25
#       SetTag      Set the "tag", default none.
26
#
27
#       SetTerm     Set the command line "terminator", default "\\n\n".
28
#
29
#       Label       Print generalised label
30
#
261 dpurdie 31
#       StartDef    Create a Definition
32
#       Def         Accumulate
33
#       EndDef      Print it out
34
#
227 dpurdie 35
#       ObjList     Generate a object list, using the specified recipe.
36
#
37
#       LibList     Generate a library list, using the specified recipe.
38
#
39
#       DepRules    Generate library dependency rules
40
#
41
###############################################################################
42
 
261 dpurdie 43
use strict;
44
use warnings;
45
 
46
 
227 dpurdie 47
package ToolsetPrinter;
48
 
49
sub New
50
{
51
    my ($tag, $cmdterm) = @_;
52
 
53
    $tag = "" if ( !defined($tag) );            # default tag
54
    $cmdterm = "\\n\n"                          # and terminator
55
        if ( !defined($cmdterm) );
56
 
57
    my ($self) = {
58
            TAG         => $tag,
59
            CMDTERM     => $cmdterm
60
        };
61
    return bless $self, __PACKAGE__;
62
}
63
 
335 dpurdie 64
sub Reset
65
{
66
    my ($self) = shift;
67
    delete $self->{DEPEND_target};
68
    delete $self->{DEPEND_list};
69
    delete $self->{DEPEND_dir};
70
    delete $self->{DEPEND_file};
71
}
227 dpurdie 72
 
73
sub Prt
74
{
75
    my ($self) = shift;
289 dpurdie 76
    ::MakePrint ("@_");
227 dpurdie 77
}
78
 
79
sub PrtLn
80
{
81
    my ($self) = shift;
289 dpurdie 82
    ::MakePrint ("@_\n");
227 dpurdie 83
}
84
 
85
sub Entry
86
{
87
    my ($self) = shift;
88
    ::MakeEntry( @_ );
89
}
90
 
91
 
92
sub Newline
93
{
94
    my ($self) = shift;
289 dpurdie 95
    ::MakePrint ("\n");
227 dpurdie 96
}
97
 
98
 
99
sub SetTag
100
{
101
    my ($self) = shift;
102
    my ($tag) = @_;
103
 
104
    $tag = "" if ( !defined($tag) );
105
    $self->{TAG} = $tag;
106
}
107
 
108
 
109
sub SetTerm
110
{
111
    my ($self) = shift;
112
    my ($cmdterm) = @_;
113
 
114
    $cmdterm = "\\n\n"                          # default terminator
115
        if ( !defined($cmdterm) );
116
    $self->{CMDTERM} = $cmdterm;
117
}
118
 
119
 
120
sub Cmd
121
{
122
    my ($self) = shift;
289 dpurdie 123
    ::MakeQuote ("$self->{TAG}\t+=@_$self->{CMDTERM}");
227 dpurdie 124
}
125
 
126
 
127
sub Tag
128
{
129
    my ($self) = shift;
289 dpurdie 130
    ::MakePrint ("$self->{TAG}\t+=@_\n");
227 dpurdie 131
}
132
 
133
 
134
sub Label
135
{
136
    my ($self) = shift;
137
    my ($desc, $target) = @_;
138
 
139
    $self->Prt( "#.. $desc ($target)\n\n" );
140
}
141
 
142
 
143
sub ObjList
144
{
145
    my ($self) = shift;
146
    my ($target, $objs, $genrecipe, @uargs) = @_;
147
 
148
    foreach (@$objs)
149
    {
150
        &$genrecipe( $self, $target, $_, @uargs );
151
    }
152
}
153
 
261 dpurdie 154
sub StartDef
155
{
156
    my ($self) = shift;
157
    my ($tag) = @_;
227 dpurdie 158
 
261 dpurdie 159
    $tag = "" if ( !defined($tag) );
160
    $self->{DEF} = $tag;
161
    $self->{DEFS} = [];
162
}
163
 
164
sub Def
165
{
166
    my ($self) = shift;
167
    push @{$self->{DEFS}}, "@_";
168
}
169
 
170
sub EndDef
171
{
172
    my ($self) = shift;
173
    ::MakeDefEntry ( $self->{DEF}, '=' , $self->{DEFS} );
174
    delete $self->{DEFS};
175
}
176
 
177
 
227 dpurdie 178
#private
179
sub CondParse
180
{
181
    my ($target, $cond) = @_;
182
 
183
    if ($cond =~ /^--ifdef=(.*)/) {             # .. ifdef XXX
184
        $cond = "ifdef $1";
185
 
186
    } elsif ($cond =~ /^--ifndef=(.*)/) {       # .. ifndef XXX
187
        $cond = "ifndef $1";
188
 
189
    } elsif ($cond =~ /^--ifdebug$/) {          # .. if DEBUG
190
        $cond = "ifeq \"\$(DEBUG)\" \"1\"";
191
 
192
    } elsif ($cond =~ /^--ifprod$/) {           # .. if PRODUCTION
193
        $cond = "ifeq \"\$(DEBUG)\" \"0\"";
194
 
195
    } elsif ($cond =~ /^--ifeq=(.*):(.*)$/) {   # .. ifeq XXXX:YYYY
196
        $cond = "ifeq \"\$($1)\" \"$2\"";
197
 
198
    } elsif ($cond =~ /^--ifneq=(.*):(.*)$/) {  # .. ifneq XXXX:YYYY
199
        $cond = "ifneq \"\$($1)\" \"$2\"";
200
 
201
    } else {                                    # .. unknown
202
        ::Error( "$target: unknown conditional construct '$cond'" );
203
        $cond = "";
204
    }
205
    return $cond;
206
}
207
 
208
 
209
#private
210
sub CondOpen
211
{
212
    my ($self) = shift;
213
 
214
    @{$self->{CONDSTACK}} = ();
215
}
216
 
217
 
218
#private
219
sub CondModify
220
{
221
    my ($self) = shift;
222
    my ($newstack) = @_;
223
    my ($oldstack) = \@{$self->{CONDSTACK}};
224
    my ($idx, $cond);
225
 
226
#   Diff the two stacks
227
#
228
    $idx = 0;
229
    while ( $idx <= $#$newstack &&
230
            $idx <= $#$oldstack &&
231
            $$newstack[$idx] eq $$oldstack[$idx] ) {
232
        $idx++;
233
    }
234
 
235
#   Pop diff
236
#
237
    while ($idx <= $#$oldstack) {
238
        $cond = pop @$oldstack;
239
        $self->Prt( "  " x ($#$oldstack+1) . "endif\n" );
240
    }
241
 
242
#   Push diff
243
#
244
    while ($idx <= $#$newstack) {
245
        $self->Prt( "  " x $idx . "$$newstack[$idx]\n" );
246
        $idx++;
247
    }
248
 
249
    @{$self->{CONDSTACK}} = @$newstack;
250
}
251
 
252
 
253
#private
254
sub CondClose
255
{
256
    my ($self) = shift;
257
    my (@newstack) = ();
258
 
259
    $self->CondModify( \@newstack );            # pop any stacked conditionals
260
}
261
 
262
 
263
sub LibList
264
{
265
    my ($self) = shift;
266
    my ($target, $libs, $genrecipe, @uargs) = @_;
267
    my (@cond, $t_cond) = ();
268
 
269
    $self->CondOpen();                          # open a conditional session
270
 
271
    foreach (@$libs)
272
    {
273
        if (/^--if/)                            # inlined conditionals
274
        {
275
            push @cond, $t_cond
276
                if (($t_cond = CondParse( $target, $_ )) ne "");
277
        }
278
        elsif (/^--/)                           # arguments
279
        {
280
            &$genrecipe( $self, $target, $_, @uargs );
281
        }
282
        else                                    # library
283
        {
284
            my (@args) = split( "\n\t\t", $_ ); # see makeif.pl
285
            my ($lib) = shift @args;
286
 
287
            #   Associated conditionals (if any)
288
            #
289
            foreach (@args) {
290
                push @cond, $t_cond
291
                    if (($t_cond = CondParse( $target, $_ )) ne "");
292
            }
293
            $self->CondModify( \@cond );        # modify
294
            @cond = ();
295
 
296
            #   Generate recipe
297
            #
298
            &$genrecipe( $self, $target, $lib, @uargs );
299
        }
300
    }
301
    $self->CondClose();                         # close session
302
}
303
 
335 dpurdie 304
#-------------------------------------------------------------------------------
305
# Function        : SetShldTarget
306
#
307
# Description     : Set up the Shared Library target information
308
#                   Main function is to calculate the name of the
309
#                   dependency file so that it can be used
310
#
311
#                   Must be called before SHLDDEPEND or DepRules
312
#
313
# Inputs          : $self
314
#                   $target         - Name of the target library
315
#                                     May or may not have $(GBE_TYPE)
316
#                   $dir            - Optional alternate directory
317
#                                     Default: LIBDIR
318
#
319
# Returns         : Full name of the dependency file
320
#
227 dpurdie 321
 
335 dpurdie 322
sub SetShldTarget
323
{
324
    my ($self, $target, $dir ) = @_;
325
    ::Warning("Internal: SetShldTarget already specified") if ( defined $self->{DEPEND_target} );
227 dpurdie 326
 
335 dpurdie 327
    #   Create a 'tag' to be used within the makefile
328
    #
329
    $self->{DEPEND_target} = $target;
330
    $self->{DEPEND_list} = $target . '_shdp';
331
 
332
    #
333
    #   Set up the name of the dependency file
334
    #
335
    $dir = 'LIBDIR' unless ( defined $dir );
336
    $self->{DEPEND_dir} = $dir;
337
 
338
    my $depfile = "\$($dir)/${target}";
339
    $depfile .= '$(GBE_TYPE)' unless ( $depfile =~ m~\$\(GBE_TYPE\)~ );
340
    $depfile .= '.dep';
341
    $self->{DEPEND_file} = $depfile;
342
 
343
    ::Verbose3("SetShldTarget",
344
                "DepDir:  $self->{DEPEND_dir}",
345
                "DepFile: $self->{DEPEND_file}",
346
                "DepList: $self->{DEPEND_list}" );
347
 
348
    return $depfile;
349
}
350
 
351
#-------------------------------------------------------------------------------
352
# Function        : SHLDDEPEND
353
#
354
# Description     : Create a set of rules and recipes to handle the creation
355
#                   of dependency files used in the creation of shared
356
#                   libraries
357
#
358
#
359
# Inputs          : $self
360
#                   $base       - SHBASE: Defines the shared library name (eg: lib)
361
#                   $name       - SHNAME: Defines the base library name (eg: lib.so.1.1)
362
#
227 dpurdie 363
sub SHLDDEPEND
364
{
365
    my ($self) = shift;
335 dpurdie 366
    my ($base, $name) = @_;
227 dpurdie 367
 
335 dpurdie 368
    #
369
    #   Sanity test: The name of the list must have been setup
370
    #
371
    my $depfile = $self->{DEPEND_file} || ::Error ("Internal error: SetShldTarget not called before SHLDDEPEND");
227 dpurdie 372
 
335 dpurdie 373
    $self->Newline();
374
    $self->Label( "Include Shared Library Dependency Rules", $self->{DEPEND_target} );
375
 
376
    $self->Prt(
377
"${depfile}:\tSHBASE=${base}
378
${depfile}:\tSHNAME=${name}
379
${depfile}:\tDPLIST=$self->{DEPEND_list}
380
${depfile}:\t\$(GBE_$self->{DEPEND_dir}) \$(SCM_MAKEFILE)
227 dpurdie 381
	\$(SHLDDEPEND)
382
 
383
ifneq \"\$(findstring \$(IFLAG),23)\" \"\"
335 dpurdie 384
-include\t${depfile}
227 dpurdie 385
endif
386
 
387
" );
335 dpurdie 388
 
389
    #   Mark file as generated by the toolset
390
    #
391
    ::ToolsetGenerate( $depfile );
227 dpurdie 392
}
393
 
335 dpurdie 394
#-------------------------------------------------------------------------------
395
# Function        : SetLdTarget
396
#
397
# Description     : Set up the Program target information
398
#                   Main function is to calculate the name of the
399
#                   dependency file so that it can be used
400
#
401
#                   Must be called before LDDEPEND or DepRules
402
#
403
# Inputs          : $self
404
#                   $target         - Name of the target program
405
#                   $dir            - Optional alternate directory
406
#                                     Default: BINDIR
407
#
408
# Returns         : Full name of the dependency file
409
#
410
sub SetLdTarget
411
{
412
    my ($self, $target, $dir ) = @_;
413
    ::Warning("Internal: SetLdTarget already specified") if ( defined $self->{DEPEND_target} );
227 dpurdie 414
 
335 dpurdie 415
    #   Create a 'tag' to be used within the makefile
416
    #
417
    $self->{DEPEND_target} = $target;
418
    $self->{DEPEND_list} = $target . '_dp';
419
 
420
    #
421
    #   Set up the name of the dependency file
422
    #
423
    $dir = 'BINDIR' unless ( defined $dir );
424
    $self->{DEPEND_dir} = $dir;
425
 
426
    my $depfile = "\$($dir)/${target}.dep";
427
    $self->{DEPEND_file} = $depfile;
428
 
429
    ::Verbose3("SetLdTarget",
430
                "DepDir:  $self->{DEPEND_dir}",
431
                "DepFile: $self->{DEPEND_file}",
432
                "DepList: $self->{DEPEND_list}" );
433
 
434
    return $depfile;
435
}
436
 
437
#-------------------------------------------------------------------------------
438
# Function        : LDDEPEND
439
#
440
# Description     : Create a set of rules and recipes to handle the creation
441
#                   of dependency files used in the creation of a program
442
#
443
#
444
# Inputs          : $self
445
#
227 dpurdie 446
sub LDDEPEND
447
{
448
    my ($self) = shift;
449
 
335 dpurdie 450
    #
451
    #   Sanity test: The name of the list must have been setup
452
    #
453
    my $depfile = $self->{DEPEND_file} || ::Error ("Internal error: SetLdTarget not called before LDDEPEND");
454
 
455
    $self->Newline();
456
    $self->Label( "Include Library Dependency Rules", $self->{DEPEND_target} );
227 dpurdie 457
 
335 dpurdie 458
    $self->Prt(
459
"${depfile}:\tDPLIST=$self->{DEPEND_list}
460
${depfile}:\t\$(GBE_$self->{DEPEND_dir}) \$(SCM_MAKEFILE)
227 dpurdie 461
	\$(LDDEPEND)
462
 
463
ifeq \"\$(IFLAG)\" \"3\"
335 dpurdie 464
-include\t${depfile}
227 dpurdie 465
endif
466
 
467
" );
335 dpurdie 468
 
469
    #   Mark file as generated by the toolset
470
    #
471
    ::ToolsetGenerate( $depfile );
227 dpurdie 472
}
473
 
335 dpurdie 474
#-------------------------------------------------------------------------------
475
# Function        : DepRules
476
#
477
# Description     : Create the list of dependency rules used
478
#                   within the dependency include file
479
#
480
# Inputs          : $libs       - Ref to a list of libraries
481
#                   $librecipe  - Ref to code to create the library recipe
482
#                   @uargs      - User arguments, passed to the librecipe function
483
#
484
# Returns         : Nothing
485
#
227 dpurdie 486
sub DepRules
487
{
488
    my ($self) = shift;
335 dpurdie 489
    my ( $libs, $librecipe, @uargs) = @_;
227 dpurdie 490
 
335 dpurdie 491
    #
492
    #   Sanity test: The name of the list must have been setup
493
    #
494
    my $target = $self->{DEPEND_target} || ::Error ("Internal error: SetShldTarget/SetLdTarget not called before DepRules");
495
 
496
    $self->SetTag( $self->{DEPEND_list});                   # command tag
497
    $self->SetTerm();
227 dpurdie 498
    unless ( $self->{DepRulesHeaderDone}{$target} )
499
    {
500
        $self->{DepRulesHeaderDone}{$target} = 1;
501
 
335 dpurdie 502
        $self->Label( "Linker Dependencies", $target );    # label
503
                                                           # library depends
261 dpurdie 504
        $self->Tag( "\\# DO NOT REMOVE - dependencies\\\\n" );
505
        $self->Tag( "\\#\\\\n" );
227 dpurdie 506
    }
261 dpurdie 507
 
227 dpurdie 508
    $self->LibList( $target, $libs, $librecipe, @uargs );
509
}
510
 
511
1;
512