Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
1119 dpurdie 1
########################################################################
6302 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
1119 dpurdie 3
#
6302 dpurdie 4
# Module name   : ManifestFiles.pm
1119 dpurdie 5
# Module type   : Makefile system
6302 dpurdie 6
# Environment(s): JATS Build System
5654 dpurdie 7
# Documents     : MASS-00232 Format of the Linux App Upgrade Manifest File
1119 dpurdie 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;
5649 dpurdie 27
use Digest::file qw(digest_file_hex);
5771 alewis 28
use Digest::file qw(digest_file_base64);
1119 dpurdie 29
 
30
#
31
#   Globals
32
#
33
my @Manifests;                      # Manifest entries
1125 alewis 34
my $Manifest_has_version = 1;       # Create Manifest_xxxx by default
1121 dpurdie 35
my %package_dirs;                   # Package dirs discovered and used
1125 alewis 36
my $pkg_subdir;                     # Alternate packaging
1119 dpurdie 37
 
38
#-------------------------------------------------------------------------------
39
# Function        : BEGIN
40
#
41
# Description     : Setup directive hooks
42
#                   Register a function to be called just before we start to
43
#                   generate makefiles. This will be used to process the data
44
#                   collected in all the ManifestFiles directives
45
#
46
# Inputs          : None
47
#
48
# Returns         : None
49
#
50
BEGIN
51
{
52
    RegisterMakefileGenerate (\&ManifestFiles_Generate);
53
}
54
 
