Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
407 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 program is invoked by the MakeDebianPackage
10
#                 directive, that is a part of this package
11
#
12
#                 The program will use a user-provided script in order
13
#                 to create a Debian Package.
14
#
15
#                 The user script may call a number of directives in order to
16
#                 construct an image of the package being installed.
17
#
18
#                 The script specifies Debian configuration scaripts that
19
#                 will be embedded in the package.
20
#
21
#                 This program will:
22
#                   Construct a filesystem image under control of the directives
23
#                   within the user script
24
#
25
#                   Massage the Debian control file
26
#
27
#                   Create a Debian Package
28
#
29
#                   Transfer it to the users 'BIN' directory, where it is
30
#                   available to be packaged.
31
#
32
#                 Summary of directives available to the user-script:
33
#                       AddInitScript           - Add an init script
34
#                       CatFile                 - Append to a file
35
#                       CopyDir                 - Copy directory tree
36
#                       CopyFile                - Copy a file
37
#                       CopyBinFile             - Copy an executable file
38
#                       CopyLibFile             - Copy a library file
39
#                       CreateDir               - Create a directory
40
#                       DebianFiles             - Specify control and script files
41
#                       EchoFile                - Place text into a file
42
#                       MakeSymLink             - Create a symbolic link
43
#                       PackageDescription      - Specify the package description
44
#                       SetFilePerms            - Set file permissions
45
#                       SetVerbose              - Control progress display
46
#                       IsProduct               - Flow control
47
#                       IsPlatform              - Flow control
48
#                       IsTarget                - Flow control
49
#
50
#                 Thoughts for expansion:
51
#                       ConvertFile             - Option to convert file(s) to Unix Text
52
#                       ReplaceTags             - Replace Tags on target file
53
#                       SrcDir                  - Extend path for resolving local files
54
#
55
#                   Less used:
56
#                        ExpandLinkFiles        - Expand .LINK files
57
#
58
#                   Internal Use:
59
#                        FindFiles              - Find a file
60
#                        ResolveFile            - Resolve a 'local' source file
61
#                        
62
#......................................................................#
63
 
64
require 5.6.1;
65
use strict;
66
use warnings;
67
 
68
use Getopt::Long;
69
use File::Path;
70
use File::Copy;
71
use File::Find;
72
use JatsSystem;
73
use FileUtils;
74
use JatsError;
75
use ReadBuildConfig;
76
 
77
#
78
#   Globals
79
#
80
my $DebianWorkDir;                          # Dir to create file system image within
81
 
82
#
83
#   Command line options
84
#
85
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
86
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
87
my $opt_vargs;                              # Verbose arg
88
my $opt_help = 0;
89
my $opt_manual = 0;
90
my $opt_clean = 0;
91
my $opt_platform;
92
my $opt_type;
93
my $opt_buildname;
94
my $opt_buildversion;
95
my $opt_interfacedir;
96
my $opt_target;
97
my $opt_product;
98
my $opt_package_script;
99
my $opt_interfaceincdir;
100
my $opt_interfacelibdir;
101
my $opt_interfacebindir;
102
my $opt_libdir;
103
my $opt_bindir;
104
my $opt_localincdir;
105
my $opt_locallibdir;
106
my $opt_localbindir;
107
my $opt_pkgdir;
108
my $opt_pkglibdir;
109
my $opt_pkgbindir;
110
my $opt_pkgpkgdir;
111
my $opt_output;
112
 
113
#
114
#   Options derived from script directives
115
#
116
my $opt_control = '';
117
my $opt_prerm = '';
118
my $opt_postrm = '';
119
my $opt_preinst = '';
120
my $opt_postinst = '';
121
my $opt_description;
122
 
123
 
