Subversion Repositories DevTools

Rev

Rev 331 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
# Copyright (C) 1998-2004 ERG Transit Systems, All rights reserved
2
#
3
# Module name   : installpkg.pl
4
# Module type   : Makefile system
5
# Environment(s): n/a
6
#											
7
# Description:    Install package definition file.
8
#		
9
#	This file is invoked during package installation
10
#
11
###############################################################################
12
#
13
#   The main purpose of this program is to take packages from dpkg_archive and
14
#   place them into the build's 'interface' directory in a form that can be used
15
#   by the rest of the build. This process is complicated by the number of
16
#   variants in package format. In the pre-JATS2 days the users were encourgaed
17
#   to dream up there own format for packages. The hard of of this script is
18
#   dealing with all the known variations. Under JATS2 the default package
19
#   layout is much easier to implemenet and users generally adhere to it.
20
#
21
#   The target 'interface' format is of the form:
22
#
23
#           interface/
24
#               include/
25
#                   PLATFORM/
26
#                   PRODUCT/
27
#                   TARGET/
28
#               lib/                                    - Should not be populated
29
#                   PLATFORM/                           - Ideal
30
#                   PRODUCT/                            - Not practical
31
#                   TARGET/
32
#               bin/                                    - Should not be populated
33
#                   PLATFORM[P|D]/                      - Ideal
34
#                   PRODUCT[P|D]/                       - Not practical
35
#                   TARGET[P|D]/
36
#
37
#               tools/
38
#                   bin/
39
#                       MACHTYPE/
40
#                   scrips/
41
#                       MACHTYPE/
42
#
43
#               pkg/
44
#
45
#               OTHERS
46
#
47
#
48
 
49
use strict;
50
use warnings;
51
 
52
use JatsError;
53
use DescPkg;
54
use JatsEnv;
55
 
56
use Cwd;
57
use File::Basename;
58
use File::Find;
59
use File::Path;
60
use File::Copy;
61
 
62
#
63
#   Global variables
64
#
65
our $GBE_VERBOSE;
66
our $GBE_MACHTYPE;
67
 
68
my %PLATFORMS = ();
69
my %dirs_processed = ();
70
my $symlinks;
331 dpurdie 71
my $allow_overwrite = 0;
227 dpurdie 72
 
73
#...
74
#
75
my $INTDIR;                                 # Interface directory (target)
76
my $BINDIR;                                 # Build directory (Not used)
77
my $PKG_ROOT=cwd();                         # Package source (CWD)
78
 
79
#
80
#   Global used for File::Find callback function
81
#
82
my $FF_SRC_DIR="";                          # Src subdir base
83
my $FF_DST_DIR="";                          # Dst subdir base
84
 
85
################################################################################
86
#
87
#
88
#
89
#   Init the error reporting package
90
#
91
ErrorConfig( 'name'    => 'installpkg' );
92
 
93
#
94
#   Ensure required environment variables are present
95
#
96
EnvImport ('GBE_MACHTYPE');
97
EnvImport ('GBE_VERBOSE');
98
 
99
ErrorConfig( 'verbose' => $GBE_VERBOSE );
100
 
101
#
102
#   Determine if symlinks are available
103
#   They may not be available at all, in which case we don't even try
104
#
105
$symlinks = eval { symlink("",""); 1 } || 0;
106
 
107
#
108
#   Report machine information
109
#
331 dpurdie 110
Verbose ("GBE_VERBOSE    : $GBE_VERBOSE" );
111
Verbose ("GBE_MACHTYPE   : $GBE_MACHTYPE" );
112
Verbose ("SymLinks       : $symlinks" );
113
Verbose ("AllowOverwrite : $allow_overwrite" );
114
Verbose ("Cmd            : @ARGV");
227 dpurdie 115
 
116
################################################################################
117
#
118
#   Parse user arguments
119
#   Arguments
120
#       Arg0    - Interface directory
121
#       Arg1    - Build Directory ( Not Used )
122
#       Arg2..  - A list of Platform specifications
123
#                 One for each platform that needs to be processed
124
#                 Each plaform specification consists of:
125
#                   --Platform:PlatformName:PlatformParts:Options
126
#                   Where:
127
#                       --Platform      - is a leadin switch
128
#                       PlatformName    - The the target platform
129
#                       PlatformParts   - A colon seperated list of platform 'parts'
130
#                                         This consist of: Platform, Product, ... Target
131
#
132
$INTDIR = shift @ARGV;
133
Error("Interface directory not specified") unless( defined $INTDIR );
134
Error("Interface directory not found: $INTDIR") unless( -d $INTDIR );
135
 
