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;
423 dpurdie 76
use JatsCopy ();                            # Don't import anything
407 dpurdie 77
 
78
#
79
#   Globals
80
#
81
my $DebianWorkDir;                          # Dir to create file system image within
82
 
83
#
84
#   Command line options
85
#
86
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
87
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
88
my $opt_vargs;                              # Verbose arg
89
my $opt_help = 0;
90
my $opt_manual = 0;
91
my $opt_clean = 0;
92
my $opt_platform;
93
my $opt_type;
94
my $opt_buildname;
95
my $opt_buildversion;
96
my $opt_interfacedir;
97
my $opt_target;
98
my $opt_product;
99
my $opt_package_script;
100
my $opt_interfaceincdir;
101
my $opt_interfacelibdir;
102
my $opt_interfacebindir;
103
my $opt_libdir;
104
my $opt_bindir;
105
my $opt_localincdir;
106
my $opt_locallibdir;
107
my $opt_localbindir;
108
my $opt_pkgdir;
109
my $opt_pkglibdir;
110
my $opt_pkgbindir;
111
my $opt_pkgpkgdir;
112
my $opt_output;
417 dpurdie 113
my $opt_name;
407 dpurdie 114
 
115
#
116
#   Options derived from script directives
117
#
118
my $opt_control = '';
119
my $opt_prerm = '';
120
my $opt_postrm = '';
121
my $opt_preinst = '';
122
my $opt_postinst = '';
123
my $opt_description;
124
 
415 dpurdie 125
#
126
#   Globals
127
#
128
my @ResolveFileList;                    # Cached Package File List
129
my @ResolveBinFileList;                 # Cached PackageBin File List
130
my @ResolveLibFileList;                 # Cached PackageLib File List
407 dpurdie 131
 
132
#-------------------------------------------------------------------------------
133
# Function        : Main Entry point
134
#
135
# Description     : This function will be called when the package is initialised
136
#                   Extract arguments from the users environment
137
#
138
#                   Done here to greatly simplify the user script
139
#                   There should be no junk in the user script - keep it simple
140
#
141
# Inputs          :
142
#
143
# Returns         : 
144
#
145
main();
146
sub main
147
{
148
    my $result = GetOptions (
149
                "verbose:s"         => \$opt_vargs,
150
                "clean"             => \$opt_clean,
151
                "Type=s"            => \$opt_type,
152
                "BuildName=s"       => \$opt_buildname,
153
                "BuildVersion=s"    => \$opt_buildversion,
154
                "Platform=s"        => \$opt_platform,
155
                "Target=s"          => \$opt_target,
156
                "Product=s"         => \$opt_product,
157
                "DebianPackage=s"   => \$opt_package_script,
158
                "InterfaceDir=s"    => \$opt_interfacedir,
159
                "InterfaceIncDir=s" => \$opt_interfaceincdir,
160
                "InterfaceLibDir=s" => \$opt_interfacelibdir,
161
                "InterfaceBinDir=s" => \$opt_interfacebindir,
162
                "LibDir=s"          => \$opt_libdir,
163
                "BinDir=s"          => \$opt_bindir,
164
                "LocalIncDir=s"     => \$opt_localincdir,
165
                "LocalLibDir=s"     => \$opt_locallibdir,
166
                "LocalBinDir=s"     => \$opt_localbindir,
167
                "PackageDir=s"      => \$opt_pkgdir,
168
                "PackageLibDir=s"   => \$opt_pkglibdir,
169
                "PackageBinDir=s"   => \$opt_pkgbindir,
170
                "PackagePkgDir=s"   => \$opt_pkgpkgdir,
171
                "Output=s"          => \$opt_output,
417 dpurdie 172
                "Name=s"            => \$opt_name,
407 dpurdie 173
    );
174
 
175
    $opt_verbose++ unless ( $opt_vargs eq '@' );
176
 
177
    ErrorConfig( 'name'    => 'DebianUtils',
178
                 'verbose' => $opt_verbose,
179
                 'debug'   => $opt_debug );
180
 
181
    #
182
    #   Init the FileSystem Uiltity interface
183
    #
184
    InitFileUtils();
185
 
186
    #
187
    #   Ensure that we have all required options
188
    #
189
    Error ("Platform not set")                  unless ( $opt_platform );
190
    Error ("Type not set")                      unless ( $opt_type );
191
    Error ("BuildName not set")                 unless ( $opt_buildname );
192
    Error ("BuildVersion not set")              unless ( $opt_buildversion );
193
    Error ("InterfaceDir not set")              unless ( $opt_interfacedir );
194
    Error ("Target not set")                    unless ( $opt_target );
195
    Error ("Product not set")                   unless ( $opt_product );
196
    Error ("DebianPackage not set")             unless ( $opt_package_script );
197
    Error ("Ouput File not set")                unless ( $opt_output );
417 dpurdie 198
    Error ("Build Name not set")                unless ( $opt_name );
407 dpurdie 199
 
200
    #
201
    #   Clean up the build name
202
    #   Match any work done in the MakeDebianPackage directive
203
    #
204
    $opt_buildname =~ s~_~-~g;
205
 
206
    #
207
    #   Read in relevent config information
208
    #
209
    ReadBuildConfig ($opt_interfacedir, $opt_platform, '--NoTest' );
210
 
211
    #
212
    #   Build the package image in a directory based on the target being created
213
    #
417 dpurdie 214
    $DebianWorkDir = "$opt_platform$opt_type.image/$opt_name";
407 dpurdie 215
 
216
    #
217
    #   Configure the System command to fail on any error
218
    #
219
    SystemConfig ( ExitOnError => 1 );
220
 
221
    #
222
    #   Extract the 'name' of the package from the output path
223
    #   Display purposes only
224
    #
225
    my $DebianPkgName = StripDirExt($opt_output);
226
 
227
    #
228
    #   Display variables used
229
    #
230
    Message    "=Building Debian Package =============================================";
417 dpurdie 231
    Message    "Build $opt_name";
407 dpurdie 232
    Message    "       Package: $opt_buildname";
233
    Message    "       Version: $opt_buildversion";
234
    Message    "  Building for: $opt_platform, $opt_target";
235
    Message    "       Product: $opt_product";
236
    Message    "          Type: $opt_type";
237
    Verbose    "       Verbose: $opt_verbose";
238
    Verbose    "  InterfaceDir: $opt_interfacedir";
239
    Message    "       Package: $DebianPkgName";
240
    Message    "======================================================================";
241
 
242
    #
243
    #   Perform Clean up
244
    #   Invoked during "make clean" or "make clobber"
245
    #
246
    if ( $opt_clean )
247
    {
248
        Message ("Remove packaging directory: $DebianWorkDir");
249
        rmtree( $DebianWorkDir );
250
        rmtree ($opt_output) if ( -f $opt_output );
251
        exit;
252
    }
253
 
254
    #
255
    #   Clean  out the WORK directory
256
    #   Always start with a clean slate
257
    #
258
    #   Ensure that the base of the directory tree does not have 'setgid'
259
    #       This will upset the debian packager
260
    #       This may be an artifact from the users directory and not expected
261
    #
262
    rmtree( $DebianWorkDir );
263
    mkpath( $DebianWorkDir );
264
 
265
    my $perm = (stat $DebianWorkDir)[2] & 0777;
266
    chmod ( $perm & 0777, $DebianWorkDir );
267
 
268
    #
269
    #   Invoke the user script to do the hard work
270
    #
271
    do $opt_package_script;
272
 
273
    #
274
    #   Complete the building of the package
275
    #
276
    BuildDebianPackage ();
277
    Message ("Created Debian Package");
278
}
279
 