124
#-------------------------------------------------------------------------------
125
# Function        : Main Entry point
126
#
127
# Description     : This function will be called when the package is initialised
128
#                   Extract arguments from the users environment
129
#
130
#                   Done here to greatly simplify the user script
131
#                   There should be no junk in the user script - keep it simple
132
#
133
# Inputs          :
134
#
135
# Returns         : 
136
#
137
main();
138
sub main
139
{
140
    my $result = GetOptions (
141
                "verbose:s"         => \$opt_vargs,
142
                "clean"             => \$opt_clean,
143
                "Type=s"            => \$opt_type,
144
                "BuildName=s"       => \$opt_buildname,
145
                "BuildVersion=s"    => \$opt_buildversion,
146
                "Platform=s"        => \$opt_platform,
147
                "Target=s"          => \$opt_target,
148
                "Product=s"         => \$opt_product,
149
                "DebianPackage=s"   => \$opt_package_script,
150
                "InterfaceDir=s"    => \$opt_interfacedir,
151
                "InterfaceIncDir=s" => \$opt_interfaceincdir,
152
                "InterfaceLibDir=s" => \$opt_interfacelibdir,
153
                "InterfaceBinDir=s" => \$opt_interfacebindir,
154
                "LibDir=s"          => \$opt_libdir,
155
                "BinDir=s"          => \$opt_bindir,
156
                "LocalIncDir=s"     => \$opt_localincdir,
157
                "LocalLibDir=s"     => \$opt_locallibdir,
158
                "LocalBinDir=s"     => \$opt_localbindir,
159
                "PackageDir=s"      => \$opt_pkgdir,
160
                "PackageLibDir=s"   => \$opt_pkglibdir,
161
                "PackageBinDir=s"   => \$opt_pkgbindir,
162
                "PackagePkgDir=s"   => \$opt_pkgpkgdir,
163
                "Output=s"          => \$opt_output,
164
    );
165
 
166
    $opt_verbose++ unless ( $opt_vargs eq '@' );
167
 
168
    ErrorConfig( 'name'    => 'DebianUtils',
169
                 'verbose' => $opt_verbose,
170
                 'debug'   => $opt_debug );
171
 
172
    #
173
    #   Init the FileSystem Uiltity interface
174
    #
175
    InitFileUtils();
176
 
177
    #
178
    #   Ensure that we have all required options
179
    #
180
    Error ("Platform not set")                  unless ( $opt_platform );
181
    Error ("Type not set")                      unless ( $opt_type );
182
    Error ("BuildName not set")                 unless ( $opt_buildname );
183
    Error ("BuildVersion not set")              unless ( $opt_buildversion );
184
    Error ("InterfaceDir not set")              unless ( $opt_interfacedir );
185
    Error ("Target not set")                    unless ( $opt_target );
186
    Error ("Product not set")                   unless ( $opt_product );
187
    Error ("DebianPackage not set")             unless ( $opt_package_script );
188
    Error ("Ouput File not set")                unless ( $opt_output );
189
 
190
    #
191
    #   Clean up the build name
192
    #   Match any work done in the MakeDebianPackage directive
193
    #
194
    $opt_buildname =~ s~_~-~g;
195
 
196
    #
197
    #   Read in relevent config information
198
    #
199
    ReadBuildConfig ($opt_interfacedir, $opt_platform, '--NoTest' );
200
 
201
    #
202
    #   Build the package image in a directory based on the target being created
203
    #
204
    $DebianWorkDir = "$opt_platform$opt_type.image";
205
 
206
    #
207
    #   Configure the System command to fail on any error
208
    #
209
    SystemConfig ( ExitOnError => 1 );
210
 
211
    #
212
    #   Extract the 'name' of the package from the output path
213
    #   Display purposes only
214
    #
215
    my $DebianPkgName = StripDirExt($opt_output);
216
 
217
    #
218
    #   Display variables used
219
    #
220
    Message    "=Building Debian Package =============================================";
221
    Message    "Build $opt_buildname";
222
    Message    "       Package: $opt_buildname";
223
    Message    "       Version: $opt_buildversion";
224
    Message    "  Building for: $opt_platform, $opt_target";
225
    Message    "       Product: $opt_product";
226
    Message    "          Type: $opt_type";
227
    Verbose    "       Verbose: $opt_verbose";
228
    Verbose    "  InterfaceDir: $opt_interfacedir";
229
    Message    "       Package: $DebianPkgName";
230
    Message    "======================================================================";
231
 
232
    #
233
    #   Perform Clean up
234
    #   Invoked during "make clean" or "make clobber"
235
    #
236
    if ( $opt_clean )
237
    {
238
        Message ("Remove packaging directory: $DebianWorkDir");
239
        rmtree( $DebianWorkDir );
240
        rmtree ($opt_output) if ( -f $opt_output );
241
        exit;
242
    }
243
 
244
    #
245
    #   Clean  out the WORK directory
246
    #   Always start with a clean slate
247
    #
248
    #   Ensure that the base of the directory tree does not have 'setgid'
249
    #       This will upset the debian packager
250
    #       This may be an artifact from the users directory and not expected
251
    #
252
    rmtree( $DebianWorkDir );
253
    mkpath( $DebianWorkDir );
254
 
255
    my $perm = (stat $DebianWorkDir)[2] & 0777;
256
    chmod ( $perm & 0777, $DebianWorkDir );
257
 
258
    #
259
    #   Invoke the user script to do the hard work
260
    #
261
    do $opt_package_script;
262
 
263
    #
264
    #   Complete the building of the package
265
    #
266
    BuildDebianPackage ();
267
    Message ("Created Debian Package");
268
}
269
 
270
#-------------------------------------------------------------------------------
271
# Function        : BuildDebianPackage
272
#
273
# Description     : This function will create the Debian Package
274
#                   and transfer it to the target directory
275
#
276
# Inputs          : None
277
#
278
# Returns         : Nothing
279
#
280
sub BuildDebianPackage
281
{
282
    Error ("BuildDebianPackage: No Control File or Package Description")
283
        unless ( $opt_control || $opt_description );
284
 
285
    #
286
    #   Convert the FileSystem Image into a Debian Package
287
    #       Insert Debian control files
288
    #
289
    Verbose ("Copy in the Debian Control Files");
290
    mkdir ( "$DebianWorkDir/DEBIAN" );
291
 
292
    CopyFile ( $opt_prerm,    "/DEBIAN", "prerm" )    if $opt_prerm;
293
    CopyFile ( $opt_postrm,   "/DEBIAN", "postrm" )   if $opt_postrm;
294
    CopyFile ( $opt_preinst,  "/DEBIAN", "preinst" )  if $opt_preinst;
295
    CopyFile ( $opt_postinst, "/DEBIAN", "postinst" ) if $opt_postinst;
296
 
297
    UpdateControlFile ($opt_control );
298
    System ( 'chmod', '-R', 'a+rx', "$DebianWorkDir/DEBIAN" );
299
    System ( 'build_dpkg.sh', '-b', $DebianWorkDir);
300
    System ( 'mv', '-f', "$DebianWorkDir.deb", $opt_output );
301
 
302
    System ("build_dpkg.sh", '-I', $opt_output) if (IsVerbose(1));
303
 
304
}
305
 
306
#-------------------------------------------------------------------------------
307
# Function        : UpdateControlFile
308
#
309
# Description     : Update the Debian 'control' file to fix up varoius fields
310
#                   within the file.
311
#
312
#                   If the files has not been specified, then a basic control
313
#                   file will be provided.
314
#
315
#                   This routine knows where the control file will be placed
316
#                   within the output work space.
317
#
318
# Inputs          : $src            - Path to source file
319
#                   Uses global variables
320
#
321
# Returns         : Nothing
322
#
323
sub UpdateControlFile
324
{
325
    my($src) = @_;
326
    my $dst = "$DebianWorkDir/DEBIAN/control";
327
 
328
    unless ( $src )
329
    {
330
        CreateControlFile();
331
        return;
332
    }
333
 
334
    Verbose ("UpdateControlFile: $dst" );
335
    $src = ResolveFile( 0, $src );
336
 
337
    open (SF, '<', $src) || Error ("UpdateControlFile: Cannot open $src");
338
    open (DF, '>', $dst) || Error ("UpdateControlFile: Cannot create:$dst");
339
    while ( <SF> )
340
    {
341
        s~\s*$~~;
342
        if ( m~^Package:~ ) {
343
            $_ = "Package: $opt_buildname";
344
 
345
        } elsif ( m~^Version:~ ) {
346
            $_ = "Version: $opt_buildversion";
347
 
348
        } elsif ( m~^Architecture:~ ) {
349
            $_ = "Architecture: $opt_platform";
350
 
351
        } elsif ( $opt_description && m~^Description:~ ) {
352
            $_ = "Description: $opt_description";
353
        }
354
        print DF $_ , "\n";
355
    }
356
    close (SF);
357
    close (DF);
358
}
359
 