136
$BINDIR = shift @ARGV;
137
Error("Program directory not specified")   unless( defined $BINDIR );
138
Error("Program directory not found: $BINDIR") unless( -d $BINDIR );
139
 
140
foreach ( @ARGV )
141
{
142
    if ( /^--Platform/ ) {
143
        Verbose2 ("ARGV = <$_>");
144
        my ($tmpVar, @platforms) = split /:/, $_;
145
 
146
        my $platform = $platforms[0];
147
        $PLATFORMS{$platform}{'PARTS'} = \@platforms;
148
 
149
    } elsif ( /^--NoSymlinks/i ) {
150
        $symlinks = 0;
151
 
331 dpurdie 152
    } elsif ( /^--AllowOverWrite/i ) {
153
        $allow_overwrite = 1;
154
 
227 dpurdie 155
    } else {
156
        Warning("Unknown argument(ignored): $_");
157
 
158
    }
159
}
160
 
161
#
162
# lets review what we have read in
163
#
164
foreach my $i ( sort keys %PLATFORMS )
165
{
166
    Verbose( "PLATFORMS{$i} = ", join( ',', @{$PLATFORMS{$i}{'PARTS'}} ) );
167
}
168
 
169
################################################################################
170
#   Read in the Packages descpkg file
171
#   The contents are not used. More a sanity test than anything else
172
#
173
my $rec = ReadDescpkg ( "descpkg" );
174
if ( $rec )
175
{
176
    Verbose ("Installing the package $rec->{NAME} $rec->{VERSION} $rec->{PROJ}");
177
}
178
else
179
{
180
    Message ("Installing the package ($PKG_ROOT)");
181
}
182
 
183
 
184
################################################################################
185
#
186
#   Lets deal with the top level flat dirs include dir(s)
187
#
188
#   For each directory listed in the ModuleList simply duplicate the entire
189
#   directory to the target location
190
#
191
my (@ModuleList) = ( "etc",
192
                     "swsfiles", 
193
                     "classes", 
194
                     "jar",
195
                     "sar",
196
                     "sql", 
197
                     "war", 
198
                     "scripts", 
199
                     "infofiles", 
200
                     "jsp", 
201
                     "thx", 
202
                     "rox", 
203
                     "rpt", 
204
                     "java", 
205
                     "achtml", 
206
                     "epedia", 
207
                     "doc", 
208
                     "docs",
209
                     "devcd",
210
                     "dat",
211
                     "mug",
261 dpurdie 212
                     "wsdl",                # Store wsdls
227 dpurdie 213
                     "include",             # Need the entire directory
214
                     "MergeModules",        # InstallShield Merge Modules
215
                     "deployfiles",         # Deployment internals
216
);
217
 
218
foreach my $i (@ModuleList)
219
{
220
    do_dir( $i, $i);
221
}
222
 
223
################################################################################
224
#
225
#   Process a "pkg" directory
226
#
227
#   There are two forms of pkg directory
228
#       1) pkg directory contains ONLY directories of the form pkg.$(GBE_MACHTYPE)
229
#          These are processed by coying:
230
#               pkg/pkg.GBE_MACHTYPE -> pkg
231
#
232
#       2) pkg without any pkg.* subdirs
233
#          Copy the entire subtree
234
#
235
#       3) Mixture
236
#          Cannot handle
237
#
238
#
239
my (@ModuleList2) =  ( "pkg" );
240
 
241
foreach my $i (@ModuleList2)
242
{
243
    #
244
    #   Determine the mode of operation
245
    #   Scan files in the directory for known format
246
    #
247
    my @dir_list = glob( "$i/*" );
248
    my $pkg_count = 0;
249
    my $other_count = 0;
250
 
251
    foreach ( @dir_list )
252
    {
253
        if ( m~/$i\.~ )
254
        {
255
            $pkg_count++;
256
        }
257
        else
258
        {
259
            $other_count++;
260
        }
261
    }
262
 
263
    if ( $pkg_count && $other_count )
264
    {
265
        Warning( "Cannot handle mixed \"${i}\" directory",
266
                 "Only machine directory will be copied" );
267
    }
268
 
269
    if ( $pkg_count )
270
    {
271
        #
272
        #   pkg/pkg.GBE_MACHTYPE -> pkg
273
        #
274
        do_dir("$i/$i\.$GBE_MACHTYPE", $i, );
275
    }
276
    else
277
    {
278
        #
279
        #   pkg -> pkg
280
        #
281
        do_dir($i, $i);
282
    }
283
}
284
 
285
 