55
#-------------------------------------------------------------------------------
56
# Function        : ManifestFiles
57
#
58
# Description     : Create a ManifestFiles entry
59
#
60
# Inputs          : Platform             - Active Platform Selector
61
#                   Options              - One or more options
62
#                       --Name=Name             - Mandatory
63
#                       --Tier=Name             - Mandatory
64
#                       --Architecture=xxxx     - Default actitecture is the current target
65
#                       --Product=yyyy          - Product Family
66
#                       --Debian=BaseName[,--Prod,--Debug,--Arch=xxxx,--Product=yyyy]
6302 dpurdie 67
#                       --Apk=BaseName[,--Prod,--Debug,--Platform=pppp]
68
#                                                   Default platform = ANDROID
69
#                                                   Default type = Production
1119 dpurdie 70
#                       --MugPackage=Package[,--Subdir=subdir[,subdir]+]
71
#                       --SrcFile=xxx
1125 alewis 72
#                       --SrcFileNoCopy=xxx
1123 dpurdie 73
#                       --Comment=xxx           - Add comment to Manifst
1125 alewis 74
#                       --NoManifestVersion     - Create unversioned Manifest File
75
#                       --PkgSubdir=xxx         - Specifies packaging subdir
5105 dpurdie 76
#                       --ImportManifest=Package[,--Subdir=subdir,--ReWrite] - Import Manifest from package
5649 dpurdie 77
#                       --Md5                   - Add MD5 checksums to the Manifest File
5767 alewis 78
#                       --Dmf                   - Generate the Device Management Framework
79
#                                                 combined archive ZIP file.
80
#                       --DmfVersion=xxxx       - Generate the Device Management Framework
81
#                                                 combined archive ZIP using a modified
82
#                                                 version number; only for testing!
1119 dpurdie 83
#
84
# Returns         : Nothing
85
#
86
sub ManifestFiles
87
{
88
    my( $platforms, @elements ) = @_;
89
    Debug2( "ManifestFiles($platforms, @elements)" );
90
    return if ( ! ActivePlatform($platforms) );
91
 
92
    my $name;
93
    my $tier;
94
    my @files;
95
    my $mug_dir;
96
    my $default_arch = $::ScmPlatform;
97
    my $default_prod = '';
1129 dpurdie 98
    my $imported_manifest = 0;
5649 dpurdie 99
    my $include_md5 = 0;
5767 alewis 100
    my $generate_dmf = 0;
5771 alewis 101
    my $dmf_version = $::ScmBuildVersionFull;
1119 dpurdie 102
 
103
    #
104
    #   Collect user options
105
    #
106
    foreach ( @elements )
107
    {
108
        if ( m~^--Name=(.+)~ ) {
6302 dpurdie 109
            if ( $name ) {
1119 dpurdie 110
                ReportError ("ManifestFiles:--Name option is only allowed once");
111
                next;
112
            }
113
            $name = $1;
114
 
115
        } elsif ( m~^--Tier=(.+)~ ) {
6302 dpurdie 116
            if ( $tier ) {
1119 dpurdie 117
                ReportError ("ManifestFiles:--Tier option is only allowed once");
118
                next;
119
            }
120
            $tier = $1;
121
 
1123 dpurdie 122
        } elsif ( m~^--Comment=~ ) {
123
            my $cmt = $_;
124
            $cmt =~ s~.+=~~;
125
            $cmt =~ s~\s*\n\s*~\n~g;
126
            push @files, {'cmt' => $cmt };
127
 
1119 dpurdie 128
        } elsif ( m~^--Debian=(.+)~ ) {
6302 dpurdie 129
            push @files, {'file' => _LocateDebianFile($1, $default_arch, $default_prod)};
1119 dpurdie 130
 
6302 dpurdie 131
        } elsif ( m~^--Apk=(.+)~ ) {
132
            push @files, {'file' => _LocateApkFile($1, $default_arch)};
133
 
1119 dpurdie 134
        } elsif ( m~^--SrcFile=(.+)~ ) {
1123 dpurdie 135
            push @files, {'file' => LocatePreReq($1)};
5649 dpurdie 136
 
1125 alewis 137
        } elsif ( m~^--SrcFileNoCopy=(.+)~ ) {
138
            push @files, {'filenocopy' => $1};
5649 dpurdie 139
 
1119 dpurdie 140
        } elsif ( m~^--MugPackage=(.+)~ ) {
6302 dpurdie 141
            if ( $mug_dir ) {
1119 dpurdie 142
                ReportError ("ManifestFiles:--MugPackage option is only allowed once");
143
                next;
5649 dpurdie 144
            }
6302 dpurdie 145
            $mug_dir = _LocateMugDir($1);
1119 dpurdie 146
 
147
        } elsif ( m/^--Arch(.*)=(.+)/ ) {
148
            $default_arch = $2;
149
 
150
        } elsif ( m/^--Product=(.+)/ ) {
151
            $default_prod = $1;
152
 
1125 alewis 153
        } elsif ( m/^--NoManifestVersion/i ) {
154
            $Manifest_has_version = 0;
155
 
156
        } elsif ( m/^--PkgSubdir=(.+)/i ) {
6302 dpurdie 157
            if ( $pkg_subdir ) {
1129 dpurdie 158
                ReportError ("ManifestFiles:--PkgSubdir option is only allowed once");
1125 alewis 159
                next;
160
            }
161
            $pkg_subdir = $1;
162
 
1129 dpurdie 163
        } elsif ( m/^--ImportManifest=(.+)/i ) {
6302 dpurdie 164
            my $import_info = _ImportManifest($1, $tier, $name);
1129 dpurdie 165
#DebugDumpData("ImportInfo", $import_info );
166
            push @files, {'manifest' => $import_info };
167
 
168
            #
169
            #   Fill in details unless already provided
170
            #
171
            $tier = $import_info->{'tier'} unless ( defined $tier );
172
            $name = $import_info->{'name'} unless ( defined $name );
173
            $imported_manifest = 1;
174
 
5649 dpurdie 175
        } elsif (m/^--Md5/i) {
176
            $include_md5 = 1
177
 
5767 alewis 178
        } elsif (m/^--Dmf/i) {
179
            $generate_dmf = 1
180
 
181
        } elsif ( m/^--DmfVersion=(.+)/ ) {
182
            $generate_dmf = 1;
183
            $dmf_version = $1;
184
 
1119 dpurdie 185
        } else {
186
            ReportError ("ManifestFiles: Unknown option or argument: $_");
187
 
188
        }
189
    }
190
 
191
    #
192
    #   Sanity test the user options
193
    #
194
    ReportError ("ManifestFiles: No name specified")
195
        unless $name;
196
    ReportError ("ManifestFiles: No tier specified")
1129 dpurdie 197
        unless defined ($tier);
6302 dpurdie 198
    ReportError ("ManifestFiles: Cannot mix --Debian/-Apk/--SrcFile with --MugPackage in one directive")
1129 dpurdie 199
        if ( $mug_dir && (@files || $imported_manifest) );
1119 dpurdie 200
    ReportError ("ManifestFiles: Must specify files to add to Manifest")
1129 dpurdie 201
        unless ( $mug_dir ||  @files || $imported_manifest);
1119 dpurdie 202
    ErrorDoExit();
203
 
204
    #
205
    #   Save information for processing at the end of the parsing phase
206
    #   Data collected from ALL the ManifestFiles directives will be collected
207
    #   and processed into one Manifest file
208
    #
209
    my %data;
210
    $data{tier} = $tier;
211
    $data{name} = $name;
212
    $data{files} = \@files;
213
    $data{mugdir} = $mug_dir;
1125 alewis 214
    $data{pkgsubdir} = $pkg_subdir;
5649 dpurdie 215
    $data{md5} = $include_md5;
5767 alewis 216
    $data{dmf} = $generate_dmf;
217
    $data{arch} = $default_arch;
218
    $data{dmf_version} = $dmf_version;
219
 
1129 dpurdie 220
#DebugDumpData("DirectiveData", \%data );
1119 dpurdie 221
 
222
    push @Manifests, \%data;
223
    return;
6302 dpurdie 224
}
1119 dpurdie 225
 
