Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
#! /usr/bin/perl
2
########################################################################
3
# Copyright (C) 1998-2004 ERG Limited, All rights reserved
4
#
5
# Module name   : jats_builder.pl
6
# Module type   : Makefile system
7
# Compiler(s)   : n/a
8
# Environment(s):
9
#
10
# Description   : A script to build an entire systems
11
#                 The script will:
12
#                   Build a tree of related modules in the correct order
13
#
14
#                   Rewrite build.pl files with correct version information
15
#
16
#                   Maintain the pkg_archive cache
17
#
18
#                   Display interanal and external dependencies
19
#
20
#
21
# Version   Who      Date        Description
22
# 1.0.0     DDP      8-Jun-04   Created
23
#
24
#......................................................................#
25
 
26
use strict;
27
use JatsError;
28
 
29
use Data::Dumper;                           # Debug only
30
use Pod::Usage;                             # required for help support
31
use Getopt::Long;
32
use Cwd;
33
use File::Path;
34
 
35
my $VERSION = "2.0.0";                      # Update this
36
 
37
#
38
#   Options
39
#
40
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
41
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
42
my $opt_help;
43
my $opt_manual;
44
my $opt_clean;
45
my $opt_expert = 1;
46
my $opt_uselog = 1;
47
my $opt_resetlog;
48
my $opt_skip = 2;
49
my $opt_quick = 0;
50
my $opt_build = 1;
51
my $opt_build_all;
52
my $opt_update_cache;
53
my @opt_only;
54
my $opt_only_prereq = 2;
55
my $opt_dump;
56
my $opt_dump_all;
57
my $opt_show;
58
my $opt_show_rule;
59
my $opt_show_pkg;
60
my $opt_label_all;
61
my $opt_audit;
62
my $opt_audit_entry;
63
 
64
my $opt_buildfiles;
65
my $opt_buildfiles_rewrite;
66
my $opt_buildfiles_checkout;
67
my $opt_buildfiles_label;
68
my $opt_buildfiles_labelall;
69
my $opt_buildfiles_labelrule;
70
my $opt_config = "build.cfg";
71
my $opt_script;
72
my $opt_gen_pathlist;
73
my $opt_create_dpkg;
74
 
75
#
76
#   Globals
77
#
78
my $GBE_PERL = $ENV{'GBE_PERL'};                # Essential ENV variables
79
my $GBE_CORE = $ENV{'GBE_CORE'};
80
 
81
my $root_dir;                                   # Root of the project
82
my $cwd;                                        # The current directory
83
my @modules;                                    # List of modules to process
84
my %dir_to_name;                                # path -> component name
85
my %internal;                                   # Internal components -> path
86
 
87
my $build_label;
88
my $label;
89
my $logfile;
90
my $logfile_dir;
91
my $logfile_name;
92
my $logfile_base;
93
my $audit_logfile;
94
my $datafile;
95
my $build_this;
96
my @audit_args;
97
my $logfile_inuse = 0;
98
 
99
 
100
#
101
#   Fixed config strings
102
#
103
my $BUILDFILE = "build.pl";                     # Basic build file
104
my $BUILDUSE = "build.use.pl";                  # Massaged build file
105
my $AUDIT_DO = "build.audit.do";                # Audit derived object
106
my $AUDIT_LOG = "build.audit.log";              # Post audit log
107
my $LOGFILE_EXT    = "builder.log";             # Builder logfile extension
108
my $AUDITFILE_EXT  = "audit.log";               # Post audit logfile
109
 
110
################################################################################
111
#   Data used in the file rewrite process
112
#
113
#
114
my $project;                    # The project name (short form)
115
 
116
#
117
#   A Hash of external components and version numbers
118
#
119
my %external_component =  ();
120
 
121
#
122
#   A hash of components that have MULTIPLE version numbers
123
#
124
my %kludge_component = ();
125
 
126
#
127
#   A hash of project extensions that should not be massaged
128
#
129
my %project_keep = (
130
    'mas'   => 'mas',
131
    'cr'    => 'cr',
132
    'cots'  => 'cots',
133
    );
134
 
135
#-------------------------------------------------------------------------------
136
# Function        : Mainline Entry Point
137
#
138
# Description     :
139
#
140
# Inputs          :
141
#
142
@audit_args = @ARGV;
143
my $result = GetOptions (
144
                "help+"         => \$opt_help,              # flag, multiple use allowed
145
                "manual"        => \$opt_manual,            # flag, multiple use allowed
146
                "verbose+"      => \$opt_verbose,           # flag, multiple use allowed
147
                "clean"         => \$opt_clean,             # flag
148
                "clear"         => \$opt_clean,             # flag
149
                "log!"          => \$opt_uselog,            # flag with [no] option
150
                "resetlog"      => \$opt_resetlog,          # flag
151
                "expert!"       => \$opt_expert,            # flag with [no] option
152
                "skip!"         => \$opt_skip,              # flag with [no] option
153
                "quick!"        => \$opt_quick,             # flag with [no] option
154
                "build!"        => \$opt_build,             # flag with [no] option
155
                "all!"          => \$opt_build_all,         # flag with [no] option
156
                "updatecache+"  => \$opt_update_cache,      # flag, multiple use allowed
157
                "only=s"        => \@opt_only,              # String
158
                "prereq!"       => \$opt_only_prereq,       # flag with [no] option
159
                "dump+"          => \$opt_dump,             # flag
160
                "dumpall"       => \$opt_dump_all,          # flag
161
                "show"          => \$opt_show,              # flag
162
                "showrule"      => \$opt_show_rule,         # flag
163
                "showpkg"       => \$opt_show_pkg,          # flag
164
                "labelall"      => \$opt_label_all,         # flag
165
                "config:s"      => \$opt_config,            # String
166
                "audit"         => \$opt_audit,             # flag
167
                "AUDITMODE:s"   => \$opt_audit_entry,       # String
168
                "script:s"      => \$opt_script,            # String
169
 
170
                "buildfiles"            => \$opt_buildfiles,            # flag
171
                "buildfiles_rewrite!"   => \$opt_buildfiles_rewrite,    # flag
172
                "buildfiles_checkout!"  => \$opt_buildfiles_checkout,   # flag
173
                "buildfiles_label!"     => \$opt_buildfiles_label,      # flag
174
                "buildfiles_labelall!"  => \$opt_buildfiles_labelall,   # flag
175
                "buildfiles_labelrule!" => \$opt_buildfiles_labelrule,  # flag
176
 
177
                "pathlist"              => \$opt_gen_pathlist,
178
                "create_dpkg"           => \$opt_create_dpkg,
179
                );
180
 
181
                #
182
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
183
                #
184
 
185
#
186
#   Process help and manual options
187
#
188
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
189
pod2usage(-verbose => 1)  if ($opt_help == 2 );
190
pod2usage(-verbose => 2)  if ($opt_manual || $opt_help > 2);
191
 
192
ErrorConfig( 'name'    =>'JBUILDER',
193
             'verbose' => $opt_verbose );
194
 