280
#-------------------------------------------------------------------------------
281
# Function        : BuildDebianPackage
282
#
283
# Description     : This function will create the Debian Package
284
#                   and transfer it to the target directory
285
#
286
# Inputs          : None
287
#
288
# Returns         : Nothing
289
#
290
sub BuildDebianPackage
291
{
292
    Error ("BuildDebianPackage: No Control File or Package Description")
293
        unless ( $opt_control || $opt_description );
294
 
295
    #
296
    #   Convert the FileSystem Image into a Debian Package
297
    #       Insert Debian control files
298
    #
299
    Verbose ("Copy in the Debian Control Files");
300
    mkdir ( "$DebianWorkDir/DEBIAN" );
301
 
302
    CopyFile ( $opt_prerm,    "/DEBIAN", "prerm" )    if $opt_prerm;
303
    CopyFile ( $opt_postrm,   "/DEBIAN", "postrm" )   if $opt_postrm;
304
    CopyFile ( $opt_preinst,  "/DEBIAN", "preinst" )  if $opt_preinst;
305
    CopyFile ( $opt_postinst, "/DEBIAN", "postinst" ) if $opt_postinst;
306
 
307
    UpdateControlFile ($opt_control );
308
    System ( 'chmod', '-R', 'a+rx', "$DebianWorkDir/DEBIAN" );
309
    System ( 'build_dpkg.sh', '-b', $DebianWorkDir);
310
    System ( 'mv', '-f', "$DebianWorkDir.deb", $opt_output );
311
 
312
    System ("build_dpkg.sh", '-I', $opt_output) if (IsVerbose(1));
313
 
314
}
315
 
