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