Subversion Repositories DevTools

Rev

Rev 6133 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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