360
#-------------------------------------------------------------------------------
361
# Function        : CreateControlFile
362
#
363
# Description     : Craete a basic debian control file
364
#
365
# Inputs          : Uses global variables
366
#
367
# Returns         : 
368
#
369
sub CreateControlFile
370
{
371
    my $dst = "$DebianWorkDir/DEBIAN/control";
372
 
373
    Verbose ("CreateControlFile: $dst" );
374
 
375
    open (DF, '>', $dst) || Error ("CreateControlFile: Cannot create:$dst");
376
    print DF "Package: $opt_buildname\n";
377
    print DF "Version: $opt_buildversion\n";
378
    print DF "Section: main\n";
379
    print DF "Priority: standard\n";
380
    print DF "Architecture: $opt_platform\n";
381
    print DF "Essential: yes\n";
382
    print DF "Maintainer: ERG\n";
383
    print DF "Description: $opt_description\n";
384
    close (DF);
385
}
386
 
387
#-------------------------------------------------------------------------------
388
# Function        : SetVerbose
389
#
390
# Description     : Set the level of verbosity
391
#                   Display activity
392
#
393
# Inputs          : Verbosity level
394
#                       0 - Use makefile verbosity (Default)
395
#                       1..2
396
#
397
# Returns         : 
398
#
399
sub SetVerbose
400
{
401
    my ($level) = @_;
402
 
403
    $level = $opt_verbose unless ( $level );
404
    $opt_verbose = $level;
405
    ErrorConfig( 'verbose' => $level);
406
}
407
 
408
 
409
#-------------------------------------------------------------------------------
410
# Function        : DebianFiles
411
#
412
# Description     : Name Debian builder control files
413
#                   May be called multiple times
414
#
415
# Inputs          : Options
416
#                       --Control=file
417
#                       --PreRm=file
418
#                       --PostRm=file
419
#                       --PreInst=file
420
#                       --PostInst=file
421
#
422
# Returns         : Nothing
423
#
424
sub DebianFiles
425
{
426
    #
427
    #   Exctact names
428
    #
429
    Verbose ("Specify Debian Control Files and Scripts");
430
    foreach  ( @_ )
431
    {
432
        if ( m/^--Control=(.+)/ ) {
433
            $opt_control = $1;
434
 
435
        } elsif ( m/^--PreRm=(.+)/ ) {
436
            $opt_prerm = $1;
437
 
438
        } elsif ( m/^--PostRm=(.+)/ ) {
439
            $opt_postrm = $1;
440
 
441
        } elsif ( m/^--PreInst=(.+)/ ) {
442
            $opt_preinst  = $1;
443
 
444
        } elsif ( m/^--PostInst=(.+)/ ) {
445
            $opt_postinst = $1;
446
 
447
        } else {
448
            Error ("DebianFiles: Unknown option: $_");
449
        }
450
    }
451
}
452
 
453
#-------------------------------------------------------------------------------
454
# Function        : PackageDescription
455
#
456
# Description     : Specify the Package Description
457
#                   Keep it short
458
#
459
# Inputs          : $description
460
#
461
# Returns         : 
462
#
463
sub PackageDescription
464
{
465
    ($opt_description) = @_;
466
}
467
 
468
#-------------------------------------------------------------------------------
469
# Function        : MakeSymLink
470
#
471
# Description     : Create a symlink - with error detection
472
#
473
# Inputs          : old_file    - Link Target
474
#                                 Path to the link target
475
#                                 If an ABS path is provided, the routine will
476
#                                 attempt to create a relative link.
477
#                   new_file    - Relative to the output work space
478
#                                 Path to where the 'link' file will be created
479
#                   Options     - Must be last
480
#                                 --NoClean         - Don't play with links
481
#                                 --NoDotDot        - Don't create symlinks with ..
482
#
483
# Returns         : Nothing
484
#
485
sub MakeSymLink
486
{
487
    my $no_clean;
488
    my $no_dot;
489
    my @args;
490
 
491
    #
492
    #   Extract options
493
    #
494
    foreach ( @_ )
495
    {
496
        if ( m/^--NoClean/i ) {
497
            $no_clean = 1;
498
 
499
        } elsif ( m/^--NoDotDot/i ) {
500
            $no_dot = 1;
501
 
502
        } elsif ( m/^--/ ) {
503
            Error ("MakeSymLink: Unknown option: $_");
504
 
505
        } else {
506
            push @args, $_;
507
        }
508
    }
509
 
510
    my ($old_file, $new_file) = @args;
511
 
512
    my $tfile = $DebianWorkDir . '/' . $new_file;
513
    $tfile =~ s~//~/~;
514
    Verbose ("Symlink $old_file -> $new_file" );
515
 
516
    #
517
    #   Create the directory in which the link will be placed
518
    #   Remove any existing file of the same name
519
    #
520
    my $dir = StripFileExt( $tfile );
521
    mkpath( $dir) unless -d $dir;
522
    unlink $tfile;
523
 
524
    #
525
    #   Determine a good name of the link
526
    #   Convert to a relative link in an attempt to prune them
527
    #
528
    my $sfile = $old_file;
529
    unless ( $no_clean )
530
    {
531
        $sfile = CalcRelPath( StripFileExt( $new_file ), $old_file );
532
        $sfile = $old_file if ( $no_dot && $sfile =~ m~^../~ );
533
    }
534
 
535
    my $result = symlink $sfile, $tfile;
536
    Error ("Cannot create symlink. $old_file -> $new_file") unless ( $result );
537
}
538
 
