Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
3965 dpurdie 1
########################################################################
2
# Copyright (C) 1998-2013 Vix Technology, All rights reserved
227 dpurdie 3
#
4
# Module name   : common.pl
5
# Module type   : Makefile system
3965 dpurdie 6
# Compiler(s)   : Perl
7
# Environment(s): jats
227 dpurdie 8
#
9
# Description   : Some function common to build and makefile processing tools.
10
#
3965 dpurdie 11
#......................................................................#
227 dpurdie 12
 
13
use strict;
14
use warnings;
15
use JatsError;
16
use JatsSystem;
17
use ConfigurationFile;
18
use FileUtils;
19
use ArrayHashUtils;
20
use ReadBuildConfig qw(:All);
21
use JatsMakeConfig;
22
 
23
our $CommonVersion          = "1.03";
24
 
25
our $ScmWho                 = "";
26
our $ScmDebug               = 0;
27
our $ScmVerbose             = 0;
28
 
29
our $CurrentYear            = "";
30
our $CurrentTime            = "";
31
our $CurrentDate            = "";
32
our $All;
33
 
34
our @BUILD_ACTIVEPLATFORMS  = ();               # Array of active platforms
35
our @DEFBUILDPLATFORMS = ();
263 dpurdie 36
our $GBE_TOOLS;
227 dpurdie 37
 
38
#-------------------------------------------------------------------------------
39
# Function        : CommonInit
40
#
41
# Description     : Initialisation routine for this common code
42
#                   The function MUST be called after the package has been
43
#                   loaded with a "require" statement.
44
#
45
#
46
# Inputs          : $who            - Name of the package using the routines
47
#                                     Used for error reporting
48
#
49
# Returns         : Nothing
50
#
51
sub CommonInit
52
{
53
    my( $who ) = @_;
54
 
55
#.. Import diagnostic levels
56
#
57
    $::ScmWho = $who;
58
    $::ScmDebug = $ENV{ "GBE_DEBUG" }       if ( exists( $ENV{ "GBE_DEBUG" } ) );
59
    $::ScmVerbose = $ENV{ "GBE_VERBOSE" }   if ( exists( $ENV{ "GBE_VERBOSE" } ) );
60
 
61
    ErrorConfig( 'name'    => $::ScmWho,
62
                 'debug'   => $::ScmDebug,
63
                 'verbose' => $::ScmVerbose );
64
 
65
    SystemConfig ('UseShell' => 1 );
66
 
67
    Debug( "Common ($::ScmWho)" );
68
    Debug( "version:   $::CommonVersion" );
69
    Debug( "Debug:     $::ScmDebug" );
70
    Debug( "Verbose:   $::ScmVerbose" );
71
 
72
    #
73
    #   Init the FileUtils package
74
    #   Sets various globals used throughout the program
75
    #
76
    InitFileUtils();
77
 
78
    #
79
    #   Init global time variables
80
    #
81
    $::CurrentTime = localtime;
82
 
83
    my ($sec, $min, $hour, $mday, $mon, $year) = localtime();
84
    $::CurrentYear = 1900 + $year;
85
    $::CurrentDate                              # eg. 13/10/86
86
        = sprintf ("%02u/%02u/%02u", $mday, $mon+1, $year % 100);
87
}
88
 
89
#-------------------------------------------------------------------------------
90
# Function        : AUTOLOAD
91
#
92
# Description     : Intercept bad user directives and issue a nice error message
93
#                   This is a simple routine to report unknown user directives
94
#                   It does not attempt to distinguish between user errors and
95
#                   programming errors. It assumes that the program has been
96
#                   tested. The function simply report filename and line number
97
#                   of the bad directive.
98
#
99
# Inputs          : Original function arguments ( not used )
100
#
101
# Returns         : This function does not return
102
#
103
sub AUTOLOAD
104
{
283 dpurdie 105
    my $args = JatsError::ArgsToString( \@_);
227 dpurdie 106
    my $fname = $::AUTOLOAD;
107
    $fname =~ s~^\w+::~~;
108
    my ($package, $filename, $line) = caller;
109
 
110
    Error ("Directive not known or not allowed in this context: $fname",
283 dpurdie 111
           "Directive: $fname( $args );",
227 dpurdie 112
           "File: $filename, Line: $line" );
113
}
114
 
