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
 
411 dpurdie 64
require 5.006_001;
407 dpurdie 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;
411 dpurdie 734
    my $from_interface = 0;
407 dpurdie 735
 
736
    $dst_dir = $DebianWorkDir . '/' . $dst_dir;
737
    $dst_dir =~ s~//~/~;
738
 
739
    #
740
    #   Detect and expand Symbolic names in the Source Directory
741
    #
742
    foreach  ( @opts )
743
    {
744
        if ( m/^--Merge/ ) {
745
            $opt_merge = 1;
746
        } elsif ( m/^--Source=(.+)/ ) {
747
            my $name = lc($1);
748
            my %CopyDirSymbolic = (
749
                'interfaceincdir'   => $opt_interfaceincdir,
750
                'interfacelibdir'   => $opt_interfacelibdir,
751
                'interfacebindir'   => $opt_interfacebindir,
752
                'libdir'            => $opt_libdir,
753
                'bindir'            => $opt_bindir,
754
                'localincdir'       => $opt_localincdir,
755
                'locallibdir'       => $opt_locallibdir,
756
                'localbindir'       => $opt_localbindir,
757
                'packagebindir'     => $opt_pkgbindir,
758
                'packagelibdir'     => $opt_pkglibdir,
759
                'packagepkgdir'     => $opt_pkgpkgdir,
760
                'packagedir'        => $opt_pkgdir,
761
            );
762
 
763
            if ( exists $CopyDirSymbolic{$name} )
764
            {
765
                $opt_base = $CopyDirSymbolic{$name};
411 dpurdie 766
 
767
                #
768
                #   If sourceing from interface, then follow
769
                #   symlinks in the copy. All files will be links anyway
770
                #
771
                $from_interface = 1
772
                    if ( $name =~ m~^interface~ );
407 dpurdie 773
            }
774
            else
775
            {
776
                DebugDumpData ("CopyDirSymbolic", \%CopyDirSymbolic);
777
                Error ("CopyDir: Unknown Source Name: $name" );
778
            }
779
        } else {
780
            Error ("CopyDir: Unknown option: $_" );
781
        }
782
    }
783
 
784
    $src_dir = $opt_base . '/' . $src_dir if ( $opt_base );
785
    $src_dir =~ s~//~/~g;
786
    $src_dir =~ s~/$~~;
787
 
788
    Verbose ("CopyDir: $src_dir, $dst_dir");
789
    Error ("CopyDir: Directory not found: $src_dir") unless ( -d $src_dir );
790
 
791
    #
792
    #   If not merging then delete the target before copying
793
    #
794
    rmtree( $dst_dir ) unless $opt_merge;
411 dpurdie 795
    mkpath ( $dst_dir );
407 dpurdie 796
 
797
    my $cpflags = '-r';
411 dpurdie 798
    $cpflags .= 'L' if ( $from_interface );
407 dpurdie 799
    $cpflags .= 'v' if ( $opt_verbose > 1 );
800
 
801
    #
802
    #   Determine the complete list of source files
803
    #   Need to allow for files begining with a .
804
    #
805
    opendir (DIR, $src_dir ) || Error ("CopyDir: Can't read directory: $src_dir");
806
    my @files = readdir(DIR);
807
    closedir(DIR);
808
 
809
    foreach ( @files  )
810
    {
811
        next if ( $_ eq '.' );
812
        next if ( $_ eq '..' );
411 dpurdie 813
        next if ( $_ eq '.svn' );
407 dpurdie 814
        System ('cp', $cpflags, "$src_dir/$_", $dst_dir );
815
    }
816
    #
817
    #   Expand link files that may have been copied in
818
    #
819
    Verbose ("Locate LINKFILES in $DebianWorkDir");
820
    ExpandLinkFiles();
821
}
822
 
