Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
227 dpurdie 1
#! perl
2
########################################################################
3
# Copyright ( C ) 2005 ERG Limited, All rights reserved
4
#
5
# Module name   : jats.sh
6
# Module type   : Perl Package
7
# Compiler(s)   : n/a
8
# Environment(s): jats
9
#
10
# Description   : This package contains functions to manipulate
11
#                 the Makefile_x configuration information
12
#
13
#                 This package uses some global variables
14
#
15
#......................................................................#
16
 
255 dpurdie 17
use 5.006_001;
227 dpurdie 18
use strict;
19
use warnings;
20
 
21
################################################################################
22
#   Global variables used by functions in this package
23
#   For historical reasons many of these variabeles are global
24
#
25
 
26
package JatsMakeConfig;
27
use JatsError;
28
use Data::Dumper;
29
use ConfigurationFile;
30
 
31
our (@ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS, $VERSION);
32
use Exporter;
33
 
34
$VERSION = 1.00;
35
@ISA = qw(Exporter);
36
 
37
# Symbols to autoexport (:DEFAULT tag)
38
@EXPORT = qw(
39
                AllocateParsedConfig
40
                WriteParsedConfig
41
                WriteCommonInfo
42
            );
43
 
44
#
45
#   Global data
46
#
47
our %cf_filelist;                   # Data from Makefile.cfg
48
our %cf_info;                       # Makefile_x.cfg data
49
our %cf_info2;
50
 
51
#
52
#   Local Data
53
#
54
my $cfg_file;                       # Last file read
55
 
56
 
57
#-------------------------------------------------------------------------------
58
# Function        : CheckGlobals
59
#
60
# Description     : Validate assumptions on global variables
61
#
62
# Inputs          : 
63
#
64
# Returns         : 
65
#
66
sub CheckGlobals
67
{
68
    Error ("JatsMakeConfig - ScmRoot not defined") unless ( $::ScmRoot  );
69
    Error ("JatsMakeConfig - ScmInterface not defined") unless ( $::ScmInterface  );
70
    Error ("JatsMakeConfig - Cwd not defined") unless ( $::Cwd  );
71
}
72
 
73
#-------------------------------------------------------------------------------
74
# Function        : ReadConfig
75
#
76
# Description     : Read in a Makefile_x configuration file
77
#
78
# Inputs          : Name of the file to read
79
#
80
# Returns         : 
81
#
82
sub ReadConfig
83
{
84
    ($cfg_file) = @_;
85
 
86
    #
87
    #   Clear before read
88
    #
89
    %cf_info = ();
90
    %cf_info2 = ();
91
 
92
    #
93
    #   Load the existing Parsed Config File
94
    #
95
    if ( -f "$::ScmRoot/$::ScmInterface/$cfg_file" )
96
    {
97
        require "$::ScmRoot/$::ScmInterface/$cfg_file";
98
    }
99
}
100
 
101
#-------------------------------------------------------------------------------
102
# Function        : WriteConfig
103
#
104
# Description     : Writes out the last config file read
105
#                   Maintains the Makefile_x.cfg file
106
#
107
# Inputs          : none
108
#
109
# Returns         : 
110
#
111
sub WriteConfig
112
{
113
    my $fh = ConfigurationFile::New( "$::ScmRoot/$::ScmInterface/$cfg_file" );
114
    $fh->Header( "JatsMakeConfig", "Makefile configuration file" );
115
 
116
#DebugDumpData ("%cf_info2", \%cf_info2);
117
#DebugDumpData ("%cf_info", \%cf_info);
118
 
119
    $fh->Dump([\%cf_info2], [qw(*cf_info2)]);
120
    $fh->Write("\n\n");
121
    $fh->Dump([\%cf_info],  [qw(*cf_info)]);
122
    $fh->Close();
123
}
124
 
125
 