316
#-------------------------------------------------------------------------------
317
# Function        : UpdateControlFile
318
#
319
# Description     : Update the Debian 'control' file to fix up varoius fields
320
#                   within the file.
321
#
322
#                   If the files has not been specified, then a basic control
323
#                   file will be provided.
324
#
325
#                   This routine knows where the control file will be placed
326
#                   within the output work space.
327
#
328
# Inputs          : $src            - Path to source file
329
#                   Uses global variables
330
#
331
# Returns         : Nothing
332
#
333
sub UpdateControlFile
334
{
335
    my($src) = @_;
336
    my $dst = "$DebianWorkDir/DEBIAN/control";
337
 
338
    unless ( $src )
339
    {
340
        CreateControlFile();
341
        return;
342
    }
343
 
344
    Verbose ("UpdateControlFile: $dst" );
345
    $src = ResolveFile( 0, $src );
346
 
347
    open (SF, '<', $src) || Error ("UpdateControlFile: Cannot open $src");
348
    open (DF, '>', $dst) || Error ("UpdateControlFile: Cannot create:$dst");
349
    while ( <SF> )
350
    {
351
        s~\s*$~~;
352
        if ( m~^Package:~ ) {
353
            $_ = "Package: $opt_buildname";
354
 
355
        } elsif ( m~^Version:~ ) {
356
            $_ = "Version: $opt_buildversion";
357
 
358
        } elsif ( m~^Architecture:~ ) {
359
            $_ = "Architecture: $opt_platform";
360
 
361
        } elsif ( $opt_description && m~^Description:~ ) {
362
            $_ = "Description: $opt_description";
363
        }
364
        print DF $_ , "\n";
365
    }
366
    close (SF);
367
    close (DF);
368
}
369
 
370
#-------------------------------------------------------------------------------
371
# Function        : CreateControlFile
372
#
373
# Description     : Craete a basic debian control file
374
#
375
# Inputs          : Uses global variables
376
#
377
# Returns         : 
378
#
379
sub CreateControlFile
380
{
381
    my $dst = "$DebianWorkDir/DEBIAN/control";
382
 
383
    Verbose ("CreateControlFile: $dst" );
384
 
385
    open (DF, '>', $dst) || Error ("CreateControlFile: Cannot create:$dst");
386
    print DF "Package: $opt_buildname\n";
387
    print DF "Version: $opt_buildversion\n";
388
    print DF "Section: main\n";
389
    print DF "Priority: standard\n";
390
    print DF "Architecture: $opt_platform\n";
391
    print DF "Essential: yes\n";
392
    print DF "Maintainer: ERG\n";
393
    print DF "Description: $opt_description\n";
394
    close (DF);
395
}
396
 
397
#-------------------------------------------------------------------------------
398
# Function        : SetVerbose
399
#
400
# Description     : Set the level of verbosity
401
#                   Display activity
402
#
403
# Inputs          : Verbosity level
404
#                       0 - Use makefile verbosity (Default)
405
#                       1..2
406
#
407
# Returns         : 
408
#
409
sub SetVerbose
410
{
411
    my ($level) = @_;
412
 
413
    $level = $opt_verbose unless ( $level );
414
    $opt_verbose = $level;
415
    ErrorConfig( 'verbose' => $level);
416
}
417
 
418
 
419
#-------------------------------------------------------------------------------
420
# Function        : DebianFiles
421
#
422
# Description     : Name Debian builder control files
423
#                   May be called multiple times
424
#
425
# Inputs          : Options
426
#                       --Control=file
427
#                       --PreRm=file
428
#                       --PostRm=file
429
#                       --PreInst=file
430
#                       --PostInst=file
431
#
432
# Returns         : Nothing
433
#
434
sub DebianFiles
435
{
436
    #
437
    #   Exctact names
438
    #
439
    Verbose ("Specify Debian Control Files and Scripts");
440
    foreach  ( @_ )
441
    {
442
        if ( m/^--Control=(.+)/ ) {
443
            $opt_control = $1;
444
 
445
        } elsif ( m/^--PreRm=(.+)/ ) {
446
            $opt_prerm = $1;
447
 
448
        } elsif ( m/^--PostRm=(.+)/ ) {
449
            $opt_postrm = $1;
450
 
451
        } elsif ( m/^--PreInst=(.+)/ ) {
452
            $opt_preinst  = $1;
453
 
454
        } elsif ( m/^--PostInst=(.+)/ ) {
455
            $opt_postinst = $1;
456
 
457
        } else {
458
            Error ("DebianFiles: Unknown option: $_");
459
        }
460
    }
461
}
462
 
463
#-------------------------------------------------------------------------------
464
# Function        : PackageDescription
465
#
466
# Description     : Specify the Package Description
467
#                   Keep it short
468
#
469
# Inputs          : $description
470
#
471
# Returns         : 
472
#
473
sub PackageDescription
474
{
475
    ($opt_description) = @_;
476
}
477
 