823
#-------------------------------------------------------------------------------
824
# Function        : AddInitScript
825
#
826
# Description     : Add an Init Script to the target
827
#                   Optionally create start and stop links
828
#
829
# Inputs          : $script     - Name of the init script
830
#                   $start      - Start Number
831
#                   $stop       - Stop Number
832
#                   Options:
833
#                       --NoCopy        - Don't copy the script, just add links
834
#                       --Afc           - Place in AFC init area
835
#                       --FromPackage   - Source is in a package
836
#
837
# Returns         : 
838
#
839
sub AddInitScript
840
{
841
    my $no_copy;
842
    my $basedir = "";
843
    my @args;
844
    my $from_package = 0;
845
 
846
    #
847
    #   Process and Remove options
848
    #
849
    foreach  ( @_ )
850
    {
851
        if ( m/^--NoCopy/ ) {
852
            $no_copy = 1;
853
 
854
        } elsif ( m/^--Afc/ ) {
855
            $basedir = "/afc";
856
 
857
        } elsif ( m/^--FromPackage/ ) {
858
            $from_package = 1;
859
 
860
        } elsif ( m/^--/ ) {
861
            Error ("AddInitScript: Unknown option: $_");
862
 
863
        } else {
864
            push @args, $_;
865
 
866
        }
867
    }
868
 
869
    my( $script, $start, $stop ) = @args;
870
    Error ("No script file specified") unless ( $script );
871
    Warning("AddInitScript: No start or stop index specified") unless ( $start || $stop );
872
    Verbose ("AddInitScript: $script, " . ($start || 'No Start') . ", " . ($stop || 'No Stop'));
873
    $script = ResolveFile($from_package, $script );
874
 
875
    my $tdir = $basedir . "/etc/init.d/init.d";
876
    my $base = StripDir($script);
877
 
878
    CopyFile( $script, $tdir ) unless $no_copy;
879
 
880
    my $link;
881
    if ( $start )
882
    {
883
        $link = sprintf ("${basedir}/etc/init.d/S%2.2d%s", $start, $base );
884
        MakeSymLink( "$tdir/$base", $link);
885
    }
886
 
887
    if ( $stop )
888
    {
889
        $link = sprintf ("${basedir}/etc/init.d/K%2.2d%s", $stop, $base );
890
        MakeSymLink( "$tdir/$base", $link);
891
    }
892
}
893
 
894
#-------------------------------------------------------------------------------
895
# Function        : CatFile
896
#
897
# Description     : Copy a file to the end of a file
898
#
899
# Inputs          : $src
900
#                   $dst    - Within the output workspace
901
#
902
# Returns         :
903
#
904
sub CatFile
905
{
906
    my ($src, $dst) = @_;
907
 
908
    $dst = $DebianWorkDir . '/' . $dst;
909
    $dst =~ s~//~/~;
910
    Verbose ("CatFile: $src, $dst");
911
    $src = ResolveFile(0, $src );
912
 
913
    open (SF, '<', $src)  || Error ("CatFile: Cannot open $src");
914
    open (DF, '>>', $dst) || Error ("CatFile: Cannot create:$dst");
915
    while ( <SF> )
916
    {
917
        print DF $_;
918
    }
919
    close (SF);
920
    close (DF);
921
}
922
 
923
#-------------------------------------------------------------------------------
924
# Function        : EchoFile
925
#
926
# Description     : Echo simple text to a file
927
#
928
# Inputs          : $file   - Within the output workspace
929
#                   $text
930
#
931
# Returns         : 
932
#
933
sub EchoFile
934
{
935
    my ($file, $text) = @_;
936
    Verbose ("EchoFile: $file");
937
 
938
    $file = $DebianWorkDir . '/' . $file;
939
    $file =~ s~//~/~;
940
 
941
    unlink $file;
942
    open (DT, ">", $file ) || Error ("Cannot create $file");
943
    print DT  $text || Error ("Cannot print to $file");
944
    close DT;
945
}
946
 