6302 dpurdie 226
#-------------------------------------------------------------------------------
227
# Function        : _LocateDebianFile
228
#
229
# Description     : Locate a debian file
230
#                   Internal Function
231
#
232
#                   Scan packages for the Debian package specified
233
#                   The user provides the base name of the package
234
#                   A Debian Package name has several fields
235
#                   These are:
236
#                       1) Base Name - Provided by the user
237
#                       2) Version - Version will be wildcarded
238
#                       3) Architecture - Wildcarded. Uses bin/arch directory
239
#
240
#                   Expect to find Debian Packages in the bin/PLATFORM subdir
241
#
242
# Inputs          : Debian base name, complete with suboptions
243
#
244
# Returns         : Full path of the file
245
#
246
sub _LocateDebianFile
247
{
248
    my ($arg, $arch, $product) = @_;
249
    Verbose("LocateDebianFile: Processing: $arg");
250
 
251
    my @type = qw( P D );
252
    my @debian_file_path;
253
 
1119 dpurdie 254
    #
6302 dpurdie 255
    #   Extract sub-options
256
    #       --Prod[uction]
257
    #       --Debug
258
    #       --Arch[itecture]=yyy
259
    #       --Product=yyy
1119 dpurdie 260
    #
6302 dpurdie 261
    my ($base_name, @opts) = split( ',', $arg );
262
    foreach ( @opts )
263
    {
264
        if ( m/^--Arch(.*)=(.+)/ ) {
265
            $arch=$2;
266
        } elsif ( m/^--Product=(.+)/ ) {
267
            $product=$1;
268
        } elsif ( m/^--Prod/ ) {
269
            @type = 'P';
270
        } elsif ( m/^--Debug/ ) {
271
            @type = 'D';
272
        } else {
273
            Warning ('--Debian: Unknown Option: ' . $_);
274
        }
275
    }
276
 
5649 dpurdie 277
    #
6302 dpurdie 278
    #   Create a list of products
279
    #   ie: PRODUCT_ARCH
1119 dpurdie 280
    #
6302 dpurdie 281
    my @products;
282
    push @products, $product . '_' . $arch if ( $product );
283
    push @products, $arch;
284
 
1119 dpurdie 285
    #
6302 dpurdie 286
    #   Scan all packages for the specified debian package
1119 dpurdie 287
    #
6302 dpurdie 288
    foreach my $package_dir ( getPackagePaths ('--All') )
1119 dpurdie 289
    {
6302 dpurdie 290
        foreach my $type ( @type )
1119 dpurdie 291
        {
6302 dpurdie 292
            foreach my $prd ( @products )
1119 dpurdie 293
            {
6302 dpurdie 294
                foreach my $joiner ( qw(/ .) )
1119 dpurdie 295
                {
6302 dpurdie 296
                    my $dir = "$package_dir/bin$joiner$prd$type";
5873 acammell 297
                    Verbose("ManifestFiles: Search in $dir");
298
                    next unless ( -d $dir );
6302 dpurdie 299
                    my @files = glob ( "$dir/${base_name}_*.deb" );
5873 acammell 300
                    next unless ( @files );
301
                    push @debian_file_path, @files;
302
                    $package_dirs{$package_dir}{used} = 1;
303
                }
304
            }
1119 dpurdie 305
        }
6302 dpurdie 306
        foreach my $type ( @type )
307
        {
308
            foreach my $prd ( @products )
309
            {
310
                my $dir = "$package_dir";
311
                Verbose("ManifestFiles: Search in $dir");
312
                next unless ( -d $dir );
313
                my @files = glob ( "$dir/${base_name}_*_${prd}_${type}.deb" );
314
                next unless ( @files );
315
                push @debian_file_path, @files;
316
                $package_dirs{$package_dir}{used} = 1;
317
            }
318
        }
1119 dpurdie 319
    }
320
 
6302 dpurdie 321
    ReportError ("Required Debian package not found: $base_name") unless @debian_file_path;
322
    ReportError ("Multiple matching Debian Packages located: $base_name", @debian_file_path ) if ( $#debian_file_path > 0 );
323
    return $debian_file_path[0];
324
}
325
 
326
#-------------------------------------------------------------------------------
327
# Function        : _LocateApkFile
328
#
329
# Description     : Locate a APK file
330
#                   Internal Function
331
#
332
#                   Scan packages for the APK package specified
333
#                   The user provides the base name of the package
334
#                   APK ( Android Packages )
335
#                   Expect to have a '-release' or '-debug' suffix, except those provided via a
336
#                   3rd party SDK.
337
#                   Expect to find APK Packages in the bin/PLATFORM(P/D) subdir
338
#                   Expect to find -debug in the <PLATFORM>D directory
339
#                   Expect to find -release' in the <PLATFORM>P directory
340
#                   
341
#                   Allow for:
342
#                       Full path to .apk file
343
#                       .apk in package root directory
344
#
345
# Inputs          : Apk base name, complete with suboptions
346
#
347
# Returns         : Full path of the file
348
#
349
sub _LocateApkFile
350
{
351
    my ($arg, $arch) = @_;
352
    Verbose("LocateApkFile: Processing: $arg");
353
 
354
    my @type = qw( P );
355
    my @apk_file_path;
356
    my %type = ('P' => '-release', 'D' => '-debug' );
357
 
1119 dpurdie 358
    #
6302 dpurdie 359
    #   Extract sub-options
360
    #       --Prod[uction]
361
    #       --Debug
362
    #       --Architecture=yyy
1119 dpurdie 363
    #
6302 dpurdie 364
    my ($base_name, @opts) = split( ',', $arg );
365
    foreach ( @opts )
1119 dpurdie 366
    {
6302 dpurdie 367
        if ( m/^--Arch(.*)=(.+)/ ) {
368
            $arch=$2;
369
        } elsif ( m/^--Prod/ ) {
370
            @type = 'P';
371
        } elsif ( m/^--Debug/ ) {
372
            @type = 'D';
373
        } else {
374
            Warning ('--Apk: Unknown Option: ' . $_);
1119 dpurdie 375
        }
6302 dpurdie 376
    }
1119 dpurdie 377
 
6302 dpurdie 378
    #
379
    #   Scan all packages for the specified APK package
380
    #   Try:
381
    #       Raw name - for apks from the SDK or 3rd parties
382
    #       PLATFORM(P|D)/baseName-(release|debug) - Expected
383
    #       baseName-(release|debug) - Repackaged badly
384
    #       
385
    foreach my $package_dir ( getPackagePaths ('--All') )
386
    {
387
        my $testFile;
388
        $testFile = "$package_dir/${base_name}.apk";
389
        if ( -f $testFile ) {
390
                push @apk_file_path, $testFile;
1119 dpurdie 391
        }
392
 
6302 dpurdie 393
 
394
        foreach my $type ( @type )
1119 dpurdie 395
        {
6302 dpurdie 396
            my $typeSuffix = $type{$type};
397
            foreach my $joiner ( qw(/ .) )
1119 dpurdie 398
            {
6302 dpurdie 399
                my $dir = "$package_dir/bin$joiner$arch$type";
400
                Verbose("ManifestFiles: Search in $dir");
401
                next unless ( -d $dir );
402
                $testFile = "$dir/${base_name}${typeSuffix}.apk";
403
                if ( -f $testFile ) {
404
                        push @apk_file_path, $testFile;
405
                }
1119 dpurdie 406
            }
407
        }
6302 dpurdie 408
        foreach my $type ( @type )
409
        {
410
            my $typeSuffix = $type{$type};
411
            my $dir = "$package_dir";
412
            Verbose("ManifestFiles: Search in $dir");
413
            next unless ( -d $dir );
414
            my $testFile = "$dir/${base_name}${typeSuffix}.apk";
415
            if ( -f $testFile ) {
416
                    push @apk_file_path, $testFile;
417
            }
418
        }
419
        $package_dirs{$package_dir}{used} = 1 if (@apk_file_path) ;
1119 dpurdie 420
    }
1129 dpurdie 421
 
6302 dpurdie 422
    ReportError ("Required APK package not found: $base_name") unless @apk_file_path;
423
    ReportError ("Multiple matching APK Packages located: $base_name", @apk_file_path ) if ( $#apk_file_path > 0 );
424
    return $apk_file_path[0];
425
}
426
 
427
#-------------------------------------------------------------------------------
428
# Function        : _LocateMugDir
429
#
430
# Description     : Locate the directory containing the mugfiles
431
#                   Internal Function
432
#
433
# Inputs          : Mufile package, with embedded options
434
#
435
# Returns         : Full path
436
#
437
sub _LocateMugDir
438
{
439
    my ($mug_package) = @_;
440
 
1129 dpurdie 441
    #
6302 dpurdie 442
    #   Locate the mugfile subdir
1129 dpurdie 443
    #
6302 dpurdie 444
    my $package_name = $mug_package;
445
    my @dirs = 'mug';
446
    my $mug_dir;
447
 
1129 dpurdie 448
    #
6302 dpurdie 449
    #   Extract sub options
450
    #       --Subdir=xxxx,yyyy,zzzz
1129 dpurdie 451
    #
6302 dpurdie 452
    if ( $package_name =~ m/(.*?),--Subdir=(.*)/ )
1129 dpurdie 453
    {
6302 dpurdie 454
        $package_name = $1;
455
        @dirs = split( ',', $2 );
456
    }
1129 dpurdie 457
 
6302 dpurdie 458
    my $package = GetPackageEntry( $package_name );
459
    unless ( $package )
460
    {
461
        ReportError ("ManifestFiles: Package not known to build: $package_name");
462
        return undef;
463
    }
1129 dpurdie 464
 
6302 dpurdie 465
    foreach my $subdir ( @dirs )
466
    {
467
        my $dir = "$package->{'ROOT'}/$subdir";
468
        if ( -d $dir )
1129 dpurdie 469
        {
6302 dpurdie 470
            Warning ("Multiple Mugfile directories located. Only the first will be used",
471
                     "Ignoring: $subdir" )if ( $mug_dir );
472
            $mug_dir = $dir;
473
        }
474
    }
475
    ReportError ("Mugfile directory not found in package: $package_name")
476
        unless $mug_dir;
5105 dpurdie 477
 
6302 dpurdie 478
    return $mug_dir;
479
}
5105 dpurdie 480
 
1129 dpurdie 481
 
6302 dpurdie 482
#-------------------------------------------------------------------------------
483
# Function        : _ImportManifest
484
#
485
# Description     : Import an existing manifest
486
#
487
# Inputs          : Args    - PackageName[,Subdir=name,--ReWrite]
488
#                   tier    - May be null
489
#                   name    - May be null
490
#
491
# Returns         : A hash of data to be used later
492
#
493
sub _ImportManifest
494
{
495
    my ($args, $tier, $name) = @_;
496
    my @file_contents;
497
    my @file_list;
1129 dpurdie 498
 
6302 dpurdie 499
    #
500
    #   Locate the mugfile subdir
501
    #
502
    my $package_name = $args;
503
    my @dirs = 'mug';
504
    my $pkg_dir;
505
    my $pkg_root;
506
    my $manifest;
507
    my $first_tier;
508
    my $first_name;
509
    my $rewrite;
510
 
511
    #
512
    #   Extract sub options
513
    #       --Subdir=xxxx,yyyy,zzzz
514
    #       --ReWrite
515
    #
516
    if ( $package_name =~ m/(.*?)(,.*)/ )
517
    {
518
        $package_name = $1;
519
        my @subargs = split(',--', $2);
520
        foreach ( @subargs)
5105 dpurdie 521
        {
6302 dpurdie 522
            next unless (length($_) > 0);
523
            if (m~^Subdir=(.*)~i){
524
                @dirs = split( ',', $1 );
5105 dpurdie 525
 
6302 dpurdie 526
            } elsif (m~^ReWrite~i) {
527
                $rewrite = 1;
528
 
529
            } else {
530
                ReportError("ManifestFiles: Unknown suboption to ImportManifest:" . $_);
1129 dpurdie 531
            }
532
        }
6302 dpurdie 533
    }
1129 dpurdie 534
 
6302 dpurdie 535
    my $package = GetPackageEntry( $package_name );
536
    unless ( $package )
537
    {
538
        ReportError ("ManifestFiles: Package not known to build: $package_name");
539
        return undef;
540
    }
5105 dpurdie 541
 
6302 dpurdie 542
    if (defined ($rewrite) && ( !defined($tier) || !defined($name)))
543
    {
544
        ReportError ("ManifestFiles: ImportManifest. --ReWrite cannot be used unless tier and name are specified");
545
        return undef;
546
    }
1129 dpurdie 547
 
6302 dpurdie 548
    foreach my $subdir ( @dirs )
549
    {
550
        my $dir = "$package->{'ROOT'}/$subdir";
551
        my $root = $package->{'ROOT'};
552
        if ( -d $dir )
5105 dpurdie 553
        {
6302 dpurdie 554
            Warning ("Multiple Package directories located. Only the first will be used",
555
                     "Ignoring: $subdir" )if ( $pkg_dir );
556
            $pkg_dir = $dir;
557
            $pkg_root = $root;
5105 dpurdie 558
        }
6302 dpurdie 559
    }
1129 dpurdie 560
 
6302 dpurdie 561
    unless ($pkg_dir)
562
    {
563
        ReportError ("Package directory not found in package: $package_name");
564
        return undef;
565
    }
5105 dpurdie 566
 
6302 dpurdie 567
    #
568
    #   Determine Manifest File name
569
    #
570
    foreach my $file ( glob ($pkg_dir . '/Manifest*' ) )
571
    {
572
            next unless ( -f $file );
573
            Warning ("Multiple Manifest Files find. Only the first will be used",
574
                     "Using: $manifest",
575
                     "Ignoring: $file" ) if ( $manifest );
576
            $manifest = $file;
577
    }
578
 
579
    unless ($manifest)
580
    {
581
        ReportError ("ImportManifest. No Manifest found: $package_name");
582
        return undef;
583
    }
584
 
585
 
586
    #
587
    #
588
    #
589
    open (MF, '<', $manifest ) || Error ("Cannot open the Manifest file: $manifest", $!);
590
    while ( <MF> )
591
    {
1129 dpurdie 592
        #
6302 dpurdie 593
        #   Clean trailing whitespace ( line-feed and new lines )
594
        #   Comment out [Version] data
1129 dpurdie 595
        #
6302 dpurdie 596
        s~\s+$~~;
597
        s~(\s*\[Version])~#$1~;
598
 
5649 dpurdie 599
        #
6302 dpurdie 600
        #   Part lines and determine files
601
        #
602
        next unless ( $_ );
603
        next if ( m~\s*#~ );
604
        next if ( m~\s*\[~ );
605
        my( $aname, $atier, $afile) = split(/\s*\,\s*/, $_);
1129 dpurdie 606
#            print "---------- $_\n";
607
#            print "T: $atier, N:$aname, F:$afile\n";
6302 dpurdie 608
        push @file_list, $afile;
1129 dpurdie 609
 
6302 dpurdie 610
        #
611
        #   Rewrite the name and tier
612
        #
613
        if ($rewrite)
614
        {
615
            $_ = join(',', $name, $tier, $afile);
616
            $first_tier = $tier;
617
            $first_name = $name;
618
        }
619
        else
620
        {
1129 dpurdie 621
            #
6302 dpurdie 622
            #   Capture first tier and name
1129 dpurdie 623
            #
6302 dpurdie 624
            $first_tier = $atier unless ( defined $first_tier );
625
            $first_name = $aname unless ( defined $first_name );
1129 dpurdie 626
        }
6302 dpurdie 627
    }
628
    continue
629
    {
630
        push @file_contents, $_;
631
    }
632
    close MF;
1129 dpurdie 633
 
6302 dpurdie 634
    #
635
    #   Create a hash of data that describes the manifest that has
636
    #   just been read in.
637
    #
638
    $package_dirs{$pkg_root}{used} = 1;
639
    $manifest =~ s~.*/~~;
640
    return { 'contents' => \@file_contents,
641
              'files' => \@file_list,
642
              'file_base' => $pkg_dir,
643
              'manifest' => $manifest,
644
              'pkg_dir' => $pkg_root,
645
              'tier' => $first_tier,
646
              'name' => $first_name,
647
              'rewrite' => $rewrite,
648
            };
1119 dpurdie 649
}
650
 
651
#-------------------------------------------------------------------------------
652
# Function        : ManifestFiles_Generate
653
#
654
# Description     : Internal Function
655
#                   Process all the collected data and create directives
656
#                   for the creation of the manifest
657
#
658
#                   This function will be called, just before the Makefile
659
#                   is created. The function will:
660
#                       1) Create the Manifest File
661
#                       2) Package the Manifest File
662
#                       3) Package the manifest file contents
663
#
664
#                   using (mostly) normal makefile.pl directives.
665
#
666
# Inputs          : None
667
#
668
# Returns         : Nothing
669
#
670
sub ManifestFiles_Generate
671
{
672
    Debug ("ManifestFiles_Generate");
673
    Message ("Generating Manifest File");
1123 dpurdie 674
 
675
    #
676
    #   Need at least one Manifest Entry
677
    #
678
    return unless ( @Manifests );
1119 dpurdie 679
#DebugDumpData ( "Manifests", \@Manifests );
680
 
681
    #
1125 alewis 682
    #   Determine the target packaging directory
683
    #   Default is .../mug
684
    #
685
    my $pkgdir = 'mug';
1129 dpurdie 686
    if ( exists $Manifests[0]->{pkgsubdir} && defined $Manifests[0]->{pkgsubdir} )
1125 alewis 687
    {
688
        my $subdir = $Manifests[0]->{pkgsubdir};
689
        $pkgdir .= '/' . $subdir;
690
        $pkgdir =~ s~^mug/mug~mug~;
691
    }
692
 
693
    #
1119 dpurdie 694
    #   Create the Manifest File as we process the lists
1125 alewis 695
    #   Place this in the 'lib' directory:
1119 dpurdie 696
    #       - So that it will be deleted on clobber
1123 dpurdie 697
    #       - So that it can be placed in a target-specific subdir
1125 alewis 698
    #       - So that we can have one per makefile.pl
1119 dpurdie 699
    #
700
    Error ("ManifestFiles: Needs local directory specified in build.pl") unless ( $::ScmLocal );
701
 
1125 alewis 702
    my $manifest_dir = "$::ScmPlatform.LIB";
1119 dpurdie 703
    System( "$::GBE_BIN/mkdir -p $manifest_dir" );
704
 
1125 alewis 705
    my $manifest_file = $manifest_dir . '/Manifest';
706
    $manifest_file .= '_' . $::ScmBuildVersion if ( $Manifest_has_version );
707
    ToolsetGenerate( $manifest_file );
1119 dpurdie 708
    Verbose ("ManifestFiles_Generate: File: $manifest_file");
5649 dpurdie 709
 
1125 alewis 710
    PackageFile ('*', $manifest_file, '--Subdir=' . $pkgdir, '--Strip' );
1119 dpurdie 711
 
712
    open (MF, '>', $manifest_file ) || Error ("Cannot create the Manifest file: $manifest_file");
713
 
5711 kspencer 714
    binmode (MF);
5767 alewis 715
 
1119 dpurdie 716
    print_mf ("# PackageName: $::ScmBuildPackage");
717
    print_mf ("# PackageVersion: $::ScmBuildVersion");
718
    print_mf ("# BuildDate: $::CurrentTime");
719
    print_mf ("#");
720
    print_mf ("[Version],$::ScmBuildVersion");
721
    print_mf ("#");
722
 
723
    #
1125 alewis 724
    #   Process each tier in the order presented in the source file
1119 dpurdie 725
    #
1123 dpurdie 726
    my $last_was_comment = 0;
1119 dpurdie 727
    foreach my $entry ( @Manifests )
728
    {
1127 alewis 729
    #print_mf ("#");
1119 dpurdie 730
 
731
#DebugDumpData ( "Manifest Entry", $entry );
732
 
733
        my $tier = $entry->{tier};
734
        my $name = $entry->{name};
5649 dpurdie 735
        my $include_md5 = $entry->{md5};
1119 dpurdie 736
 
5767 alewis 737
        if ( $entry->{dmf} )
738
        {
6302 dpurdie 739
            DmfGenerate($entry);
5767 alewis 740
        }
741
 
1119 dpurdie 742
        #
743
        #   Insert all the files that have been specified
744
        #   The user specified order is preserved
745
        #
1123 dpurdie 746
        #   Entries may be either a file or a comment
747
        #   Comments: Merge multiple comments and create blocks
748
        #
749
        #
1119 dpurdie 750
        my @files = @{ $entry->{files} };
1123 dpurdie 751
        foreach my $fentry ( @files )
1119 dpurdie 752
        {
1123 dpurdie 753
            if ( my $cmt = $fentry->{'cmt'} )
754
            {
755
                print_mf ('') unless ( $last_was_comment ) ;
756
                print_mf ( map (('# ' . $_) , split ("\n", $cmt) ));
757
                $last_was_comment = 1;
758
                next;
759
            }
760
 
761
            print_mf ('#') if ( $last_was_comment );
762
            if ( my $file = $fentry->{'file'} )
763
            {
764
                my $base_file = StripDir( $file );
5649 dpurdie 765
                if ($include_md5) {
766
                    my $md5 = digest_file_hex($file, 'MD5');
5654 dpurdie 767
                    print_mf ('--NoCheckLineWidth', "$name,$tier,$base_file,MD5=$md5");
5649 dpurdie 768
                } else {
769
                    print_mf ("$name,$tier,$base_file");
770
                }
1125 alewis 771
                PackageFile ('*', $file, '--Subdir=' . $pkgdir, '--Strip' );
1123 dpurdie 772
                $last_was_comment = 0;
773
            }
1125 alewis 774
 
775
            if ( my $file = $fentry->{'filenocopy'} )
776
            {
777
                print_mf ("$name,$tier,$file");
778
                $last_was_comment = 0;
779
            }
1129 dpurdie 780
 
781
            if ( my $emf = $fentry->{'manifest'} )
782
            {
783
                $last_was_comment = 0;
784
                #
785
                #   Insert the entire manifest
786
                #   Items are:
787
                #        contents
788
                #        files
789
                #        file_base
790
                #        manifest
791
                #
792
#DebugDumpData ( "Embedded Manifest Entry", $emf );
793
                print_mf ( '## Included Manifest: ' .  $emf->{'manifest'}  );
794
                print_mf ($_) foreach  ( @{$emf->{'contents'}} );
795
                PackageFile ('*', $emf->{'file_base'}. '/' . $_, '--Subdir=' . $pkgdir, '--Strip' )foreach  ( @{$emf->{'files'}});;
796
                print_mf ( '## End Included Manifest' );
797
            }
1119 dpurdie 798
        }
799
 
800
        #
801
        #   Expand out the entire MUG directory
802
        #   All .mug files in the MUG directory will be added to the manifest
803
        #   The assumption is that the MUG directory has been created by
804
        #   something that knows what its doing
805
        #
806
        if ( my $mugdir = $entry->{mugdir} )
807
        {
808
            foreach my $file ( glob ($mugdir . '/*.mug' ) )
809
            {
810
                next unless ( -f $file );
811
                my $base_file = StripDir($file);
5654 dpurdie 812
                if ($include_md5) {
813
                    my $md5 = digest_file_hex($file, 'MD5');
814
                    print_mf ('--NoCheckLineWidth', "$name,$tier,$base_file,MD5=$md5");
815
                } else {
816
                    print_mf ("$name,$tier,$base_file");
817
                }
1119 dpurdie 818
                PackageFile ('*', $file, '--Subdir=mug', '--Strip' );
819
            }
820
        }
821
    }
822
 
823
    #
824
    #   Complete the creation of the Manifest File
825
    #
826
    print_mf ("#");
827
    print_mf ("# End of File");
828
    close MF;
829
    ErrorDoExit();
1121 dpurdie 830
 
831
    #
832
    #   Sanity test of packages that did not provide a debian file
833
    #   Just a hint that something may have been missed
834
    #
835
    my @not_used_packages;
836
    foreach my $package_dir ( getPackagePaths ('--All') )
837
    {
838
        next if ( $package_dir =~ m~/manifest-tool/~ );
839
        unless ( exists $package_dirs{$package_dir}{used} )
840
        {
841
            push @not_used_packages, $package_dir;
842
        }
843
    }
844
    if ( @not_used_packages )
845
    {
846
        Warning ("Packages that did not contribute packages to the manifest:",
847
                  @not_used_packages );
848
    }
849
 
1119 dpurdie 850
    return;
851
 
852
    #-------------------------------------------------------------------------------
853
    # Function        : print_mf
854
    #
855
    # Description     : Internal Function
856
    #                   Print one line to the Manifest File
857
    #                   Checks the length of the line being created
858
    #
859
    # Inputs          : $line
860
    #
5649 dpurdie 861
    # Returns         :
1119 dpurdie 862
    #
863
 
864
    sub print_mf
865
    {
5649 dpurdie 866
        my $check_line_width = 1;
867
 
868
        if ($_[0] eq '--NoCheckLineWidth')
869
        {
870
            shift @_;
871
            $check_line_width = 0;
872
        }
873
 
1119 dpurdie 874
        foreach  ( @_ )
875
        {
876
            ReportError ( "Manifest line too long",
5649 dpurdie 877
                    "Line: $_" ) if ( $check_line_width && length ($_) > 79);
1119 dpurdie 878
            print MF $_ . "\n";
879
        }
880
    }
881
}
882
 
5767 alewis 883
# Bring in the DMF build requirements.
884
my $directory;
885
BEGIN {
886
    use File::Spec::Functions qw(rel2abs);
887
    use File::Basename qw(dirname);
888
 
889
    my $path = rel2abs( __FILE__ );
890
    $directory = dirname( $path );
891
}
892
use lib $directory;
893
 
894
use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
895
use JSON;
896
 
897
#-------------------------------------------------------------------------------
898
# Function        : DmfGenerate
899
#
900
# Description     : Import an existing manifest
901
#
902
# Inputs          : entry   - The manifest that is being processed.
903
#
904
# Returns         : Nothing
905
#
906
sub DmfGenerate
907
{
908
    my ($entry) = @_;
909
 
910
    # Get the generation time.
911
    my $gen_time = time();
912
 
913
    my $work_dir = "$::ScmPlatform.BIN/";
914
    System( "$::GBE_BIN/mkdir -p $work_dir" );
915
 
916
    my $name = $entry->{name};
917
    my $version = $entry->{dmf_version};
918
 
919
    # Configure base manifest information.
920
    my %manifest;
5771 alewis 921
    $manifest{'mugsetId'} = $name . '_' . $version;
5767 alewis 922
    $manifest{'name'} = $name;
923
    $manifest{'version'} = $version;
5771 alewis 924
    $manifest{'packageName'} = $::ScmBuildPackage;
925
    $manifest{'packageVersion'} = $::ScmBuildVersionFull;
5767 alewis 926
    $manifest{'datetime'} = localtime($gen_time);
927
    $gen_time *= 1000;  # Make to milliseconds
928
    $manifest{'timestamp'} = $gen_time;
929
    $manifest{'tier'} = $entry->{tier};
930
 
931
    # Process each file.
932
    my @files = @{ $entry->{files} };
933
    my $zip = Archive::Zip->new();
934
    my $i = 0;
935
    foreach my $fentry ( @files )
936
    {
937
        if ( my $file = $fentry->{'file'} )
938
        {
6302 dpurdie 939
            my $order = $i + 1;
5767 alewis 940
            my $base_file = StripDir( $file );
941
            my $publish_file = $name . '_' . $version . '_' . $order . '.aup';
942
            my $aup_file = $work_dir . $publish_file;
943
 
944
            GenerateCesFile($file, $aup_file, 0x3, $gen_time, $publish_file);
945
 
946
            my $file_member = $zip->addFile( $aup_file, $publish_file );
947
 
948
            $manifest{'tasks'}[$i]{'order'} = 1 * $order;
949
            $manifest{'tasks'}[$i]{'filename'} = $base_file;
950
            $manifest{'tasks'}[$i]{'download'} = $publish_file;
5771 alewis 951
            $manifest{'tasks'}[$i]{'sha256'} = digest_file_base64($file, 'SHA-256');
952
            $manifest{'tasks'}[$i]{'size'} = -s $file;
953
 
5767 alewis 954
            if ($base_file =~ /\.sh$/)
955
            {
956
                $manifest{'tasks'}[$i]{'action'} = 'exec-shell';
957
            }
958
            elsif ($base_file =~ /\.deb$/)
959
            {
960
                $manifest{'tasks'}[$i]{'action'} = 'dpkg-install';
5771 alewis 961
 
962
                my ($pkg_name, $pkg_version, $pkg_arch) = ($base_file =~ /([^_]*)_([^_]*)_(.*)/);
963
                $manifest{'tasks'}[$i]{'arch'} = $pkg_arch;
964
                $manifest{'tasks'}[$i]{'name'} = $pkg_name;
965
                $manifest{'tasks'}[$i]{'version'} = $pkg_version;
5767 alewis 966
            }
967
            else
968
            {
969
                ReportError ("Manifest entry $base_file does not have a supported DMF install action");
970
            }
971
 
972
            $i = $i + 1;
973
        }
974
    }
975
 
976
    # Encode and commit the JSON.
977
    my $json_encoder = JSON->new->allow_nonref;
978
    my $json = $json_encoder->pretty->encode( \%manifest );
979
 
980
    my $manifest_filename = $name . '_' . $version;
981
    my $aum_filename = $manifest_filename . '_0.aum';
982
    my $manifest_file = $work_dir . $manifest_filename . '.json';
983
    my $aum_file = $work_dir . $aum_filename;
984
 
985
    # Save our manifest.
986
    open (J, '>', $manifest_file ) || Error ("Cannot create the DMF Manifest file");
987
    binmode (J);
988
    print J $json;
989
 
990
    close J;
991
 
992
    GenerateCesFile($manifest_file, $aum_file, 0x2, $gen_time, $aum_filename);
993
 
994
    $zip->addFile($aum_file, $aum_filename);
995
 
996
    my $zip_filename = $work_dir . $name . '_' . $version . '.zip';
997
    if ( $zip->writeToFileNamed($zip_filename) != AZ_OK )
998
    {
999
        ReportError("DMF ZIP file creation failed");
1000
    }
1001
    PackageFile('*', $zip_filename, '--Strip');
1002
    PackageFile('*', $manifest_file, '--Strip');
1003
 
1004
}
1005
 
1006
#-------------------------------------------------------------------------------
1007
# Function        : DmfGenerate
1008
#
1009
# Description     : Import an existing manifest
1010
#
1011
# Inputs          : src_file     - The input file.
1012
#                   dst_file     - The output CES file.
1013
#                   content_type - The content type to report.
1014
#                   gen_time     - The generation time for the file.
1015
#                   filename     - The filename to embed in the CES file.
1016
#
1017
#
1018
# Returns         : Nothing
1019
#
1020
sub GenerateCesFile
1021
{
1022
    my ($src_file, $dst_file, $content_type, $gen_time, $filename) = @_;
1023
 
1024
    open (INF, '<', $src_file ) || Error ("Cannot open file $src_file for reading");
1025
    binmode (INF);
1026
 
1027
    open (OUTF, '>', $dst_file ) || Error ("Cannot open file $dst_file for writing");
1028
    binmode (OUTF);
1029
 
1030
    my $signing_key_name = "";
1031
    my $signature_size = 0;
1032
    my $format_version = 0xCE500000;
1033
    my $compression_method = 0;
1034
    my $encryption_method = 0;
1035
    my $kek_name = "";
1036
    my $encryption_key_size = 0;
1037
    my $filename_size = length($filename);
1038
 
1039
    print OUTF pack("Z32", $signing_key_name);
1040
    print OUTF pack("n", $signature_size);
1041
    print OUTF pack("N", $format_version);
1042
    print OUTF pack("N", $content_type);
1043
    print OUTF pack("Q>", $gen_time);
1044
    print OUTF pack("N", $compression_method);
1045
    print OUTF pack("N", $encryption_method);
1046
    print OUTF pack("Z32", $kek_name);
1047
    print OUTF pack("n", $encryption_key_size);
1048
    print OUTF pack("n", $filename_size);
1049
    # Encryption key HERE
1050
    print OUTF pack("A$filename_size", $filename);
1051
 
1052
    my $buf;
1053
    while (read(INF,$buf,65536))
1054
    {
1055
        print OUTF $buf;
1056
    }
1057
    print OUTF $buf;
1058
    close INF;
1059
 
1060
    # Signature HERE
1061
 
1062
    # Finish with file.
1063
    close OUTF;
1064
}
1065
 
1119 dpurdie 1066
1;