126
#-------------------------------------------------------------------------------
127
# Function        : AllocateParsedConfig
128
#
129
# Description     : Determine the Makefile_X.cfg file to be used for parsed
130
#                   makefile information
131
#
132
#                   This routine will pre-allocate names
133
#                   It may be called to determine the name that will be used
134
#                   The name will be allocated at that point
135
#
136
#                   Maintains Makefile.cfg
137
#                   This is an index file linking paths to Makefile_x.cfg
138
#
139
# Inputs          : None
140
#                   $::Cwd          - Current directory
141
#
142
# Returns         : Name of the config file
143
#
144
sub AllocateParsedConfig
145
{
146
    #
147
    #   Maintain a file of config file names
148
    #   This process will also allocate new configuration file names
149
    #
150
    if ( -f "$::ScmRoot/$::ScmInterface/Makefile.cfg" )
151
    {
152
        require "$::ScmRoot/$::ScmInterface/Makefile.cfg";
153
    }
154
 
155
    my $cfg_file = $cf_filelist{$::Cwd};
156
    unless ( defined( $cfg_file ) )
157
    {
158
        my $num_keys = keys %cf_filelist;
159
        $cfg_file = "Makefile_" . ( $num_keys + 1 ) . ".cfg";
160
        $cf_filelist{$::Cwd} = $cfg_file;
161
 
162
        my $fh = ConfigurationFile::New( "$::ScmRoot/$::ScmInterface/Makefile.cfg" );
163
        $fh->Dump( [\%cf_filelist], [qw(*cf_filelist)] );
164
        $fh->Close();
165
 
166
        #
167
        #   Have allocated a 'new' file
168
        #   Ensure that it doesn't exist. May be left over from another life
169
        #
170
        unlink "$::ScmRoot/$::ScmInterface/$cfg_file";
171
    }
172
 
173
    return $cfg_file;
174
}
175
 
176
#-------------------------------------------------------------------------------
177
# Function        : WriteParsedConfig
178
#
179
# Description     : Adds information to the Parsed Config File
180
#                   Does not handle complex structures as a deep copy is
181
#                   not used. In the current implementation this is OK.
182
#
183
# Inputs          :
184
#
185
# Returns         :
186
#
187
sub WriteParsedConfig
188
{
189
 
190
    CheckGlobals();
191
    Error ("ScmPlatform not defined") unless ( $::ScmPlatform );
192
 
193
    #
194
    #   Load the existing Parsed Config File
195
    #
196
    ReadConfig( AllocateParsedConfig() );
197
 
198
    #
199
    #   Remove current information before adding it. This will allow
200
    #   the makefiles to be rebuilt.
201
    #
202
    $cf_info{$::ScmPlatform} = ();
203
 
204
    #
205
    #   Examine the symbol table and capture most of the entries
206
    #
207
    foreach my $symname (keys %main:: )
208
    {
209
        next if ( $symname =~ m/::/  );                 # No Typeglobs
210
        next unless ( $symname =~ m/^[A-Za-z]/  );      # No system type names
211
        next if ( $symname =~ m/^SIG$/  );              # Useless
212
        next if ( $symname =~ m/^ENV$/  );              # Don't keep the user ENV
213
        next if ( $symname =~ m/^INC$/  );              # Don't keep the INC paths
214
        next if ( $symname =~ m/^DEFINES/  );           # Don't keep
215
        next if ( $symname =~ m/^TOOLSETRULES/  );      # Don't keep
216
 
217
        next if ( $symname =~ m/^ScmCompilerOptions/ );         # Not internal data
218
        next if ( $symname =~ m/^ScmToolsetCompilerOptions/ );  # Not internal data
219
 
220
        local *::sym = $main::{$symname};
221
        $cf_info{$::ScmPlatform}{"\$$symname"} = $::sym  if defined $::sym;
222
        $cf_info{$::ScmPlatform}{"\@$symname"} = \@::sym if defined @::sym;
223
        $cf_info{$::ScmPlatform}{"\%$symname"} = \%::sym if defined %::sym;
224
    }
225
 
226
    #
227
    #   Write out the Parsed Config File with new information
228
    #
229
    WriteConfig();
230
}
231
 
232
 