115
#-------------------------------------------------------------------------------
116
# Function        : ConfigLoad
117
#
118
# Description     : Loads the global configuration details
119
#                   Details are held within the interface directory in "build.cfg"
120
#
121
# Inputs          : None
122
#
123
# Returns         : Nothing
124
#                   Will populate the global environment space with the contents
125
#                   of the build.cfg file. These variables may need to be access
126
#                   with the :: syntax ($::Variable)
127
#
128
#                   This function will remove lumps of the configuration that
129
#                   are not needed by the current platform simply to reduce the
130
#                   data retaied in other config files.
131
#
132
#
133
sub ConfigLoad
134
{
135
   ReadBuildConfig("$::ScmRoot/$::ScmInterface", $::ScmPlatform );
136
}
137
 
138
 
139
#   ExpandPlatforms ---
140
#       Expand a platform list applying aliases.
141
#..
142
 
143
sub ExpandPlatforms
144
{
145
    our( @_expandarg ) = @_;
146
    our( @_expandresult, $_expandnest );
147
 
148
    @_expandresult = ();
149
    $_expandnest = 0;
150
 
151
    Debug3( "ExpandPlatforms(@_)" );
152
 
153
    sub ExpandPlatform
154
    {
155
        sub ExpandAlias
156
        {
157
            my( $key ) = @_;
158
 
369 dpurdie 159
            if (%::BUILDALIAS)         # buildlib.pl
227 dpurdie 160
            {
161
                return ExpandPlatform( split( ' ', $::BUILDALIAS{ $key } ) )
162
                    if ( $key !~ /^--/ && $::BUILDALIAS{ $key } );
163
            }
164
            else
165
            {
166
                return $key                     # argument || no aliases
369 dpurdie 167
                    if ( $key =~ /^--/ || !(%::ScmBuildAliases) );
227 dpurdie 168
 
169
                return ExpandPlatform( split( ' ', $::ScmBuildAliases{ $key } ) )
170
                    if ( $::ScmBuildAliases{ $key } );
171
            }
172
 
173
            return $key;
174
        }
175
 
176
        sub ExpandPush
177
        {
178
            my( $pResult, $operator, $pPlatforms, @arguments ) = @_;
179
 
180
            foreach my $platform ( @$pPlatforms )
181
            {                                   # unfold arguments
182
                push( @$pResult, $operator.$platform );
183
                next if ( $platform =~ /^--/ );
184
                push( @$pResult, @arguments );
185
            }
186
        }
187
 
188
        Error( "ExpandPlatforms( @_expandarg ) nesting error.",
189
               "",
190
               "Check for recursive definitions within the follow directives",
191
               "       - BuildAlias and BuildProduct."
192
             ) if ( $_expandnest++ > 42 );
193
 
194
        my( @result, $operator, @platforms, @arguments ) = ();
195
 
196
        Debug3( "  +$_expandnest: @_ " );
197
 
198
        foreach my $arg ( @_ ) {
199
            if ( $arg =~ /^--/ ) {              # argument, accumulate
200
                push( @arguments, $arg );
201
 
202
            } else {                            # group, product or platform
203
                ExpandPush( \@result, $operator, \@platforms, @arguments );
204
 
205
                if ( ($operator = substr($arg, 0, 1)) eq "!" ) {
206
                    @platforms = ExpandAlias( substr($arg, 1) );
207
                } else {
208
                    $operator = "";
209
                    @platforms = ExpandAlias( $arg );
210
                }
211
                @arguments = ();
212
            }
213
        }
214
        ExpandPush( \@result, $operator, \@platforms, @arguments );
215
 
216
        $_expandnest--;
217
        Debug3( "  -$_expandnest: @result" );
218
        return @result;
219
    }
220
 
221
    ############################################################################
222
    #   Function body
223
    #
224
 
225
    foreach (@_expandarg) {                      # break out embedded args
226
        if ( /^--/ ) {
227
            push @_expandresult, $_;
228
 
229
        } else {
230
 
231
            push @_expandresult, split( ',', $_ );
232
        }
233
    }
234
 
235
    @_expandresult = ExpandPlatform( @_expandresult );
236
    Debug2( "ExpandPlatforms(@_expandarg) = @_expandresult" );
237
    return @_expandresult;
238
}
239
 
