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