478
#-------------------------------------------------------------------------------
479
# Function        : MakeSymLink
480
#
481
# Description     : Create a symlink - with error detection
482
#
483
# Inputs          : old_file    - Link Target
484
#                                 Path to the link target
485
#                                 If an ABS path is provided, the routine will
486
#                                 attempt to create a relative link.
487
#                   new_file    - Relative to the output work space
488
#                                 Path to where the 'link' file will be created
489
#                   Options     - Must be last
490
#                                 --NoClean         - Don't play with links
491
#                                 --NoDotDot        - Don't create symlinks with ..
492
#
493
# Returns         : Nothing
494
#
495
sub MakeSymLink
496
{
497
    my $no_clean;
498
    my $no_dot;
499
    my @args;
500
 
501
    #
502
    #   Extract options
503
    #
504
    foreach ( @_ )
505
    {
506
        if ( m/^--NoClean/i ) {
507
            $no_clean = 1;
508
 
509
        } elsif ( m/^--NoDotDot/i ) {
510
            $no_dot = 1;
511
 
512
        } elsif ( m/^--/ ) {
513
            Error ("MakeSymLink: Unknown option: $_");
514
 
515
        } else {
516
            push @args, $_;
517
        }
518
    }
519
 
520
    my ($old_file, $new_file) = @args;
521
 
522
    my $tfile = $DebianWorkDir . '/' . $new_file;
523
    $tfile =~ s~//~/~;
524
    Verbose ("Symlink $old_file -> $new_file" );
525
 
526
    #
527
    #   Create the directory in which the link will be placed
528
    #   Remove any existing file of the same name
529
    #
530
    my $dir = StripFileExt( $tfile );
531
    mkpath( $dir) unless -d $dir;
532
    unlink $tfile;
533
 
534
    #
535
    #   Determine a good name of the link
536
    #   Convert to a relative link in an attempt to prune them
537
    #
538
    my $sfile = $old_file;
539
    unless ( $no_clean )
540
    {
541
        $sfile = CalcRelPath( StripFileExt( $new_file ), $old_file );
542
        $sfile = $old_file if ( $no_dot && $sfile =~ m~^../~ );
543
    }
544
 
545
    my $result = symlink $sfile, $tfile;
546
    Error ("Cannot create symlink. $old_file -> $new_file") unless ( $result );
547
}
548
 
549
#-------------------------------------------------------------------------------
550
# Function        : CopyFile
551
#
552
# Description     : Copy a file to a target dir
553
#                   Used for text files, or files with fixed names
554
#
555
# Inputs          : $src
556
#                   $dst_dir    - Within the output workspace
557
#                   $dst_name   - Output Name [Optional]
558
#                   Options     - Common Copy Options
559
#
560
# Returns         : Full path to destination file
561
#
562
sub CopyFile
563
{
564
    CopyFileCommon( \&ResolveFile, @_ );
565
}
566
 
567
#-------------------------------------------------------------------------------
568
# Function        : CopyBinFile
569
#
570
# Description     : Copy a file to a target dir
571
#                   Used for executable programs. Will look in places where
572
#                   programs are stored.
573
#
574
# Inputs          : $src
575
#                   $dst_dir    - Within the output workspace
576
#                   $dst_name   - Output Name [Optional]
577
#
578
#                   Options:
579
#                       --FromPackage
580
#                       --SoftLink=xxxx
581
#                       --LinkFile=xxxx
582
#
583
#
584
# Returns         : Full path to destination file
585
#
586
sub CopyBinFile
587
{
588
    CopyFileCommon( \&ResolveBinFile, @_ );
589
}
590
 
591
#-------------------------------------------------------------------------------
592
# Function        : CopyLibFile
593
#
594
# Description     : Copy a file to a target dir
595
#                   Used for shared programs. Will look in places where
596
#                   shared libraries are stored.
597
#
598
# Inputs          : $src        - Base for 'realname' (no lib, no extension)
599
#                   $dst_dir    - Within the output workspace
600
#                   $dst_name   - Output Name [Optional, but not suggested]
601
#
602
# Returns         : Full path to destination file
603
#
604
# Notes           : Copying 'lib' files
605
#                   These are 'shared libaries. There is no provision for copying
606
#                   static libraries.
607
#
608
#                   The tool will attempt to copy a well-formed 'realname' library
609
#                   The soname of the library should be constructed on the target
610
#                   platform using ldconfig.
611
#                   There is no provision to copy the 'linker' name
612
#
613
#                   Given a request to copy a library called 'fred', then the
614
#                   well formed 'realname' will be:
615
#                           libfred[P|D|]].so.nnnnn
616
#                   where:
617
#                           nnnn is the library version
618
#                           [P|D|] indicates Production, Debug or None
619
#
620
#                   The 'soname' is held within the realname form of the library
621
#                   and will be created by lsconfig.
622
#
623
#                   The 'linkername' would be libfred[P|D|].so. This is only
624
#                   needed when linking against the library.
625
#
626
#
627
#                   The routine will also recognize Windows DLLs
628
#                   These are of the form fred[P|D|].nnnnn.dll
629
#
630
sub CopyLibFile
631
{
632
    CopyFileCommon( \&ResolveLibFile, @_ );
633
}
634
 
