Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
########################################################################
2
# Copyright ( C ) 2004 ERG Limited, All rights reserved
3
#
4
# Module name   : MugFiles.pl
5
# Module type   : JATS Build System
6
# Compiler(s)   : n/a
7
# Environment(s): jats
8
#
9
# Description   : This is a  JATS toolset extension package
10
#                 The package will add seeral directives to allow the
11
#                 creation of MUG files.
12
#
249 dpurdie 13
#                 The package is platform independant.
227 dpurdie 14
#
249 dpurdie 15
#                 Full details on the Mug File Generation process and the use of
16
#                 the functions provided by this extension are in:
17
#                       MASS-00099 Generating MUG files with JATS
227 dpurdie 18
#
19
#......................................................................#
20
 
21
require 5.6.1;
22
use strict;
23
use warnings;
24
use File::Basename;
25
use File::Path;
26
use File::Copy;
27
 
28
#
29
#   Global data
30
#
247 dpurdie 31
my %Tiers;                              # Hash of Tiers already seen
32
my @ThxOnly;                            # Array of ThxOnly entries
227 dpurdie 33
my $verbose = 0;
34
 
35
MugInit();
36
 
37
#-------------------------------------------------------------------------------
38
# Function        : MugInit
39
#
40
# Description     : Module initialisation
41
#                   This function is run automaticlly when the package is loaded
42
#
43
# Inputs          :
44
#
45
# Returns         :
46
#
47
sub MugInit
48
{
247 dpurdie 49
}
50
 
51
#-------------------------------------------------------------------------------
52
# Function        : MugUtilities
53
#
54
# Description     : Ensure that required utilities can be located
55
#                   Only needs to be called if MugFiles are being created
56
#
57
# Inputs          : None
58
#
59
# Returns         : Will exit on error
60
#
61
sub MugUtilities
62
{
227 dpurdie 63
    #
64
    #   Ensure that required utilities can be located
65
    #
66
    my @not_found;
67
    foreach my $util ( qw(genappa.exe modcrc.exe) )
68
    {
69
        unless ( my $path = ToolExtensionProgram( $util ) )
70
        {
71
            push @not_found, $util;
72
        }
73
    }
74
 
75
    Error ("MugFiles: Required utility programs not found:", @not_found )
76
        if ( @not_found );
77
}
78
 
247 dpurdie 79
 
227 dpurdie 80
#-------------------------------------------------------------------------------
81
# Function        : MugFiles
82
#
83
# Description     : Collect MugFile information
84
#                   information
85
#
86
# Inputs          : $1  - platform(s)
87
#                   $*  - an argument list
88
#
89
# Returns         :
90
#
91
 
