Subversion Repositories DevTools

Rev

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

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