947
#-------------------------------------------------------------------------------
948
# Function        : SetFilePerms
949
#
950
# Description     : Set file permissions on one or more files or directories
951
#
952
# Inputs          : $perm           - Perm Mask
953
#                   @paths          - List of paths/files to process
954
#                   Options
955
#                       --Recurse   - Recurse subdirs
956
#
957
# Returns         : 
958
#
959
sub SetFilePerms
960
{
961
 
962
    my @args;
963
    my $perms;
964
    my $recurse = 0;
965
 
966
    #
967
    #   Process and Remove options
968
    #
969
    foreach  ( @_ )
970
    {
971
        if ( m/^--Recurse/ ) {
972
            $recurse = 1;
973
 
974
        } elsif ( m/^--/ ) {
975
            Error ("SetFilePerms: Unknown option: $_");
976
 
977
        } else {
978
            push @args, $_;
979
 
980
        }
981
    }
982
 
983
    $perms = shift @args;
984
    Error ("SetFilePerms: No Permissions" ) unless ( $perms );
985
 
986
    foreach my $path ( @args )
987
    {
988
        Verbose ("Set permissions; $perms, $path");
989
        my $full_path = $DebianWorkDir . '/' . $path;
990
        if ( -f $full_path )
991
        {
992
            System ('chmod', $perms, $full_path );
993
        }
994
        elsif ( -d $full_path )
995
        {
996
            System ('chmod', '-R', $perms, $full_path ) if ($recurse);
997
            System ('chmod', $perms, $full_path ) unless ($recurse);
998
        }
999
        else
1000
        {
1001
            Warning("SetFilePerms: Path not found: $path");
1002
        }
1003
    }
1004
}
1005
 
1006
#-------------------------------------------------------------------------------
1007
# Function        : CreateDir
1008
#
1009
# Description     : Create a directory within the target workspace
1010
#
1011
# Inputs          : $path           - Name of the target directory
1012
#
1013
# Returns         : Nothing
1014
#
1015
sub CreateDir
1016
{
1017
    my ($path) = @_;
1018
 
1019
    Verbose ("Create Dir: $path");
1020
    mkpath( $DebianWorkDir . '/' . $path );
1021
}
1022
 
1023
#-------------------------------------------------------------------------------
1024
# Function        : IsProduct
1025
#                   IsPlatform
1026
#                   IsTarget
1027
#
1028
# Description     : This function allows some level of control in the
1029
#                   packaging scripts. It will return true if the current
1030
#                   product is listed.
1031
#
1032
#                   Ugly after thought
1033
#
1034
#                   Intended use:
1035
#                       Xxxxxx(...) if (IsProduct( 'aaa',bbb' );
1036
#
1037
# Inputs          : products    - a list of products to compare against
1038
#
1039
# Returns         : True if the current build is for one of the listed products
1040
#
1041
sub IsProduct
1042
{
1043
    foreach ( @_ )
1044
    {
1045
        return 1 if ( $opt_product eq $_ );
1046
    }
1047
    return 0;
1048
}
1049
 
1050
sub IsPlatform
1051
{
1052
    foreach ( @_ )
1053
    {
1054
        return 1 if ( $opt_platform eq $_ );
1055
    }
1056
    return 0;
1057
}
1058
 
1059
sub IsTarget
1060
{
1061
    foreach ( @_ )
1062
    {
1063
        return 1 if ( $opt_target eq $_ );
1064
    }
1065
    return 0;
1066
}
1067
 
1068
 
1069
#-------------------------------------------------------------------------------
1070
# Function        : FindFiles
1071
#
1072
# Description     : Locate files within a given dir tree
1073
#
1074
# Inputs          : $root           - Base of the search
1075
#                   $match          - Re to match
1076
#
1077
# Returns         : A list of files that match
1078
#
1079
my @FIND_LIST;
1080
my $FIND_NAME;
1081
 