233
#-------------------------------------------------------------------------------
234
# Function        : WriteCommonInfo
235
#
236
# Description     : Add information to the Makefile_x.cfg file
237
#                   This routine deals with the second section of the file
238
#                   One that is common to all makefiles.
239
#
240
# Inputs          : $SUBDIRS_ref        - Ref to an array of subdirs
241
#                   $PLATFORMS_ref,     - Ref to a hash of platform info
242
#                   $noplatforms,       - 1: No platforms in this dir
243
#                   $rmf                - 1: Root Makefile
244
#
245
# Returns         : 
246
#
247
sub WriteCommonInfo
248
{
249
    my ( $SUBDIRS_ref, $PLATFORMS_ref, $noplatforms, $rmf ) = @_;
250
    CheckGlobals();
251
 
252
    #
253
    #   Load the existing Parsed Config File
254
    #
255
    ReadConfig( AllocateParsedConfig() );
256
 
257
    #
258
    #   Prepare the data
259
    #
260
    %cf_info2 = ();
261
    $cf_info2{version} = 1;
262
    $cf_info2{subdirs} = $SUBDIRS_ref;
263
    $cf_info2{platforms} = $PLATFORMS_ref;
264
    $cf_info2{noplatforms} = 1 if ( $noplatforms );
265
    $cf_info2{root} = 1 if ( $rmf );
266
 
267
    #
268
    #   Sanity test and cleanse data
269
    #   Remove cf_info entries if the platform is not present
270
    #   Remove the associated .mk file if the platform is not present
271
    #   Note: Assumes that the common part is written after all others
272
    #
273
    foreach my $tgt ( keys %cf_info  )
274
    {
275
        unless ( exists ($cf_info2{platforms}{$tgt}) )
276
        {
277
            Verbose ("WriteCommonInfo:Purge data for $tgt");
278
            delete $cf_info{$tgt};
279
            unlink ($tgt . '.mk');
280
        }
281
    }
282
 
283
 
284
    #
285
    #   Write out the Parsed Config File with new information
286
    #
287
    WriteConfig ();
288
}
289
 
290
################################################################################
291
#   Package to contain makefile reader operations
292
#
293
package JatsMakeConfigReader;
294
use FileUtils;
295
use JatsError;
296
 
297
#
298
#   Global data
299
#
300
our %cf_filelist;                   # Data from Makefile.cfg
301
 
302
#-------------------------------------------------------------------------------
303
# Function        : GetAllMakeInfo
304
#
305
# Description     : This function will read all the Makefile_x.cfg files and
306
#                   create a large data structure that contains all the
307
#                   information
308
#
309
#                   Intended to be used by utiltites that want to process
310
#                   all the information
311
#
312
# Inputs          : Nothing
313
#
314
# Returns         : MakefileInfo Class
315
#
316
sub GetAllMakeInfo
317
{
318
    #
319
    #   Create Class Data
320
    #
321
    my ($self) = {
322
            CFG             => {},      # Config files used
323
            DIRS            => [],      # Array of dirs to walk
324
            IDX             => {},
325
        };
326
 
327
    #
328
    #   Read in the index file
329
    #
330
 
331
    my $fname = "$::ScmRoot/$::ScmInterface/Makefile.cfg";
332
    Error "Cannot locate Make index file: Makefile.cfg\n" unless ( -f $fname );
333
 
334
    delete $INC{ $fname };
335
    require $fname;
336
 
337
    #
338
    #   Validate the index file
339
    #
340
    Error ("Data in Makefile.cfg is not valid - Empty")
341
        unless ( keys(%cf_filelist) > 0 );
342
    Error ("Data in Makefile.cfg is not valid - No Root")
343
        unless ( exists $cf_filelist{$::ScmRoot} );
344
 
345
    #
346
    #   Process all the constituent makefile data and build up a huge data structure
347
    #   Order of reading isn't important. It will be sorted out later
348
    #
349
    foreach my $dir ( keys(%cf_filelist) )
350
    {
351
        $self->{IDX}{$dir} = JatsMakeConfigDataReader::New( $cf_filelist{$dir} );
352
    }
353
 
354
#    DebugDumpData ("all", \$self );
355
    return bless $self, __PACKAGE__;
356
}
357
 
358
#-------------------------------------------------------------------------------
359
# Function        : AllDirs
360
#
361
# Description     : Return an array of paths required in order to walk the
362
#                   makefiles
363
#
364
#                   The returned order is from the root directory down in the
365
#                   order specified in the build and makefiles.
366
#
367
# Inputs          :
368
#
369
# Returns         : 
370
#
371
sub AllDirs
372
{
373
    my( $self ) = shift;
374
 
375
    #
376
    #   Return cached result
377
    #
378
    return @{$self->{DIRS}}
379
        if ( @{$self->{DIRS}} );
380
 
381
 
382
    #
383
    #   Determine the walking order
384
    #   This is based on the subdir tree
385
    #
386
    sub RecurseDown
387
    {
388
        my ($self, $dir) = @_;
389
        push @{$self->{DIRS}}, $dir;
390
 
391
        foreach my $subdir ( @{$self->{IDX}{$dir}->GetInfoItem('subdirs')} )
392
        {
393
            RecurseDown( $self, CleanDirName( "$dir/$subdir") );
394
        }
395
    }
396
 
397
    #
398
    #   Depth first recursion through the tree
399
    #
400
    RecurseDown ( $self, $::ScmRoot );
401
 
402
    return @{$self->{DIRS}};
403
}
404
 