286
################################################################################
287
#
288
#   Deal with the complex directories:
289
#           bin,
290
#           lib,
291
#           inc
292
#           include
293
#
294
#   Look for, and process the first of:
295
#
296
#   for each item in module list we shall process (if it exists) 
297
#   the following variants:
298
#
299
#       module.<platform>
300
#       module.<product>
301
#       module.<target>
302
#
303
#       module/<platform>
304
#       module/<product>
305
#       module/<target>
306
#
307
#   The platform, product and target are all passed on the command
308
#   line.  They are configured in the build.pl using the BuildProduct
309
#   directives.
310
#
311
#   For the bin dirs we need to consider the 'Debug' and 'Prod' 
312
#   build types as well as some cots packages that are both.
313
#
314
#   For the bin and lib dirs we also need to consider the format:
315
#       bin/bin.<platform>
316
#       lib/lib.<platform>
317
#
318
#
319
 
320
my %ModuleList3 =   (
321
                    "lib"           => 1,       # Copy root files
322
                    "inc"           => 1,       # Copy root files
323
                    "bin"           => 0,       # Should not be any root files
324
                    "include"       => 0,       # Root files already processed
325
                    );
326
 
327
foreach my $i (sort keys %ModuleList3)
328
{
329
    my $mDstDir;
330
    my $bType;
331
    my $mPart;
332
    my $mode =  $ModuleList3{$i};
333
 
334
    Verbose ("Processing: [Mode:$mode] $i");
335
 
336
    foreach my $j ( sort keys %PLATFORMS )
337
    {
338
        foreach $bType ( 'D', 'P', '' )
339
        {
340
            foreach $mPart ( sort @{$PLATFORMS{$j}{'PARTS'}} )
341
            {
342
                $mDstDir = "$i/$mPart$bType";
343
 
344
                #
345
                #   Try various combinations of directories to catter for
346
                #   all the crazy legacy combinations
347
                #
348
                do_dir("$i.$mPart$bType"    ,$mDstDir);
349
                do_dir("$i/$mPart$bType"    ,$mDstDir);
350
                do_dir("$i/$i.$mPart$bType" ,$mDstDir);
351
            }
352
        }
353
    }
354
 
355
    #
356
    # Transfer files in the root directory if required
357
    #
358
    # Now lets us deal with the simple case
359
    # here we are only interested in the top level files
360
    # sub-dirs are handles separately.
361
    #
362
    if ( ($mode & 1) && -d $i)
363
    {
364
        Verbose ("Processing: $i - Copy root directory files");
365
        do_FilesOnly ( $i );
366
    }
367
}
368
 
369
################################################################################
370
#   Deal with toolset extensions
371
#   These are JATS extensions that are platform specific and not a function of
372
#   the target. ie: If we are building on a 'win32' piece of hardware then we
373
#   need the win32 tools, independant of the target platforms
374
#
375
#   Use GBE_MACHTYPE to determine correct subdirs
376
#
377
my %ModuleList4 =   (
378
                    "tools/bin"             => 3,       # Copy GBE_MACHTYPE + root files
379
                    "tools/scripts"         => 4,       # Copy Subdir
380
                    "gbe"                   => 4,       # JATS General Build Environment
381
                    );
382
foreach my $i (sort keys %ModuleList4)
383
{
384
    my $mode = $ModuleList4{$i};
385
    Verbose ("Processing: $i, Machine Type: $GBE_MACHTYPE, Mode: $mode");
386
 
387
    #
388
    #   Transfer a machine specfic subdir
389
    #
390
    if ( $mode & 1 )
391
    {
392
        do_dir("$i.$GBE_MACHTYPE", "$i/$GBE_MACHTYPE") ;
393
        do_dir("$i/$GBE_MACHTYPE", "$i/$GBE_MACHTYPE") ;
394
    }
395
 
396
    #
397
    # Transfer files in the root directory if required
398
    #
399
    # Now lets us deal with the simple case
400
    # here we are only interested in the top level files
401
    # sub-dirs are handles separately.
402
    #
403
    if ( ($mode & 2) && -d $i)
404
    {
405
        Verbose ("Processing: $i - Copy root directory files");
406
        do_FilesOnly ( $i );
407
    }
408
 
409
    #
410
    #   Copy the entire subtree
411
    #   Used for non-machine specifc directories
412
    #
413
    if ( ($mode & 4) && -d $i)
414
    {
415
        Verbose ("Processing: $i - Copy directory tree");
416
        do_dir($i, $i) ;
417
    }
418
 
419
}
420
 
421
 
422
 
423
# done
424
exit 0;
425
 
426
 