635
#-------------------------------------------------------------------------------
636
# Function        : CopyFileCommon
637
#
638
# Description     : Common ( internal File Copy )
639
#
640
# Inputs          : $resolver           - Ref to function to resolve source file
641
#                   $src                - Source File Name
642
#                   $dst_dir            - Target Dir
643
#                   $dst_name           - Target Name (optional)
644
#                   Options
645
#                   Options:
646
#                       --FromPackage
647
#                       --SoftLink=xxxx
648
#                       --LinkFile=xxxx
649
#
650
# Returns         : 
651
#
652
sub CopyFileCommon
653
{
654
    my $from_package = 0;
655
    my $isa_linkfile = 0;
656
    my @llist;
657
    my @args;
658
 
659
    #
660
    #   Parse options
661
    #
662
    foreach ( @_ )
663
    {
664
        if ( m/^--FromPackage/ ) {
665
            $from_package = 1;
666
 
667
        } elsif ( m/^--LinkFile/ ) {
668
            $isa_linkfile = 1;
669
 
670
        } elsif ( m/^--SoftLink=(.+)/ ) {
671
            push @llist, $1;
672
 
673
        } elsif ( m/^--/ ) {
674
            Error ("FileCopy: Unknown option: $_");
675
 
676
        } else {
677
            push @args, $_;
678
        }
679
    }
680
 
681
    #
682
    #   Extract non-options.
683
    #   These are the bits that are left over
684
    #
685
    my ($resolver, $src, $dst_dir, $dst_name ) = @args;
686
 
687
    #
688
    #   Clean up dest_dir. Must start with a / and not end with one
689
    #
690
    $dst_dir = "/$dst_dir/";
691
    $dst_dir =~ s~/+~/~g;
692
    $dst_dir =~ s~/$~~;
693
 
694
    Verbose ("CopyFile: $src, $dst_dir, " . ($dst_name || ''));
695
    foreach $src ( &$resolver( $from_package, $src ) )
696
    {
697
        my $dst_fname = $dst_name ? $dst_name : StripDir($src);
698
        my $dst_file = "$dst_dir/$dst_fname";
699
        Verbose ("CopyFile: Copy $src, $dst_file" );
700
 
701
 
702
        #
703
        #   LinkFiles are special
704
        #   They get concatenated to any existing LINKS File
705
        #
706
        if ( $isa_linkfile )
707
        {
708
            CatFile ( $src, "$dst_dir/.LINKS" );
709
        }
710
        else
711
        {
712
            mkpath( "$DebianWorkDir$dst_dir", 0, 0775);
713
            unlink ("$DebianWorkDir$dst_file");
714
            System ('cp','-f', $src, "$DebianWorkDir$dst_file" );
715
 
716
            foreach my $lname ( @llist )
717
            {
718
                $lname = $dst_dir . '/' . $lname unless ( $lname =~ m ~^/~ );
719
                MakeSymLink( $dst_file ,$lname);
720
            }
721
        }
722
    }
723
}
724
 
