Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
1119 dpurdie 1
########################################################################
2
# Copyright (C) 2007 ERG Limited, All rights reserved
3
#
4
# Module name   : jats.sh
5
# Module type   : Makefile system
6
# Compiler(s)   : n/a
7
# Environment(s): jats
8
#
9
# Description   : This package extends the JATS toolset at build time
10
#                 It provides additional directives to the JATS makefiles
11
#                 to simplify the directives.
12
#
13
#                 This directive does all its work at 'build' time
14
#                 It uses makefile.pl directives
15
#
16
# Operation     : This package adds the JATS directive ManifestFiles
17
#                 This is used to create linux manifest files
18
#
19
# Syntax        : ManifestFiles (<platforms>, Options+);
20
#                 See the function header for details
21
#
22
#......................................................................#
23
 
24
require 5.6.1;
25
use strict;
26
use warnings;
27
 
28
#
29
#   Globals
30
#
31
my @Manifests;                      # Manifest entries
1125 alewis 32
my $Manifest_has_version = 1;       # Create Manifest_xxxx by default
1121 dpurdie 33
my %package_dirs;                   # Package dirs discovered and used
1125 alewis 34
my $pkg_subdir;                     # Alternate packaging
1119 dpurdie 35
 
36
#-------------------------------------------------------------------------------
37
# Function        : BEGIN
38
#
39
# Description     : Setup directive hooks
40
#                   Register a function to be called just before we start to
41
#                   generate makefiles. This will be used to process the data
42
#                   collected in all the ManifestFiles directives
43
#
44
# Inputs          : None
45
#
46
# Returns         : None
47
#
48
BEGIN
49
{
50
    RegisterMakefileGenerate (\&ManifestFiles_Generate);
51
}
52
 