240
#-------------------------------------------------------------------------------
241
# Function        : Exists( $path, $name, $msg, [@paths] ) ---
242
#
243
# Description     : Case insensitive 'exists'.
244
#
245
# Inputs          :
246
#       $path       Represents either the absolute path of the file
247
#                   named 'name' in the case of @path being an empty
248
#                   list, or the subdir appended to each entry
249
#                   contained within the @paths list.
250
#
251
#       $name       The file name
252
#
253
#       $desc       Text used to describe the file upon the image
254
#                   not being found.
255
#
256
#       @paths      Optional list of paths to be searched.
257
#
258
# Returns         : Full path of resolved filename, otherwise nothing.
259
#
260
#   Examples:
261
#
262
#       a)  Exists( "/mypath", "Myfile", "stuff" );
263
#
264
#           Resolve the name of the file called "myfile" within the
265
#           directory "/mypath", using the following matching order
266
#
267
#               1.  "/mypath/Myfile".       As supplied.
268
#               2.  "/mypath/myfile".       then Lower case
269
#               3.  "/mypath/MYFILE".       and finally upper case.
270
#
271
#           Upon being not found displays the message
272
#
273
#               "stuff (/mypath/Myfile) not found".
274
#
275
#       b)  @paths = ( '/dir1', '/dir2' );
276
#           Exists( "cfg", "Myfile", "stuff", @paths );
277
#
278
#           Resolve the name of the file called "Myfile" within the
279
#           set of directories "/dir1/cfg/" and "/dir2/cfg/", using
280
#           the following matching order:
281
#
282
#               1.  "/dir1/cfg/Myfile".
283
#               2.  "/dir1/cfg/myfile".
284
#               3.  "/dir1/cfg/MYFILE".
285
#               4.  "/dir2/cfg/Myfile".
286
#               5.  "/dir2/cfg/myfile".
287
#               6.  "/dir2/cfg/MYFILE".
288
#
289
#           Upon being not found displays the message
290
#
291
#               "stuff (cfg/Myfile) not found".
292
#
293
sub Exists
294
{
295
    my( $path, $name, $msg, @paths ) = @_;
296
    my( $dir, $file, $lc_name, $uc_name );
297
 
298
    Debug2 "Searching for $path/$name (" . ($msg || '') . ")";
299
    Debug2 " using @paths" if ( @paths );
300
 
301
    if ( scalar( @paths ) > 0 ) {
302
        $dir = pop( @paths );                   # search path
303
    } else {
304
        $dir = "";                              # path is absolute
305
    }
306
 
307
    $lc_name = lc( $name );
308
    $uc_name = uc( $name );
309
    do {
310
        $dir .= "/"                             # directory delimitor
311
            if ( $dir ne "" );
312
 
313
        $file = "$dir$path/$name";              # quoted, can be mixed case
314
 
315
        Debug2 " -> $file";
316
 
317
        if ( ! -f $file )
318
        {
319
            $file = "$dir$path/$lc_name";       # lower case
320
            if ( ! -f $file )
321
            {
322
                $file = "$dir$path/$uc_name";   # upper case
323
                $file = ""                      # NO MATCH
324
                    if ( ! -f $file );
325
            }
326
        }
327
    } while ( ($file eq "") &&
328
                ($dir ne "") && ($dir = pop( @paths )) );
329
 
330
    #
331
    #   If the user has defined an error message and the file does not
332
    #   exist, then generate an error message
333
    #
334
    Error("$msg","File: $path/$name not found.")
335
        if ($msg && $file eq "");
336
 
337
    Debug2 " == $file";
338
 
339
    Debug( "Exists:     = $file" );
340
    return $file;
341
}
342
 
343
 
344
#-------------------------------------------------------------------------------
345
#   Require( $path, $name, $msg, [@paths] ) ---
346
#
347
#   Description:
348
#       Case insensitive 'require', see Exists() for usage.
349
#
350
#   Returns:
351
#       Full path of resolved filename.
352
#..
353
 
354
sub Require
355
{
356
    my( $file );
357
 
358
    $file = Exists( @_ );
359
    require $file if ($file);
360
    return $file;
361
}
362
 
363
 
364
#   Require2( \@args, $path, $name, $msg, [@paths] ) ---
365
#       Case insensitive 'require' same as Require(), but allows the
366
#       argument list \@args to passed thru to the included image
367
#       via a localised @_.
368
#
369
#   Returns:
370
#       Full path of resolved filename.
371
#..
372
 
373
sub Require2
374
{
375
    my( $args ) = shift;
376
    my( $file, $result );
377
 
378
    $file = Exists( @_ );
379
    if (exists $::INC{$file}) {
380
        Error( "Included $file has already been loaded." );
381
    }
382
    unless (-f $file) {
383
        Error ("Can't locate the include $file");
384
    } else {
385
        local @_;                               # Include argument vector
386
 
387
        push @_, @$args;
388
        $::INC{$file} = $file;
389
        $result = do $file;                     # exec
390
    }
391
    if ($@) {
392
        $::INC{$file} = undef;
393
        Error ($@);
394
    } elsif (!$result) {
395
        delete $::INC{$file};
396
        Error ("Included $file did not return true value.");
397
    }
398
    return $file;
399
}
400
 