405
#-------------------------------------------------------------------------------
406
# Function        : GetEntry
407
#
408
# Description     : Return a ref to the makefile data
409
#
410
# Inputs          : 
411
#
412
# Returns         : 
413
#
414
sub GetEntry
415
{
416
    my( $self, $dir ) = @_;
417
    return $self->{IDX}{$dir};
418
}
419
 
420
################################################################################
421
#   Package to contain makefile data reader operations
422
#
423
package JatsMakeConfigDataReader;
424
use JatsError;
425
#
426
#   Global data
427
#
428
our %cf_info;                       # Makefile_x.cfg data
429
our %cf_info2;
430
 
431
#-------------------------------------------------------------------------------
432
# Function        : New
433
#
434
# Description     : Create an object to conatin the Makefile Data
435
#
436
# Inputs          : Name of the config file to read
437
#
438
# Returns         : Ref
439
#
440
 
441
sub New
442
{
443
    my ( $cfg_file ) = @_;
444
 
445
    #
446
    #   Create Class Data
447
    #
448
    my ($self) = {
449
            INFO            => {},      # Basic data
450
            FULL            => {},      # Full data
451
            CFG             => {},      # Config files used
452
        };
453
 
454
    $cfg_file = "$::ScmRoot/$::ScmInterface/$cfg_file";
455
    Error ("Makefile index entry missing: $cfg_file. Rebuild required")
456
        unless -f $cfg_file;
457
 
458
    %cf_info = ();
459
    %cf_info2 = ();
460
    Verbose ("Reading: $cfg_file");
461
 
462
    delete $INC{ $cfg_file };
463
    require $cfg_file;
464
 
465
    #
466
    #   BAsic sanity test
467
    #
468
    Error ("Makefile info2 not present")
469
        unless ( keys %cf_info2 );
470
 
471
    Error ("Makefile info2 incorrect version. Rebuild required")
472
        unless ( exists $cf_info2{version} && $cf_info2{version} eq 1 );
473
 
474
    $self->{CFG} = $cfg_file;
475
    %{$self->{INFO}} = %cf_info2;
476
    %{$self->{FULL}} = %cf_info;
477
 
478
    return bless $self, __PACKAGE__;
479
}
480
 
481
#-------------------------------------------------------------------------------
482
# Function        : GetPlatforms
483
#
484
# Description     : Return an array of platforms of this makefile
485
#
486
# Inputs          : 
487
#
488
# Returns         : 
489
#
490
sub GetPlatforms
491
{
492
    my( $self ) = @_;
493
    return keys %{$self->{FULL}};
494
}
495
 
496
#-------------------------------------------------------------------------------
497
# Function        : GetData
498
#
499
# Description     : Return a ref to the complete raw data
500
#
501
# Returns         :
502
#
503
sub GetData
504
{
505
    my( $self ) = @_;
506
    return $self->{FULL};
507
}
508
 
509
sub GetInfo
510
{
511
    my( $self ) = @_;
512
    return $self->{INFO};
513
}
514
 
515
#-------------------------------------------------------------------------------
516
# Function        : GetDataItem
517
#
518
# Description     : Return a data item
519
#
520
# Inputs          : self            - Object data
521
#                   platform        - Required platform
522
#                   item            - Item within the platform data
523
#
524
# Returns         : 
525
#
526
 
527
sub GetDataItem
528
{
529
    my( $self, $platform, $item ) = @_;
530
 
531
    return undef unless ( exists $self->{FULL}{$platform} );
532
    return undef unless ( exists $self->{FULL}{$platform}{$item} );
533
 
534
    return $self->{FULL}{$platform}{$item};
535
}
536
 
537
sub GetInfoItem
538
{
539
    my( $self, $item ) = @_;
540
 
541
    return undef unless ( exists $self->{INFO}{$item} );
542
    return $self->{INFO}{$item};
543
}
544
 
545
1;
546
 
547