539
#-------------------------------------------------------------------------------
540
# Function        : CopyFile
541
#
542
# Description     : Copy a file to a target dir
543
#                   Used for text files, or files with fixed names
544
#
545
# Inputs          : $src
546
#                   $dst_dir    - Within the output workspace
547
#                   $dst_name   - Output Name [Optional]
548
#                   Options     - Common Copy Options
549
#
550
# Returns         : Full path to destination file
551
#
552
sub CopyFile
553
{
554
    CopyFileCommon( \&ResolveFile, @_ );
555
}
556
 
557
#-------------------------------------------------------------------------------
558
# Function        : CopyBinFile
559
#
560
# Description     : Copy a file to a target dir
561
#                   Used for executable programs. Will look in places where
562
#                   programs are stored.
563
#
564
# Inputs          : $src
565
#                   $dst_dir    - Within the output workspace
566
#                   $dst_name   - Output Name [Optional]
567
#
568
#                   Options:
569
#                       --FromPackage
570
#                       --SoftLink=xxxx
571
#                       --LinkFile=xxxx
572
#
573
#
574
# Returns         : Full path to destination file
575
#
576
sub CopyBinFile
577
{
578
    CopyFileCommon( \&ResolveBinFile, @_ );
579
}
580
 
581
#-------------------------------------------------------------------------------
582
# Function        : CopyLibFile
583
#
584
# Description     : Copy a file to a target dir
585
#                   Used for shared programs. Will look in places where
586
#                   shared libraries are stored.
587
#
588
# Inputs          : $src        - Base for 'realname' (no lib, no extension)
589
#                   $dst_dir    - Within the output workspace
590
#                   $dst_name   - Output Name [Optional, but not suggested]
591
#
592
# Returns         : Full path to destination file
593
#
594
# Notes           : Copying 'lib' files
595
#                   These are 'shared libaries. There is no provision for copying
596
#                   static libraries.
597
#
598
#                   The tool will attempt to copy a well-formed 'realname' library
599
#                   The soname of the library should be constructed on the target
600
#                   platform using ldconfig.
601
#                   There is no provision to copy the 'linker' name
602
#
603
#                   Given a request to copy a library called 'fred', then the
604
#                   well formed 'realname' will be:
605
#                           libfred[P|D|]].so.nnnnn
606
#                   where:
607
#                           nnnn is the library version
608
#                           [P|D|] indicates Production, Debug or None
609
#
610
#                   The 'soname' is held within the realname form of the library
611
#                   and will be created by lsconfig.
612
#
613
#                   The 'linkername' would be libfred[P|D|].so. This is only
614
#                   needed when linking against the library.
615
#
616
#
617
#                   The routine will also recognize Windows DLLs
618
#                   These are of the form fred[P|D|].nnnnn.dll
619
#
620
sub CopyLibFile
621
{
622
    CopyFileCommon( \&ResolveLibFile, @_ );
623
}
624
 
625
#-------------------------------------------------------------------------------
626
# Function        : CopyFileCommon
627
#
628
# Description     : Common ( internal File Copy )
629
#
630
# Inputs          : $resolver           - Ref to function to resolve source file
631
#                   $src                - Source File Name
632
#                   $dst_dir            - Target Dir
633
#                   $dst_name           - Target Name (optional)
634
#                   Options
635
#                   Options:
636
#                       --FromPackage
637
#                       --SoftLink=xxxx
638
#                       --LinkFile=xxxx
639
#
640
# Returns         : 
641
#
642
sub CopyFileCommon
643
{
644
    my $from_package = 0;
645
    my $isa_linkfile = 0;
646
    my @llist;
647
    my @args;
648
 
649
    #
650
    #   Parse options
651
    #
652
    foreach ( @_ )
653
    {
654
        if ( m/^--FromPackage/ ) {
655
            $from_package = 1;
656
 
657
        } elsif ( m/^--LinkFile/ ) {
658
            $isa_linkfile = 1;
659
 
660
        } elsif ( m/^--SoftLink=(.+)/ ) {
661
            push @llist, $1;
662
 
663
        } elsif ( m/^--/ ) {
664
            Error ("FileCopy: Unknown option: $_");
665
 
666
        } else {
667
            push @args, $_;
668
        }
669
    }
670
 
671
    #
672
    #   Extract non-options.
673
    #   These are the bits that are left over
674
    #
675
    my ($resolver, $src, $dst_dir, $dst_name ) = @args;
676
 
677
    #
678
    #   Clean up dest_dir. Must start with a / and not end with one
679
    #
680
    $dst_dir = "/$dst_dir/";
681
    $dst_dir =~ s~/+~/~g;
682
    $dst_dir =~ s~/$~~;
683
 
684
    Verbose ("CopyFile: $src, $dst_dir, " . ($dst_name || ''));
685
    foreach $src ( &$resolver( $from_package, $src ) )
686
    {
687
        my $dst_fname = $dst_name ? $dst_name : StripDir($src);
688
        my $dst_file = "$dst_dir/$dst_fname";
689
        Verbose ("CopyFile: Copy $src, $dst_file" );
690
 
691
 
692
        #
693
        #   LinkFiles are special
694
        #   They get concatenated to any existing LINKS File
695
        #
696
        if ( $isa_linkfile )
697
        {
698
            CatFile ( $src, "$dst_dir/.LINKS" );
699
        }
700
        else
701
        {
702
            mkpath( "$DebianWorkDir$dst_dir", 0, 0775);
703
            unlink ("$DebianWorkDir$dst_file");
704
            System ('cp','-f', $src, "$DebianWorkDir$dst_file" );
705
 
706
            foreach my $lname ( @llist )
707
            {
708
                $lname = $dst_dir . '/' . $lname unless ( $lname =~ m ~^/~ );
709
                MakeSymLink( $dst_file ,$lname);
710
            }
711
        }
712
    }
713
}
714
 