427
#------------------------------------------------------------------------------
428
#------------------------------------------------------------------------------
429
#------------------------------------------------------------------------------
430
# subroutines
431
#------------------------------------------------------------------------------
432
#------------------------------------------------------------------------------
433
#------------------------------------------------------------------------------
434
 
435
#-------------------------------------------------------------------------------
436
# Function        : do_FilesOnly
437
#
438
# Description     : Copy all files in the current directory to the target
439
#                   directory. Assume that the target directory will be called
440
#                   the same as the source directory
441
#
442
#                   Do not process sub directories. These may be handled elsewhere
443
#
444
# Inputs          : $dir        - Src and Dst subdir name
445
#
446
# Returns         : Nothing
447
#
448
sub do_FilesOnly
449
{
450
    my ($dir) = @_;
451
    Verbose2 ("do_FilesOnly: dir=[$dir]");
452
 
453
    # define the type of dir we are working on
454
 
455
    my ($srcDir) = "$PKG_ROOT/$dir";
456
    my ($dstDir) = "$INTDIR/$dir";
457
 
458
    Verbose2("do_FilesOnly: INTDIR=[$INTDIR]");
459
    Verbose2("do_FilesOnly: dstDir=[$dstDir]");
460
    Verbose2("do_FilesOnly: srcDir=[$srcDir]");
461
 
462
    #
463
    # Create the interface dir if it does not exists
464
    #
465
    mkpath ( $dstDir, $GBE_VERBOSE, 0775) unless ( -d $dstDir );
466
 
467
 
468
    # Have a valid dst value we now need to get a hold of all the
469
    # lib scripts files.
470
    #
471
    local *DIR;
472
    opendir ( DIR, $srcDir ) or  Error ("Failed to open dir [$srcDir]");
473
 
474
    #
475
    # Process all directory entries
476
    #
477
    while (defined(my $_item = readdir(DIR)))
478
    {
479
        next if ( $_item eq '.' );
480
        next if ( $_item eq '..' );
481
 
482
        my $srcFile = "$srcDir/$_item";
483
        if ( -d $srcFile )
484
        {
485
            Verbose2 ("NOT processing dir item [$srcFile]");
486
        }
487
        else
488
        {
489
            FileLinkCopy ($srcFile, "$dstDir/$_item" );
490
        }
491
    }
285 dpurdie 492
    closedir DIR;
227 dpurdie 493
 
494
 
495
    # done
496
    return 1;
497
}
498
#-------------------------------------------------------------------------------
499
# Function        : do_dir
500
#
501
# Description     : Transfer an entire subdirectory tree
502
#                   Can detect that the tree has already been processed
503
#
504
# Inputs          : $src            - Source subdir (within PKG_ROOT)
505
#                   $dst            - Target path (within INTDIR)
506
#
507
# Returns         : Nothing
508
#
509
sub do_dir
510
{
511
    my ($src, $dst) = @_;
512
    Verbose2 ("do_dir: src=[$src], dst=[$dst]");
513
 
514
    #
515
    #   Prevent processing of the same source directory by multiple
516
    #   operations. Need only do them once
517
    #
518
    if ( $dirs_processed{$src} )
519
    {
520
        Verbose2 ("do_dir: Already processed");
521
        return 1;
522
    }
523
 
524
    $dirs_processed{$src} = 1;
525
 
526
    #
527
    #   Only if it exists
528
    #   Do the test in this function to simplify processing
529
    #
530
    unless ( -d $src )
531
    {
532
        Verbose2 ("do_dir: Directory not found");
533
        return 0;
534
    }
535
 
536
    #
537
    #   Setup values for the File::Find callback
538
    #   These need to be global due to the way that File::Find works
539
    #
540
    $FF_SRC_DIR = "$PKG_ROOT/$src";
541
    $FF_DST_DIR = "$INTDIR/$dst";
542
 
543
    Verbose2("do_dir: FF_SRC_DIR=[$FF_SRC_DIR]");
544
    Verbose2("do_dir: FF_DST_DIR=[$FF_DST_DIR]");
545
 
546
    #
547
    #   Handle directories that are really symbolic links
548
    #   This will only occur on system that handle symlinks
549
    #   May not always want to use symlinks.
550
    #
551
    if ( $symlinks && -l $FF_SRC_DIR )
552
    {
553
        Verbose2("do_dir: symlink $FF_SRC_DIR,$FF_DST_DIR");
554
        unless (symlink $FF_SRC_DIR, $FF_DST_DIR  )
555
        {
556
            Error("Failed to create symlink",
557
                  "Src: $FF_SRC_DIR",
558
                  "Dst: $FF_DST_DIR");
559
        }
560
        return 1;
561
    }
562
 
563
    #
564
    # Create the interface dir if it does not exists
565
    #
566
    mkpath ( $FF_DST_DIR, $GBE_VERBOSE, 0775)
567
        unless ( -d $FF_DST_DIR );
568
 
569
    File::Find::find( \&pkgFind2, $FF_SRC_DIR);
570
 
571
    # done
572
    return 1;
573
}
574
 