401
 
402
sub RequireTool
403
{
404
    my( $script, @arguments ) = @_;
405
    my( $file );
406
 
407
    Debug2( "RequireTool(@_)" );
408
 
409
    $file = Require( "", $script,
410
                "RequireTool", @::BUILDTOOLSPATH, $::GBE_TOOLS );
411
}
412
 
413
 
414
 
415
 
416
#   Trim( string ) ---
417
#       Trim leading/trailing whitespace
418
#..
419
 
420
sub Trim
421
{
422
    my( $str ) = @_;
423
 
424
    if ( $str )
425
    {
426
        $str =~ s/^\s*//g;                          # leading white space
427
        $str =~ s/\s*(\n|$)//;                      # trailing white space
428
    }
429
    return $str;
430
}
431
 
432
 
433
 
434
#   CommifySeries ---
435
#       Format the array into comma seperate list.
436
#..
437
 
438
sub CommifySeries
439
{
440
    my $sepchar = grep(/,/ => @_) ? ";" : ",";
441
 
442
    (@_ == 0) ? '' :
443
    (@_ == 1) ? $_[0] :
444
    (@_ == 2) ? join(" and ", @_)  :
445
                    join("$sepchar ", @_[0 .. ($#_-1)], "and $_[-1]");
446
}
447
 
3890 dpurdie 448
#-------------------------------------------------------------------------------
449
# Function        : ToolsetFile
450
#
451
# Description     : Maintain a datastructure of files that are created
452
#                   by the makefile creation process.
453
#
454
#                   Used to simplify the clobber process
455
#
456
#                   Maintains a in-memory datastructure
457
#
458
# Inputs          : fileList        - Files to add to the list
459
#
460
# Returns         : Nothing
461
#
462
our %GBE_TOOLSETFiles;
463
sub ToolsetFile
464
{
465
    my (@fileList) = @_;
466
    Verbose2 ("ToolsetFile:", @fileList);
467
    Error ("Internal: ToolsetFile. ScmRoot or ScmInterface not defined")
468
        unless ( defined $::ScmRoot && defined $::ScmInterface );
227 dpurdie 469
 
4001 dpurdie 470
    my $dataDir = "$::ScmRoot/$::ScmInterface";
471
    my $dataFile = "$dataDir/GbeFiles.cfg";
3890 dpurdie 472
 
473
    Error ("Internal: ToolsetFile. Cwd not defined")
474
        unless ( defined $::Cwd );
475
 
476
 
477
    #
478
    #   Initial read of data structure
479
    #   Only read on first call
480
    #
481
    unless ( %GBE_TOOLSETFiles )
482
    {
483
        if ( -f  $dataFile )
484
        {
485
            require ( $dataFile );
486
        }
487
 
488
        # Capture the package root directory
489
        $GBE_TOOLSETFiles{Root} = AbsPath($::ScmRoot)
490
            unless defined $GBE_TOOLSETFiles{Root};
491
    }
492
 
493
    #
4001 dpurdie 494
    # Save to disk if
495
    #   Target directory exists - creation may be delayed
496
    #   We have added entries
3890 dpurdie 497
    #
4001 dpurdie 498
    if ( @fileList )
499
    {
500
        #
501
        #   Add files
502
        #       Need to be full paths
503
        #
504
        $GBE_TOOLSETFiles{Files}{RelPath(AbsPath($_), $GBE_TOOLSETFiles{Root} )} = 1 foreach ( @fileList );
3890 dpurdie 505
 
4001 dpurdie 506
        #
507
        #   Save file
508
        #   Simply rewrite the file - if the terget directory exists
509
        #   Its creation may be after we have started accumulating files
510
        #
511
        if ( -d $dataDir  ) {
512
            my $fh = ConfigurationFile::New( $dataFile );
513
            $fh->Header( "ToolsetFile", "Toolset Files" );
514
            $fh->Dump( [\%GBE_TOOLSETFiles], [qw(*GBE_TOOLSETFiles)] );
515
            $fh->Close();
516
        }
517
    }
3890 dpurdie 518
}
519
 
227 dpurdie 520
1;  #success
521