715
#-------------------------------------------------------------------------------
716
# Function        : CopyDir
717
#
718
# Description     : Copy a directory to a target dir
719
#
720
# Inputs          : $src_dir    - Local to the user
721
#                                 Symbolic Name
722
#                   $dst_dir    - Within the output workspace
723
#                   Options
724
#                       --Merge
725
#                       --
726
#
727
# Returns         :
728
#
729
sub CopyDir
730
{
731
    my ($src_dir, $dst_dir, @opts) = @_;
732
    my $opt_merge;
733
    my $opt_base;
734
 
735
    $dst_dir = $DebianWorkDir . '/' . $dst_dir;
736
    $dst_dir =~ s~//~/~;
737
 
738
    #
739
    #   Detect and expand Symbolic names in the Source Directory
740
    #
741
    foreach  ( @opts )
742
    {
743
        if ( m/^--Merge/ ) {
744
            $opt_merge = 1;
745
        } elsif ( m/^--Source=(.+)/ ) {
746
            my $name = lc($1);
747
            my %CopyDirSymbolic = (
748
                'interfaceincdir'   => $opt_interfaceincdir,
749
                'interfacelibdir'   => $opt_interfacelibdir,
750
                'interfacebindir'   => $opt_interfacebindir,
751
                'libdir'            => $opt_libdir,
752
                'bindir'            => $opt_bindir,
753
                'localincdir'       => $opt_localincdir,
754
                'locallibdir'       => $opt_locallibdir,
755
                'localbindir'       => $opt_localbindir,
756
                'packagebindir'     => $opt_pkgbindir,
757
                'packagelibdir'     => $opt_pkglibdir,
758
                'packagepkgdir'     => $opt_pkgpkgdir,
759
                'packagedir'        => $opt_pkgdir,
760
            );
761
 
762
            if ( exists $CopyDirSymbolic{$name} )
763
            {
764
                $opt_base = $CopyDirSymbolic{$name};
765
            }
766
            else
767
            {
768
                DebugDumpData ("CopyDirSymbolic", \%CopyDirSymbolic);
769
                Error ("CopyDir: Unknown Source Name: $name" );
770
            }
771
        } else {
772
            Error ("CopyDir: Unknown option: $_" );
773
        }
774
    }
775
 
776
    $src_dir = $opt_base . '/' . $src_dir if ( $opt_base );
777
    $src_dir =~ s~//~/~g;
778
    $src_dir =~ s~/$~~;
779
 
780
    Verbose ("CopyDir: $src_dir, $dst_dir");
781
    Error ("CopyDir: Directory not found: $src_dir") unless ( -d $src_dir );
782
 
783
    #
784
    #   If not merging then delete the target before copying
785
    #
786
    rmtree( $dst_dir ) unless $opt_merge;
787
    mkdir ( $dst_dir );
788
 
789
    my $cpflags = '-r';
790
    $cpflags .= 'v' if ( $opt_verbose > 1 );
791
 
792
 
793
    #
794
    #   Determine the complete list of source files
795
    #   Need to allow for files begining with a .
796
    #
797
    opendir (DIR, $src_dir ) || Error ("CopyDir: Can't read directory: $src_dir");
798
    my @files = readdir(DIR);
799
    closedir(DIR);
800
 
801
    foreach ( @files  )
802
    {
803
        next if ( $_ eq '.' );
804
        next if ( $_ eq '..' );
805
        System ('cp', $cpflags, "$src_dir/$_", $dst_dir );
806
    }
807
    #
808
    #   Expand link files that may have been copied in
809
    #
810
    Verbose ("Locate LINKFILES in $DebianWorkDir");
811
    ExpandLinkFiles();
812
}
813
 
814
#-------------------------------------------------------------------------------
815
# Function        : AddInitScript
816
#
817
# Description     : Add an Init Script to the target
818
#                   Optionally create start and stop links
819
#
820
# Inputs          : $script     - Name of the init script
821
#                   $start      - Start Number
822
#                   $stop       - Stop Number
823
#                   Options:
824
#                       --NoCopy        - Don't copy the script, just add links
825
#                       --Afc           - Place in AFC init area
826
#                       --FromPackage   - Source is in a package
827
#
828
# Returns         : 
829
#
830
sub AddInitScript
831
{
832
    my $no_copy;
833
    my $basedir = "";
834
    my @args;
835
    my $from_package = 0;
836
 
837
    #
838
    #   Process and Remove options
839
    #
840
    foreach  ( @_ )
841
    {
842
        if ( m/^--NoCopy/ ) {
843
            $no_copy = 1;
844
 
845
        } elsif ( m/^--Afc/ ) {
846
            $basedir = "/afc";
847
 
848
        } elsif ( m/^--FromPackage/ ) {
849
            $from_package = 1;
850
 
851
        } elsif ( m/^--/ ) {
852
            Error ("AddInitScript: Unknown option: $_");
853
 
854
        } else {
855
            push @args, $_;
856
 
857
        }
858
    }
859
 
860
    my( $script, $start, $stop ) = @args;
861
    Error ("No script file specified") unless ( $script );
862
    Warning("AddInitScript: No start or stop index specified") unless ( $start || $stop );
863
    Verbose ("AddInitScript: $script, " . ($start || 'No Start') . ", " . ($stop || 'No Stop'));
864
    $script = ResolveFile($from_package, $script );
865
 
866
    my $tdir = $basedir . "/etc/init.d/init.d";
867
    my $base = StripDir($script);
868
 
869
    CopyFile( $script, $tdir ) unless $no_copy;
870
 
871
    my $link;
872
    if ( $start )
873
    {
874
        $link = sprintf ("${basedir}/etc/init.d/S%2.2d%s", $start, $base );
875
        MakeSymLink( "$tdir/$base", $link);
876
    }
877
 
878
    if ( $stop )
879
    {
880
        $link = sprintf ("${basedir}/etc/init.d/K%2.2d%s", $stop, $base );
881
        MakeSymLink( "$tdir/$base", $link);
882
    }
883
}
884
 