92
sub MugFiles
93
{
94
    my( $platforms, @elements ) = @_;
95
    my (%muginfo);
96
    my $tier;
97
 
98
    #
99
    #   Is this platform currently active
100
    #
101
    return if ( ! ActivePlatform($platforms) );
102
    DebugPush("MugFiles");
103
 
104
    #
105
    #   Process directive arguments
106
    #
107
    for (@elements)
108
    {
109
        if ( m/^--DeviceId=(.*)/ ) {
110
            $muginfo{'Device'} = $1;
111
 
112
        } elsif ( m/^--Name=(.*)/ ) {
113
            $muginfo{'Name'} = $1;
114
 
115
        } elsif ( m/^--Tier=(.*)/ ) {
116
            $muginfo{'Tier'} = $1;
117
            $tier = $1;
118
 
119
        } elsif ( m/^--Package=(.*)/ ) {
120
            my $package_name = $1;
121
            my @dirs = 'thx';
122
            if ( $package_name =~ m/(.*?),--Subdir=(.*)/ )
123
            {
124
                $package_name = $1;
125
                @dirs = split( ',', $2 );
126
            }
127
 
128
            my $package = LocatePackage( $package_name );
129
            foreach my $subdir ( @dirs )
130
            {
131
                my $dir = "$package->{'ROOT'}/$subdir";
132
                if ( -d $dir )
133
                {
134
                    UniquePush( \@{$muginfo{'Dirs'}}, $dir );
135
                }
136
                else
137
                {
138
                    Warning("Directory not found in package: $package_name, Subdir: $subdir")
139
                        unless ( $subdir eq 'thx' );
140
                }
141
            }
142
            UniquePush( \@{$muginfo{'Dirs'}}, "$package->{'ROOT'}" );
143
 
144
        } elsif ( m/^--Dir=(.*)/ ) {
145
            my $dir = $1;
146
 
147
            Error("Directory not found: $dir") unless ( -d $dir );
148
            UniquePush( \@{$muginfo{'Dirs'}}, $dir );
149
 
150
        } elsif ( m/^--Load=(.*)/ ) {
151
            Error("Multiple Load files specified") if ( $muginfo{'Load'} );
152
            $muginfo{'Load'} = $1;
153
 
154
        } elsif ( m/^--Exclude=(.*)/ ) {
155
            foreach ( split( ',', lc($1)) )
156
            {
157
                $muginfo{'Exclude'}{$_} = 0;
158
            }
159
 
160
 
161
        } elsif ( m/^--ThxDir=(.*)/ ) {
162
            $muginfo{'ThxCopyDir'} = $1;
163
 
247 dpurdie 164
        } elsif ( m{^--NoMugFiles} || m{^--ThxOnly}  ) {
165
            $muginfo{'NoMug'} = 1;
166
 
227 dpurdie 167
        } else {
168
            Error("Unknown option: $_ ");
169
        }
170
    }
171
 
172
    #
173
    #   Ensure the user has provided all the parameters
174
    #
247 dpurdie 175
    unless ( $muginfo{'NoMug'} )
176
    {
177
        Error("No Device specified") unless ( $muginfo{'Device'} );
178
        Error("No Name specified") unless ( $muginfo{'Name'} );
179
        Error("No Tierspecified") unless ( $muginfo{'Tier'} );
180
        Error("Duplicated Tier: $tier") if ( exists $Tiers{$tier} );
181
 
182
        #
183
        #   Process Name
184
        #   It MUST be 4 characters padded with '-'
185
        #
186
        my $name = $muginfo{'Name'};
187
        Error( "Name too long. Must be less that 4: $name") if ( length($name) > 4 );
188
        $name .= '----';
189
        $name = substr($name,0,4);
190
        $muginfo{'Name'} = $name;
191
        $Tiers{$tier} = \%muginfo;
192
    }
193
    else
194
    {
195
        push @ThxOnly, \%muginfo;
196
    }
227 dpurdie 197
    Error("No Packages or directories specified") unless ( $muginfo{'Dirs'} );
198
 
199
    DebugPop();
200
}
201
 
202
#-------------------------------------------------------------------------------
203
# Function        : MugGenerate
204
#
205
# Description     : Process all the collected data and generate MUG files
206
#
207
#                   Create a genappa.ini file as required for genappa.exe
208
#                   Create load.cmd files as required for genappa.exe
209
#
210
# Inputs          : None
211
#
212
# Returns         : Even less
213
#
214
 