575
#-------------------------------------------------------------------------------
576
sub pkgFind2
577
#
578
# Description     : Callback function: Process a directory
579
#                   Target name is NOT the same as the source name
580
#
581
#                   The function is called for each file to be processed
582
#                   The name of the file is extracted from $File::Find::name
583
#
584
#                   Processes
585
#                       Directory: Create same directory in the target
586
#                       File     : Link/Copy file to the target
587
#
588
# Inputs          : None passed
589
#                   Globals are used
590
#
591
# Returns         :
592
#
593
#------------------------------------------------------------------------------
594
{
595
    Verbose2("pkgFind2:");
596
 
241 dpurdie 597
    my $item = "$File::Find::name";                     # Full source path
598
    my $dest_path = $FF_DST_DIR . substr ( $item, length ($FF_SRC_DIR) ); # Full destination path
227 dpurdie 599
 
600
    Verbose2 ("---- Src = [$item]");
601
    Verbose2 ("---- Dst = [$dest_path]");
602
    if ( -d $item )
603
    {
604
        #
605
        #   Create a directory
606
        #
607
        mkpath ( $dest_path, $GBE_VERBOSE, 0775) unless( -d $dest_path );
608
 
609
        #
610
        #   Flag the subdir as being processed
611
        #   Prevent multiple copy operations (and warnings)
612
        #
241 dpurdie 613
        my $subdir = substr ( $item, 1 + length ($PKG_ROOT) );
227 dpurdie 614
        $dirs_processed{$subdir} = 1;
615
 
616
    }
617
    else
618
    {
619
        #
620
        #   Copy/Link the file
621
        #
622
        FileLinkCopy ( $item, $dest_path);
623
    }
624
    return 1;
625
}
626
 
627
#-------------------------------------------------------------------------------
628
# Function        : FileLinkCopy
629
#
630
# Description     : Copy a file to a destination
631
#                   If possible create a symlink (Not always be possible)
632
#                   If the file is copied, then chmod it.
633
#
634
# Inputs          : $srcFile                 - Source path (Full)
635
#                   $dstFile                 - Destination path (Full)
636
#
637
#
638
# Globals         : symlinks                - Set if Symlinks are available
639
#                                             Will be cleared if the operation
640
#                                             failed, forcing copy
641
#
642
# Returns         : Nothing
643
#                   Will terminate, with a message, on error
644
#
645
sub FileLinkCopy
646
{
647
    my ($srcFile, $dstFile ) = @_;
648
    my $done;
649
    (my $file = $srcFile) =~ s~.*/~~;       # Filename. Just to be pretty
650
 
651
    #
652
    #   Delete target file. If it exists
331 dpurdie 653
    #       Don't warn if we are allowed to overwrite files
654
    #       This is done for sandbox and local_archive packages
227 dpurdie 655
    #
656
    if ( -f $dstFile )
657
    {
658
        unlink ($dstFile );
331 dpurdie 659
        Message("overwriting existing dpkg_archive item [$file] --> [$dstFile]\n")
660
            unless ( $allow_overwrite );
227 dpurdie 661
    }
662
 
663
    #
664
    #   Try a symlink first
665
    #
666
    if ( $symlinks )
667
    {
668
        Verbose("linking file [$file] --> [$dstFile]...ok");
669
        unless (symlink ($srcFile, $dstFile)  )
670
        {
671
            #
672
            #   Symlink has failed
673
            #   Flag: Don't symlink anymore
674
            #
675
            $symlinks = 0;
676
            Verbose ("Failed to create symlink from: [$file] --> [$dstFile]");
677
        }
678
        else
679
        {
680
            $done = 1;
681
        }
682
    }
683
 
684
    #
685
    #   Try a copy
686
    #
687
    unless ( $done )
688
    {
689
        if(File::Copy::copy($srcFile, $dstFile))
690
        {
691
            Verbose("copying file [$file] --> [$dstFile]...ok");
692
            CORE::chmod oct("0755"), $dstFile;
693
        }
694
        else
695
        {
696
            Error("copying file [$file] --> [$dstFile]: $!");
697
        }
698
    }
699
}
700
 
701
############ EOF ###############################################################
702