195
#
196
#   Validate user options
197
#   Not expecting any user arguments, other than options, so spit if any are found
198
#
199
Error ("Unexpected command line arguments present" )
200
    if ( $#ARGV >= 0 );
201
 
202
#
203
#   Determine the current working directory
204
#
205
$cwd = getcwd();
206
Verbose ("Current Working Directory: " . $cwd );
207
 
208
#
209
#   Locate the base config file
210
#   This will be located with in the root directory and this will be where
211
#   the build log file will be created
212
#
213
my $test_dir = $cwd;
214
LOOP: {
215
    do
216
    {
217
        Verbose2 ("Testing: $test_dir");
218
        my $win_test_file = "$test_dir/$opt_config" ;
219
        if ( -f $win_test_file )
220
        {
221
            Verbose ("Found build config file: $win_test_file");
222
            $root_dir = $test_dir;
223
            last;
224
        }
225
        #
226
        #   Remove one directory
227
        #   Terminate the loop when no more can be removed
228
        #
229
    } while ( $test_dir =~ s~[/][^/]*$~~ );
230
}
231
 
232
$datafile = "$root_dir/$opt_config";
233
Error ("Cannot locate config file: $opt_config")
234
    unless ( -f $datafile );
235
 
236
#
237
#   Intercept AUDITMODE operation
238
#       ClearCase audit requires a program shell to be audited. It can't simply
239
#       be turned on and off. This is achived by using a special invocation of
240
#       this program to provide the auditable suite of functions
241
#
242
audit_operation()
243
    if ( $opt_audit_entry );
244
 
245
if ( $opt_audit )
246
{
247
    Error ("Cannot audit a non-dynamic clearcase view")
248
        unless ( is_dynamic_view() );
249
}
250
 
251
 
252
#
253
#   Read in the build config file
254
#       There are a few directives that are parsed as we go
255
#       The root directory may be redefined
256
#
257
read_config_file( $datafile );
258
Error ("No LABEL found in config file")
259
    unless ( $label );
260
Error ("No components to build in the config file")
261
    unless ( $#modules >= 0  );
262
 
263
#
264
#   Generate the name of the logfile
265
#
266
( $logfile_base = $opt_config ) =~ s~\.\w*$~~;
267
$logfile_dir = $root_dir;
268
 
269
#
270
#   Determine default operation (no local build.pl file)
271
#   If we are in the root directory, then, by default, build ALL modules
272
#                               otherwise, by default, build the current one
273
#
274
unless ( $opt_build_all || ( $#opt_only >= 0 ) )
275
{
276
    #
277
    #   If a local build file is found, then just build it
278
    #   Set default operation to skip and nopreq
279
    #
280
    if ( -f $BUILDFILE )
281
    {
282
        $build_this = 1;
283
    }
284
    else
285
    {
286
        #
287
        #   No user specified modules to build
288
        #   If we are not in the root directory, then die
289
        #
290
        Error ("Cannot determine what to do from this directory\n")
291
            unless ( -f $opt_config );
292
    }
293
}
294
 
295
#
296
#   Determine the "here" component
297
#   Ensure that the component is in the module list, even if its not in the config file
298
#
299
if ( $build_this )
300
{
301
    $build_this = substr ( $cwd, 1 + length ( $root_dir ) );
302
    Verbose2 ("Here: $build_this" );
303
    my $file = "$root_dir/$build_this/$BUILDFILE" ;
304
    Error ("Cannot determine component. Not Found: $file" )
305
        unless ( -f $file );
306
    push @modules, $build_this;
307
 
308
    #
309
    #   Building the module in the current directory
310
    #   Set a few options - if they are still defaulted
311
    #       Force noskip to ensure the component is built
312
    #       Force nopreq to prevent prerequisites being built
313
    #       Generate a logfile in the current directory
314
    #
315
#    $opt_skip = 0
316
#        if ( $opt_skip == 2 );
317
#    $opt_only_prereq = 0
318
#        if ( $opt_only_prereq == 2 );
319
 
320
    $logfile_dir = ".";
321
    $opt_resetlog = 1;
322
}
323
 
324
################################################################################
325
#   Restart the log file
326
#
327
$audit_logfile = "$logfile_dir/$logfile_base.$AUDITFILE_EXT";
328
$logfile = "$logfile_dir/$logfile_base.$LOGFILE_EXT";
329
if ( $opt_resetlog || $opt_clean )
330
{
331
    print "Delete logfile: $logfile\n";
332
    System ("rm -f $logfile" );
333
 
334
    print "Delete audit log: $logfile\n";
335
    System ("rm -f $audit_logfile" );
336
}
337
 
338
################################################################################
339
#
340
#   Label all files in the view
341
#
342
if ( $opt_label_all )
343
{
344
    label_all_files();
345
    exit 0;
346
}
347
 
348
################################################################################
349
#
350
#   Update the local dpkg_archive cache - if required
351
#   This does not require processing of the external packages
352
#
353
if ( $opt_update_cache )
354
{
355
    my @cache_list;
356
    my $mode;
357
 
358
    $mode = "-refresh" if ( $opt_update_cache > 1 );
359
 
360
    for my $file (sort keys %external_component)
361
    {
362
        if ( $kludge_component{$file} )
363
        {
364
            for my $fl (sort keys %{$kludge_component{$file}} )
365
            {
366
                push @cache_list, "$file/$kludge_component{$file}{$fl}.$fl";
367
            }
368
        }
369
        else
370
        {
371
            push @cache_list, "$file/$external_component{$file}";
372
        }
373
    }
374
 
375
    JatsCmd( "dpkg_cache $mode @cache_list" );
376
}
377
 
378
################################################################################
379
#
380
#   Examine all named modules and determine the build order
381
#   Limit the list of built modules if required
382
#
383
@modules = determine_build_order( @modules );
384
 
385
################################################################################
386
#   Generate a directory list
387
#
388
if ( $opt_gen_pathlist )
389
{
390
    generate_pathlist();
391
    exit 0;
392
}
393
 
394
################################################################################
395
#
396
#   External Script Interface
397
#
398
if ( $opt_script )
399
{
400
    Verbose ("Script:perl $ENV{'GBE_TOOLS'}/$opt_script @modules");
401
    System ("perl $ENV{'GBE_TOOLS'}/$opt_script @modules");
402
    exit $result;
403
}
404
 
405
################################################################################
406
#   Display the external packages as LinkPkgArchive statements
407
#
408
if ( $opt_show_pkg)
409
{
410
    my  $pkg;
411
    my  $ver;
412
 
413
    for my $file (sort keys %external_component)
414
    {
415
        if ( $kludge_component{$file} )
416
        {
417
            for my $fl (sort keys %{$kludge_component{$file}} )
418
            {
419
                $pkg = $file;
420
                $ver = "$kludge_component{$file}{$fl}.$fl";
421
                print "LinkPkgArchive( '$pkg', '$ver' );\n";
422
            }
423
        }
424
        else
425
        {
426
            $pkg = $file;
427
            $ver = $external_component{$file};
428
            print "LinkPkgArchive( '$pkg', '$ver' );\n";
429
        }
430
    }
431
    exit 0;
432
}
433
 
434
################################################################################
435
#   Display the external packages and the build order
436
#
437
if ( $opt_show || $opt_show_rule || $opt_show_pkg)
438
{
439
    print "\nExternal packages (Alphabetic Order)\n";
440
    for my $file (sort keys %external_component)
441
    {
442
        if ( $kludge_component{$file} )
443
        {
444
            for my $fl (sort keys %{$kludge_component{$file}} )
445
            {
446
                printf "    %-20s %s.%s\n", $file,$kludge_component{$file}{$fl},$fl;
447
            }
448
        }
449
        else
450
        {
451
            printf "    %-20s %s\n", $file,$external_component{$file};
452
        }
453
    }
454
 
455
    print "\nInternal Components (Build Order)\n";
456
    for my $module ( @modules )
457
    {
458
        if ( $opt_show_rule )
459
        {
460
            printf "    %-50s %-25s %s\n", $module, $dir_to_name{$module}, cleacase_rule($module);
461
        }
462
        else
463
        {
464
            printf "    %-50s %s\n", $module, $dir_to_name{$module};
465
        }
466
    }
467
    print "\n";
468
 
469
#    print "\nBuildFiles\n";
470
#    for my $module ( @modules )
471
#    {
472
#        printf "    %s/build.pl\n", $module ;
473
#    }
474
#    print "\n";
475
 
476
}
477
 
478
################################################################################
479
#
480
#   Setup STDOUT and STDERR to a logfile
481
#   This will force all output to be directed to the logfile, by default
482
#
483
logfile_control(1);
484
 
485
################################################################################
486
#
487
#   Start a clean build
488
#   Delete the local package archive and then clean out all packages
489
#
490
if ( $opt_clean )
491
{
492
    for my $module ( @modules )
493
    {
494
        my  $dir = "$root_dir/$module";
495
        print OLDOUT "Cleaning package: $module";
496
        if ( -d $dir )
497
        {
498
            chdir ( $dir );
499
 
500
            System ("rm -f $BUILDUSE $AUDIT_DO $AUDIT_LOG *$LOGFILE_EXT *$AUDITFILE_EXT" );
501
            JatsCmd ( "clean" );
502
            JatsCmd ( "clobber" );
503
            rm_dir ( "pkg" ) if ( -d pkg );
504
        }
505
        print OLDOUT "\n";
506
    }
507
 
508
    #
509
    #   Remove local archive LAST to give the user a chance to control-C out
510
    #   of this massive delete - iff done in Error :(
511
    #
512
    print OLDOUT "Removing local_dpkg_archive";
513
    rm_dir ( "$root_dir/local_dpkg_archive" );
514
    print OLDOUT "\n";
515
}
516
 
517
################################################################################
518
#
519
#   Ensure that the local dpkg_archive directory exists
520
#
521
System ("mkdir -p $root_dir/local_dpkg_archive" );
522
 
523
################################################################################
524
#   Process build files only
525
#
526
#   Ensure that the $BUILDFILE files are up to date
527
#   If required the files will be checkedout and updated
528
#   A label will be applied to all the build files ( + makefile.pl )
529
#
530
 
531
sub ed4w
532
{
533
    my ($name) = @_;
534
    system ( "c:/Progra~1/SAIG/ED4W/ED32.exe $name" );
535
}
536
 
537
if ( $opt_buildfiles )
538
{
539
    my $same = 0;
540
    my $not_same = 0;
541
    my $ecount = 0;
542
 
543
    for my $module ( @modules )
544
    {
545
        my  $dir = "$root_dir/$module";
546
        my  $efound = 0;
547
        printf OLDOUT "Processing %-50s", $module;
548
        if ( -d $dir )
549
        {
550
            chdir ( $dir );
551
 
552
#            if ( ! is_checked_out ("$BUILDFILE") )
553
#            {
554
#                print OLDOUT " Checkout";
555
#                System ("cleartool co -nc $BUILDFILE" );
556
#                print OLDOUT "\n";
557
#            }
558
#            ed4w( "$dir/build.pl" );
559
#            next;
560
 
561
            $result = rewrite_build_file ( $module );
562
            Verbose ("rewrite build.pl result): $result");
563
            if ( $result )
564
            {
565
                print OLDOUT "DIFFERENT";
566
                $not_same++;
567
 
568
                if ( $opt_buildfiles_checkout )
569
                {
570
                    if ( ! is_checked_out ("$BUILDFILE") )
571
                    {
572
                        print OLDOUT " Checkout";
573
                        System ("cleartool co -nc $BUILDFILE" );
574
                    }
575
                }
576
 
577
                if ( $opt_buildfiles_rewrite || $opt_buildfiles_checkout )
578
                {
579
                    System ("rm -f $BUILDFILE" );
580
                    if ( System ("mv -f $BUILDUSE $BUILDFILE" ) )
581
                    {
582
                        print OLDOUT " ERROR:ReWrite";
583
                    }
584
                    else
585
                    {
586
                        print OLDOUT " ReWrite";
587
                    }
588
                }
589
 
590
 
591
            }
592
            elsif ( $result == 0 )
593
            {
594
                print OLDOUT "Same";
595
                $same++;
596
            }
597
            else
598
            {
599
                print OLDOUT "Error";
600
                $ecount++;
601
                $efound = 1;
602
            }
603
        }
604
        else
605
        {
606
            print OLDOUT "Not Found";
607
            $ecount++;
608
            $efound = 1;
609
        }
610
 
611
        if ( $opt_buildfiles_label || $opt_buildfiles_labelall || $opt_buildfiles_labelrule )
612
        {
613
            if ( ! $efound )
614
            {
615
                my @list;
616
                my $label = $build_label;
617
 
618
                if ( $opt_buildfiles_labelrule )
619
                {
620
                    $label = cleacase_rule( $module );
621
                }
622
 
623
                #
624
                #   Determine files to label
625
                #
626
                unless ( $opt_buildfiles_labelall )
627
                {
628
                   @list = qw ( build.pl );
629
                }
630
                else
631
                {
632
                    @list = qw ( build.pl makefile.pl src/makefile.pl src . ..);
633
                    push @list, glob ("warnings.*" );
634
                }
635
 
636
                for my $file ( @list )
637
                {
638
                    if ( ! has_label( $file, $label) )
639
                    {
640
                        print OLDOUT " Label:$file";
641
                        my $mode = "";
642
                        my $mode = "-replace" unless($file eq ".." );
643
                        Verbose ("cleartool mklabel -nc $mode $label $file" );
644
                        $result = System ("cleartool mklabel -nc $mode $label $file" );
645
                        print OLDOUT "-ERR"
646
                            if ( $result );
647
 
648
                    }
649
                }
650
            }
651
        }
652
        print OLDOUT "\n";
653
    }
654
    printf OLDOUT "Diffs: %d, Same: %d, Errors: %d\n", $not_same, $same, $ecount;
655
    exit 0;
656
}
657
 
658
################################################################################
659
#
660
#   Compile each module
661
#
662
$result = 0;
663
if ( $opt_build )
664
{
665
    for my $module ( @modules )
666
    {
667
        if ( build_module ( $module ) > 0 )
668
        {
669
            $result = 1;
670
            last;
671
        }
672
    }
673
 
674
    #
675
    #   Install packages into dpkg_archive, but only if the packages built OK
676
    #   This is an interactive process, so disable the logfile
677
    #
678
    if ( ! $result and $opt_create_dpkg )
679
    {
680
        logfile_control ( 0 );
681
        for my $module ( @modules )
682
        {
683
            if ( install_package ( $module ) > 0 )
684
            {
685
                $result = 1;
686
                last;
687
            }
688
        }
689
    }
690
}
691
 
692
logfile_control ( 0 );
693
exit $result;
694
 
695
 
696
#-------------------------------------------------------------------------------
697
# Function        : logfile_control
698
#
699
# Description     : Enable and disable the use of a logfile
700
#
701
# Inputs          : $1  - True: Enable logfile
702
#                         False: Disable logfile
703
#
704
# Returns         :
705
#
706
sub logfile_control
707
{
708
    ( my $enable ) = @_;
709
    if ( $enable )
710
    {
711
        if ( ! $logfile_inuse )
712
        {
713
            open OLDOUT, ">&STDOUT"     or Error ("Can't dup STDOUT: $!");
714
            open OLDERR, ">&STDERR"     or Error ("Can't dup STDERR: $!");
715
 
716
            if ( $opt_uselog )
717
            {
718
                open STDOUT, '>>', $logfile or die "Can't redirect STDOUT: $!";
719
                open STDERR, ">&STDOUT"     or die "Can't dup STDOUT: $!";
720
 
721
 
722
                select OLDERR; $| = 1;      # make unbuffered
723
                select OLDOUT; $| = 1;      # make unbuffered
724
 
725
                select STDERR; $| = 1;      # make unbuffered
726
                select STDOUT; $| = 1;      # make unbuffered
727
            }
728
            $logfile_inuse = 1;
729
        }
730
    }
731
    else
732
    {
733
        if ( $logfile_inuse )
734
        {
735
            #
736
            # Restore redirection
737
            #
738
            close STDOUT;
739
            close STDERR;
740
 
741
            open STDOUT, ">&OLDOUT"     or die "Can't dup OLDOUT: $!";
742
            open STDERR, ">&OLDERR"     or die "Can't dup OLDERR: $!";
743
 
744
            select STDERR; $| = 1;      # make unbuffered
745
            select STDOUT; $| = 1;      # make unbuffered
746
 
747
            $logfile_inuse = 0;
748
        }
749
    }
750
}
751
 
752
#-------------------------------------------------------------------------------
753
# Function        : audit_operation
754
#
755
# Description     : Provide a basic set of functions to be used by the
756
#                   clearaudit operation.
757
#
758
#                   This mode should only be invoked by the program itself
759
#
760
#
761
# Inputs          :
762
#
763
# Returns         :
764
#
765
sub audit_operation
766
{
767
    my $result;
768
    Verbose ( "AUDIT Operation: $datafile, $opt_audit_entry" );
769
 
770
    #
771
    #   Read in the config file(s)
772
    #   This will ensure that all the relevent config files are noted by audit
773
    #
774
    #   Do not perform any sanity test. This will have been done by the wrapper
775
    #   invocation.
776
    #
777
    read_config_file( $datafile );
778
 
779
    #
780
    #   Rewrite the build.pl file
781
    #
782
    rewrite_build_file( $opt_audit_entry );
783
 
784
    my $mode = "";
785
    $mode = "--expert" if ( $opt_expert );
786
 
787
    $result = JatsCmd ( "-b $BUILDUSE build $mode" );
788
 
789
    $mode = "all";
790
    $mode = "debug package_debug" if ( $opt_quick );
791
    $result = JatsCmd ( "-b $BUILDUSE make $mode" )
792
        unless ( $result );
793
 
794
    #
795
    #   Generate a "derived object" so that the audit has something to track
796
    #   This file is created last to ensure that ALL build activity is captured
797
    #
798
    open  AUDO, ">$AUDIT_DO" or die "Cannot create audit derived object\n";
799
    print AUDO "This file is used to create an audit trail - it can be deleted";
800
    close AUDO;
801
 
802
    Verbose ( "AUDIT Operation Result: $result" );
803
    exit $result;
804
}
805
 
806
#-------------------------------------------------------------------------------
807
# Function        : SystemLog
808
#
809
# Description     : Similar to the System command, except that standard
810
#                   output and standard Error are appended to a log file
811
#
812
#                   Used since I was having problems with calling other programs
813
#                   and control-C. It could hang the terminal session.
814
#
815
# Inputs          :
816
#
817
# Returns         :
818
#
819
sub System
820
{
821
    my( $cmd ) = @_;
822
 
823
    Verbose2 "... $cmd";
824
 
825
    if ( $logfile_inuse )
826
    {
827
        open(CMD, "$cmd |")    || Error "can't run command: $!";
828
        while (<CMD>)
829
        {
830
            print $_;
831
        }
832
        close(CMD);
833
    }
834
    else
835
    {
836
        system( "$cmd" );
837
    }
838
 
839
    return $? / 256;
840
}
841
 
842
#-------------------------------------------------------------------------------
843
# Function        : JatsCmd
844
#
845
# Description     : Issue a command to JATS.PL
846
#
847
# Inputs          : Command line
848
#
849
# Returns         : Error code
850
#
851
sub JatsCmd
852
{
853
    Error ("Environment variable GBE_PERL not set") unless ( defined $GBE_PERL );
854
    Error ("Environment variable GBE_CORE not set") unless ( defined $GBE_CORE );
855
 
856
    System ( "$GBE_PERL $GBE_CORE/TOOLS/jats.pl @_" );
857
}
858
 
859
#-------------------------------------------------------------------------------
860
# Function        : read_config_file
861
#
862
# Description     : Read in the config file and build up data structures
863
#                   Format of the configuration file
864
#
865
#                     Comments begin with a # and go the end of the line
866
#                     There are three types of config line
867
#                       LABEL nn.nn.nn.prj
868
#                            Specifies the build label
869
#                            Specifies the 3 letter project name (Mandatory)
870
#                            This value is used to substitute xxx project names
871
#
872
#                       ROOTDIR name
873
#
874
#                       INLCUDE filename
875
#
876
#                       EXTERNAL package version [ALLOW_MULTI]
877
#                            Specifies the version of a package to use
878
#                            The version may be of the form:
879
#                                nn.nn.nn.aaa
880
#                            or
881
#                                nn.nn.nn
882
#                            A project specifier of .mas and .cr are not modified
883
#                            A project specifier of .xxx will be changed to the current project
884
#
885
#                            The "ALLOW_MULTI" tag handles the special case where
886
#                            a package may have a project specific version AND a
887
#                            generic MAS version - that are not the same.
888
#
889
#                       LinkPkgArchive ('package', 'version' );  [ALLOW_MULTI]
890
#                       BuildPkgArchive ('package', 'version' );  [ALLOW_MULTI]
891
#                            See EXTERNAL
892
#
893
#                       MESSAGE text
894
#                           Display the text
895
#
896
#                       EXCLUDED text
897
#                           Display the text
898
#
899
#                       Otherwise the line is taken to be the path to a
900
#                       $BUILDFILE file that will be part of the build.
901
#
902
# Inputs          : Name of the config file
903
#                   Name of the current file handle - used for recusive calls
904
#
905
# Returns         : Will terminate on error
906
#
907
sub read_config_file
908
{
909
    my ($datafile, $fh) = @_;
910
    my $root_found;
911
    Verbose2 ("Read Config File: $datafile");
912
 
913
    #
914
    #   Detect too many levels of inclusion
915
    #
916
    Error ("Too many levels of include file. Possible circular inclusion")
917
        if ( $fh > 10 );
918
 
919
no strict 'refs';
920
    $fh++;
921
    open ( $fh, $datafile ) or Error ("Config file ($datafile) not found" );
922
use strict 'refs';
923
 
924
    while ( <$fh> )
925
    {
926
        #
927
        #   Clean up lines
928
        #   Skip comments and blank lines
929
        #   Remove leading and training white space
930
        #
931
        chomp;
932
        s~^\s*~~;
933
        s~#.*$~~;
934
        s~\s*$~~;
935
        next if ( length( $_) <= 0 );
936
 
937
        Verbose3 ("CFG: " . $_);
938
 
939
        #
940
        #   LABEL nn.nn.nn.prj
941
        #       Required project label
942
        #       Extract the project suffix from the label
943
        #
944
        if ( m/LABEL/ )
945
        {
946
            my ($key, $ext) = split( ' ', $_, 2);
947
            Error ("Multiple LABEL statements not allowed") if ( $build_label );
948
            Error ("Missing label") unless ( $ext );
949
            Error ("Bad label format") unless ( $ext =~ m~^\d+\.\d+\.\d+.(\w+)$~ );
950
 
951
            $project = $1;
952
            $project_keep{$project} = $project;
953
 
954
            $label = $ext;
955
            $build_label="daf_build_$label";
956
 
957
            Verbose ("Label: $label, $build_label, Project: $project");
958
            next;
959
        }
960
 
961
        #
962
        #   ROOTDIR name
963
        #       Specify the name of the project root directory
964
        #       This MUST be a parent directory
965
        #
966
        if ( m/^ROOTDIR/ )
967
        {
968
            my ($key, $dir_name) = split( ' ', $_, 2);
969
            Error ("Multiple ROOTDIR statements not allowed") if ( $root_found );
970
            Error ("Missing root directory name") unless ( $dir_name );
971
 
972
            #
973
            #   Locate the root directory within the current file tree
974
            #
975
            Error ("ROOTDIR not in CWD. $dir_name not in $cwd") unless ( $cwd =~ m~/$dir_name~ );
976
 
977
            $root_dir = substr( $cwd, 0, $+[0] );
978
            $root_found = 1;
979
            Verbose ("ROOTDIR: $root_dir");
980
            next;
981
        }
982
 
983
        #
984
        #   INCLUDE config_file
985
        #   Include another configuration file
986
        #
987
        #   The included confg file must reside in the same directory as the
988
        #   current config file
989
        #
990
        if ( m/^INCLUDE/ )
991
        {
992
            my ($key, $ifile) = split( ' ', $_, 2);
993
            Error ("No include file specified") unless ( $ifile );
994
 
995
            #
996
            #   Extract the path from the current config file
997
            #
998
            ( my $path = $datafile ) =~ s~/[^/]+$~~;
999
            my $cfile = $path . '/' . $ifile;
1000
 
1001
            Error ("Include file not found: $cfile") unless ( -f $cfile );
1002
            Verbose ("INCLUDE: $fh, $cfile");
1003
            read_config_file ( $cfile, $fh );
1004
            next;
1005
        }
1006
 
1007
        #
1008
        #   MESSAGE Text
1009
        #   Display message
1010
        #
1011
        if ( m/^MESSAGE/ )
1012
        {
1013
            my ($key, $ext) = split( ' ', $_, 2);
1014
            print $ext . "\n";
1015
            next;
1016
        }
1017
 
1018
        #
1019
        #   EXCLUDE dirname
1020
        #   Allows a config line to be ignored and displayed
1021
        #
1022
        if ( m/^EXCLUDE/ )
1023
        {
1024
            my ($key, $ext) = split( ' ', $_, 2);
1025
            print "EXCLUDED: " . $ext . "\n";
1026
            next;
1027
        }
1028
 
1029
        #
1030
        #   EXTERNAL
1031
        #   Defines external packages AND the version of such packages
1032
        #
1033
        if ( m/^EXTERNAL/ )
1034
        {
1035
            my ( $key, $comp, $ver, $opt ) = split( ' ', $_, 4);
1036
            Error ("Version not specified for: $comp") unless ( $ver );
1037
            Error ("Bad version format for: $comp ($ver)") unless ( $ver =~ m~^\d+\.\d+\.\d+.\w+$~ || $ver =~ m~^\d+\.\d+\.\d+$~ );
1038
            Error ("Invalid options: $comp($opt)") if ( $opt && ($opt ne "ALLOW_MULTI" ));
1039
            if ( $opt eq "ALLOW_MULTI" )
1040
            {
1041
                #
1042
                #   Some special components are allowed to have mutliple
1043
                #   versions. These are a gross kludge and are handled with great care
1044
                #
1045
                #   Split out the vesrion into two parts
1046
                #
1047
                (my $suff = $ver) =~ s~^\d+\.\d+\.\d+.~~;
1048
                (my $vnum = $ver) =~ s~.\w+$~~;
1049
                Error ("Bad format for ALLOW_MULTI. Suffix($suff) must be present") unless ( length($suff) > 2 );
1050
 
1051
                $kludge_component{$comp}{$suff} = $vnum;
1052
                $external_component{$comp} = $ver;
1053
                Verbose ("MULTI package: $comp, $vnum, $suff");
1054
                next;
1055
            }
1056
 
1057
            Error ("Multiple definition of $comp") if defined $external_component{$comp};
1058
 
1059
            #
1060
            #   Save the data
1061
            #
1062
            $external_component{$comp} = $ver;
1063
            Verbose  ("Package: $comp, $ver");
1064
            next;
1065
        }
1066
 
1067
        #
1068
        #   Process LinkPkgArchive and BuildPkgArchive statements
1069
        #   These allow simple updating of the config file from Release manager
1070
        #
1071
        if ( m/LinkPkgArchive/ or m/BuildPkgArchive/ )
1072
        {
1073
            my $comp;
1074
            my $ver;
1075
 
1076
            m/'(.*)'[^']*'(.*)'/;
1077
 
1078
            my $comp = $1;
1079
            my $ver = $2;
1080
 
1081
            m/;(.*)/;
1082
            my $opt = $1;
1083
            $opt =~ s~^\s*~~;
1084
            $opt =~ s~\s*$~~;
1085
#print "Got Archive stuff: $_ : $comp, $ver : \"$opt\"\n";
1086
 
1087
            Error ("Version not specified for: $comp") unless ( $ver );
1088
            Error ("Bad version format for: $comp ($ver)") unless ( $ver =~ m~^\d+\.\d+\.\d+.\w+$~ || $ver =~ m~^\d+\.\d+\.\d+$~ );
1089
            Error ("Invalid options: $comp($opt)") if ( $opt && ($opt ne "ALLOW_MULTI" ));
1090
            if ( $opt eq "ALLOW_MULTI" )
1091
            {
1092
                #
1093
                #   Some special components are allowed to have mutliple
1094
                #   versions. These are a gross kludge and are handled
1095
                #   with great care
1096
                #
1097
                #   Split out the vesrion into two parts
1098
                #
1099
#print "Process MULTI\n";
1100
                (my $suff = $ver) =~ s~^\d+\.\d+\.\d+.~~;
1101
                (my $vnum = $ver) =~ s~.\w+$~~;
1102
                Error "Bad format for ALLOW_MULTI. Suffix($suff) must be present" unless ( length($suff) > 2 );
1103
 
1104
                $kludge_component{$comp}{$suff} = $vnum;
1105
                $external_component{$comp} = $ver;
1106
                Verbose "MULTI package: $comp, $vnum, $suff";
1107
                next;
1108
            }
1109
 
1110
 
1111
            Error "Multiple definition of $comp" if defined $external_component{$comp};
1112
 
1113
            #
1114
            #   Save the data
1115
            #
1116
            $external_component{$comp} = $ver;
1117
            Verbose  "Package: $comp, $ver";
1118
            next;
1119
        }
1120
 
1121
 
1122
        #
1123
        #   SET var string
1124
        #   Set and export an environment variable
1125
        #   Primarilry used to setup GBE_PLATFORM and GBE_BUILDFILTER
1126
        #
1127
        if ( m/^SET/ )
1128
        {
1129
            my ($key, $var, $val) = split( ' ', $_, 3);
1130
            Error ("SET has missing parameters") unless ( $var );
1131
 
1132
            $ENV{$var} = $val;
1133
            Verbose ("Set: $var, $val");
1134
            next;
1135
        }
1136
 
1137
        #
1138
        #   Default
1139
        #   Save the line as the path to a $BUILDFILE file to be included
1140
        #
1141
 
1142
        push @modules, $_;
1143
    }
1144
    close ($fh);
1145
}
1146
 
1147
 
1148
#-------------------------------------------------------------------------------
1149
# Function        : build_module
1150
#
1151
# Description     : Build one module
1152
#
1153
# Inputs          : The path to the module to build
1154
#
1155
sub build_module
1156
{
1157
    my ($module) = @_;
1158
    my  $dir = "$root_dir/$module";
1159
    my  $exit_string;
1160
    my  $result = 0;
1161
 
1162
 
1163
    #
1164
    #   A nice header in the log file
1165
    #
1166
    print   "=" x 40 . " " . localtime() . " " . "=" x 40;
1167
    print   "\nModule: $module\n";
1168
 
1169
    printf OLDOUT "%-50s %-30s", $module, $dir_to_name{$module};
1170
    chdir ($dir);
1171
 
1172
    #
1173
    #   If the module conatins a pkg directory and that directory is also
1174
    #   in the local dpkg_archive, then skip this module
1175
    #
1176
    #       The following check assumes that the package name is the same
1177
    #       as the modules BuildName.
1178
    #
1179
    #       It does not check the contents simply, that the target exists
1180
    #
1181
    if (    $opt_skip
1182
         && -d $root_dir ."/local_dpkg_archive/" . $dir_to_name{$module}
1183
         && $build_this ne "$module" )
1184
#    if ( $opt_skip && -d "$dir/pkg" )
1185
    {
1186
        my $pkg_name = qx( ls $dir/pkg );
1187
        chomp( $pkg_name );
1188
        Verbose "pkg name: $pkg_name";
1189
        $exit_string = "Skipped - Pkg Found"
1190
            if ( -d "$root_dir/local_dpkg_archive/$pkg_name" );
1191
    }
1192
 
1193
    unless ( $exit_string )
1194
    {
1195
        rm_dir ("$dir/pkg" );
1196
        rewrite_build_file( $module );
1197
 
1198
        if ( $opt_audit )
1199
        {
1200
            #
1201
            #   Audit the build
1202
            #   Refer to comments in "audit_operation"
1203
            #
1204
            is_in_vob();
1205
            $result = System ("clearaudit /c perl $0 -AUDITMODE=$module @audit_args" );
1206
            System ("cleartool catcr -element -type fdl -long $AUDIT_DO > $AUDIT_LOG" );
1207
            System ("cat $AUDIT_LOG" );
1208
            System ("cat $AUDIT_LOG >> $audit_logfile" );
1209
            System ("rm -f $AUDIT_DO");
1210
        }
1211
        else
1212
        {
1213
            #
1214
            #   Build the component
1215
            #
1216
            my $mode = "";
1217
            $mode = "--expert" if ( $opt_expert );
1218
 
1219
            $result = JatsCmd ( "-b $BUILDUSE build $mode" );
1220
 
1221
            $mode = "all";
1222
            $mode = "debug package_debug" if ( $opt_quick );
1223
            $result = JatsCmd ( "-b $BUILDUSE make $mode" )
1224
                unless ( $result );
1225
 
1226
        }
1227
 
1228
        $result = JatsCmd ( "-b $BUILDUSE install" )
1229
            unless ( $result );
1230
 
1231
        $exit_string = "Package did not build and compile"
1232
            if ( $result );
1233
    }
1234
 
1235
    #
1236
    #   Double check that the package installed
1237
    #
1238
    unless ( $exit_string )
1239
    {
1240
        if ( -d "$dir/pkg" )
1241
        {
1242
            my $pkg_name = qx( ls $dir/pkg );
1243
            chomp( $pkg_name );
1244
 
1245
            unless ( -d "$root_dir/local_dpkg_archive/$pkg_name" )
1246
            {
1247
                $exit_string = "Package not transferred";
1248
                $result = 1;
1249
            }
1250
 
1251
            unless ( $dir_to_name{$module} eq $pkg_name )
1252
            {
1253
                $exit_string = "OK, but package name should be:$dir_to_name{$module} ";
1254
            }
1255
        }
1256
        else
1257
        {
1258
            $exit_string = "Package not found";
1259
            $result = 1;
1260
        }
1261
    }
1262
 
1263
    $exit_string = "OK" unless ( $exit_string );
1264
    print OLDOUT "$exit_string\n";
1265
    Verbose "build_module: Exit code: $result";
1266
 
1267
    #
1268
    #   A nice footer in the log file
1269
    #
1270
    printf   ("\nEnd Module: %s Name: %s\n", scalar( gmtime()), $module );
1271
 
1272
    return $result;
1273
}
1274
 
1275
#-------------------------------------------------------------------------------
1276
# Function        : install_package
1277
#
1278
# Description     : Install packages into dpkg_archive
1279
#                   This should only be done IFF all modules have been built
1280
#
1281
# Inputs          :
1282
#
1283
# Returns         :
1284
#
1285
sub install_package
1286
{
1287
    my ($module) = @_;
1288
    my  $dir = "$root_dir/$module";
1289
    my  $result = 0;
1290
 
1291
 
1292
    printf "Install Package: %-50s %-30s\n", $module, $dir_to_name{$module};
1293
    chdir ($dir);
1294
 
1295
    $result = JatsCmd ( "-b $BUILDUSE create_dpkg -o" );
1296
 
1297
    return $result;
1298
}
1299
 
1300
#-------------------------------------------------------------------------------
1301
# Function        : has_label
1302
#
1303
# Description     : Determine if a file has a clearcase label
1304
#
1305
# Inputs          : Name of the file
1306
#                   Label
1307
#
1308
# Returns         : True if it has the label
1309
#
1310
 
1311
sub has_label
1312
{
1313
    my( $file, $label ) = @_;
1314
 
1315
    my $data = qx( cleartool describe -fmt %Nl $file );
1316
    for (split ' ', $data)
1317
    {
1318
        return 1
1319
            if ( /$label/ );
1320
    }
1321
    return 0;
1322
}
1323
 
1324
#-------------------------------------------------------------------------------
1325
# Function        : is_checked_out
1326
#
1327
# Description     : Determine if a file has been checked out
1328
#
1329
# Inputs          : $file
1330
#
1331
# Returns         : True if checked out
1332
#
1333
sub is_checked_out
1334
{
1335
    my( $file ) = @_;
1336
    my $data = qx( cleartool describe -fmt %f $file );
1337
    Verbose ("is_checked_out:$data\n");
1338
    return 1
1339
        if ( length ($data) > 0 );
1340
    return 0;
1341
}
1342
 
1343
#-------------------------------------------------------------------------------
1344
# Function        : is_dynamic_view
1345
#
1346
# Description     : Determine if the current clearcase view is dynamic
1347
#
1348
# Inputs          :
1349
#
1350
# Returns         : True if it is a Dynamic View
1351
#
1352
sub is_dynamic_view
1353
{
1354
    my $data = qx( cleartool lsview -cview );
1355
    Verbose ("is_dynamic_view:$data\n");
1356
    return 1
1357
        if ( $data =~ m~^\*~ );
1358
    return 0;
1359
}
1360
 
1361
#-------------------------------------------------------------------------------
1362
# Function        : is_in_vob
1363
#
1364
# Description     : Determine if the current directory is with a VOB
1365
#                   clearaudit will generate an error if the CWD is not within
1366
#                   a knwon VOB.
1367
#
1368
#                   This can be caused by the case of the name of the current
1369
#                   directory. Windows is not case sensitive, but clearaudit is.
1370
#
1371
# Inputs          :
1372
#
1373
# Returns         :
1374
#
1375
sub is_in_vob
1376
{
1377
    my $data = qx( cleartool ls . );
1378
 
1379
    if ( $? / 256 )
1380
    {
1381
        my $cwd = getcwd();
1382
        Error ("Directory $cwd is not within a ClearCase VOB.\n",
1383
                "Possible problems:\n",
1384
                "   The directory is under version control\n",
1385
                "   The case of the directory does not match that stored within the VOB\n",
1386
                );
1387
    }
1388
}
1389
 
1390
#-------------------------------------------------------------------------------
1391
# Function        : clearcase_rule
1392
#
1393
# Description     : Return a string that is the clearcase rule used to conatin
1394
#                   the component.
1395
#
1396
#                   Use the ../.. directory.
1397
#
1398
# Inputs          : Directory
1399
#
1400
# Returns         :
1401
#
1402
#
1403
sub cleacase_rule
1404
{
1405
    (my $base) = @_;
1406
 
1407
    $base =~ s~/[^/]+$~~;
1408
    $base =~ s~/[^/]+$~~;
1409
    $base = "$root_dir/$base";
1410
 
1411
    my $data = qx(cleartool ls -d $base);
1412
 
1413
    $data =~ m~([^\s]+$)~;
1414
    my $rule = $1;
1415
 
1416
    return $rule;
1417
}
1418
 
1419
 
1420
#-------------------------------------------------------------------------------
1421
# Function        : determine_build_order
1422
#
1423
# Description     : This function will determine the build order of all of
1424
#                   the component modules
1425
#
1426
#                   This routine also sets up some important data structures
1427
#                   and supports the creation of a subset of the modules.
1428
#
1429
# Inputs          : None
1430
#
1431
# Returns         :
1432
#
1433
sub determine_build_order
1434
{
1435
    my %src;
1436
    my @build_order;
1437
    my %opt_list;
1438
    my %component;
1439
 
1440
    for my $module (@modules)
1441
    {
1442
        my $file = "$root_dir/$module/$BUILDFILE";
1443
        Verbose2 "Now Processing File: $file";
1444
        open (FILE, "<$file" ) or Error "Can't open the file: $file\n";
1445
        while (<FILE>)
1446
        {
1447
            if ( m/^BuildName\s/)
1448
            {
1449
 
1450
                m/'([^\s]*)\s+(.*)'/;
1451
                my $build_name = $1;
1452
                $src{$module}{'name'} = $build_name;
1453
 
1454
                $component{$build_name} = $module;
1455
                $dir_to_name{$module} = $build_name;
1456
 
1457
                $internal{$build_name} = $module
1458
                    unless ( defined $external_component{$build_name} );
1459
 
1460
                Verbose2 "   BuildName: $build_name";
1461
            }
1462
 
1463
            if ( m/^LinkPkgArchive/ || m/^BuildPkgArchive/ )
1464
            {
1465
                chomp;
1466
                m/'(.*)'[^']*'(.*)'/;
1467
    #            print "$_ : $1 :: $2\n";
1468
 
1469
                #
1470
                #   Only interested in the non-external components
1471
                #   These are components not encountered in the config file
1472
                #   We can't build external components, but should be able to build
1473
                #   all others.
1474
                #
1475
                my $comp = $1;
1476
                my $ver = $2;
1477
                if ( defined $external_component{$comp} )
1478
                {
1479
                    $src{$module}{'external'}{$comp} = $ver;
1480
                    Verbose2 "   External: $comp : $ver";
1481
                    next;
1482
                }
1483
 
1484
                $src{$module}{'depend'}{$comp} = $ver;
1485
# Stuffs %internal !!               $internal{$comp} = $module;
1486
#                Verbose2 "   Internal: $comp : $module, $ver";
1487
            }
1488
        }
1489
        close FILE;
1490
    }
1491
 
1492
    #
1493
    #   Build only the component in the current directory
1494
    #   Add the component to the list to build
1495
    #
1496
    if ( $build_this )
1497
    {
1498
        push @opt_only, $dir_to_name{$build_this};
1499
        Verbose2 "Build this: $build_this\n";
1500
    }
1501
 
1502
    #
1503
    #   If the user has requested that a single package be built then
1504
    #   create a hash of the prerequiste packages to limit the
1505
    #   algorithm to these packages
1506
    #
1507
    if ( $#opt_only >= 0 )
1508
    {
1509
        my @examine;
1510
 
1511
        for (@opt_only)
1512
        {
1513
            Error ("Specified package not found: $_")
1514
                if ( ! defined $component{$_} );
1515
 
1516
            #
1517
            #   Add user specified components to the list
1518
            #
1519
            Verbose2 "Specified user package: $_\n";
1520
            $opt_list{$_} = 1;
1521
            push @examine, keys (%{$src{$component{$_}}{'depend'}} )
1522
                if ( $opt_only_prereq );
1523
        }
1524
 
1525
        while ( $#examine >= 0)
1526
        {
1527
            my $file = pop @examine;
1528
            Verbose2 "NEED: $file   ; $component{$file}\n";
1529
            unless ( $opt_list{$file}  )
1530
            {
1531
                $opt_list{$file} = 1;
1532
                push @examine, keys %{$src{$component{$file}}{'depend'}};
1533
            }
1534
        }
1535
    }
1536
 
1537
    #
1538
    #   Dump all the modules dependency information
1539
    #
1540
    if ( $opt_dump_all || $opt_dump )
1541
    {
1542
        $opt_build = 0;
1543
 
1544
        sub pscan
1545
        {
1546
            my ( $ptr, $ptrbase, $comp ) = @_;
1547
            for ( sort keys %{$src{$internal{$comp}}{'depend'}} )
1548
            {
1549
                $ptr->{$_}++
1550
                    unless( $ptrbase->{$_} );
1551
                pscan ($ptr, $ptrbase, $_ );
1552
            }
1553
        }
1554
 
1555
        for my $file (sort keys %src)
1556
        {
1557
            my %base_dep;
1558
            for ( sort keys %{$src{$file}{'depend'}} )
1559
            {
1560
                $base_dep{$_}++;
1561
            }
1562
 
1563
            #
1564
            #   Determine complete list of all dependants other than those in the
1565
            #   top level.
1566
            #
1567
            my %full_dep = ();
1568
            for ( keys %base_dep )
1569
            {
1570
                pscan (\%full_dep, \%base_dep , $_ );
1571
            }
1572
 
1573
            #
1574
            #   Print it all out
1575
            #
1576
            print "Component: $src{$file}{'name'} in ${file} requires:\n";
1577
            for ( sort keys %base_dep )
1578
            {
1579
                print "    $_\n";
1580
            }
1581
 
1582
            if ( $opt_dump > 1 )
1583
            {
1584
                for ( sort keys %full_dep )
1585
                {
1586
                    print "            + $_\n";
1587
                }
1588
            }
1589
 
1590
 
1591
            if ( $opt_dump_all )
1592
            {
1593
                for ( sort keys %{$src{$file}{'external'}} )
1594
                {
1595
                    print "    $_/$src{$file}{'external'}{$_}\n";
1596
                }
1597
            }
1598
        }
1599
#        print Dumper( \%src, \%internal );
1600
    }
1601
 
1602
    #
1603
    #   Determine the order in which modules must be built
1604
    #   This is done by:
1605
    #       Determine ALL modules that don't have a dependency
1606
    #       Remove all discovered dependencies from ALL modules
1607
    #       Repeat, until no more dependencies are discovered
1608
    #
1609
 
1610
    my $go = 1;
1611
    while ( $go)
1612
    {
1613
        #
1614
        #   Append those entries that don't have any dependencies
1615
        #
1616
        my @dep_list;
1617
        for my $file (sort keys %src)
1618
        {
1619
            next if ( $src{$file}{'done'} );
1620
 
1621
            my $num_dep = keys %{$src{$file}{'depend'}};
1622
            if ( ! $num_dep  )
1623
            {
1624
                my $module = $src{$file}{'name'};
1625
                Verbose3 "BuildOrder: $file : $module";
1626
                push @dep_list, $module;
1627
                $src{$file}{'done'} = 1;
1628
 
1629
                push @build_order, $file
1630
                    unless ( ($#opt_only >= 0 ) && ! $opt_list{$module} );
1631
            }
1632
        }
1633
 
1634
        #
1635
        #   Remove all of the discovered dependencies
1636
        #
1637
        my $mod;
1638
        $go = 0;
1639
        for my $file (sort keys %src)
1640
        {
1641
            for $mod (@dep_list)
1642
            {
1643
                $go =1;
1644
                if (  exists ($src{$file}{'depend'}{$mod})  )
1645
                {
1646
                    $src{$file}{'discovered'}{$mod} = $src{$file}{'depend'}{$mod};
1647
                    delete $src{$file}{'depend'}{$mod};
1648
                }
1649
            }
1650
        }
1651
    }
1652
 
1653
    #
1654
    #   Ensure that there is nothing left to build
1655
    #
1656
    for my $file (sort keys %src)
1657
    {
1658
        my $num_dep = keys %{$src{$file}{'depend'}};
1659
        if ( $num_dep )
1660
        {
1661
            printf "CANNOT BUILD: %s(%s). Missing: %s\n", $file, $src{$file}{'name'}, join ' ' ,sort (keys %{$src{$file}{'depend'}});
1662
        }
1663
    }
1664
 
1665
    #
1666
    #   Return the ordered list of components to build
1667
    #
1668
    return @modules
1669
        if ( $opt_buildfiles );
1670
 
1671
    return @build_order;
1672
}
1673
 
1674
#-------------------------------------------------------------------------------
1675
# Function        : label_all_files
1676
#
1677
# Description     : Label all files in the view
1678
#
1679
# Inputs          :
1680
#
1681
# Returns         :
1682
#
1683
sub label_all_files
1684
{
1685
    my $result;
1686
    print "Label all files in the view with: $build_label\n";
1687
    $result = System ("cleartool mklabel -rec $build_label $root_dir");
1688
    if ( $result )
1689
    {
1690
        print "WARNING: Error reported by the labeling program";
1691
    }
1692
}
1693
 
1694
 
1695
#-------------------------------------------------------------------------------
1696
# Function        : rewrite_build_file
1697
#
1698
# Description     : Use a set of re-write rules to update directives within
1699
#                   the $BUILDFILE file. Creates a $BUILDUSE file
1700
#
1701
# Inputs          : Directory of the target $BUILDFILE file
1702
#
1703
# Returns         : 0 - all is well, file not modified
1704
#                   1 - all is well, file was modified
1705
#
1706
#
1707
sub rewrite_build_file
1708
{
1709
    my ( $dir ) = @_;
1710
    my $modified = 0;
1711
 
1712
    my $infile = "$root_dir/$dir/$BUILDFILE";
1713
    my $ofile = "$root_dir/$dir/$BUILDUSE";
1714
 
1715
    #
1716
    #   Adutit mode is special
1717
    #       Ensure that ALL files read by this function are audited
1718
    #       Do not delete or re-write the output file as we don't have enough
1719
    #       information to do this
1720
    #
1721
    if ( $opt_audit_entry )
1722
    {
1723
        open ( INFILE, "<$infile" )   || Error "Rewrite: Cannot open $infile\n";
1724
        my $dummy = readline( INFILE );
1725
        close (INFILE );
1726
        return;
1727
    }
1728
 
1729
 
1730
    #
1731
    #   Unlink any OLD output file
1732
    #
1733
    unlink $ofile;
1734
 
1735
    #
1736
    #   Open the input and output files
1737
    #
1738
    open ( INFILE, "<$infile" )   || Error "Rewrite: Cannot open $infile\n";
1739
    open ( OUTFILE, ">$ofile" ) || Error "Rewrite: Cannot open $ofile\n";
1740
 
1741
    my $build_name = "UNKNOWN";
1742
    my $build_version;
1743
 
1744
    my $release_name;
1745
    my $release_version;
1746
 
1747
    print "\nRewrite: $infile\n";
1748
    while ( <INFILE> )
1749
    {
1750
        next if ( m~^\s*#~ );            # Skip comments
1751
 
1752
        #
1753
        #   Process BuildName
1754
        #
1755
        if ( m~\s*BuildName[\s\(]~ )
1756
        {
1757
            m/'([^\s]+)\s+(.*)'/;
1758
            $build_name = $1;
1759
            $build_version = $2;
1760
 
1761
            #
1762
            #   Ensure that we have a valid name
1763
            #
1764
            my $new_ver;
1765
            my $message;
1766
 
1767
            unless (is_known($build_name))
1768
            {
1769
                $message = " Error: BuildName not known";
1770
                $new_ver = $build_version;
1771
            }
1772
            else
1773
            {
1774
                #
1775
                #   Process the current line
1776
                #
1777
                $new_ver = version_to_project ( $build_name, "current" );
1778
 
1779
                #
1780
                #   The version bit needs a space in it
1781
                #
1782
                $new_ver =~ s~\.(\w+)$~ $1~;
1783
 
1784
                s/'(.*)\s+(.*)'/'$build_name $new_ver'/;
1785
            }
1786
            print_update( $build_name ,$build_version, $new_ver, $message );
1787
            $modified = 1
1788
                if ( $build_version ne $new_ver );
1789
 
1790
 
1791
        }
1792
 
1793
        #
1794
        #   Process BuildReleaseFile
1795
        #
1796
        if ( m~\s*BuildReleaseFile[\s\(]~ )
1797
        {
1798
            m/'(.*)\s(.*)'/;
1799
            $release_name = $1;
1800
            $release_version = $2;
1801
 
1802
            my $new_ver;
1803
            my $message;
1804
 
1805
            unless (is_known($build_name))
1806
            {
1807
                $message = " Error: BuildName not known";
1808
                $new_ver = $release_version;
1809
            }
1810
            else
1811
            {
1812
 
1813
                #
1814
                #   Process the current line
1815
                #
1816
                $new_ver = version_to_project ( $build_name, "current" );
1817
                s/'(.*)\s(.*)'/'$build_name $new_ver'/;
1818
            }
1819
 
1820
            print_update ($release_name ,$release_version, $new_ver, $message );
1821
            $modified = 1
1822
                if ( $release_version ne $new_ver );
1823
        }
1824
 
1825
        #
1826
        #   Process BuildPkgArchive and LinkPkgArchive
1827
        #   Must take care to handle project and non-project extensions
1828
        #       ie: version 12.12.12.mas needs to be replaced with 13.13.13.mas
1829
        #      and          12.12.12.syd needs to be replaced with 13.13.13.syd
1830
        #      for the SAME component.
1831
        #
1832
        #
1833
        if ( m/^LinkPkgArchive/ or m/^BuildPkgArchive/ )
1834
        {
1835
            my $comp;
1836
            my $ver;
1837
            my $new_ver;
1838
            my $message;
1839
 
1840
            m/'(.*)'[^']*'(.*)'/;
1841
 
1842
            my $comp = $1;
1843
            my $ver = $2;
1844
 
1845
            #
1846
            #   Ensure that we have a valid name
1847
            #
1848
            unless (is_known($comp))
1849
            {
1850
                $message = " ERROR: Name not known: $comp";
1851
                $new_ver = $ver;
1852
 
1853
            }
1854
            else
1855
            {
1856
                #
1857
                #   Examine the version part and determine if there is any project
1858
                #   specfic part
1859
                #
1860
                $new_ver = version_to_project ( $comp, $ver );
1861
 
1862
                #
1863
                #   Process the current line
1864
                #
1865
                s/'(.*)'([^']*)'(.*)'/'$comp'$2'$new_ver'/;
1866
            }
1867
 
1868
            print_update ($comp ,$ver, $new_ver, $message );
1869
            $modified = 1
1870
                if ( $ver ne $new_ver );
1871
        }
1872
 
1873
 
1874
    }
1875
    continue
1876
    {
1877
        #
1878
        #   Always output the resultant line
1879
        #
1880
        print OUTFILE $_;
1881
    }
1882
 
1883
    #
1884
    #   Cleanup
1885
    #
1886
    close INFILE;
1887
    close OUTFILE;
1888
 
1889
    return $modified;
1890
}
1891
 
1892
#-------------------------------------------------------------------------------
1893
# Function        : is_known
1894
#
1895
# Description     : Determine if this component is known to the program
1896
#                   Internal and external packages are KNOWN
1897
#                   Other packages need to be specified
1898
#
1899
# Inputs          : Component
1900
#
1901
# Returns         :
1902
#
1903
# is_known
1904
sub is_known
1905
{
1906
    my ( $comp ) = @_;
1907
 
1908
    return 1
1909
        if ( (defined $external_component{$comp}) || ( defined $internal{$comp} ) );
1910
 
1911
    return 0;
1912
}
1913
 
1914
 
1915
#-------------------------------------------------------------------------------
1916
# Function        : version_to_project
1917
#
1918
# Description     : Take a version string and return a project extension
1919
#
1920
# Inputs          :
1921
#
1922
# Returns         :
1923
#
1924
sub version_to_project
1925
{
1926
    my ( $comp, $ver ) = @_;
1927
    my $proj;
1928
 
1929
    #
1930
    #   Replace Internal components with a single project wide build version
1931
    #
1932
    return $label
1933
        unless ( $external_component{$comp}  );
1934
 
1935
 
1936
    #
1937
    #   The version string may have a trailing project specifier
1938
    #       ie: 12.12.12.mas
1939
    #   Determine the suffix
1940
    #
1941
    $proj = $1
1942
        if ($ver =~ m/\.([^\d]+)$/);
1943
 
1944
 
1945
#print "         Project: comp=$comp, ver=$ver, proj=$proj,\n";
1946
 
1947
    #
1948
    #   Some extension need special treatment
1949
    #   "current"   - Assume that the TAG is in the component HASH
1950
    #
1951
    if ( $ver =~ m/current/ )
1952
    {
1953
        $proj = "";
1954
    }
1955
    elsif ( $proj )
1956
    {
1957
        $proj = $project unless ( $project_keep{$proj} );
1958
    }
1959
    $proj = "." . $proj if ( $proj );
1960
 
1961
 
1962
    my $new_comp;
1963
    if ( $kludge_component{$comp} )
1964
    {
1965
        my $type = "xxx";
1966
        $type = "mas"
1967
            if ( $proj =~ m/mas/ );
1968
        if ( $kludge_component{$comp}{$type} )
1969
        {
1970
            $new_comp = $kludge_component{$comp}{$type};
1971
        }
1972
        else
1973
        {
1974
            $new_comp = $kludge_component{$comp}{$project};
1975
        }
1976
 
1977
    }
1978
    else
1979
    {
1980
        $new_comp = $external_component{$comp};
1981
    }
1982
    $new_comp =~ s~xxx~$project~;
1983
    $proj = "" if ( $new_comp =~ m/\.([^\d]+)$/ );
1984
 
1985
 
1986
    return $new_comp . $proj;
1987
 
1988
}
1989
 
1990
#-------------------------------------------------------------------------------
1991
# Function        : print_update
1992
#
1993
# Description     : Generate a display line tracking the changes made
1994
#
1995
# Inputs          :
1996
#
1997
# Returns         :
1998
#
1999
sub print_update
2000
{
2001
    my ($name, $version, $new_version, $message ) = @_;
2002
    my $diff = " ";
2003
    $diff = "*"
2004
        if ( $version ne $new_version );
2005
 
2006
    printf "Name     : %-25s, Version: %-12s %s-> %-12s %s\n", $name ,$version, $diff, $new_version,$message;
2007
}
2008
 
2009
#-------------------------------------------------------------------------------
2010
# Function        : rm_directory
2011
#
2012
# Description     : Cannot rely on the underlying 'rm' command. Many of them
2013
#                   are brain-dead. ie: The one in the JATS BIN.win32 directory
2014
#
2015
# Inputs          :
2016
#
2017
# Returns         :
2018
#
2019
sub rm_dir
2020
{
2021
    print ("Remove Directory: @_\n");
2022
    rmtree( @_ , $opt_verbose, 0);
2023
}
2024
 
2025
#-------------------------------------------------------------------------------
2026
# Function        : generate_pathlist
2027
#
2028
# Description     :
2029
#
2030
# Inputs          :
2031
#
2032
# Returns         :
2033
#
2034
sub generate_pathlist
2035
{
2036
    our %cf_info;                           # Contains Makefile.cfg data
2037
    our %cf_build_info;                     # Contains Buildfile.cfg
2038
    our %cf_filelist;                       # Contains a hash of other makefiles
2039
 
2040
    my %mdata;                              # Hash of collected data
2041
 
2042
    #-------------------------------------------------------------------------------
2043
    #   Process each module specified and create a data structure that represents
2044
    #   all the relevent information
2045
    #
2046
    for my $module ( @modules )
2047
    {
2048
        Verbose( "Processing: $module" );
2049
 
2050
        #
2051
        #   Locate the JATS generated data file
2052
        #   This will be in the "interface" directory, or if this directory does not
2053
        #   exist the file will be found in the current directory
2054
        #
2055
        #   The data file can be "require"ed directly by Perl. The data will be
2056
        #   conatined with a few cf_xxxx hashes
2057
        #
2058
        for (qw(Makefile.cfg Buildfile.cfg))
2059
        {
2060
            Verbose( "generate_pathlist: $_" );
2061
            my $fname = "$root_dir/$module/$_";
2062
            $fname = "$root_dir/$module/interface/$_" unless ( -f $fname );
2063
            Error ( "Cannot locate $fname") unless ( -f $fname );
2064
            require $fname;
2065
        }
2066
 
2067
        Error ("Data in Makefile.cfg is not valid" )
2068
            unless ( keys(%cf_filelist) > 0 );
2069
 
2070
        #
2071
        #   Process all the Makefile_xx.cfg files
2072
        #
2073
        for my $cfg_file ( sort values(%cf_filelist))
2074
        {
2075
            Verbose( "generate_pathlist: Processing: $cfg_file" );
2076
            my $fname = "$root_dir/$module/$cfg_file";
2077
            $fname = "$root_dir/$module/interface/$cfg_file" unless ( -f $fname );
2078
 
2079
            #
2080
            #   Simply ignore missing config files
2081
            #
2082
            next unless ( -f $fname );
2083
            require $fname;
2084
            Verbose( "generate_pathlist: Have data from: $cfg_file" );
2085
 
2086
            #
2087
            #   All the data is held within %cf_info, which is hashed
2088
            #   by platform
2089
            #
2090
            foreach my $key ( sort keys(%cf_info) )
2091
            {
2092
                my %dirs;
2093
                my $pData = \%{$mdata{$key}};
2094
 
2095
                Verbose( "Processing $cfg_file, PLATFORM: $key" );
2096
 
2097
                my $pInfo = \%{$cf_info{$key}};
2098
 
2099
                $pData->{'Platform'} = $pInfo->{'$ScmPlatform'};
2100
                $pData->{'Product'}  = $pInfo->{'$ScmProduct'};
2101
                $pData->{'Target'}   = $pInfo->{'$ScmTarget'};
2102
 
2103
                for ( @{$pInfo->{'@INCDIRS'}}, @{$pInfo->{'@SRCDIRS'}} )
2104
                {
2105
                    $dirs{$_}++;
2106
                }
2107
 
2108
                push @{$pData->{'dirs'}}, keys (%dirs);
2109
            }
2110
        }
2111
 
2112
        #
2113
        #   Release the memory used by the read data
2114
        #   This will also clear it for next iteration of the loop
2115
        #
2116
        %cf_info = ();
2117
        %cf_build_info = ();
2118
    }
2119
 
2120
    #-------------------------------------------------------------------------------
2121
    #   Data has been collected, but it is a bit mixed up.
2122
    #   There are basically two types of modules encountered
2123
    #       1) Platforms that have a PRODUCT and a TARGET
2124
    #       2) Simple modules that have a TARGET
2125
    #          These are used by all many modules
2126
    #
2127
    #   To add to the confusion, some PLATFORM are really simple TARGETS too.
2128
    #   The only difference is that they are not used by anything else
2129
    #
2130
    #   Make a single pass over the data and MARK entries that are used as targets
2131
    #   Ignore entries where the target and the platform are the same as these are
2132
    #   simple
2133
    #
2134
    for my $key ( keys %mdata)
2135
    {
2136
        my $target = $mdata{$key}{'Target'};
2137
        $mdata{$target}{'MARK'}++
2138
            unless ( $key eq $target );
2139
    }
2140
 
2141
    #
2142
    #   Generate complete source directory lists for entries with NO mark
2143
    #   These are the platforms at the top of the food chain, not simply targets
2144
    #   for use by products and platforms.
2145
    #
2146
    for my $key ( keys %mdata)
2147
    {
2148
        my $pData = \%{$mdata{$key}};
2149
 
2150
        next if ( $pData->{'MARK'}  );
2151
        Verbose ( "PLATFORM: $key" );
2152
 
2153
        my $Platform = $pData->{'Platform'};
2154
        my $Product  = $pData->{'Product'};
2155
        my $Target   = $pData->{'Target'};
2156
 
2157
        #
2158
        #   Generate a list of unique directories
2159
        #
2160
        my %dirs;
2161
        for ( @{$pData->{'dirs'}} )
2162
        {
2163
            $dirs{$_}++;
2164
        }
2165
        #
2166
        #   Add in the Target directories too
2167
        #
2168
        unless ( $Platform eq $Target )
2169
        {
2170
            for ( @{$mdata{$Target}{'dirs'}} )
2171
            {
2172
                $dirs{$_}++;
2173
            }
2174
        }
2175
 
2176
        #
2177
        #   Generate the output file
2178
        #
2179
        my $ofile = "$key.pathlist";
2180
        my $localtime = localtime();
2181
        print "Generate pathlist for: $key\n";
2182
        open ( OFILE, ">$ofile" ) or Error ("Cannot create $ofile");
2183
        select OFILE;
2184
 
2185
        print <<EOF;
2186
#   List of directories specified in the build
2187
#
2188
#   Generated: $localtime
2189
#
2190
#   Platform : $Platform
2191
#   Product  : $Product
2192
#   Target   : $Target
2193
#
2194
EOF
2195
        for (sort keys %dirs )
2196
        {
2197
            #
2198
            #   Convert / -> \ for Windows
2199
            #   Remove paths with internal names, like: $(OBJDIR)
2200
            #
2201
            (my $dirs = $_) =~ s~/~\\~g;
2202
            print $dirs . "\n"
2203
                unless ( $dirs =~ m~\$\([A-Z]+\)~ );
2204
        }
2205
 
2206
        close OFILE;
2207
        select STDOUT;
2208
    }
2209
}
2210
 
2211
 
2212
#-------------------------------------------------------------------------------
2213
#   Documentation
2214
#
2215
 
2216
=pod
2217
 
2218
=head1 NAME
2219
 
2220
jats_builder - Build a system with multiple build.pl files
2221
 
2222
=head1 SYNOPSIS
2223
 
2224
 perl jats_builder.pl [options]
2225
 
2226
 Options:
2227
    -help              - brief help message
2228
    -help -help        - Detailed help message
2229
    -man               - Full documentation
2230
    -config=xxx        - Specify config file. Default is build.cfg
2231
    -clean             - Clean out packages. Clean build
2232
    -only pkg          - Build a single package - and possibly all prerequisites.
2233
                         This option can be used multiple times.
2234
    -resetlog          - Restart the logfile
2235
    -show              - Display external modules and the build order
2236
    -showrule          - Display external modules, the build order, and clearcase rule
2237
    -showpkg           - Display external modules as LinkPkgArchive statements
2238
    -verbose           - Verbose operation
2239
    -updatecache       - Ensure all external packages are cached
2240
 
2241
    -audit             - Generate a clearaudit trail of the build
2242
    -[no]build         - Build (default is build)
2243
    -[no]all           - Build all components (default is noall)
2244
    -[no]expert        - Expert mode. Allows build to restart. (default is expert)
2245
    -[no]log           - Use a logfile (default is log)
2246
    -[no]prereq        - Build prerequisites to "only" components. Default
2247
    -[no]quick         - Build only debug packages (default is noquick)
2248
    -[no]skip          - Skip installed packages (default)
2249
    -create_dpkg       - Install packages into dpkg_archive, after all has built
2250
 
2251
    The following options imply "nobuild"
2252
 
2253
    -buildfiles                     - Enables operations only build.pl and build.use.pl
2254
        -[no]buildfiles_rewrite     - Rewrite build.pl (default is no)
2255
        -[no]buildfiles_checkout    - Checkout build.pl if required (default is no)
2256
        -[no]buildfiles_label       - Label build.pl (default is no)
2257
        -[no]buildfiles_labelall    - Label all builder files (default is no)
2258
        -[no]buildfiles_labelrule   - Label all builder files with a rule based label (default is no)
2259
 
2260
    -dump              - Dump component dependency info, except external packages
2261
    -dump -dump        - Dump component dependency info (with sub components), except external packages
2262
    -dumpall           - Dump all component dependency info
2263
    -labelall          - Label all files in the view
2264
    -pathlist          - Generate pathlists for all platforms
2265
 
2266
=head1 OPTIONS
2267
 
2268
=over 8
2269
 
2270
=item B<-help>
2271
 
2272
Print a brief help message and exits.
2273
 
2274
=item B<-help -help>
2275
 
2276
Print a detailed help message with an explanation for each option.
2277
 
2278
=item B<-man>
2279
 
2280
Prints the manual page and exits.
2281
 
2282
 
2283
=item B<-config=file>
2284
 
2285
Specify the name of a config file to use. If no configuration file is specified
2286
then the program will be use B<build.cfg>. The program will search for the specified
2287
config file upwards from the current directory.
2288
 
2289
The name of the config file will be used as the basis for the logfile name;
2290
any extension is removed and an extension of ".log" will be added.
2291
 
2292
The directory in which the config file is found will be used as the basis for
2293
the log file.
2294
 
2295
=item B<-clean>
2296
 
2297
Deletes the local_dpkg_archive directory contents and then cleans and clobbers
2298
all the configured components. The logfile is also deleted.
2299
 
2300
=item B<-only pkg>
2301
 
2302
Will build a single component. This option may be used multiple times to force
2303
multiple components to be built.
2304
 
2305
If the "-prereq" option is selected, then the prerequisites components will be
2306
determined and may be built.
2307
 
2308
=item B<-resetlog>
2309
 
2310
Deletes the build.log logfile.
2311
 
2312
In a full system build the logfile is not deleted be default. This allows the
2313
build to be stopped and restarted.
2314
 
2315
If a single ( or a list ) of components is being built, then the logfile will
2316
always be deleted.
2317
 
2318
=item B<-show>
2319
 
2320
Display the external and internal components.
2321
 
2322
The external components together with their version numbers, in alphabetic order.
2323
 
2324
The internal components are displayed in the required build order. When building
2325
a selected set of components only the selected components are displayed.
2326
 
2327
=item B<-showrule>
2328
 
2329
Display the external and internal components. The clearcase selection rule are
2330
also shown for the internal components.
2331
 
2332
The external components together with their version numbers, in alphabetic order.
2333
 
2334
The internal components are displayed in the required build order. When building
2335
a selected set of components only the selected components are displayed.
2336
 
2337
The clearcase selection rule is taken from the directory two above the build file.
2338
This ensures that the rule for the component is used.
2339
 
2340
=item B<-showpkg>
2341
 
2342
Display the external components as LinkPkgArchive statements.
2343
 
2344
This is intended to generate list of external components that can be copied
2345
directly into release manager.
2346
 
2347
This command will terminate the program. It implies B<-nobuild>.
2348
 
2349
=item B<-verbose>
2350
 
2351
Increase the level of debugging information displayed. This option may be used
2352
multiple times.
2353
 
2354
=item B<-updatecache>
2355
 
2356
Allows external components are determined and are copied into a local
2357
dpkg_archive cache, if  present. This will significantly speed up operation if
2358
dpkg_archive is on a network drive.
2359
 
2360
The local dpkg_archive cache is located by examining the DPKG_ARCHIVE variable
2361
for an archive name that contains the word "cache".
2362
 
2363
If used once then, packages will be copied into the cache only if not already
2364
present. If used more than once, then packages will be refreshed - they
2365
will be deleted and copied again.
2366
 
2367
=item B<-[no]build>
2368
 
2369
The nobuild option will prevent the program from building components.
2370
The configuration file will be read and any errors will be reported.
2371
 
2372
The default is "build", which will determine the components to be built, the
2373
order in which the components should be built and then proceed to build the
2374
components.
2375
 
2376
=item B<-[no]all>
2377
 
2378
Normally the program will build B<all> components only if it is started in the same
2379
directory as the configuration file, otherwise it will build the named components
2380
or the component found in the current directory.
2381
 
2382
The B<all> option will force the program to build all components within
2383
the configuration file. The default is "noall".
2384
 
2385
=item B<-[no]expert>
2386
 
2387
The use of the -expert mode allows the build to be restarted at the point were
2388
item had been terminated. The components are not cleaned before being built.
2389
 
2390
The default mode is expert.
2391
 
2392
=item B<-[no]log>
2393
 
2394
Capture and log all the build information to a logfile.
2395
 
2396
With nolog the build information is displayed on the screen. This may be useful
2397
for debugging.
2398
 
2399
=item B<-[no]prereq>
2400
 
2401
When building one or more named components the complete list of prerequisites
2402
modules will be built.
2403
 
2404
The "noprereq" option allows one modules to be built without examination of the
2405
prerequisites. This may lead to a build problem unless all the prerequisites can
2406
be located.
2407
 
2408
=item B<-[no]quick>
2409
 
2410
The "quick" option only builds the "debug" version of all the components.
2411
 
2412
The, default, "noquick" option builds the "debug" and "production" version of components.
2413
 
2414
=item B<-[no]skip>
2415
 
2416
By default, a component will not be build if item looks as though item has been
2417
built. The "noskip" option suppresses this operation.
2418
 
2419
A component is deemed to have been built iff:
2420
 
2421
=over 8
2422
 
2423
=item 1
2424
 
2425
The components "pkg" directory exists
2426
 
2427
=item 2
2428
 
2429
The component is found in the local dpkg_archive
2430
 
2431
=back
2432
 
2433
=item B<-audit>
2434
 
2435
If B<audit> is enabled then the clearcase audit system will be invoked and an
2436
audit log of the files used in the build will be recorded.
2437
 
2438
The audit log will be recorded with each built component and a global audit logfile
2439
will be created in the root directory.
2440
 
2441
=item B<-create_dpkg>
2442
 
2443
Install built packages into the main dpkg_archive.
2444
 
2445
This operation is performed in conjunction with a build, but only after all the
2446
packages have been built sucessfully.
2447
 
2448
The installation process is interactive and the output is not logged to a logfile.
2449
 
2450
=item B<-buildfiles>
2451
 
2452
If this option is present, then the otherwise buildfile options are activated and
2453
will the build.pl and p=build.use.pl files may be modified.
2454
 
2455
In all cases a file called build.use.pl file will be created.
2456
 
2457
The use of this option prevents components being built.
2458
 
2459
=item B<-[no]buildfiles_rewrite>
2460
 
2461
If -buildfiles is present then this option will allows the build.pl file to be re-written.
2462
 
2463
The default operation is to NOT modify the build.pl file, only the build.use.pl.
2464
 
2465
=item B<-[no]buildfiles_checkout>
2466
 
2467
If -buildfiles is present then this option will instruct the program to checkout the
2468
build.pl file, before it is modified. The file is not checked in.
2469
 
2470
The default operation is to NOT checkout the build.pl file.
2471
 
2472
=item B<-[no]buildfiles_label>
2473
 
2474
If -buildfiles is present then this option instructs the program to label the
2475
build.pl file.
2476
 
2477
The default operation is to NOT label the files.
2478
 
2479
=item B<-[no]buildfiles_labelall>
2480
 
2481
If -buildfiles is present then this option instructs the program to label the
2482
build.pl file as well as : makefile.pl src/makefile.pl and the directories . and ..
2483
 
2484
The default operation is to use a label derived from the B<LABEL> directive
2485
in the builder configuration file. This is modified if the  B<-[no]buildfiles_labelrule>
2486
option is specified.
2487
 
2488
The default operation is to NOT label the files.
2489
 
2490
=item B<-[no]buildfiles_labelrule>
2491
 
2492
If -buildfiles is present then this option instructs the program to label the
2493
build.pl file as well as : makefile.pl src/makefile.pl and the directories . and ..
2494
 
2495
The label that is used is derived from the clearcase rule that loads the parents
2496
parents directory. This is the label shown with the B<-showrule> option.
2497
 
2498
The default operation is to use a label derived from the B<LABEL> directive
2499
in the builder configuration file.
2500
 
2501
 
2502
=item B<-dump>
2503
 
2504
Dump the the dependency information for all internal components
2505
 
2506
When used twice the dump also includes all dependants of the dependants.
2507
 
2508
The use of this option prevents components being built.
2509
 
2510
=item B<-dumpall>
2511
 
2512
Dump the the dependency information for all external and internal components
2513
 
2514
The use of this option prevents components being built.
2515
 
2516
=item B<-labelall>
2517
 
2518
Label all files in the view
2519
 
2520
The use of this option prevents components being built.
2521
 
2522
=item B<-pathlist>
2523
 
2524
This option will generate files for each major platform that contain pathlists
2525
for all files used in the compilation. This file is intended to be used by
2526
source level debuggers.
2527
 
2528
The path information is extracted from information generated by the makefile build
2529
operation. The modules not need to be compiled. Conversely only
2530
information that is present to the build system will be in the pathlist file.
2531
 
2532
Pathlist files are named as F<xxxx.pathlist>.
2533
 
2534
=back
2535
 
2536
=head1 DESCRIPTION
2537
 
2538
B<This program> will build a system containing one or more inter-related build
2539
files using the JATS build tools.
2540
 
2541
The program also provides a numbers of ancillary function to assist in the
2542
maintenance of build systems.
2543
 
2544
In normal operation the program will:
2545
 
2546
=over 8
2547
 
2548
=item *
2549
 
2550
Locate a configuration file called F<build.cfg>
2551
 
2552
=item *
2553
 
2554
Determine the components in the build
2555
 
2556
=item *
2557
 
2558
Determine the build order of the components
2559
 
2560
=item *
2561
 
2562
Build and install the components
2563
 
2564
=back
2565
 
2566
=head1  THE CONFIGURATION FILE
2567
 
2568
The configuration provides information essential to the building process. It is
2569
located in the root of the build tree and as such determines the root directory
2570
for the build. The root directory is used to contain the local dpkg_archive
2571
directory and the logfile.
2572
 
2573
The configuration file is called F<build.cfg>. It is a simple text file.
2574
Comments begin with a "#" and continue to the end of the line. Blank line are
2575
ignored.
2576
 
2577
The file provides the following information:
2578
 
2579
=over 8
2580
 
2581
=item *
2582
 
2583
The project version number and name.
2584
 
2585
=item *
2586
 
2587
Location of the project root directory
2588
 
2589
=item *
2590
 
2591
Other configuration files
2592
 
2593
=item *
2594
 
2595
A list of external components and required versions
2596
 
2597
=item *
2598
 
2599
A list of internal components.
2600
 
2601
=back
2602
 
2603
=head2 Project Version number and name
2604
 
2605
A LABEL statement is used to specify the version number of the build as well as
2606
the project name. The project name is used to identify project specific options
2607
within the build, such as external packages. The label used as a basis for
2608
labeling the build files.
2609
 
2610
=head3 LABEL directive format
2611
 
2612
The format of the label directive is
2613
 
2614
=over 8
2615
 
2616
=item   B<LABEL> C<nn.nn.nn.prj>
2617
 
2618
=back
2619
 
2620
=head2 Root Directory
2621
 
2622
A ROOTDIR statement is used to specify the root of all the internal components.
2623
If no ROOTDIR statement is encountered then the root directory is that in which
2624
the config file was found.
2625
 
2626
The ROOTDIR directory must be within the current path. The config file must be
2627
within the file tree at the same level, or below the root directory.
2628
 
2629
=head3 ROOTDIR directive format
2630
 
2631
The format of the ROOTDIR directive is
2632
 
2633
=over 8
2634
 
2635
=item   B<ROOTDIR> C<dir_name>
2636
 
2637
Where C<dir_name> is a simple name. It cannot contain ".", ".." or "/" characters.
2638
 
2639
=back
2640
 
2641
=head2 Included configuration files
2642
 
2643
An INCLUDE statement is used to include another configuration file.
2644
 
2645
Configuration files may include a common component, perhaps tools define a core
2646
set of external components, or a common label or root directory.
2647
 
2648
Included Configuration files may be nested to a depth of 10.
2649
 
2650
=head3 INCLUDE directive format
2651
 
2652
The format of the INCLUDE directive is
2653
 
2654
=over 8
2655
 
2656
=item   B<INCLUDE> C<file_name>
2657
 
2658
Where C<file_name> is the name of a configuration file to be included.
2659
 
2660
=back
2661
 
2662
 
2663
=head2 External components
2664
 
2665
An external component is a component that is not to be built by this program.
2666
The component is provided by a package to be found in dpkg_archive.
2667
 
2668
Several directives are available to specify external components. These include:
2669
 
2670
=over 8
2671
 
2672
=item *
2673
 
2674
EXTERNAL directive
2675
 
2676
=item *
2677
 
2678
LinkPkgArchive statements
2679
 
2680
=item *
2681
 
2682
BuildPkgArchive statements
2683
 
2684
=back
2685
 
2686
The LinkPkgArchive and BuildPkgArchive statements allows a simple interface to
2687
the B<Release Manager> and perform the same job as the EXTERNAL directive.
2688
 
2689
=head3 EXTERNAL directive
2690
 
2691
The format of the EXTERNAL directive is:
2692
 
2693
=over 8
2694
 
2695
=item   B<EXTERNAL> I<name> I<version> [OPTIONS]
2696
 
2697
=back
2698
 
2699
Where B<name> is the name of the external package.
2700
B<version> is the version of the external package. This may contain a suffix.
2701
B<OPTIONS> is an optional option.
2702
 
2703
The version may contain a project specific suffix. If this is "xxx" then it will
2704
be replaced with the project suffix.
2705
 
2706
Available options include:
2707
 
2708
=over 8
2709
 
2710
=item   B<ALLOW_MULTI>
2711
 
2712
This option allows multiple packages with the same name, but different version
2713
information. This is required to provide correct processing of packages that
2714
have a project independent part and a project dependent part, such a
2715
C<sysbasetypes>.
2716
 
2717
=back
2718
 
2719
=head4 EXTERNAL directive example
2720
 
2721
    BuildPkgArchive ( 'solidbasetypes', '1.0.0.mas' );
2722
    BuildPkgArchive ( 'sysbasetypes'  , '20.0.0.mas' );       ALLOW_MULTI
2723
    BuildPkgArchive ( 'sysbasetypes'  , '20.0.0.syd' );       ALLOW_MULTI
2724
    BuildPkgArchive ( 'sysswis'       , '20.1.0.syd' );
2725
    EXTERNAL          crypta_dsi        20.0.0.cr
2726
    EXTERNAL          crc               1.0.2.cr
2727
 
2728
=head2 Internal components
2729
 
2730
Internal components are those that can be built by this program. Allows lines in
2731
the configuration file that are not another directive will be treated as the
2732
specification of an internal component.
2733
 
2734
Internal components are specified by the path, from the project root directory
2735
to the JATS build.pl file. The order in which the components is specified is
2736
B<not> important.
2737
 
2738
=head4 Internal component example
2739
 
2740
     ar/build/jats
2741
     br/enquiry/build/jats
2742
     br/farepayment/build/jats
2743
     br/framework/build/jats
2744
 
2745
=head2 Miscellaneous directives
2746
 
2747
The configuration file may contain a number of Miscellaneous directives.
2748
 
2749
=head3 MESSAGE
2750
 
2751
The MESSAGE directive simply displays the remainder of the line.
2752
 
2753
=head3 EXCLUDE
2754
 
2755
The EXCLUDE directive displays the remainder of the line with the prefix
2756
of B<EXCLUDED>. It may be used to indicate that a directive is being suppressed.
2757
 
2758
=head1  BUILD OPERATION
2759
 
2760
The steps in building a components are detailed in the following sections.
2761
 
2762
=head2  Determine if the component needs to be built
2763
 
2764
The program will not build a component if it has already been built and
2765
installed into the local dpkg_archive, unless the -noskip option is present.
2766
 
2767
=head2  Re-write the build.pl file
2768
 
2769
The components build.pl file is re-written as build.use.pl. The re-write process
2770
will massage the package versions found within the B<BuildName>,
2771
B<BuildRelease>, B<LnkPkgArchive> and B<BuildPkgArchive> directives. This file
2772
is then used in later operations and is available for manual use by JATS.
2773
 
2774
=head2  Generate the JATS makefiles
2775
 
2776
Use the re-written build.use.pl file to create the JATS build environment. This will
2777
copy into the user sandbox any external components specified with a B<BuildPkgArchive>
2778
as well as generate makefiles for (all the required targets.
2779
 
2780
=head2  Compile the component
2781
 
2782
JATS is used to "make" the component. The B<quick> option allows only the
2783
"debug" portions to be created, otherwise both the B<debug> and B<prod>unction portions
2784
are made.
2785
 
2786
=head2  Install the component
2787
 
2788
If the component is successfully built and made, then the resultant package
2789
will be installed into a local dpkg_archive for use by otherwise dependent
2790
components.
2791
 
2792
=cut
2793