53
#-------------------------------------------------------------------------------
54
# Function        : ManifestFiles
55
#
56
# Description     : Create a ManifestFiles entry
57
#
58
# Inputs          : Platform             - Active Platform Selector
59
#                   Options              - One or more options
60
#                       --Name=Name             - Mandatory
61
#                       --Tier=Name             - Mandatory
62
#                       --Architecture=xxxx     - Default actitecture is the current target
63
#                       --Product=yyyy          - Product Family
64
#                       --Debian=BaseName[,--Prod,--Debug,--Arch=xxxx,--Product=yyyy]
65
#                       --MugPackage=Package[,--Subdir=subdir[,subdir]+]
66
#                       --SrcFile=xxx
1125 alewis 67
#                       --SrcFileNoCopy=xxx
1123 dpurdie 68
#                       --Comment=xxx           - Add comment to Manifst
1125 alewis 69
#                       --NoManifestVersion     - Create unversioned Manifest File
70
#                       --PkgSubdir=xxx         - Specifies packaging subdir
1129 dpurdie 71
#                       --ImportManifest=Package[,--Subdir=subdir] - Import Manifest from package
1119 dpurdie 72
#
73
# Returns         : Nothing
74
#
75
sub ManifestFiles
76
{
77
    my( $platforms, @elements ) = @_;
78
    Debug2( "ManifestFiles($platforms, @elements)" );
79
    return if ( ! ActivePlatform($platforms) );
80
 
81
    my $name;
82
    my $tier;
83
    my @files;
84
    my $mug_dir;
85
    my $default_arch = $::ScmPlatform;
86
    my $default_prod = '';
1129 dpurdie 87
    my $imported_manifest = 0;
1119 dpurdie 88
 
89
    #
90
    #   Collect user options
91
    #
92
    foreach ( @elements )
93
    {
94
        if ( m~^--Name=(.+)~ ) {
95
            if ( $name )
96
            {
97
                ReportError ("ManifestFiles:--Name option is only allowed once");
98
                next;
99
            }
100
            $name = $1;
101
 
102
        } elsif ( m~^--Tier=(.+)~ ) {
103
            if ( $tier )
104
            {
105
                ReportError ("ManifestFiles:--Tier option is only allowed once");
106
                next;
107
            }
108
            $tier = $1;
109
 
1123 dpurdie 110
        } elsif ( m~^--Comment=~ ) {
111
            my $cmt = $_;
112
            $cmt =~ s~.+=~~;
113
            $cmt =~ s~\s*\n\s*~\n~g;
114
            push @files, {'cmt' => $cmt };
115
 
1119 dpurdie 116
        } elsif ( m~^--Debian=(.+)~ ) {
1123 dpurdie 117
            push @files, {'file' => LocateDebianFile($1, $default_arch, $default_prod)};
1119 dpurdie 118
 
119
        } elsif ( m~^--SrcFile=(.+)~ ) {
1123 dpurdie 120
            push @files, {'file' => LocatePreReq($1)};
1119 dpurdie 121
 
1125 alewis 122
        } elsif ( m~^--SrcFileNoCopy=(.+)~ ) {
123
            push @files, {'filenocopy' => $1};
124
 
1119 dpurdie 125
        } elsif ( m~^--MugPackage=(.+)~ ) {
126
            if ( $mug_dir )
127
            {
128
                ReportError ("ManifestFiles:--MugPackage option is only allowed once");
129
                next;
130
            }    
131
            $mug_dir = LocateMugDir($1);
132
 
133
        } elsif ( m/^--Arch(.*)=(.+)/ ) {
134
            $default_arch = $2;
135
 
136
        } elsif ( m/^--Product=(.+)/ ) {
137
            $default_prod = $1;
138
 
1125 alewis 139
        } elsif ( m/^--NoManifestVersion/i ) {
140
            $Manifest_has_version = 0;
141
 
142
        } elsif ( m/^--PkgSubdir=(.+)/i ) {
143
            if ( $pkg_subdir )
144
            {
1129 dpurdie 145
                ReportError ("ManifestFiles:--PkgSubdir option is only allowed once");
1125 alewis 146
                next;
147
            }
148
            $pkg_subdir = $1;
149
 
1129 dpurdie 150
        } elsif ( m/^--ImportManifest=(.+)/i ) {
151
            my $import_info = ImportManifest($1);
152
#DebugDumpData("ImportInfo", $import_info );
153
            push @files, {'manifest' => $import_info };
154
 
155
            #
156
            #   Fill in details unless already provided
157
            #
158
            $tier = $import_info->{'tier'} unless ( defined $tier );
159
            $name = $import_info->{'name'} unless ( defined $name );
160
 
161
            $imported_manifest = 1;
162
 
1119 dpurdie 163
        } else {
164
            ReportError ("ManifestFiles: Unknown option or argument: $_");
165
 
166
        }
167
    }
168
 
169
    #
170
    #   Sanity test the user options
171
    #
172
    ReportError ("ManifestFiles: No name specified")
173
        unless $name;
174
    ReportError ("ManifestFiles: No tier specified")
1129 dpurdie 175
        unless defined ($tier);
1119 dpurdie 176
    ReportError ("ManifestFiles: Cannot mix --Debian/--SrcFile with --MugPackage in one directive")
1129 dpurdie 177
        if ( $mug_dir && (@files || $imported_manifest) );
1119 dpurdie 178
    ReportError ("ManifestFiles: Must specify files to add to Manifest")
1129 dpurdie 179
        unless ( $mug_dir ||  @files || $imported_manifest);
1119 dpurdie 180
    ErrorDoExit();
181
 
182
    #
183
    #   Save information for processing at the end of the parsing phase
184
    #   Data collected from ALL the ManifestFiles directives will be collected
185
    #   and processed into one Manifest file
186
    #
187
    my %data;
188
    $data{tier} = $tier;
189
    $data{name} = $name;
190
    $data{files} = \@files;
191
    $data{mugdir} = $mug_dir;
1125 alewis 192
    $data{pkgsubdir} = $pkg_subdir;
1129 dpurdie 193
#DebugDumpData("DirectiveData", \%data );
1119 dpurdie 194
 
195
    push @Manifests, \%data;
196
    return;
197
 
198
    #-------------------------------------------------------------------------------
199
    # Function        : LocateDebianFile
200
    #
201
    # Description     : Locate a debian file
202
    #                   Internal Function
203
    #
204
    #                   Scan packages for the Debian package specified
205
    #                   The user provides the base name of the package
206
    #                   A Debian Package name has several fields
207
    #                   These are:
208
    #                       1) Base Name - Provided by the user
209
    #                       2) Version - Version will be wildcarded
210
    #                       3) Architecture - Wildcarded. Uses bin/arch directory
211
    #                   
212
    #                   Expect to find Debian Packages in the bin/PLATFORM subdir
213
    #
214
    # Inputs          : Debian base name, complete with suboptions
215
    #
216
    # Returns         : Full path of the file
217
    #
218
    sub LocateDebianFile
219
    {
220
        my ($arg, $arch, $product) = @_;
221
        Verbose("LocateDebianFile: Processing: $arg");
222
 
223
        my @type = qw( P D );
224
        my @debian_file_path;
225
 
226
        #
227
        #   Extract sub-options
228
        #       --Prod[uction]
229
        #       --Debug
230
        #       --Arch[itecture]=yyy
231
        #
232
        my ($base_name, @opts) = split( ',', $arg );
233
        foreach ( @opts )
234
        {
235
            if ( m/^--Arch(.*)=(.+)/ ) {
236
                $arch=$2;
237
            } elsif ( m/^--Product=(.+)/ ) {
238
                $product=$1;
239
            } elsif ( m/^--Prod/ ) {
240
                @type = 'P';
241
            } elsif ( m/^--Debug/ ) {
242
                @type = 'D';
243
            }
244
        }
245
 
246
        #
247
        #   Create a list of products
248
        #   ie: PRODUCT_ARCH
249
        #
250
        my @products;
251
        push @products, $product . '_' . $arch if ( $product );
252
        push @products, $arch;
253
 
254
        #
255
        #   Scan all packages for the specified debian package
256
        #
257
        foreach my $package_dir ( getPackagePaths ('--All') )
258
        {
259
            foreach my $type ( @type )
260
            {
261
                foreach my $prd ( @products )
262
                {
263
                    foreach my $joiner ( qw(/ .) )
264
                    {
265
                        my $dir = "$package_dir/bin$joiner$prd$type";
266
                        Verbose("ManifestFiles: Search in $dir");
267
                        next unless ( -d $dir );
268
                        my @files = glob ( "$dir/${base_name}_*.deb" );
269
                        next unless ( @files );
270
                        push @debian_file_path, @files;
1121 dpurdie 271
                        $package_dirs{$package_dir}{used} = 1;
1119 dpurdie 272
                    }
273
                }
274
            }
275
        }
276
 
277
        ReportError ("Required Debain package not found: $base_name") unless @debian_file_path;
1121 dpurdie 278
        ReportError ("Multiple matching Debian Packages located: $base_name", @debian_file_path ) if ( $#debian_file_path > 0 );
1119 dpurdie 279
        return $debian_file_path[0];
280
    }
281
 
282
    #-------------------------------------------------------------------------------
283
    # Function        : LocateMugDir
284
    #
285
    # Description     : Locate the directory containing the mugfiles
286
    #                   Internal Function
287
    #
288
    # Inputs          : Mufile package, with embedded options
289
    #
290
    # Returns         : Full path
291
    #
292
    sub LocateMugDir
293
    {
294
        my ($mug_package) = @_;
295
 
296
        #
297
        #   Locate the mugfile subdir
298
        #
299
        my $package_name = $mug_package;
300
        my @dirs = 'mug';
301
        my $mug_dir;
302
 
303
        #
304
        #   Extract sub options
305
        #       --Subdir=xxxx,yyyy,zzzz
306
        #
307
        if ( $package_name =~ m/(.*?),--Subdir=(.*)/ )
308
        {
309
            $package_name = $1;
310
            @dirs = split( ',', $2 );
311
        }
312
 
313
        my $package = GetPackageEntry( $package_name );
314
        unless ( $package )
315
        {
316
            ReportError ("ManifestFiles: Package not known to build: $package_name");
317
            return undef;
318
        }
319
 
320
        foreach my $subdir ( @dirs )
321
        {
322
            my $dir = "$package->{'ROOT'}/$subdir";
323
            if ( -d $dir )
324
            {
325
                Warning ("Multiple Mugfile directories located. Only the first will be used",
326
                         "Ignoring: $subdir" )if ( $mug_dir );
327
                $mug_dir = $dir;
328
            }
329
        }
330
        ReportError ("Mugfile directory not found in package: $package_name")
331
            unless $mug_dir;
332
 
333
        return $mug_dir;
334
    }
1129 dpurdie 335
 
336
    #-------------------------------------------------------------------------------
337
    # Function        : ImportManifest
338
    #
339
    # Description     : Import an existing manifest
340
    #
341
    # Inputs          : Args
342
    #                           PackageName[,Subdir=name]
343
    #
344
    # Returns         : A hash of data to be used later
345
    #
346
    sub ImportManifest
347
    {
348
        my ($args) = @_;
349
        my @file_contents;
350
        my @file_list;
351
 
352
        #
353
        #   Locate the mugfile subdir
354
        #
355
        my $package_name = $args;
356
        my @dirs = 'mug';
357
        my $pkg_dir;
358
        my $pkg_root;
359
        my $manifest;
360
        my $first_tier;
361
        my $first_name;
362
 
363
        #
364
        #   Extract sub options
365
        #       --Subdir=xxxx,yyyy,zzzz
366
        #
367
        if ( $package_name =~ m/(.*?),--Subdir=(.*)/ )
368
        {
369
            $package_name = $1;
370
            @dirs = split( ',', $2 );
371
        }
372
 
373
        my $package = GetPackageEntry( $package_name );
374
        unless ( $package )
375
        {
376
            ReportError ("ManifestFiles: Package not known to build: $package_name");
377
            return undef;
378
        }
379
 
380
        foreach my $subdir ( @dirs )
381
        {
382
            my $dir = "$package->{'ROOT'}/$subdir";
383
            my $root = $package->{'ROOT'};
384
            if ( -d $dir )
385
            {
386
                Warning ("Multiple Package directories located. Only the first will be used",
387
                         "Ignoring: $subdir" )if ( $pkg_dir );
388
                $pkg_dir = $dir;
389
                $pkg_root = $root;
390
            }
391
        }
392
        ReportError ("Package directory not found in package: $package_name")
393
            unless $pkg_dir;
394
 
395
        #
396
        #   Determine Manifest File name
397
        #
398
        foreach my $file ( glob ($pkg_dir . '/Manifest*' ) )
399
        {
400
                next unless ( -f $file );
401
                Warning ("Multiple Manifest Files find. Only the first will be used",
402
                         "Using: $manifest",
403
                         "Ignoring: $file" ) if ( $manifest );
404
                $manifest = $file;
405
        }
406
        ReportError ("ImportManifest. No Manifest found: $package_name")
407
            unless $manifest;
408
 
409
 
410
        #
411
        #   
412
        #
413
        open (MF, '<', $manifest ) || Error ("Cannot open the Manifest file: $manifest", $!);
414
        while ( <MF> )
415
        {
416
            s~\s+$~~;
417
            push @file_contents, $_;
418
 
419
            #
420
            #   Part lines and determine files
421
            #
422
            next unless ( $_ );
423
            next if ( m~\s*#~ );
424
            next if ( m~\s*\[~ );
425
            my( $aname, $atier, $afile) = split(/\s*\,\s*/, $_);
426
#            print "---------- $_\n";
427
#            print "T: $atier, N:$aname, F:$afile\n";
428
            push @file_list, $afile;
429
 
430
            #
431
            #   Capture first tier and name
432
            #
433
            $first_tier = $atier unless ( defined $first_tier );
434
            $first_name = $aname unless ( defined $first_name );
435
 
436
        }
437
        close MF;
438
 
439
        #
440
        #   Create a hash of data that describes the manifest that has
441
        #   just been read in.
442
        #
443
        $package_dirs{$pkg_root}{used} = 1;
444
        $manifest =~ s~.*/~~;
445
        return { 'contents' => \@file_contents,
446
                  'files' => \@file_list,
447
                  'file_base' => $pkg_dir,
448
                  'manifest' => $manifest,
449
                  'pkg_dir' => $pkg_root,
450
                  'tier' => $first_tier,
451
                  'name' => $first_name,
452
                };
453
    }
1119 dpurdie 454
}
455
 
456
#-------------------------------------------------------------------------------
457
# Function        : ManifestFiles_Generate
458
#
459
# Description     : Internal Function
460
#                   Process all the collected data and create directives
461
#                   for the creation of the manifest
462
#
463
#                   This function will be called, just before the Makefile
464
#                   is created. The function will:
465
#                       1) Create the Manifest File
466
#                       2) Package the Manifest File
467
#                       3) Package the manifest file contents
468
#
469
#                   using (mostly) normal makefile.pl directives.
470
#
471
# Inputs          : None
472
#
473
# Returns         : Nothing
474
#
475
sub ManifestFiles_Generate
476
{
477
    Debug ("ManifestFiles_Generate");
478
    Message ("Generating Manifest File");
1123 dpurdie 479
 
480
    #
481
    #   Need at least one Manifest Entry
482
    #
483
    return unless ( @Manifests );
1119 dpurdie 484
#DebugDumpData ( "Manifests", \@Manifests );
485
 
486
    #
1125 alewis 487
    #   Determine the target packaging directory
488
    #   Default is .../mug
489
    #
490
    my $pkgdir = 'mug';
1129 dpurdie 491
    if ( exists $Manifests[0]->{pkgsubdir} && defined $Manifests[0]->{pkgsubdir} )
1125 alewis 492
    {
493
        my $subdir = $Manifests[0]->{pkgsubdir};
494
        $pkgdir .= '/' . $subdir;
495
        $pkgdir =~ s~^mug/mug~mug~;
496
    }
497
 
498
    #
1119 dpurdie 499
    #   Create the Manifest File as we process the lists
1125 alewis 500
    #   Place this in the 'lib' directory:
1119 dpurdie 501
    #       - So that it will be deleted on clobber
1123 dpurdie 502
    #       - So that it can be placed in a target-specific subdir
1125 alewis 503
    #       - So that we can have one per makefile.pl
1119 dpurdie 504
    #
505
    Error ("ManifestFiles: Needs local directory specified in build.pl") unless ( $::ScmLocal );
506
 
1125 alewis 507
    my $manifest_dir = "$::ScmPlatform.LIB";
1119 dpurdie 508
    System( "$::GBE_BIN/mkdir -p $manifest_dir" );
509
 
1125 alewis 510
    my $manifest_file = $manifest_dir . '/Manifest';
511
    $manifest_file .= '_' . $::ScmBuildVersion if ( $Manifest_has_version );
512
    ToolsetGenerate( $manifest_file );
1119 dpurdie 513
    Verbose ("ManifestFiles_Generate: File: $manifest_file");
514
 
1125 alewis 515
    PackageFile ('*', $manifest_file, '--Subdir=' . $pkgdir, '--Strip' );
1119 dpurdie 516
 
517
    open (MF, '>', $manifest_file ) || Error ("Cannot create the Manifest file: $manifest_file");
518
 
519
    print_mf ("# PackageName: $::ScmBuildPackage");
520
    print_mf ("# PackageVersion: $::ScmBuildVersion");
521
    print_mf ("# BuildDate: $::CurrentTime");
522
    print_mf ("#");
523
    print_mf ("[Version],$::ScmBuildVersion");
524
    print_mf ("#");
525
 
526
    #
1125 alewis 527
    #   Process each tier in the order presented in the source file
1119 dpurdie 528
    #
1123 dpurdie 529
    my $last_was_comment = 0;
1119 dpurdie 530
    foreach my $entry ( @Manifests )
531
    {
1127 alewis 532
    #print_mf ("#");
1119 dpurdie 533
 
534
#DebugDumpData ( "Manifest Entry", $entry );
535
 
536
        my $tier = $entry->{tier};
537
        my $name = $entry->{name};
538
 
539
        #
540
        #   Insert all the files that have been specified
541
        #   The user specified order is preserved
542
        #
1123 dpurdie 543
        #   Entries may be either a file or a comment
544
        #   Comments: Merge multiple comments and create blocks
545
        #
546
        #
1119 dpurdie 547
        my @files = @{ $entry->{files} };
1123 dpurdie 548
        foreach my $fentry ( @files )
1119 dpurdie 549
        {
1123 dpurdie 550
            if ( my $cmt = $fentry->{'cmt'} )
551
            {
552
                print_mf ('') unless ( $last_was_comment ) ;
553
                print_mf ( map (('# ' . $_) , split ("\n", $cmt) ));
554
                $last_was_comment = 1;
555
                next;
556
            }
557
 
558
            print_mf ('#') if ( $last_was_comment );
559
            if ( my $file = $fentry->{'file'} )
560
            {
561
                my $base_file = StripDir( $file );
562
                print_mf ("$name,$tier,$base_file");
1125 alewis 563
                PackageFile ('*', $file, '--Subdir=' . $pkgdir, '--Strip' );
1123 dpurdie 564
                $last_was_comment = 0;
565
            }
1125 alewis 566
 
567
            if ( my $file = $fentry->{'filenocopy'} )
568
            {
569
                print_mf ("$name,$tier,$file");
570
                $last_was_comment = 0;
571
            }
1129 dpurdie 572
 
573
            if ( my $emf = $fentry->{'manifest'} )
574
            {
575
                $last_was_comment = 0;
576
                #
577
                #   Insert the entire manifest
578
                #   Items are:
579
                #        contents
580
                #        files
581
                #        file_base
582
                #        manifest
583
                #
584
#DebugDumpData ( "Embedded Manifest Entry", $emf );
585
                print_mf ( '## Included Manifest: ' .  $emf->{'manifest'}  );
586
                print_mf ($_) foreach  ( @{$emf->{'contents'}} );
587
                PackageFile ('*', $emf->{'file_base'}. '/' . $_, '--Subdir=' . $pkgdir, '--Strip' )foreach  ( @{$emf->{'files'}});;
588
                print_mf ( '## End Included Manifest' );
589
            }
1119 dpurdie 590
        }
591
 
592
        #
593
        #   Expand out the entire MUG directory
594
        #   All .mug files in the MUG directory will be added to the manifest
595
        #   The assumption is that the MUG directory has been created by
596
        #   something that knows what its doing
597
        #
598
        if ( my $mugdir = $entry->{mugdir} )
599
        {
600
            foreach my $file ( glob ($mugdir . '/*.mug' ) )
601
            {
602
                next unless ( -f $file );
603
                my $base_file = StripDir($file);
604
                print_mf ("$name,$tier,$base_file");
605
                PackageFile ('*', $file, '--Subdir=mug', '--Strip' );
606
            }
607
        }
608
    }
609
 
610
    #
611
    #   Complete the creation of the Manifest File
612
    #
613
    print_mf ("#");
614
    print_mf ("# End of File");
615
    close MF;
616
    ErrorDoExit();
1121 dpurdie 617
 
618
    #
619
    #   Sanity test of packages that did not provide a debian file
620
    #   Just a hint that something may have been missed
621
    #
622
    my @not_used_packages;
623
    foreach my $package_dir ( getPackagePaths ('--All') )
624
    {
625
        next if ( $package_dir =~ m~/manifest-tool/~ );
626
        unless ( exists $package_dirs{$package_dir}{used} )
627
        {
628
            push @not_used_packages, $package_dir;
629
        }
630
    }
631
    if ( @not_used_packages )
632
    {
633
        Warning ("Packages that did not contribute packages to the manifest:",
634
                  @not_used_packages );
635
    }
636
 
1119 dpurdie 637
    return;
638
 
639
    #-------------------------------------------------------------------------------
640
    # Function        : print_mf
641
    #
642
    # Description     : Internal Function
643
    #                   Print one line to the Manifest File
644
    #                   Checks the length of the line being created
645
    #
646
    # Inputs          : $line
647
    #
648
    # Returns         : 
649
    #
650
 
651
    sub print_mf
652
    {
653
        foreach  ( @_ )
654
        {
655
            ReportError ( "Manifest line too long",
656
                    "Line: $_" ) if ( length ($_) > 79 );
657
            print MF $_ . "\n";
658
        }
659
    }
660
 
661
}
662
 
663
1;