215
sub MugGenerate
216
{
217
    my (@args) = @_;
247 dpurdie 218
    my @versions;
219
    my $version_hex;
220
    my $version_decimal;
221
 
227 dpurdie 222
    foreach ( @args )
223
    {
224
        if ( /^--Debug$/ ) {
225
            $verbose++;
226
 
227
        } elsif ( /^--Debug=(\d+)/ ) {
228
            $verbose = $1;
229
 
230
        } else {
231
            Warning("MugFiles: Unknown option: $_");
232
        }
233
    }
234
 
235
    #
236
    #   Set new Debug header and level
237
    #   These will be popped later
238
    #
239
    $verbose = DebugPush("MugGenerate", $verbose);
240
    Debug("Mugfiles: Set Verbosity: $verbose");
241
 
247 dpurdie 242
    if ( keys %Tiers )
243
    {
244
        #
245
        #   Ensure that utilities are available
246
        #
247
        MugUtilities();
248
 
249
        #
250
        #   Determine the system version
251
        #   This is based on the Build Version ( XX.YY.ZZ )
252
        #   This is massaged into the required system version, which is required
253
        #   in two forms:
254
        #       1) As hex XX.YY
255
        #       2) As the decimal version of 1)
256
        #
257
        #   The version is held in two bytes so it is limited
258
        #
259
        @versions = split( /\./, $::ScmBuildVersion );
260
        Error ("MugFiles: Cannot encode versions with a patch number: $::ScmBuildVersion",
261
                "Major: $versions[0]",
262
                "Minor: $versions[1]",
263
                "Patch: $versions[2]")
264
            if ( $versions[2] > 0 ) ;
227 dpurdie 265
 
247 dpurdie 266
        $version_hex = $versions[0] * 100 + $versions[1];
267
        $version_decimal = hex $version_hex;
268
        Debug ("MugSet version: $version_decimal, HEX:$version_hex");
269
    }
227 dpurdie 270
 
271
    #
272
    #   Create the list of THX files to be used for each device
273
    #   These files are calculated by:
274
    #       Merging all the THX files in the specified packages
275
    #       Excluding the specified files
276
    #
247 dpurdie 277
    foreach my $mugref ( values(%Tiers), @ThxOnly )
227 dpurdie 278
    {
279
 
280
        #
281
        #   If the user has specified a load file, then use it to provide
282
        #   the complete list of files to load
283
        #
284
        if ( $mugref->{'Load'} )
285
        {
286
            ReadLoadFile( $mugref, LocateLoadFile( $mugref, $mugref->{'Load'} ));
287
        }
288
 
289
        my %files_found;
290
        my @ffiles;
291
        foreach my $dir ( @{$mugref->{'Dirs'}} )
292
        {
293
            #
294
            #   Locate the THX files within the package ( directory )
295
            #   Exclude any user specified files
296
            #
297
            my @files = glob( "$dir/*.thx" );
298
            Debug("Searching for THX files in directory: $dir");
299
            foreach  ( @files )
300
            {
301
                my $base = lc(basename($_));
302
 
303
                #
304
                #   Include only loaded files
305
                #
306
                if ( exists $mugref->{'LoadList'} )
307
                {
308
                    next unless( exists $mugref->{'LoadList'}{$base} );
309
                    $mugref->{'LoadList'}{$base}++;
310
                }
311
 
312
                #
313
                #   Skip excluded files
314
                #
315
                if ( exists $mugref->{'Exclude'}{$base} )
316
                {
317
                    $mugref->{'Exclude'}{$base}++;
318
                    Debug2 ("   Excluding: $base");
319
                    next;
320
                }
321
 
322
                #
323
                #   Test for duplicated files
324
                #
325
                if ( exists($files_found{$base}) )
326
                {
327
                    Warning("Multiple instances a file ignored: $base",
328
                            "Using file: $files_found{$base}",
329
                            "Ignoring  : $_");
330
                    next;
331
                }
332
                $files_found{$base} = $_;
333
 
334
                push @ffiles, $_;
335
                Debug2 ("   File: $_");
336
 
337
            }
338
        }
339
        $mugref->{'Files'} = \@ffiles;
340
 
341
        #
342
        #   If using a Load file then reprocess the complete file list
343
        #   to retain only those
344
 
345
 
346
        #
347
        #   Report excluded files that were not excluded
348
        #
349
        foreach ( keys %{$mugref->{'Exclude'}} )
350
        {
351
            next if ( $mugref->{'Exclude'}{$_} );
352
            Warning ("Excluded THX file not encountered: $_" );
353
        }
354
 
355
        #
356
        #   Report loaded files that are not located
357
        #
358
        my @not_nice;
359
        foreach ( keys %{$mugref->{'LoadList'}} )
360
        {
361
            next if ( $mugref->{'LoadList'}{$_} );
362
            push @not_nice, $_;
363
        }
364
        Error ("Incomplete THX file set. Missing files", @not_nice)
365
            if ( $#not_nice >= 0 );
366
 
367
 
368
        #
369
        #   Generate the loadfull.ini file
370
        #   This file simply contains the full path names to all THXs
371
        #   Unique INI files will be created in the "interface" directory
372
        #
247 dpurdie 373
        unless ( $mugref->{'NoMug'} )
374
        {
375
            my $loadname = "$::ScmRoot/$::ScmInterface/load_$mugref->{'Tier'}.ini";
376
            $mugref->{'IniName'} = $loadname;
227 dpurdie 377
 
247 dpurdie 378
            Debug("Generating loadfile: $loadname" );
379
            open (INI, ">$loadname" ) || Error ("Cannot create: $loadname" );
380
            foreach ( @{$mugref->{'Files'}} )
381
            {
382
                (my $dos_path = $_) =~ s~/~\\~g;
383
                print INI "e=o:$dos_path\n";
384
            }
385
            close INI;
227 dpurdie 386
        }
387
 
388
 
389
        #
390
        #   Transfer THX files into the package
391
        #
392
        if ( $mugref->{'ThxCopyDir'} )
393
        {
394
            my $thxdir = "$::ScmRoot/pkg/$::ScmBuildPackage/thx/$mugref->{'ThxCopyDir'}";
395
            $thxdir =~ s/-$//g;
396
            Debug("THX files will be placed in: $thxdir" );
397
            mkpath( $thxdir );
398
            foreach ( @{$mugref->{'Files'}}, @{$mugref->{'LoadFiles'}} )
399
            {
400
                Debug2("Copy Thx: $_" );
401
                copy($_ ,$thxdir);
402
            }
403
        }
404
 
405
        DebugDumpData("Processed Mug", $mugref)
406
            if $verbose > 2;
407
    }
408
 
247 dpurdie 409
    if ( keys %Tiers )
410
    {
411
        #
412
        #   Create the master genappi.ini file
413
        #   This file will be created in the interface directory
414
        #
415
        my $genappa = "$::ScmRoot/$::ScmInterface/genappa.ini";
416
        Debug("Generating genappa control file: $genappa" );
417
        open (INI, ">$genappa" ) || Error ("Cannot create: $genappa" );
227 dpurdie 418
 
247 dpurdie 419
        #
420
        #   Insert the header
421
        #
422
        print INI "[Header]\n";
423
        print INI "SystemVer                = ",$version_hex, "\n";
424
        print INI "NumDevTypes              = ", scalar keys %Tiers, "\n";
425
        print INI "\n";
227 dpurdie 426
 
247 dpurdie 427
        #
428
        #   Insert per device information
429
        #   This is performed in reverse Tier order
430
        #
431
        my $device_number = 0;
432
        foreach my $tier ( reverse sort keys %Tiers )
433
        {
434
            $device_number++;
435
            my $mugref = $Tiers{$tier};
227 dpurdie 436
 
247 dpurdie 437
            print INI "[DeviceType$device_number]\n";
438
            print INI "Name                     = ", $mugref->{'Name'}, "\n";
439
            print INI "Id                       = ", $mugref->{'Device'}, "\n";
440
            print INI "Ver                      = ", $version_decimal, "\n";
441
            print INI "Tier                     = ", $mugref->{'Tier'}, "\n";
442
            print INI "ModulesPath              = ", $mugref->{'IniName'}, "\n";
443
            print INI "ScanMemBackupSuper       = N\n";
444
            print INI "ScanMemBackupUserSuper   = N\n";
445
            print INI "ScanMemFlashSuper        = Y\n";
446
            print INI "ScanMemFlashUserSuper    = Y\n";
447
            print INI "\n";
448
        }
449
 
450
        #
451
        #   Insert options
452
        #
453
        print INI "[Options]\n";
454
        print INI "SuppressCDHeader         = TRUE\n";
227 dpurdie 455
        print INI "\n";
456
 
457
 
247 dpurdie 458
        close INI;
227 dpurdie 459
 
247 dpurdie 460
        #
461
        #   Run the GENAPPA utility
462
        #   This will create a directory full of MUG files
463
        #   Generate the files directly into the pkg subdirectory
464
        #
465
        my $mugdir = "$::ScmRoot/pkg/$::ScmBuildPackage/mug";
466
        Debug("Mugfiles will be placed in: $mugdir" );
467
        mkpath( $mugdir );
227 dpurdie 468
 
247 dpurdie 469
        #
470
        #   Extend the PATH to include the toolset extensions
471
        #   to allow use to find genappa and modcrc
472
        #
473
        my $PATH = join ';', ToolExtensionPaths(), $ENV{'PATH'};
474
        $ENV{'PATH'} = $PATH;
227 dpurdie 475
 
247 dpurdie 476
        my $opts = ($verbose > 1) ? " -d" : "";
477
        Debug( "Running GENAPPA");
478
        System( "genappa $genappa$opts -o $mugdir" ) && Error( "Problem running genappa" );
479
    }
227 dpurdie 480
 
481
    #
482
    #   Cleanup the debugging interface
483
    #
484
    DebugPop();
485
}
486
 
487
#-------------------------------------------------------------------------------
488
# Function        : LocateLoadFile
489
#
490
# Description     : Locate a specified loadfile
491
#
492
# Inputs          : $mugref         - Per device Data store
493
#                   $cmdfile        - The full path to the load file
494
#
495
# Returns         : Path to the load file
496
#                   Will not return on error
497
#
498
sub LocateLoadFile
499
{
500
    my( $mugref, $cmdfile) = @_;
501
    my @load_list;
502
    #
503
    #   Has the load file been sourced
504
    #
505
    Debug ("   Locate command file: $cmdfile");
506
    push @load_list, $::SRCS{$cmdfile}
507
        if ( exists $::SRCS{$cmdfile} && -f $::SRCS{$cmdfile} );
508
 
509
    #
510
    #   The load file must exist in one of the packages or directories
511
    #   Locate the file and warn if multiple files are found
512
    #
513
    foreach my $dir ( @{$mugref->{'Dirs'}} )
514
    {
515
        my $path = "$dir/$cmdfile";
516
        Debug2 ("   Locate command file. Try: $path");
517
        push @load_list, $path if ( -f $path );
518
    }
519
 
520
    Error ("Load file not found in any package or directory: $cmdfile")
521
        unless ( $#load_list >= 0 );
522
 
523
    Warning ("Multiple load files found. The first one will be used",
524
             @load_list ) if( $#load_list > 0) ;
525
 
526
    #
527
    #   Return the full path to the first loadfile located
528
    #
529
    return $load_list[0];
530
}
531
 
532
#-------------------------------------------------------------------------------
533
# Function        : ReadLoadFile
534
#
535
# Description     : Read and Process a load.cmd file
536
#                   This file will provide the complete list of files to be
537
#                   mugged
538
#
539
# Inputs          : $mugref         - Per device Data store
540
#                   $cmdfile        - The full path to the load file
541
#
542
# Returns         :
543
#
544
sub ReadLoadFile
545
{
546
    my( $mugref, @cmdfile) = @_;
547
    my %filelist;
548
    my %seen;
549
 
550
    while ( @cmdfile )
551
    {
552
        my $cmdfile = pop( @cmdfile );
553
        $cmdfile =~ tr~\\/~/~s;
554
        $seen{$cmdfile} = 1;
555
        push @{$mugref->{'LoadFiles'}}, $cmdfile;
556
 
557
        Debug ("Reading load file: $cmdfile");
558
 
559
        #
560
        #   Process the cmdfile and extract the names of files to transfer
561
        #   Extract data of the form
562
        #       e=o:pathname
563
        #       f=pathname
564
        #
565
        open (CMD, "<$cmdfile") || Error ("Cannot open command file: $cmdfile" );
566
        while ( <CMD> )
567
        {
568
            #
569
            #   Clean up whitespace and comments
570
            #
571
            chomp;
572
            s~^\s*~~;
573
            s~\*.*$~~;
574
            s~\s*$~~;
575
            next if ( length( $_) <= 0 );
576
 
577
            #
578
            #   Clean pathnames
579
            #
580
            tr~\\/~/~s;
581
 
582
            if ( m/e=o:(.*)/ )
583
            {
584
                    #
585
                    #   Ignore any path information
586
                    #       - Its not valid within the context of the package
587
                    #   Process excluded files
588
                    #
589
                    my $file = lc StripDir($1);
590
                    if ( exists $mugref->{'Exclude'}{$file} )
591
                    {
592
                        $mugref->{'Exclude'}{$file}++;
593
                        Debug2 ("   Excluding: $file");
594
                    }
595
                    else
596
                    {
597
                        Debug2 ("   Entry: $file");
598
                        $filelist{$file} = 0;
599
                    }
600
 
601
            } elsif ( m/f=(.*)/ )
602
            {
603
                my $file = lc StripDir($1);
604
                Debug2 ("   Included load file: $file");
605
 
606
                $file = LocateLoadFile($mugref, $file );
607
 
608
                Error ("Load file already processed: $file")
609
                    if ( exists $seen{ $file } );
610
 
611
                unshift @cmdfile, $file;
612
                $seen{$file} = 1;
613
            }
614
        }
615
        close( CMD );
616
    }
617
 
618
    $mugref->{'LoadList'} = \%filelist;
619
 
620
}
621
 
622
#-------------------------------------------------------------------------------
623
# Function        : LocatePackage
624
#
625
# Description     : Locate a package entry
626
#
627
# Inputs          : $pname          - Name of the package
628
#
629
# Returns         : Ref to package data
630
#
631
sub LocatePackage
632
{
633
    my($pname) = @_;
634
 
635
    #
636
    #   Locate the Package
637
    #
638
    my $packagebase = $::ScmBuildPkgRules{$::ScmPlatform};
639
    my $package;
640
 
641
    foreach my $pptr ( @{$packagebase} )
642
    {
643
        if ( $pptr->{'NAME'} eq $pname )
644
        {
645
            $package = $pptr;
646
            last;
647
        }
648
    }
649
 
650
    Error("Required Package cannot be located: $pname") unless ( $package );
651
    return $package;
652
}
653
 
654
 
655
 
656
1;