885
#-------------------------------------------------------------------------------
886
# Function        : CatFile
887
#
888
# Description     : Copy a file to the end of a file
889
#
890
# Inputs          : $src
891
#                   $dst    - Within the output workspace
892
#
893
# Returns         :
894
#
895
sub CatFile
896
{
897
    my ($src, $dst) = @_;
898
 
899
    $dst = $DebianWorkDir . '/' . $dst;
900
    $dst =~ s~//~/~;
901
    Verbose ("CatFile: $src, $dst");
902
    $src = ResolveFile(0, $src );
903
 
904
    open (SF, '<', $src)  || Error ("CatFile: Cannot open $src");
905
    open (DF, '>>', $dst) || Error ("CatFile: Cannot create:$dst");
906
    while ( <SF> )
907
    {
908
        print DF $_;
909
    }
910
    close (SF);
911
    close (DF);
912
}
913
 
914
#-------------------------------------------------------------------------------
915
# Function        : EchoFile
916
#
917
# Description     : Echo simple text to a file
918
#
919
# Inputs          : $file   - Within the output workspace
920
#                   $text
921
#
922
# Returns         : 
923
#
924
sub EchoFile
925
{
926
    my ($file, $text) = @_;
927
    Verbose ("EchoFile: $file");
928
 
929
    $file = $DebianWorkDir . '/' . $file;
930
    $file =~ s~//~/~;
931
 
932
    unlink $file;
933
    open (DT, ">", $file ) || Error ("Cannot create $file");
934
    print DT  $text || Error ("Cannot print to $file");
935
    close DT;
936
}
937
 
938
#-------------------------------------------------------------------------------
939
# Function        : SetFilePerms
940
#
941
# Description     : Set file permissions on one or more files or directories
942
#
943
# Inputs          : $perm           - Perm Mask
944
#                   @paths          - List of paths/files to process
945
#                   Options
946
#                       --Recurse   - Recurse subdirs
947
#
948
# Returns         : 
949
#
950
sub SetFilePerms
951
{
952
 
953
    my @args;
954
    my $perms;
955
    my $recurse = 0;
956
 
957
    #
958
    #   Process and Remove options
959
    #
960
    foreach  ( @_ )
961
    {
962
        if ( m/^--Recurse/ ) {
963
            $recurse = 1;
964
 
965
        } elsif ( m/^--/ ) {
966
            Error ("SetFilePerms: Unknown option: $_");
967
 
968
        } else {
969
            push @args, $_;
970
 
971
        }
972
    }
973
 
974
    $perms = shift @args;
975
    Error ("SetFilePerms: No Permissions" ) unless ( $perms );
976
 
977
    foreach my $path ( @args )
978
    {
979
        Verbose ("Set permissions; $perms, $path");
980
        my $full_path = $DebianWorkDir . '/' . $path;
981
        if ( -f $full_path )
982
        {
983
            System ('chmod', $perms, $full_path );
984
        }
985
        elsif ( -d $full_path )
986
        {
987
            System ('chmod', '-R', $perms, $full_path ) if ($recurse);
988
            System ('chmod', $perms, $full_path ) unless ($recurse);
989
        }
990
        else
991
        {
992
            Warning("SetFilePerms: Path not found: $path");
993
        }
994
    }
995
}
996
 
997
#-------------------------------------------------------------------------------
998
# Function        : CreateDir
999
#
1000
# Description     : Create a directory within the target workspace
1001
#
1002
# Inputs          : $path           - Name of the target directory
1003
#
1004
# Returns         : Nothing
1005
#
1006
sub CreateDir
1007
{
1008
    my ($path) = @_;
1009
 
1010
    Verbose ("Create Dir: $path");
1011
    mkpath( $DebianWorkDir . '/' . $path );
1012
}
1013
 
1014
#-------------------------------------------------------------------------------
1015
# Function        : IsProduct
1016
#                   IsPlatform
1017
#                   IsTarget
1018
#
1019
# Description     : This function allows some level of control in the
1020
#                   packaging scripts. It will return true if the current
1021
#                   product is listed.
1022
#
1023
#                   Ugly after thought
1024
#
1025
#                   Intended use:
1026
#                       Xxxxxx(...) if (IsProduct( 'aaa',bbb' );
1027
#
1028
# Inputs          : products    - a list of products to compare against
1029
#
1030
# Returns         : True if the current build is for one of the listed products
1031
#
1032
sub IsProduct
1033
{
1034
    foreach ( @_ )
1035
    {
1036
        return 1 if ( $opt_product eq $_ );
1037
    }
1038
    return 0;
1039
}
1040
 
1041
sub IsPlatform
1042
{
1043
    foreach ( @_ )
1044
    {
1045
        return 1 if ( $opt_platform eq $_ );
1046
    }
1047
    return 0;
1048
}
1049
 
1050
sub IsTarget
1051
{
1052
    foreach ( @_ )
1053
    {
1054
        return 1 if ( $opt_target eq $_ );
1055
    }
1056
    return 0;
1057
}
1058
 
1059
 
1060
#-------------------------------------------------------------------------------
1061
# Function        : FindFiles
1062
#
1063
# Description     : Locate files within a given dir tree
1064
#
1065
# Inputs          : $root           - Base of the search
1066
#                   $match          - Re to match
1067
#
1068
# Returns         : A list of files that match
1069
#
1070
my @FIND_LIST;
1071
my $FIND_NAME;
1072
 