1082
sub FindFiles
1083
{
1084
    my ($root, $match ) = @_;
1085
    Verbose2("FindFiles: Root: $root, Match: $match");
1086
 
1087
    #
1088
    #   Becareful of closure, Must use globals
1089
    #
1090
    @FIND_LIST = ();
1091
    $FIND_NAME = $match;
1092
    File::Find::find( \&find_files, $root);
1093
 
1094
    #
1095
    #   Find callback program
1096
    #
1097
    sub find_files
1098
    {
1099
        my $item =  $File::Find::name;
1100
 
1101
        return if ( -d $File::Find::name );
1102
        return unless ( $_ =~ m~$FIND_NAME~ );
1103
        push @FIND_LIST, $item;
1104
    }
1105
    return @FIND_LIST;
1106
}
1107
 
1108
#-------------------------------------------------------------------------------
1109
# Function        : CalcRelPath
1110
#
1111
# Description     : Return the relative path to the current working directory
1112
#                   as provided in $Cwd
1113
#
1114
# Inputs          : $Cwd - Base dir
1115
#                   $base - Path to convert
1116
#
1117
# Returns         : Relative path from the $Cwd
1118
#
1119
sub CalcRelPath
1120
{
1121
    my ($Cwd, $base) = @_;
1122
 
1123
    my @base = split ('/', $base );
1124
    my @here = split ('/', $Cwd );
1125
    my $result;
1126
 
1127
    Debug("RelPath: Source: $base");
1128
 
1129
    return $base unless ( $base =~ m~^/~ );
1130
 
1131
    #
1132
    #   Remove common bits from the head of both lists
1133
    #
1134
    while ( $#base >= 0 && $#here >= 0 && $base[0] eq $here[0] )
1135
    {
1136
        shift @base;
1137
        shift @here;
1138
    }
1139
 
1140
    #
1141
    #   Need to go up some directories from here and then down into base
1142
    #
1143
    $result = '../' x ($#here + 1);
1144
    $result .= join ( '/', @base);
1145
    $result = '.' unless ( $result );
1146
    $result =~ s~//~/~g;
1147
    $result =~ s~/$~~;
1148
 
1149
    Debug("RelPath: Result: $result");
1150
    return $result;
1151
}
1152
 
1153
#-------------------------------------------------------------------------------
1154
# Function        : ExpandLinkFiles
1155
#
1156
# Description     : Look for .LINK files in the output image and expand
1157
#                   the links into softlinks
1158
#
1159
# Inputs          : None
1160
#                   The rouine works on the $DebianWorkDir directory tree
1161
#
1162
# Returns         : Nothing
1163
#                   Will remove .LINKS files that are processed
1164
#
1165
sub ExpandLinkFiles
1166
{
1167
    foreach my $linkfile ( FindFiles( $DebianWorkDir, ".LINKS" ))
1168
    {
1169
        next if ( $linkfile =~ m~/\.svn/~ );
1170
        my $BASEDIR = StripFileExt( $linkfile );
1171
        $BASEDIR =~ s~^$DebianWorkDir/~~;
1172
        Verbose "Expand links: $BASEDIR";
1173
 
1174
        open (LF, "<", $linkfile ) || Error ("Cannot open link file: $linkfile" );
1175
        while ( <LF> )
1176
        {
1177
            chomp;
1178
            next if ( m~^#~ );
1179
            next unless ( $_ );
1180
            my ($link, $file) = split;
1181
 
1182
            MakeSymLink($file ,"$BASEDIR/$link", '--NoDotDot' );
1183
        }
1184
        close (LF);
1185
        unlink $linkfile;
1186
    }
1187
}
1188
 
1189
#-------------------------------------------------------------------------------
1190
# Function        : ResolveFile
1191
#
1192
# Description     : Determine where the source for a file is
1193
#                   Will look in:
1194
#                       Local directory
1195
#                       Local Include
1196
#                   Will scan 'parts' subdirs
1197
#
1198
# Inputs          : $from_package       - 0 - Local File
1199
#                   $file
1200
#
1201
# Returns         : Path
1202
#
1203
sub ResolveFile
1204
{
1205
    my ($from_package, $file) = @_;
1206
    my @path = $from_package ? ($opt_pkgdir ,$opt_interfacedir) : ('.', $opt_localincdir);
1207
    my $wildcard = ($file =~ /[*?]/);
1208
 
1209
    #
1210
    #   Determine a full list of 'parts' to search
1211
    #   This is provided within the build information
1212
    #
1213
    my @parts = getPlatformParts ();
1214
    push @parts, '';
1215
 
1216
    my @done;
1217
    foreach my $root (  @path )
1218
    {
1219
        foreach my $subdir ( @parts )
1220
        {
1221
            my $sfile;
1222
                $sfile = "$root/$subdir/$file";
1223
                $sfile =~ s~//~/~g;
1224
                $sfile =~ s~^./~~g;
1225
                Verbose2("LocateFile: $sfile, $root, $subdir");
1226
                if ( $wildcard )
1227
                {
1228
                    push @done, glob ( $sfile );
1229
                }
1230
                else
1231
                {
1232
                    push @done, $sfile if ( -f $sfile )
1233
                }
1234
        }
1235
    }
1236
 
1237
    Error ("ResolveFile: File not found: $file")
1238
        unless ( @done );
1239
 
1240
    Warning ("ResolveFile: Multiple instances of file found. Only first is used", @done)
1241
        if ( $#done > 0 && ! $wildcard && !wantarray );
1242
 
1243
    return wantarray ? @done : $done[0];
1244
}
1245
 
1246
#-------------------------------------------------------------------------------
1247
# Function        : ResolveBinFile
1248
#
1249
# Description     : Determine where the source for a file is
1250
#                   Will look in:
1251
#                       Local artifacts bin
1252
#                       Local Bin
1253
#                   Will scan 'parts' subdirs
1254
#
1255
# Inputs          : $from_package       - 0 - Local File
1256
# Inputs          : $file
1257
#
1258
# Returns         : Path
1259
#
1260
sub ResolveBinFile
1261
{
1262
    my ($from_package, $file) = @_;
1263
    my @path;
1264
    my @types;
1265
    my $wildcard = ($file =~ /[*?]/);
1266
 
1267
    if ( $from_package )
1268
    {
1269
        @path = ($opt_pkgdir . '/bin' ,$opt_interfacedir . '/bin' );
1270
        @types = ($opt_type, '');
1271
    }
1272
    else
1273
    {
1274
        @path = ($opt_bindir, $opt_localbindir);
1275
        @types = '';
1276
    }
1277
 
1278
    #
1279
    #   Determine a full list of 'parts' to search
1280
    #   This is provided within the build information
1281
    #
1282
    my @parts = getPlatformParts ();
1283
    push @parts, '';
1284
 
1285
    my @done;
1286
    foreach my $root (  @path )
1287
    {
1288
        foreach my $subdir ( @parts )
1289
        {
1290
            foreach my $type ( @types )
1291
            {
1292
                my $sfile;
1293
                $sfile = "$root/$subdir$type/$file";
1294
                $sfile =~ s~//~/~g;
1295
                Verbose2("LocateBinFile: $sfile");
1296
                if ( $wildcard )
1297
                {
1298
                    push @done, glob ( $sfile );
1299
                }
1300
                else
1301
                {
1302
                    push @done, $sfile if ( -f $sfile )
1303
                }
1304
            }
1305
        }
1306
    }
1307
 
1308
    Error ("ResolveBinFile: File not found: $file")
1309
        unless ( @done );
1310
 
1311
    Warning ("ResolveBinFile: Multiple instances of file found. Only first is used", @done)
1312
        if ( $#done > 0 && ! $wildcard && !wantarray );
1313
 
1314
    return wantarray ? @done : $done[0];
1315
}
1316
 
1317
#-------------------------------------------------------------------------------
1318
# Function        : ResolveLibFile
1319
#
1320
# Description     : Determine where the source for a file is
1321
#                   Will look in:
1322
#                       Local artifacts library
1323
#                       Local Lib
1324
#                   Will scan 'parts' subdirs
1325
#
1326
# Inputs          : $from_package       - 0 - Local File
1327
# Inputs          : $file       - Basename for a 'realname'
1328
#                                 Do not provide 'lib' or '.so' or version info
1329
#                                 May contain embedded options
1330
#                                   --Dll - use Windows style versioned DLL
1331
#                                   --VersionDll - USe the versioned DLL
1332
#
1333
# Returns         : Path
1334
#
1335
sub ResolveLibFile
1336
{
1337
    my ($from_package, $file) = @_;
409 alewis 1338
    my @path = $from_package ? ($opt_pkgdir . '/lib', $opt_interfacedir . '/lib') : ($opt_libdir, $opt_locallibdir);
407 dpurdie 1339
    my $wildcard = ($file =~ /[*?]/);
1340
    my @options;
1341
    my $num_dll;
1342
 
1343
    #
1344
    #   Extract options from file
1345
    #
409 alewis 1346
    $num_dll = 0;
407 dpurdie 1347
    ($file, @options) = split ( ',', $file);
1348
    foreach ( @options )
1349
    {
1350
        if ( m/^--Dll/ ) {
1351
            $num_dll = 1;
1352
        } elsif ( m/^--VersionDll/ ) {
1353
            $num_dll = 2;
1354
        } else {
1355
            Error ("Unknown suboption to ResolveLibFile: $_" );
1356
        }
1357
    }
1358
 
1359
    #
1360
    #   Determine a full list of 'parts' to search
1361
    #   This is provided within the build information
1362
    #
1363
    my @parts = getPlatformParts ();
1364
    push @parts, '';
1365
 
1366
    my @done;
1367
    foreach my $root (  @path )
1368
    {
1369
        foreach my $type ( $opt_type, '' )
1370
        {
1371
            foreach my $subdir ( @parts )
1372
            {
1373
                my $sfile;
1374
                my $exact;
1375
                if ( $num_dll == 2 ) {
1376
                    $sfile = $file . $type . '.*.dll' ;
1377
                } elsif ( $num_dll == 1 ) {
1378
                    $sfile = $file . $type . '.dll' ;
1379
                    $exact = 1;
1380
                } else {
1381
                    $sfile = "lib" . $file . $type . '.so.*';
1382
                }
1383
 
1384
                $sfile = "$root/$subdir/$sfile";
1385
                $sfile =~ s~//~/~g;
1386
                Verbose2("LocateLibFile: $sfile");
1387
                if ( $exact )
1388
                {
1389
                    push @done, $sfile if ( -f $sfile );
1390
                }
1391
                else
1392
                {
1393
                    push @done, glob ( $sfile );
1394
                }
1395
            }
1396
        }
1397
    }
1398
 
1399
    Error ("ResolveLibFile: File not found: $file")
1400
        unless ( @done );
1401
 
1402
    Warning ("ResolveLibFile: Multiple instances of file found. Only first is used", @done)
1403
        if ( $#done > 0 && ! $wildcard && !wantarray );
1404
 
1405
    return wantarray ? @done : $done[0];
1406
}
1407
 
1408
 
1409
#-------------------------------------------------------------------------------
1410
# Function        : AUTOLOAD
1411
#
1412
# Description     : Intercept bad user directives and issue a nice error message
1413
#                   This is a simple routine to report unknown user directives
1414
#                   It does not attempt to distinguish between user errors and
1415
#                   programming errors. It assumes that the program has been
1416
#                   tested. The function simply report filename and line number
1417
#                   of the bad directive.
1418
#
1419
# Inputs          : Original function arguments ( not used )
1420
#
1421
# Returns         : This function does not return
1422
#
1423
our $AUTOLOAD;
1424
sub AUTOLOAD
1425
{
1426
    my $fname = $AUTOLOAD;
1427
    $fname =~ s~^main::~~;
1428
    my ($package, $filename, $line) = caller;
1429
 
1430
    Error ("Directive not known or not allowed in this context: $fname",
1431
           "Directive: $fname( @_ );",
1432
           "File: $filename, Line: $line" );
1433
}
1434
 
1435
 
1436
1;
1437