725
#-------------------------------------------------------------------------------
726
# Function        : CopyDir
727
#
728
# Description     : Copy a directory to a target dir
729
#
730
# Inputs          : $src_dir    - Local to the user
731
#                                 Symbolic Name
732
#                   $dst_dir    - Within the output workspace
733
#                   Options
423 dpurdie 734
#                       --Merge             - Don't delete first
735
#                       --Source=Name       - Source via Symbolic Name
407 dpurdie 736
#
737
# Returns         :
738
#
739
sub CopyDir
740
{
741
    my ($src_dir, $dst_dir, @opts) = @_;
742
    my $opt_merge;
743
    my $opt_base;
411 dpurdie 744
    my $from_interface = 0;
407 dpurdie 745
 
746
    $dst_dir = $DebianWorkDir . '/' . $dst_dir;
747
    $dst_dir =~ s~//~/~;
748
 
749
    #
750
    #   Detect and expand Symbolic names in the Source Directory
751
    #
752
    foreach  ( @opts )
753
    {
754
        if ( m/^--Merge/ ) {
755
            $opt_merge = 1;
756
        } elsif ( m/^--Source=(.+)/ ) {
757
            my $name = lc($1);
758
            my %CopyDirSymbolic = (
759
                'interfaceincdir'   => $opt_interfaceincdir,
760
                'interfacelibdir'   => $opt_interfacelibdir,
761
                'interfacebindir'   => $opt_interfacebindir,
762
                'libdir'            => $opt_libdir,
763
                'bindir'            => $opt_bindir,
764
                'localincdir'       => $opt_localincdir,
765
                'locallibdir'       => $opt_locallibdir,
766
                'localbindir'       => $opt_localbindir,
767
                'packagebindir'     => $opt_pkgbindir,
768
                'packagelibdir'     => $opt_pkglibdir,
769
                'packagepkgdir'     => $opt_pkgpkgdir,
770
                'packagedir'        => $opt_pkgdir,
771
            );
772
 
773
            if ( exists $CopyDirSymbolic{$name} )
774
            {
775
                $opt_base = $CopyDirSymbolic{$name};
411 dpurdie 776
 
777
                #
778
                #   If sourceing from interface, then follow
779
                #   symlinks in the copy. All files will be links anyway
780
                #
781
                $from_interface = 1
782
                    if ( $name =~ m~^interface~ );
407 dpurdie 783
            }
784
            else
785
            {
786
                DebugDumpData ("CopyDirSymbolic", \%CopyDirSymbolic);
787
                Error ("CopyDir: Unknown Source Name: $name" );
788
            }
789
        } else {
790
            Error ("CopyDir: Unknown option: $_" );
791
        }
792
    }
793
 
794
    $src_dir = $opt_base . '/' . $src_dir if ( $opt_base );
795
    $src_dir =~ s~//~/~g;
796
    $src_dir =~ s~/$~~;
797
 
798
    Verbose ("CopyDir: $src_dir, $dst_dir");
799
    Error ("CopyDir: Directory not found: $src_dir") unless ( -d $src_dir );
800
 
801
    #
423 dpurdie 802
    #   Setup the copy options
407 dpurdie 803
    #
423 dpurdie 804
    my %copyOpts;
805
    $copyOpts{'IgnoreDirs'} = ['.svn'];
806
    $copyOpts{'EmptyDirs'} = 1;
807
    $copyOpts{'DeleteFirst'} = 1 unless $opt_merge;
808
    $copyOpts{'Log'} = 1 if ( $opt_verbose > 1 );
809
    $copyOpts{'DuplicateLinks'} = 1 unless ( $from_interface );
407 dpurdie 810
 
811
    #
423 dpurdie 812
    #   Transfer the directory
407 dpurdie 813
    #
423 dpurdie 814
    JatsCopy::CopyDir ( $src_dir, $dst_dir, \%copyOpts );
407 dpurdie 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
415 dpurdie 1193
#                   Will look in (default):
407 dpurdie 1194
#                       Local directory
1195
#                       Local Include
415 dpurdie 1196
#                   Or  (FromPackage)
1197
#                       Our Package directory
1198
#                       Interface directory (BuildPkgArchives)
1199
#                       Packages (LinkPkgArchive)
1200
#
407 dpurdie 1201
#                   Will scan 'parts' subdirs
1202
#
1203
# Inputs          : $from_package       - 0 - Local File
1204
#                   $file
1205
#
1206
# Returns         : Path
1207
#
1208
sub ResolveFile
1209
{
1210
    my ($from_package, $file) = @_;
1211
    my $wildcard = ($file =~ /[*?]/);
415 dpurdie 1212
    my @path;
407 dpurdie 1213
 
1214
    #
415 dpurdie 1215
    #   Determine the paths to search
1216
    #
1217
    if ( $from_package )
1218
    {
1219
        unless ( @ResolveFileList )
1220
        {
1221
            push @ResolveFileList, $opt_pkgdir;
1222
            foreach my $entry ( getPackageList() )
1223
            {
1224
                push @ResolveFileList, $entry->getBase(3);
1225
            }
1226
        }
1227
        @path = @ResolveFileList;
1228
    }
1229
    else
1230
    {
1231
        @path = ('.', $opt_localincdir);
1232
    }
1233
 
1234
    #
407 dpurdie 1235
    #   Determine a full list of 'parts' to search
1236
    #   This is provided within the build information
1237
    #
1238
    my @parts = getPlatformParts ();
1239
    push @parts, '';
1240
 
1241
    my @done;
1242
    foreach my $root (  @path )
1243
    {
1244
        foreach my $subdir ( @parts )
1245
        {
1246
            my $sfile;
415 dpurdie 1247
            $sfile = "$root/$subdir/$file";
1248
            $sfile =~ s~//~/~g;
1249
            $sfile =~ s~^./~~g;
1250
            Verbose2("LocateFile: $sfile, $root, $subdir");
1251
            if ( $wildcard )
1252
            {
1253
                push @done, glob ( $sfile );
1254
            }
1255
            else
1256
            {
1257
                push @done, $sfile if ( -f $sfile || -l $sfile )
1258
            }
407 dpurdie 1259
        }
1260
    }
1261
 
415 dpurdie 1262
    Error ("ResolveFile: File not found: $file", "Search Path:", @path)
407 dpurdie 1263
        unless ( @done );
1264
 
1265
    Warning ("ResolveFile: Multiple instances of file found. Only first is used", @done)
1266
        if ( $#done > 0 && ! $wildcard && !wantarray );
1267
 
1268
    return wantarray ? @done : $done[0];
1269
}
1270
 
1271
#-------------------------------------------------------------------------------
1272
# Function        : ResolveBinFile
1273
#
415 dpurdie 1274
# Description     : Determine where the source for a BIN file is
1275
#                   Will look in (default):
1276
#                       Local directory
1277
#                       Local Include
1278
#                   Or  (FromPackage)
1279
#                       Our Package directory
1280
#                       Interface directory (BuildPkgArchives)
1281
#                       Packages (LinkPkgArchive)
407 dpurdie 1282
#                   Will scan 'parts' subdirs
1283
#
1284
# Inputs          : $from_package       - 0 - Local File
415 dpurdie 1285
#                   $file
407 dpurdie 1286
#
1287
# Returns         : Path
1288
#
1289
sub ResolveBinFile
1290
{
1291
    my ($from_package, $file) = @_;
1292
    my @path;
1293
    my @types;
1294
    my $wildcard = ($file =~ /[*?]/);
1295
 
415 dpurdie 1296
    #
1297
    #   Determine the paths to search
1298
    #
407 dpurdie 1299
    if ( $from_package )
1300
    {
415 dpurdie 1301
        unless ( @ResolveBinFileList )
1302
        {
1303
            push @ResolveBinFileList, $opt_pkgdir . '/bin';
1304
            foreach my $entry ( getPackageList() )
1305
            {
1306
                if ( my $path = $entry->getBase(3) )
1307
                {
1308
                    $path .= '/bin';
1309
                    push @ResolveBinFileList, $path if ( -d $path );
1310
                }
1311
            }
1312
        }
1313
        @path = @ResolveBinFileList;
407 dpurdie 1314
        @types = ($opt_type, '');
1315
    }
1316
    else
1317
    {
1318
        @path = ($opt_bindir, $opt_localbindir);
1319
        @types = '';
1320
    }
1321
 
1322
    #
1323
    #   Determine a full list of 'parts' to search
1324
    #   This is provided within the build information
1325
    #
1326
    my @parts = getPlatformParts ();
1327
    push @parts, '';
1328
 
1329
    my @done;
1330
    foreach my $root (  @path )
1331
    {
1332
        foreach my $subdir ( @parts )
1333
        {
1334
            foreach my $type ( @types )
1335
            {
1336
                my $sfile;
1337
                $sfile = "$root/$subdir$type/$file";
1338
                $sfile =~ s~//~/~g;
1339
                Verbose2("LocateBinFile: $sfile");
1340
                if ( $wildcard )
1341
                {
1342
                    push @done, glob ( $sfile );
1343
                }
1344
                else
1345
                {
415 dpurdie 1346
                    push @done, $sfile if ( -f $sfile || -l $sfile )
407 dpurdie 1347
                }
1348
            }
1349
        }
1350
    }
1351
 
415 dpurdie 1352
    Error ("ResolveBinFile: File not found: $file", "Search Path:", @path)
407 dpurdie 1353
        unless ( @done );
1354
 
1355
    Warning ("ResolveBinFile: Multiple instances of file found. Only first is used", @done)
1356
        if ( $#done > 0 && ! $wildcard && !wantarray );
1357
    return wantarray ? @done : $done[0];
1358
}
1359
 
1360
#-------------------------------------------------------------------------------
1361
# Function        : ResolveLibFile
1362
#
415 dpurdie 1363
# Description     : Determine where the source for a LIB file is
1364
#                   Will look in (default):
1365
#                       Local directory
1366
#                       Local Include
1367
#                   Or  (FromPackage)
1368
#                       Our Package directory
1369
#                       Interface directory (BuildPkgArchives)
1370
#                       Packages (LinkPkgArchive)
407 dpurdie 1371
#                   Will scan 'parts' subdirs
1372
#
1373
# Inputs          : $from_package       - 0 - Local File
415 dpurdie 1374
#                   $file       - Basename for a 'realname'
407 dpurdie 1375
#                                 Do not provide 'lib' or '.so' or version info
1376
#                                 May contain embedded options
1377
#                                   --Dll - use Windows style versioned DLL
1378
#                                   --VersionDll - USe the versioned DLL
1379
#
1380
# Returns         : Path
1381
#
1382
sub ResolveLibFile
1383
{
1384
    my ($from_package, $file) = @_;
1385
    my $wildcard = ($file =~ /[*?]/);
1386
    my @options;
1387
    my $num_dll;
415 dpurdie 1388
    my @path;
407 dpurdie 1389
    #
1390
    #   Extract options from file
1391
    #
409 alewis 1392
    $num_dll = 0;
407 dpurdie 1393
    ($file, @options) = split ( ',', $file);
1394
    foreach ( @options )
1395
    {
1396
        if ( m/^--Dll/ ) {
1397
            $num_dll = 1;
1398
        } elsif ( m/^--VersionDll/ ) {
1399
            $num_dll = 2;
1400
        } else {
1401
            Error ("Unknown suboption to ResolveLibFile: $_" );
1402
        }
1403
    }
1404
 
1405
    #
415 dpurdie 1406
    #   Determine the paths to search
1407
    #
1408
    if ( $from_package )
1409
    {
1410
        unless ( @ResolveLibFileList )
1411
        {
1412
            push @ResolveLibFileList, $opt_pkgdir . '/lib';
1413
            foreach my $entry ( getPackageList() )
1414
            {
1415
                push @ResolveLibFileList, $entry->getLibDirs(3);
1416
            }
1417
        }
1418
        @path = @ResolveLibFileList;
1419
    }
1420
    else
1421
    {
1422
        @path = ($opt_libdir, $opt_locallibdir);
1423
    }
1424
 
1425
    #
407 dpurdie 1426
    #   Determine a full list of 'parts' to search
1427
    #   This is provided within the build information
1428
    #
1429
    my @parts = getPlatformParts ();
1430
    push @parts, '';
1431
 
1432
    my @done;
1433
    foreach my $root (  @path )
1434
    {
1435
        foreach my $type ( $opt_type, '' )
1436
        {
1437
            foreach my $subdir ( @parts )
1438
            {
1439
                my $sfile;
1440
                my $exact;
1441
                if ( $num_dll == 2 ) {
1442
                    $sfile = $file . $type . '.*.dll' ;
1443
                } elsif ( $num_dll == 1 ) {
1444
                    $sfile = $file . $type . '.dll' ;
1445
                    $exact = 1;
1446
                } else {
1447
                    $sfile = "lib" . $file . $type . '.so.*';
1448
                }
1449
 
1450
                $sfile = "$root/$subdir/$sfile";
1451
                $sfile =~ s~//~/~g;
1452
                Verbose2("LocateLibFile: $sfile");
1453
                if ( $exact )
1454
                {
415 dpurdie 1455
                    push @done, $sfile if ( -f $sfile || -l $sfile );
407 dpurdie 1456
                }
419 dpurdie 1457
                elsif ($num_dll)
407 dpurdie 1458
                {
1459
                    push @done, glob ( $sfile );
1460
                }
419 dpurdie 1461
                else
1462
                {
1463
                    #
1464
                    #   Looking for .so files
1465
                    #   Filter out the soname so files
1466
                    #   Assume that the soname is shorter than the realname
1467
                    #
1468
                    my %sieve;
1469
                    foreach ( glob ( $sfile )  )
1470
                    {
421 alewis 1471
                        m~(.*\.so\.)([\d\.]*\d)$~;
1472
                        if ( $1 )
1473
                        {
1474
                            my $file = $1;
1475
                            my $len = exists $sieve{$file} ? length($sieve{$file}) : 0;
1476
                            $sieve{$file} = $_
1477
                                if ( $len == 0 || length($_) > $len );
1478
                        }                                
419 dpurdie 1479
                    }
1480
 
1481
                    push @done, values %sieve;
1482
                }
407 dpurdie 1483
            }
1484
        }
1485
    }
1486
 
415 dpurdie 1487
    Error ("ResolveLibFile: File not found: $file", "Search Path:", @path)
407 dpurdie 1488
        unless ( @done );
1489
 
1490
    Warning ("ResolveLibFile: Multiple instances of file found. Only first is used", @done)
1491
        if ( $#done > 0 && ! $wildcard && !wantarray );
1492
 
1493
    return wantarray ? @done : $done[0];
1494
}
1495
 
1496
 
1497
#-------------------------------------------------------------------------------
1498
# Function        : AUTOLOAD
1499
#
1500
# Description     : Intercept bad user directives and issue a nice error message
1501
#                   This is a simple routine to report unknown user directives
1502
#                   It does not attempt to distinguish between user errors and
1503
#                   programming errors. It assumes that the program has been
1504
#                   tested. The function simply report filename and line number
1505
#                   of the bad directive.
1506
#
1507
# Inputs          : Original function arguments ( not used )
1508
#
1509
# Returns         : This function does not return
1510
#
1511
our $AUTOLOAD;
1512
sub AUTOLOAD
1513
{
1514
    my $fname = $AUTOLOAD;
1515
    $fname =~ s~^main::~~;
1516
    my ($package, $filename, $line) = caller;
1517
 
1518
    Error ("Directive not known or not allowed in this context: $fname",
1519
           "Directive: $fname( @_ );",
1520
           "File: $filename, Line: $line" );
1521
}
1522
 
1523
 
1524
1;
1525