1073
sub FindFiles
1074
{
1075
    my ($root, $match ) = @_;
1076
    Verbose2("FindFiles: Root: $root, Match: $match");
1077
 
1078
    #
1079
    #   Becareful of closure, Must use globals
1080
    #
1081
    @FIND_LIST = ();
1082
    $FIND_NAME = $match;
1083
    File::Find::find( \&find_files, $root);
1084
 
1085
    #
1086
    #   Find callback program
1087
    #
1088
    sub find_files
1089
    {
1090
        my $item =  $File::Find::name;
1091
 
1092
        return if ( -d $File::Find::name );
1093
        return unless ( $_ =~ m~$FIND_NAME~ );
1094
        push @FIND_LIST, $item;
1095
    }
1096
    return @FIND_LIST;
1097
}
1098
 
1099
#-------------------------------------------------------------------------------
1100
# Function        : CalcRelPath
1101
#
1102
# Description     : Return the relative path to the current working directory
1103
#                   as provided in $Cwd
1104
#
1105
# Inputs          : $Cwd - Base dir
1106
#                   $base - Path to convert
1107
#
1108
# Returns         : Relative path from the $Cwd
1109
#
1110
sub CalcRelPath
1111
{
1112
    my ($Cwd, $base) = @_;
1113
 
1114
    my @base = split ('/', $base );
1115
    my @here = split ('/', $Cwd );
1116
    my $result;
1117
 
1118
    Debug("RelPath: Source: $base");
1119
 
1120
    return $base unless ( $base =~ m~^/~ );
1121
 
1122
    #
1123
    #   Remove common bits from the head of both lists
1124
    #
1125
    while ( $#base >= 0 && $#here >= 0 && $base[0] eq $here[0] )
1126
    {
1127
        shift @base;
1128
        shift @here;
1129
    }
1130
 
1131
    #
1132
    #   Need to go up some directories from here and then down into base
1133
    #
1134
    $result = '../' x ($#here + 1);
1135
    $result .= join ( '/', @base);
1136
    $result = '.' unless ( $result );
1137
    $result =~ s~//~/~g;
1138
    $result =~ s~/$~~;
1139
 
1140
    Debug("RelPath: Result: $result");
1141
    return $result;
1142
}
1143
 
1144
#-------------------------------------------------------------------------------
1145
# Function        : ExpandLinkFiles
1146
#
1147
# Description     : Look for .LINK files in the output image and expand
1148
#                   the links into softlinks
1149
#
1150
# Inputs          : None
1151
#                   The rouine works on the $DebianWorkDir directory tree
1152
#
1153
# Returns         : Nothing
1154
#                   Will remove .LINKS files that are processed
1155
#
1156
sub ExpandLinkFiles
1157
{
1158
    foreach my $linkfile ( FindFiles( $DebianWorkDir, ".LINKS" ))
1159
    {
1160
        next if ( $linkfile =~ m~/\.svn/~ );
1161
        my $BASEDIR = StripFileExt( $linkfile );
1162
        $BASEDIR =~ s~^$DebianWorkDir/~~;
1163
        Verbose "Expand links: $BASEDIR";
1164
 
1165
        open (LF, "<", $linkfile ) || Error ("Cannot open link file: $linkfile" );
1166
        while ( <LF> )
1167
        {
1168
            chomp;
1169
            next if ( m~^#~ );
1170
            next unless ( $_ );
1171
            my ($link, $file) = split;
1172
 
1173
            MakeSymLink($file ,"$BASEDIR/$link", '--NoDotDot' );
1174
        }
1175
        close (LF);
1176
        unlink $linkfile;
1177
    }
1178
}
1179
 
1180
#-------------------------------------------------------------------------------
1181
# Function        : ResolveFile
1182
#
1183
# Description     : Determine where the source for a file is
1184
#                   Will look in:
1185
#                       Local directory
1186
#                       Local Include
1187
#                   Will scan 'parts' subdirs
1188
#
1189
# Inputs          : $from_package       - 0 - Local File
1190
#                   $file
1191
#
1192
# Returns         : Path
1193
#
1194
sub ResolveFile
1195
{
1196
    my ($from_package, $file) = @_;
1197
    my @path = $from_package ? ($opt_pkgdir ,$opt_interfacedir) : ('.', $opt_localincdir);
1198
    my $wildcard = ($file =~ /[*?]/);
1199
 
1200
    #
1201
    #   Determine a full list of 'parts' to search
1202
    #   This is provided within the build information
1203
    #
1204
    my @parts = getPlatformParts ();
1205
    push @parts, '';
1206
 
1207
    my @done;
1208
    foreach my $root (  @path )
1209
    {
1210
        foreach my $subdir ( @parts )
1211
        {
1212
            my $sfile;
1213
                $sfile = "$root/$subdir/$file";
1214
                $sfile =~ s~//~/~g;
1215
                $sfile =~ s~^./~~g;
1216
                Verbose2("LocateFile: $sfile, $root, $subdir");
1217
                if ( $wildcard )
1218
                {
1219
                    push @done, glob ( $sfile );
1220
                }
1221
                else
1222
                {
1223
                    push @done, $sfile if ( -f $sfile )
1224
                }
1225
        }
1226
    }
1227
 
1228
    Error ("ResolveFile: File not found: $file")
1229
        unless ( @done );
1230
 
1231
    Warning ("ResolveFile: Multiple instances of file found. Only first is used", @done)
1232
        if ( $#done > 0 && ! $wildcard && !wantarray );
1233
 
1234
    return wantarray ? @done : $done[0];
1235
}
1236
 
1237
#-------------------------------------------------------------------------------
1238
# Function        : ResolveBinFile
1239
#
1240
# Description     : Determine where the source for a file is
1241
#                   Will look in:
1242
#                       Local artifacts bin
1243
#                       Local Bin
1244
#                   Will scan 'parts' subdirs
1245
#
1246
# Inputs          : $from_package       - 0 - Local File
1247
# Inputs          : $file
1248
#
1249
# Returns         : Path
1250
#
1251
sub ResolveBinFile
1252
{
1253
    my ($from_package, $file) = @_;
1254
    my @path;
1255
    my @types;
1256
    my $wildcard = ($file =~ /[*?]/);
1257
 
1258
    if ( $from_package )
1259
    {
1260
        @path = ($opt_pkgdir . '/bin' ,$opt_interfacedir . '/bin' );
1261
        @types = ($opt_type, '');
1262
    }
1263
    else
1264
    {
1265
        @path = ($opt_bindir, $opt_localbindir);
1266
        @types = '';
1267
    }
1268
 
1269
    #
1270
    #   Determine a full list of 'parts' to search
1271
    #   This is provided within the build information
1272
    #
1273
    my @parts = getPlatformParts ();
1274
    push @parts, '';
1275
 
1276
    my @done;
1277
    foreach my $root (  @path )
1278
    {
1279
        foreach my $subdir ( @parts )
1280
        {
1281
            foreach my $type ( @types )
1282
            {
1283
                my $sfile;
1284
                $sfile = "$root/$subdir$type/$file";
1285
                $sfile =~ s~//~/~g;
1286
                Verbose2("LocateBinFile: $sfile");
1287
                if ( $wildcard )
1288
                {
1289
                    push @done, glob ( $sfile );
1290
                }
1291
                else
1292
                {
1293
                    push @done, $sfile if ( -f $sfile )
1294
                }
1295
            }
1296
        }
1297
    }
1298
 
1299
    Error ("ResolveBinFile: File not found: $file")
1300
        unless ( @done );
1301
 
1302
    Warning ("ResolveBinFile: Multiple instances of file found. Only first is used", @done)
1303
        if ( $#done > 0 && ! $wildcard && !wantarray );
1304
 
1305
    return wantarray ? @done : $done[0];
1306
}
1307
 
1308
#-------------------------------------------------------------------------------
1309
# Function        : ResolveLibFile
1310
#
1311
# Description     : Determine where the source for a file is
1312
#                   Will look in:
1313
#                       Local artifacts library
1314
#                       Local Lib
1315
#                   Will scan 'parts' subdirs
1316
#
1317
# Inputs          : $from_package       - 0 - Local File
1318
# Inputs          : $file       - Basename for a 'realname'
1319
#                                 Do not provide 'lib' or '.so' or version info
1320
#                                 May contain embedded options
1321
#                                   --Dll - use Windows style versioned DLL
1322
#                                   --VersionDll - USe the versioned DLL
1323
#
1324
# Returns         : Path
1325
#
1326
sub ResolveLibFile
1327
{
1328
    my ($from_package, $file) = @_;
409 alewis 1329
    my @path = $from_package ? ($opt_pkgdir . '/lib', $opt_interfacedir . '/lib') : ($opt_libdir, $opt_locallibdir);
407 dpurdie 1330
    my $wildcard = ($file =~ /[*?]/);
1331
    my @options;
1332
    my $num_dll;
1333
 
1334
    #
1335
    #   Extract options from file
1336
    #
409 alewis 1337
    $num_dll = 0;
407 dpurdie 1338
    ($file, @options) = split ( ',', $file);
1339
    foreach ( @options )
1340
    {
1341
        if ( m/^--Dll/ ) {
1342
            $num_dll = 1;
1343
        } elsif ( m/^--VersionDll/ ) {
1344
            $num_dll = 2;
1345
        } else {
1346
            Error ("Unknown suboption to ResolveLibFile: $_" );
1347
        }
1348
    }
1349
 
1350
    #
1351
    #   Determine a full list of 'parts' to search
1352
    #   This is provided within the build information
1353
    #
1354
    my @parts = getPlatformParts ();
1355
    push @parts, '';
1356
 
1357
    my @done;
1358
    foreach my $root (  @path )
1359
    {
1360
        foreach my $type ( $opt_type, '' )
1361
        {
1362
            foreach my $subdir ( @parts )
1363
            {
1364
                my $sfile;
1365
                my $exact;
1366
                if ( $num_dll == 2 ) {
1367
                    $sfile = $file . $type . '.*.dll' ;
1368
                } elsif ( $num_dll == 1 ) {
1369
                    $sfile = $file . $type . '.dll' ;
1370
                    $exact = 1;
1371
                } else {
1372
                    $sfile = "lib" . $file . $type . '.so.*';
1373
                }
1374
 
1375
                $sfile = "$root/$subdir/$sfile";
1376
                $sfile =~ s~//~/~g;
1377
                Verbose2("LocateLibFile: $sfile");
1378
                if ( $exact )
1379
                {
1380
                    push @done, $sfile if ( -f $sfile );
1381
                }
1382
                else
1383
                {
1384
                    push @done, glob ( $sfile );
1385
                }
1386
            }
1387
        }
1388
    }
1389
 
1390
    Error ("ResolveLibFile: File not found: $file")
1391
        unless ( @done );
1392
 
1393
    Warning ("ResolveLibFile: Multiple instances of file found. Only first is used", @done)
1394
        if ( $#done > 0 && ! $wildcard && !wantarray );
1395
 
1396
    return wantarray ? @done : $done[0];
1397
}
1398
 
1399
 
1400
#-------------------------------------------------------------------------------
1401
# Function        : AUTOLOAD
1402
#
1403
# Description     : Intercept bad user directives and issue a nice error message
1404
#                   This is a simple routine to report unknown user directives
1405
#                   It does not attempt to distinguish between user errors and
1406
#                   programming errors. It assumes that the program has been
1407
#                   tested. The function simply report filename and line number
1408
#                   of the bad directive.
1409
#
1410
# Inputs          : Original function arguments ( not used )
1411
#
1412
# Returns         : This function does not return
1413
#
1414
our $AUTOLOAD;
1415
sub AUTOLOAD
1416
{
1417
    my $fname = $AUTOLOAD;
1418
    $fname =~ s~^main::~~;
1419
    my ($package, $filename, $line) = caller;
1420
 
1421
    Error ("Directive not known or not allowed in this context: $fname",
1422
           "Directive: $fname( @_ );",
1423
           "File: $filename, Line: $line" );
1424
}
1425
 
1426
 
1427
1;
1428