Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
227 dpurdie 1
########################################################################
6177 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
227 dpurdie 3
#
4
# Module name   : jats.sh
5
# Module type   : Makefile system
6
# Compiler(s)   : n/a
7
# Environment(s): jats
8
#
9
# Description   : Top level Makefile supervisor
10
#                 The function of this program is to call the target makefiles
6133 dpurdie 11
#                 in a suitable manner.
227 dpurdie 12
#
13
# History       : Once upon a time this was done with another makefile and
6133 dpurdie 14
#                 some really ugly shell, embedded within the makefile
227 dpurdie 15
#                 This had a number of limitations, including
16
#                   - Limited to makefile command line syntax
17
#                   - Overly complex makefile
6133 dpurdie 18
#                   - Very slow execution
227 dpurdie 19
#
6133 dpurdie 20
# Usage         : See POD
227 dpurdie 21
#
22
#......................................................................#
23
 
255 dpurdie 24
require 5.006_001;
227 dpurdie 25
use strict;
26
use warnings;
27
 
28
use Pod::Usage;                             # For help support
29
use JatsError;
30
use JatsSystem;
31
use JatsEnv;
32
use JatsMakeInfo;
33
use ReadBuildConfig qw(:All);
34
use Getopt::Long;
35
use FileUtils;
36
use ArrayHashUtils;
37
use JatsDPackage;
38
 
39
my $VERSION = "1.0.0";                      # Update this
40
 
41
#
5708 dpurdie 42
#   Default values
43
#   
5746 dpurdie 44
use constant GBE_MAXMAKE_DEFAULT => '4h';
5708 dpurdie 45
#
227 dpurdie 46
#   Options
47
#
48
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
49
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
50
my $opt_help = 0;
51
my $opt_silent = 1;
52
my $opt_default;
5695 dpurdie 53
my $opt_max_make;
227 dpurdie 54
 
55
#
56
#   Global variables
57
#
58
our %cf_info;
59
our $GBE_TOOLS;                             # Base of tools
60
our $GBE_ABT;                               # Optional ABT indication
61
our $GBE_PLATFORM;                          # Optional GBE_PLATFORM
5695 dpurdie 62
our $GBE_MAXMAKE;                           # Optional GBE_MAXMAKE
227 dpurdie 63
our $ScmInterface;                          # Current interface directory
64
our $ScmRoot;                               # Build root
4003 dpurdie 65
our $ScmNoBuild;                            # Dummy Build and Make
227 dpurdie 66
 
67
my $Tags;                                   # Reference to hash of tags
68
my %defs;                                   # Make definitions
69
my @defs;                                   # Make definitions
70
my @targets;                                # Make targets
71
my $makelib;                                # Path to makelib.pl
72
my $update = 0;                             # Makefiles updated
73
my $build_error = 0;                        # Build Error encountered
74
my $tlen = 4;                               # Max length of targets
75
my %common_cmd;                             # Short circuit some commands
76
my %gbe_platform;                           # Nice form of GBE_PLATFORM
77
 
78
#
79
#   Known commands
4761 dpurdie 80
#   A hash of known commands and information about the commands
81
#       common      - Command operation modifiers
227 dpurdie 82
#                     Flags: 1 - Command not executed for debug+prod
83
#                     Flags: 2 - Command is only executed ONCE per platform
84
#       local       - The command is handled locally.
85
#       nomakecheck - Don't check for makefile being out of date
86
#       IFLAG       - iteration flag,
87
#                       0   No external dependencies.
88
#                       1   Source dependency list.
89
#                       2   Shared library dependency list.
90
#                       3   Application dependency list.
91
#   Note:   gmake attempts to build includes prior to invoking other
92
#   rules when the source is non-existent, which can/do fail as a
93
#   result of the prereq rules not being executed, the IFLAG inhabits
94
#   includes during these prereq rules.
95
#
96
my %composite_commands = (
97
    #
98
    #   Composite commands
99
    #
100
    'lint'                  => [ 'mkdepends', 'generate_debug', 'install_hdr_debug',
101
                                 'lint_lib', 'lint_shlib', 'lint_prog' ] ,
102
    'ctags'                 => [ 'mkdepends', 'generate_debug', 'ctags_debug' ] ,
103
    'test'                  => [ 'make_test' ] ,
104
    'mkdepends'             => [ 'makefiles', 'make_init'] ,
4728 dpurdie 105
    'run_tests'             => [ 'preprocess_tests', 'exec_tests', 
106
                                 'postprocess_tests', 'collate_test_results' ] ,
107
    'run_unit_tests'        => [ 'preprocess_tests', 'exec_unit_tests', 
108
                                 'postprocess_tests', 'collate_test_results' ] ,
5073 dpurdie 109
    # Convenient phases of the build
110
    'hdrs'                  => [ 'mkdepends', 'generate', 'install_hdr'],
111
    'libs'                  => [ 'hdrs', 'depend', 'make_lib', 'install_lib'],
112
    'slibs'                 => [ 'libs', 'make_install_shlib'],
113
    'progs'                 => [ 'slibs', 'make_prog', 'make_test', 'install_prog', 'install_class'],
6387 dpurdie 114
    'build'                 => [ 'progs','install_dirs'],
5073 dpurdie 115
    'install'               => [ 'build' ] ,
116
    'all'                   => [ 'install', 'package', 'deploy' ] ,
227 dpurdie 117
    );
118
 
119
my %commands = (
120
    #
121
    #   Basic commands / phases of the build process
122
    #   This should be a list of all known makefile commands
123
    #
124
    'help'                  => { 'tag' => 0, 'local' => \&DoHelp },
281 dpurdie 125
    'show'                  => { 'tag' => 0, 'local' => \&ShowMakefiles },
227 dpurdie 126
    'rebuild'               => { 'tag' => 0, 'local' => \&TestMakeFiles },
127
    'makefiles'             => { 'tag' => 0, 'local' => \&TestMakeFiles },
128
    'unmakefiles'           => { 'tag' => 0, 'local' => \&UnMakeFiles },
129
    'make_init'             => { 'tag' => 1, 'nomakecheck' => 1, 'common' => 3, },
130
    'generate'              => { 'tag' => 1 },
131
    'install_hdr'           => { 'tag' => 1 },
261 dpurdie 132
    'depend'                => { 'tag' => 1, 'unless' => ['NODEPEND','EXPERT'] },
227 dpurdie 133
    'make_lib'              => { 'tag' => 1, 'IFLAG' => 1 },
261 dpurdie 134
    'make_mlib'             => { 'tag' => 1, 'IFLAG' => 1 },
227 dpurdie 135
    'install_lib'           => { 'tag' => 1, 'IFLAG' => 1 },
136
    'make_install_shlib'    => { 'tag' => 1, 'IFLAG' => 2 },
137
    'make_prog'             => { 'tag' => 1, 'IFLAG' => 3 },
138
    'make_test'             => { 'tag' => 1, 'IFLAG' => 3 },
139
    'install_prog'          => { 'tag' => 1, 'IFLAG' => 3 },
140
    'install_class'         => { 'tag' => 1 },
6387 dpurdie 141
    'install_dirs'          => { 'tag' => 1 },
227 dpurdie 142
    'package'               => { 'tag' => 1, 'IFLAG' => 3 },
143
    'deploy'                => { 'tag' => 1, 'IFLAG' => 1 },
144
 
145
    #
261 dpurdie 146
    #   Special
147
    #   make_dir is directly invoked by jmake. It doesn't need
148
    #   to be a part of a command sequence
149
    #
150
    'make_dir'              => { 'nomakecheck' => 1, 'tag' => 1 },
151
 
152
    #
227 dpurdie 153
    #   Basic commands, that appear to be unused in composite commands
154
    #   Not too sure why
155
    #
156
    'make_script'           => { 'commands' => [], 'tag' => 1 },
157
 
158
    #
159
    #   Lint related targets
160
    #
161
    'lint_lib',             => { 'tag' => 'make_lib'            , 'IFLAG' => 1 },
162
    'lint_shlib',           => { 'tag' => 'make_install_shlib'  , 'IFLAG' => 2 },
163
    'lint_prog'             => { 'tag' => 'make_prog'           , 'IFLAG' => 3 },
164
 
165
    #
4728 dpurdie 166
    #   Unit testing related commands
167
    #
168
    'exec_tests'            => { 'nomakecheck' => 1, 'tag' => 1, 'IFLAG' => 3},
169
    'exec_unit_tests'       => { 'nomakecheck' => 1, 'tag' => 1, 'IFLAG' => 3},
170
    'preprocess_tests'      => { 'nomakecheck' => 1, 'tag' => 'process_tests'},
171
    'postprocess_tests'     => { 'nomakecheck' => 1, 'tag' => 'process_tests'},
4761 dpurdie 172
    'collate_test_results'  => { 'nomakecheck' => 1, 'tag' => 'process_tests', 'common' => 2},
4728 dpurdie 173
 
174
    #
227 dpurdie 175
    #   Following commands should NOT be a part of a composite command
176
    #
177
    'clean'                 => { 'nomakecheck' => 1},
178
    'clobber'               => { 'nomakecheck' => 1},
179
    'rmlitter'              => { 'nomakecheck' => 1},
180
    'unbuild'               => { 'nomakecheck' => 1},
261 dpurdie 181
    'undepend'              => { 'nomakecheck' => 1 , 'tag' => 'depend'},
182
    'ungenerate'            => { 'nomakecheck' => 1 , 'tag' => 'generate'},
227 dpurdie 183
    'uninstall'             => { 'nomakecheck' => 1},
6387 dpurdie 184
    'uninstall_dirs'        => { 'nomakecheck' => 1},
227 dpurdie 185
    'uninstall_class'       => { 'nomakecheck' => 1},
261 dpurdie 186
    'uninstall_hdr'         => { 'nomakecheck' => 1 , 'tag' => 'install_hdr'},
187
    'uninstall_lib'         => { 'nomakecheck' => 1 , 'tag' => 'install_lib'},
188
    'uninstall_prog'        => { 'nomakecheck' => 1 , 'tag' => 'install_prog'},
189
    'unmake_lib'            => { 'nomakecheck' => 1 , 'tag' => 'make_mlib'},
190
    'unmake_mlib'           => { 'nomakecheck' => 1 , 'tag' => 'make_mlib'},
191
    'unmake_prog'           => { 'nomakecheck' => 1 , 'tag' => 'make_prog'},
192
    'unmake_script'         => { 'nomakecheck' => 1 , 'tag' => 'make_script'},
193
    'unmake_test'           => { 'nomakecheck' => 1 , 'tag' => 'make_test'},
227 dpurdie 194
    'unobj'                 => { 'nomakecheck' => 1},
261 dpurdie 195
    'unpackage'             => { 'nomakecheck' => 1 , 'tag' => 'package'},
196
    'unmake_dir'            => { 'nomakecheck' => 1 , 'tag' => 'make_dir'},
227 dpurdie 197
 
198
    );
199
#    DebugDumpData ("Commands", \%commands);
200
 
201
#-------------------------------------------------------------------------------
202
# Function        : Mainline Entry Point
203
#
204
# Description     :
205
#
206
# Inputs          :
207
#
208
 
209
#
210
#   Parse the user options
211
#
212
my $result = GetOptions (
261 dpurdie 213
                "help:+"        => \$opt_help,              # flag, multiple use allowed
214
                "manual:3"      => \$opt_help,              # flag, multiple use allowed
215
                "verbose:+"     => \$opt_verbose,           # flag, multiple use allowed
216
                "d|debug:+"     => \$opt_debug,             # flag, multiple use allowed
227 dpurdie 217
                "default=s"     => \$opt_default,           # string
5695 dpurdie 218
                "maxTime=s"     => \$opt_max_make,          # string
227 dpurdie 219
                );
220
 
221
                #
222
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
223
                #
224
 
225
#
226
#   Process help and manual options
227
#
228
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
261 dpurdie 229
pod2usage(-verbose => 1)  if ( $opt_help == 2 );
230
pod2usage(-verbose => 2)  if ( $opt_help > 2 );
227 dpurdie 231
 
232
#
233
#   Configure the error reporting process now that we have the user options
234
#
235
ErrorConfig( 'name'    => 'Make',
236
             'verbose' => $opt_verbose,
237
             'debug'   => $opt_debug );
238
 
5695 dpurdie 239
# Global information
227 dpurdie 240
#
5695 dpurdie 241
EnvImportOptional ( 'GBE_ABT' );
242
EnvImportOptional ( 'GBE_PLATFORM' );
5708 dpurdie 243
EnvImportOptional ( 'GBE_MAXMAKE', GBE_MAXMAKE_DEFAULT );
5695 dpurdie 244
 
245
#
246
#   Sanity check arguments
247
#
248
$opt_max_make = $GBE_MAXMAKE unless defined $opt_max_make;
249
Error ("Invalid maxTime: $opt_max_make") 
250
    unless ($opt_max_make =~ m~^[0-9]*\.?[0-9]+[smhd]?$~);
251
Warning("Time limit is disabled ") unless $opt_max_make;
5708 dpurdie 252
Verbose("Time limit: $opt_max_make");
5695 dpurdie 253
 
254
#
227 dpurdie 255
#   Configure the 'System' process so that it will terminate on any error
256
#   and not report the complete command line
257
#
258
SystemConfig ( 'ExitOnError' => 2);
259
 
260
#
261
#   Extract non-option commands
262
#   Much of this is for backward compatability
263
#   Support the following arguments
264
#       XXXXX=yyyy      Makefile Definition
265
#       -XXXX           Flags passed to make
266
#       XXXX            Raw target name
267
#
268
foreach my $arg ( @ARGV )
269
{
270
    Verbose2 ("Arg: $arg");
271
    if ( $arg =~ m~(\w+)=(.+)~ ) {
272
        $defs{uc($1)} = $2;
273
 
274
    } elsif ( $arg =~ m/^-/ ) {
275
        push @defs, $arg;
276
 
277
    } else {
278
        push @targets, $arg;
279
 
280
    }
281
}
282
 
283
#
284
#   Misc. Initialisation
285
#
286
InitFileUtils();
287
 
288
EnvImport( 'GBE_TOOLS' );
289
$makelib = "$GBE_TOOLS/makelib.pl";
290
Error ("Cannot locate JATS file: $makelib") unless ( -f $makelib );
291
 
292
#
293
#   Validate user options
294
#
295
@targets = ($opt_default)
296
    if ( $opt_default && ! @targets);
297
Error ("No make targets specified" ) unless ( @targets );
298
 
299
#
300
#   Build the @defs array
301
#   This is a set of definitions passed to the makefiles
302
#   It is created on the fly to allow command line options to modify the definitions
303
#
304
foreach  ( sort keys %defs )
305
{
306
    next if ( m~^DEBUG$~i );                    # Naughty user
307
    push @defs, "$_=$defs{$_}";                 # Makefile defs are XXXX=aaaa
308
}
309
 
310
#
311
#   Look for OPTIONS=*args* and disable the silent make operation
312
#   This will allow the make to output messages
313
#
314
if (( exists $defs{OPTIONS} && $defs{OPTIONS} =~ m/args/ ) || $opt_verbose || $opt_debug )
315
{
316
    $opt_silent = 0;
317
}
318
 
319
#
320
#   Read in the local Makefile.gbe file
321
#   This will provide a path to the interface directory
322
#
323
ReadMakeInfo();
324
 
325
#
326
#   Read in the global build variables
327
#
328
ReadBuildConfig( "$::ScmRoot/$::ScmInterface" );
329
 
330
#
4551 dpurdie 331
#   Process GBE_PLATFORM and create a usable hash
332
#
333
if ( $GBE_PLATFORM )
334
{
335
    Verbose2 ("GBE_PLATFORM: $GBE_PLATFORM");
336
    $gbe_platform{$_} = 1 foreach ( split( / /, $GBE_PLATFORM ) );
337
 
338
    # Insert targets that are GENERIC, there should only be one
339
    foreach my $target (keys %BUILDINFO) {
340
        if ($BUILDINFO{$target}{IS_GENERIC})
341
        {
342
            $gbe_platform{$target} = 1;
343
        }
344
    }
345
}
346
 
347
#
4003 dpurdie 348
#   Process the user specified targets
227 dpurdie 349
#
4003 dpurdie 350
ProcessTargets();
227 dpurdie 351
 
4003 dpurdie 352
#
353
#   All done
354
#
355
exit (0);
356
 
227 dpurdie 357
#-------------------------------------------------------------------------------
4003 dpurdie 358
# Function        : ProcessTargets
227 dpurdie 359
#
4003 dpurdie 360
# Description     : Process the user specified targets
227 dpurdie 361
#
4003 dpurdie 362
# Inputs          :
363
#
364
# Returns         : 
365
#
366
sub ProcessTargets
227 dpurdie 367
{
4003 dpurdie 368
    if($ScmNoBuild)
369
    {
370
            Verbose2 ("Processing Skipped in noBuild");
371
            return;
372
    }
227 dpurdie 373
 
374
    #
4003 dpurdie 375
    #   Determine the max size of the target name
376
    #   Makes a nice display
227 dpurdie 377
    #
4003 dpurdie 378
    foreach ( @BUILDPLATFORMS )
379
    {
380
        my $len = length ($_);
381
        $tlen = $len if ( $len > $tlen );
227 dpurdie 382
    }
383
 
4003 dpurdie 384
    #-------------------------------------------------------------------------------
385
    #   Scan the list of targets and perform 'alias' expansion
386
    #   targets are of the form
387
    #       platform_command_type
388
    #       Where:
389
    #           type        may be _prod or _debug or not present
390
    #           command     may be either a composite command or a simple command
391
    #           platform    may be a platform or an alias
227 dpurdie 392
    #
393
    #
4003 dpurdie 394
    foreach my $arg ( @targets )
227 dpurdie 395
    {
4003 dpurdie 396
        my $suffix = '';
397
        my @commands;
398
        my @platforms;
399
 
400
        #
401
        #   Remove the only available suffix ( _debug | _prod )
402
        #   Also detect commnads of debug or prod
403
        #
404
        if ( $arg =~ m~(.+)_(debug)$~ ) {
405
            $suffix = $2;
406
            $arg = $1;
407
        } elsif ( $arg =~ m~(.+)_(prod)$~ ) {
408
            $suffix = $2;
409
            $arg = $1;
410
        } elsif ( $arg eq 'debug' ) {
411
            $suffix = $arg;
227 dpurdie 412
            $arg = '';
4003 dpurdie 413
        } elsif ( $arg eq 'prod' ) {
414
            $suffix = $arg;
415
            $arg = '';
227 dpurdie 416
        }
4003 dpurdie 417
 
418
        #
419
        #   Remove valid make commands from the remaining argument
420
        #   Have a hash of all known makefile commands
421
        #
422
        foreach my $cmd ( keys %composite_commands, keys %commands )
227 dpurdie 423
        {
4003 dpurdie 424
            if ( $arg eq $cmd )
425
            {
426
                @commands = ExpandComposite($cmd);
427
                $arg = '';
428
            }
429
            elsif ( $arg =~ m~(.+)_($cmd)$~ )
430
            {
431
                $arg = $1;
432
                @commands = ExpandComposite($2);
433
                last;
434
            }
227 dpurdie 435
        }
436
 
4003 dpurdie 437
        #
438
        #   See of we can extract an platform alias from the command
439
        #   Rip into target + command
440
        #
441
        if ( $arg )
227 dpurdie 442
        {
4003 dpurdie 443
            if ( exists $ScmBuildAliases{$arg}  )
227 dpurdie 444
            {
4003 dpurdie 445
                @platforms =  split (/ /, $ScmBuildAliases{$arg} );
227 dpurdie 446
            }
4003 dpurdie 447
            elsif ( exists $ScmBuildPlatforms{$arg} )
448
            {
449
                @platforms = ($arg);
450
            }
227 dpurdie 451
            else
452
            {
4003 dpurdie 453
                if ( @commands )
454
                {
455
                    Error ("Unknown target: $arg");
456
                }
457
                else
458
                {
459
                    Message ("Unknown command. Passed to make: $arg");
460
                    @commands = $arg;
461
                }
227 dpurdie 462
            }
463
        }
464
 
4003 dpurdie 465
        #
466
        #   Insert defaults
467
        #
468
        @platforms = @DEFBUILDPLATFORMS
469
            unless ( @platforms );
470
        @commands = ExpandComposite('all')
471
            unless ( @commands);
227 dpurdie 472
 
4003 dpurdie 473
        #
474
        #   Perform GBE_PLATFORM filtering
475
        #
476
        @platforms = grep ( exists $gbe_platform{$_} , @platforms )
477
            if ( %gbe_platform );
227 dpurdie 478
 
4003 dpurdie 479
        Error ("No platforms to be processed. Check GBE_PLATFORM")
480
            unless ( @platforms );
227 dpurdie 481
 
4003 dpurdie 482
        #
483
        #   Iterate commands over platforms
484
        #
485
        foreach my $cmd ( @commands )
486
        {
487
            PerformCommand (\@platforms, $cmd, $suffix );
488
        }
227 dpurdie 489
    }
490
}
491
 
492
#-------------------------------------------------------------------------------
493
# Function        : PerformCommand
494
#
495
# Description     : Perform the make on a platform command
496
#
497
# Inputs          : $platform_ref   - platforms to process
498
#                   $cmd            - simple make command
499
#                   $suffix         - debug,prod,none
500
#
501
# Returns         : 
502
#
503
sub PerformCommand
504
{
505
    my ($platform_ref, $cmd, $suffix) = @_;
506
    my $do_prod = 1;
507
    my $do_debug = 1;
508
 
509
    #
510
    #   Clean up some ugly commands from lint and ctags
511
    #
512
    if ( $cmd =~ m~(.+)_(debug)$~ )
513
    {
514
        $cmd = $1;
515
        $suffix = $2;
516
    }
517
    Verbose2 ("Processing Target: $cmd, $suffix");
518
 
519
    #
520
    #   Limit command to production or debug
521
    #
522
    if ( $suffix eq 'debug' ) {
523
        $do_prod  = 0;
524
    } elsif ( $suffix eq 'prod' ) {
525
        $do_debug  = 0;
526
    }
527
 
528
    #
529
    #   Some commands can be suppressed by options
261 dpurdie 530
    #   These are an array of options
227 dpurdie 531
    #
532
    if ( exists $commands{$cmd}{'unless'}  )
533
    {
261 dpurdie 534
        foreach my $check ( @{$commands{$cmd}{'unless'}} )
227 dpurdie 535
        {
261 dpurdie 536
            if ( exists $defs{$check} && $defs{$check} )
537
            {
538
                Verbose2 ("Skipping: $cmd because $check");
539
                return;
540
            }
227 dpurdie 541
        }
542
    }
543
 
544
    #
545
    #   Interecpt commands that are handled locally
546
    #
547
    if ( exists $commands{$cmd}{'local'} )
548
    {
549
        $commands{$cmd}{'local'}( $cmd, $platform_ref );
550
        return;
551
    }
552
 
553
    #
554
    #   Process and recurse directory tree
555
    #
556
    Verbose ("Processing: $cmd, @{$platform_ref}");
557
 
558
    #
559
    #   Determine the local tag name and state
560
    #   The tag is used to short circuit makefile commands in recursive makes
561
    #   It greatly reduces the work required
562
    #
563
    #   Many commands have a tag that is the same as the command, but a few don't
564
    #
565
    my $tag = 0;
566
    if ( exists $commands{$cmd}{tag}  )
567
    {
568
        $tag = $commands{$cmd}{tag};
569
        $tag = $cmd if ( $tag eq '1' );
570
    }
571
 
4761 dpurdie 572
    #   Ensure this element is defined
573
    #       Simplifies testing in the remainder of the code
574
    $commands{$cmd}{'common'} = 0 
575
        unless exists($commands{$cmd}{'common'});
576
 
577
    if ( $commands{$cmd}{'common'} & 1 )
227 dpurdie 578
    {
4761 dpurdie 579
        InvokeSubMake( $::Cwd, $platform_ref ,$cmd, $tag, 1, 'C' );
227 dpurdie 580
    }
581
    else
582
    {
4761 dpurdie 583
        InvokeSubMake( $::Cwd, $platform_ref ,$cmd, $tag, 1, 'D' ) if $do_debug;
584
        InvokeSubMake( $::Cwd, $platform_ref ,$cmd, $tag, 0, 'P' ) if $do_prod;
227 dpurdie 585
    }
586
}
587
 
588
#-------------------------------------------------------------------------------
589
# Function        : InvokeSubMake
590
#
591
# Description     : Build recursion
592
#                   Determine if there is anything to be done for the current
593
#                   target within a specified directory
594
#
595
# Inputs          : $dir
596
#                   $pref                   - Ref to an array of platforms
597
#                   $cmd
598
#                   $tag
4761 dpurdie 599
#                   $do_debug               - 0:Production, 1:Debug
600
#                   $text                   - Single Char display text (C, P or D)
227 dpurdie 601
#
602
# Returns         : 
603
#
604
sub InvokeSubMake
605
{
4761 dpurdie 606
    my ( $dir, $pref, $cmd, $tag, $do_debug, $text) = @_;
227 dpurdie 607
 
608
    #
609
    #   Ensure the current directory is known to the Tags database
610
    #
611
    $Tags = ReadMaketags( $dir );
612
    Error ("Directory not in tag database", $dir ) unless ( $Tags );
613
 
614
    #
615
    #   Process commands in the current directory
616
    #   If the command is tagged, then we may be able to skip it
617
    #   Otherwise we need to do it
618
    #
4761 dpurdie 619
    InvokeMake( $dir, $pref, $cmd, $tag, $do_debug, $text );
227 dpurdie 620
 
621
    #
622
    #   Recurse into any subdirectories that may be a part of the build
623
    #
624
    unless ( exists $defs{NORECURSE} && $defs{NORECURSE}  )
625
    {
626
        #
627
        #   Process subdirectories for the current command
628
        #   If the command is tagged, then we may be able to skip it
629
        #   Otherwise we need to do it
630
        #
631
        foreach my $subdir (@{$Tags->{$dir}{subdirs}} )
632
        {
633
 
4761 dpurdie 634
            InvokeSubMake( CleanDirName( "$dir/$subdir"), $pref, $cmd, $tag, $do_debug, $text );
227 dpurdie 635
        }
636
    }
637
}
638
 
639
#-------------------------------------------------------------------------------
640
# Function        : InvokeMake
641
#
642
# Description     : Actually invoke the make for debug and production as required
643
#
644
# Inputs          : $dir
645
#                   $pref
646
#                   $cmd
647
#                   $tag
4761 dpurdie 648
#                   $do_debug               - 0:Production, 1:Debug
649
#                   $text                   - Single Char display text (C, P or D)
227 dpurdie 650
#
651
#
652
# Returns         : 
653
#
654
sub InvokeMake
655
{
4761 dpurdie 656
    my ( $dir, $pref, $cmd, $tag, $do_debug, $text ) = @_;
227 dpurdie 657
 
279 dpurdie 658
    Verbose2 ("InvokeMake: $dir");
227 dpurdie 659
    #
660
    #   Ensure that the current directory actually has makefile targets
661
    #   Not all makefile.pl create .mk files
662
    #       1) Top-level makefile.pl
663
    #       2) Makefiles that use --NoPlatformBuilds
664
    #
665
    if ( $Tags->{$dir}{root} )
666
    {
667
        Verbose2 "Root directory has no makefiles: $dir";
668
        return;
669
    }
670
 
671
    if ( $Tags->{$dir}{noplatforms} )
672
    {
673
        Verbose2 "No make targets in $dir";
674
        return;
675
    }
676
 
677
    #
678
    #   Process each platform
679
    #
680
    foreach my $target ( @{$pref} )
681
    {
682
        unless ( exists $Tags->{$dir}{platforms}{$target} )
683
        {
684
            Verbose2 "No make targets in $dir, for $target";
685
            next;
686
        }
687
 
688
        #
689
        #   Do we need to do any thing for this target / tag
690
        #
691
        if ( $tag )
692
        {
693
            unless ( exists $Tags->{$dir}{full}{$target}{'%MakeTags'}{$tag} )
694
            {
261 dpurdie 695
                Verbose2 ("Skipping $cmd in $dir for $tag");
227 dpurdie 696
                next;
697
            }
698
        }
699
 
700
        #
4761 dpurdie 701
        #   common modifier mask=2, (Bit-1)
702
        #       Only process target ONCE for each platform
703
        #       Don't care when its used
227 dpurdie 704
        #
4761 dpurdie 705
        if ( $commands{$cmd}{'common'} & 2 )
227 dpurdie 706
        {
4761 dpurdie 707
            if ( $common_cmd{$cmd}{$text}{$target} )
227 dpurdie 708
            {
4761 dpurdie 709
                Verbose2 "Already performed $cmd for $target in mode $text";
227 dpurdie 710
                next;
711
            }
4761 dpurdie 712
            $common_cmd{$cmd}{$text}{$target} = 1;
227 dpurdie 713
        }
714
 
715
        #
716
        #   Is the build limited to only debug or production
717
        #
4761 dpurdie 718
        unless ( $commands{$cmd}{'common'} & 1 )
227 dpurdie 719
        {
720
            if ( $do_debug == 0 ) {
5619 dpurdie 721
                unless ( $Tags->{$dir}{platforms}{$target}{prod} )
722
                {
723
                    Verbose("Skip debug build in Production Only build");
724
                    next;
725
                }
227 dpurdie 726
 
727
            } elsif  ( $do_debug == 1 ) {
5619 dpurdie 728
                unless ( $Tags->{$dir}{platforms}{$target}{debug} )
729
                {
730
                    Verbose("Skip prod build in Debug Only build");
731
                    next;
732
                }
227 dpurdie 733
            }
734
        }
735
 
736
        #
737
        #   Final sanity test
738
        #   Must have the makefile. We should have detected this error before now
739
        #
740
        Error ("Makefile not found - $target") unless ( -f "$dir/$target.mk" );
741
 
742
        #
275 dpurdie 743
        #   Export data into the user environment
744
        #   Allows underlying tools to locate data files with little effort
745
        #
746
        $ENV{'GBE_MAKE_TYPE'} = $text;                  # P or D or C
747
        $ENV{'GBE_MAKE_TARGET'} = $target;              # Target platform
748
        $ENV{'GBE_MAKE_CFG'} = $Tags->{$dir}{config};   # Ref to config data
749
        $ENV{'GBE_MAKE_CMD'} = $cmd;                    # Make phase
750
 
751
        #
227 dpurdie 752
        #   Build up the make command line
753
        #   Examine command specfic flags
754
        #
755
        my @args = @defs;
756
        push @args, "IFLAG=$commands{$cmd}{IFLAG}" if ( exists $commands{$cmd}{IFLAG} );
757
 
758
        my $cdir = CleanDirName ($dir);
759
        my @make_command;
5695 dpurdie 760
        push @make_command, "timeout", "-Time:$opt_max_make" if ($opt_max_make); 
227 dpurdie 761
        push @make_command, "$ENV{GBE_BIN}/xmake";
762
        push @make_command, "-s" if $opt_silent;
763
        push @make_command, "--no-print-directory";
764
        push @make_command, "-C", $cdir unless ( $cdir eq $::Cwd );
765
        push @make_command, "-f", "$target.mk";
766
        push @make_command, @args;
767
        push @make_command, 'make_dir' unless exists $commands{$cmd}{nomakecheck} ;
768
        push @make_command, $cmd;
769
 
770
        Message ( sprintf ("[$text] %-${tlen}s, $cmd, $cdir", $target ));
771
        System (@make_command, "DEBUG=$do_debug" );
772
    }
773
}
774
 
775
#-------------------------------------------------------------------------------
776
# Function        : TestMakeFiles
777
#
778
# Description     : Test all the makefile dependent files to see if any of the
779
#                   makefiles need to be rebuilt.
780
#
781
#                   Walk the directory tree looking for makefiles to be
782
#                   rebuilt.
783
#
784
# Inputs          : $cmd            - Current command
785
#                   $pref           - Ref to an array of platforms
786
#
787
# Returns         : 
788
#
789
sub TestMakeFiles
790
{
791
    my ( $cmd, $pref ) = @_;
792
    Verbose ("Test makefile dependencies");
793
 
794
    #
795
    #   Read in the Tag file for the current directory
796
    #   This will provide the current list of subdirectories
797
    #
798
    #   Process Test the current makefiles, then test any subdirs
799
    #
800
    TestSubMake( $cmd, $Cwd, $pref );
801
 
802
    #
803
    #   Report build errors
804
    #   Done after all makefiles have been processed
805
    #
806
    if ( $build_error )
807
    {
808
        Error ("Error creating makefiles. Errors previously reported");
809
    }
810
 
811
    #
812
    #   Post makefile build processing
813
    #   Only required if a files have been re-built
814
    #
815
    if ( $update )
816
    {
817
        #
818
        #   Sanity test the makefile structure
819
        #   Ensure that makefiles have only one parent.
820
        #
821
        TestParents();
822
 
823
        #
824
        #   Sanity test the installed and packaged files
825
        #   Generate warnings and errors if a file if packaged from two
826
        #   locations
827
        #
828
        TestPackages();
829
    }
830
 
831
    #
832
    #
833
    #   Check that the build.pl file is not newer that the tags file
834
    #   This will not be an error, but it will be a nagging warning
835
    #
836
    my @build_warn;
837
    my $bstamp = -M "$::ScmRoot/$ScmBuildSrc";
838
    my $tstamp = -M "$::ScmRoot/Makefile.gbe";
839
 
840
    push @build_warn, "Missing: Makefile.gbe" unless ( defined $tstamp );
841
    push @build_warn, "Modified build file ($ScmBuildSrc)" if ( $tstamp && $bstamp < $tstamp );
842
    if ( @build_warn )
843
    {
844
        Warning ("The build file is newer than the generated files",
845
                 "The project needs to be built for these changes to be included",
846
                 @build_warn );
847
    }
848
}
849
 
850
#-------------------------------------------------------------------------------
851
# Function        : TestSubMake
852
#
853
# Description     : Test the makefiles in the current directory
854
#                   Recurse into subdirectories
855
#
856
# Inputs          : $cmd            - Current command
857
#                   $dir            - Directory to test
858
#                   $pref           - Ref to an array of platforms
859
#
860
# Returns         : 
861
#
862
sub TestSubMake
863
{
864
    my ($cmd, $dir, $pref ) = @_;
865
 
866
    $Tags = ReadMaketags( $dir, 1 );
867
    unless ( $Tags )
868
    {
869
        Verbose2 ("TestSubMake :Directory not in tag database", $dir );
870
        MakeBuild( $dir);
871
    }
872
    else
873
    {
874
        TestMake( $cmd, $dir, $pref );
875
    }
876
 
877
    #
878
    #   Recurse into any subdirectories that may be a part of the build
879
    #
880
    unless ( exists $defs{NORECURSE} && $defs{NORECURSE}  )
881
    {
882
        foreach my $subdir (@{$Tags->{$dir}{subdirs}} )
883
        {
884
            TestSubMake( $cmd, CleanDirName( "$dir/$subdir"), $pref );
885
        }
886
    }
887
}
888
 
889
#-------------------------------------------------------------------------------
281 dpurdie 890
# Function        : ShowMakefiles
891
#
892
# Description     : Show the makefiles used in the build
893
#
894
# Inputs          : $cmd            - Current command
895
#                   $pref           - Ref to an array of platforms
896
#
897
# Returns         : 
898
#
899
sub ShowMakefiles
900
{
901
    my ( $cmd, $pref ) = @_;
902
    Verbose ("Show makefiles");
363 dpurdie 903
    ShowTargetsAlaises();
281 dpurdie 904
 
905
    #
906
    #   Read in the Tag file for the current directory
907
    #   This will provide the current list of subdirectories
908
    #
909
    #   Process Test the current makefiles, then any subdirs
910
    #
911
    ShowSubMake( $cmd, $Cwd, $pref, 0 );
912
}
913
 
914
#-------------------------------------------------------------------------------
915
# Function        : ShowSubMake
916
#
917
# Description     : Test the makefiles in the current directory
918
#                   Recurse into subdirectories
919
#
920
# Inputs          : $cmd            - Current command
921
#                   $dir            - Directory to test
922
#                   $pref           - Ref to an array of platforms
923
#                   $level          - Recursion depth
924
#
925
# Returns         : 
926
#
927
sub ShowSubMake
928
{
929
    my ($cmd, $dir, $pref, $level ) = @_;
930
 
931
    $Tags = ReadMaketags( $dir, 1 );
932
    unless ( $Tags )
933
    {
934
        Verbose2 ("ShowSubMake :Directory not in tag database", $dir );
935
        MakeBuild( $dir);
936
    }
937
    elsif ( $level )
938
    {
939
        print ("Makefile : " . ' ' x (4 * ($level - 1) ) . DisplayPath(RelPath($dir)) ,"\n");
940
    } else {
941
        print ("\nBuildfile: ", DisplayPath($dir), "\n" );
942
    }
943
 
944
    #
945
    #   Recurse into any subdirectories that may be a part of the build
946
    #
947
    foreach my $subdir (@{$Tags->{$dir}{subdirs}} )
948
    {
949
        ShowSubMake( $cmd, CleanDirName( "$dir/$subdir"), $pref, $level + 1 );
950
    }
951
}
952
 
953
#-------------------------------------------------------------------------------
227 dpurdie 954
# Function        : TestMake
955
#
956
# Description     : Test the makefiles component files
957
#                   and determine if the makefile(s) need to be rebuilt
958
#
959
# Inputs          : $cmd            - Current command
960
#                   $dir            - Directory to test
961
#                   $pref           - Ref to an array of platforms
962
#
963
# Returns         : 
964
#
965
sub TestMake
966
{
967
    my ( $cmd, $dir, $pref ) = @_;
968
    my @must_rebuild;
969
 
970
    if ( $cmd eq 'rebuild' )
971
    {
972
        MakeBuild( $dir);
973
        return;
974
    }
975
 
976
    #
977
    #   Check that the local makefile.pl is not newer than
978
    #   the Tags file. Not all makefile.pl's create .mk files
979
    #
980
    my $mstamp = -M "$dir/makefile.pl";
981
    my $tstamp = -M "$dir/Makefile.gbe";
982
 
983
    unless ( defined $tstamp )
984
    {
985
        UniquePush (\@must_rebuild, "Missing: $dir/Makefile.gbe");
986
    }
987
 
988
    if ( $mstamp && $mstamp < $tstamp  )
989
    {
990
        UniquePush (\@must_rebuild, "Updated: $dir/makefile.pl");
991
    }
992
    else
993
    {
994
        if ( $Tags->{$dir}{root} )
995
        {
996
            Verbose2 "TestMake: Root directory has no makefiles: $dir";
997
            return;
998
        }
999
 
1000
        if ( $Tags->{$dir}{noplatforms} )
1001
        {
1002
            Verbose2 "TestMake: No make targets in $dir";
1003
            return;
1004
        }
1005
 
1006
        #
1007
        #   Process only the required build targets
1008
        #
1009
        foreach my $tgt ( keys %{$Tags->{$dir}{platforms}}   )
1010
        {
285 dpurdie 1011
            next if ( %gbe_platform && ! exists $gbe_platform{$tgt} );
227 dpurdie 1012
            #
1013
            #   Locate all the makefile dependent files
1014
            #
1015
            my $data = $Tags->{$dir}{full}{$tgt}{'@ScmDepends'};
1016
            if ( $data )
1017
            {
1018
                Verbose2 ("Processing: $dir : $tgt");
1019
                my $base_stamp = -M "$dir/$tgt.mk";
1020
                unless ( defined $base_stamp )
1021
                {
1022
                    UniquePush (\@must_rebuild, "Missing: $dir/$tgt.mk");
1023
                }
1024
                else
1025
                {
1026
                    foreach my $file ( "$dir/makefile.pl" ,@$data )
1027
                    {
325 dpurdie 1028
                        $file = FullPath ( $file, $dir );
227 dpurdie 1029
                        my $stamp = -M $file;
1030
                        if ( defined $stamp )
1031
                        {
1032
                            Verbose3 ("Timestamp: $stamp, $file");
1033
                            if ( $stamp < $base_stamp  )
1034
                            {
1035
                                UniquePush (\@must_rebuild, $file);
1036
                            }
1037
                        }
1038
                        else
1039
                        {
1040
                            UniquePush (\@must_rebuild, "Missing: $file");
1041
                        }
1042
                    }
1043
                }
1044
            }
1045
            else
1046
            {
1047
                Warning ("No dependency information for: $tgt in $dir");
1048
            }
1049
        }
1050
    }
1051
 
1052
    if ( @must_rebuild )
1053
    {
1054
        my @display;
1055
        push (@display, CleanDirName($_) ) foreach ( @must_rebuild );
1056
        Message ("One or more JATS source or internal files have changed, Makefiles will be rebuilt",
1057
                  "Target is: $dir",
1058
                  @display );
1059
        MakeBuild ($dir);
1060
    }
1061
    return;
1062
}
1063
 
1064
#-------------------------------------------------------------------------------
1065
# Function        : MakeBuild
1066
#
1067
# Description     : Rebuild the makefiles in the specified directory
1068
#                   This does not involve recursion - thats already been
1069
#                   done.
1070
#
1071
#                   Once the makefiles have been re-built the tags database
1072
#                   must be read in again as it may have changed.
1073
#
1074
# Inputs          : 
1075
#
1076
# Returns         : 
1077
#
1078
sub MakeBuild
1079
{
1080
    my ($dir) = @_;
1081
 
1082
    #
1083
    #   No makefiles to build in the root directory
1084
    #   Can't rebuild the top-level Makefile.gbe file
1085
    #
1086
    return if ( $Tags->{$dir}{root} );
1087
 
1088
    #
1089
    #   Try to rebuild the makefile
1090
    #
1091
    chdir $dir || Error ("Cannot change directory to $dir");
261 dpurdie 1092
    my $result = System ('--NoExit', $ENV{GBE_PERL}, 'makefile.pl',
1093
                            $::ScmRoot, $makelib, "--interface=$::ScmInterface" );
227 dpurdie 1094
    chdir $::Cwd || Error ("Cannot change directory to $::Cwd");
1095
 
1096
    #
1097
    #   Re-read the tags database
1098
    #
1099
    $Tags = ReadMaketags( $dir, 2 );
1100
 
1101
    #
1102
    #   Flag that makefiles have been modified
1103
    #
1104
    $update = 1;
261 dpurdie 1105
    $build_error = 1 if ( $result );
227 dpurdie 1106
}
1107
 
1108
#-------------------------------------------------------------------------------
1109
# Function        : UnMakeFiles
1110
#
1111
# Description     : Delete generated makefiles and control files
1112
#
1113
# Inputs          : $cmd            - Current command
1114
#                   $pref           - Ref to an array of platforms
1115
#
1116
# Returns         : 
1117
#
1118
sub UnMakeFiles
1119
{
1120
    #
1121
    #   Recurse down the tree
1122
    #   Recurse, then performs operations in the current directory
1123
    #
1124
    sub UnSubMakeFiles
1125
    {
1126
        my ($dir) = @_;
1127
        $Tags = ReadMaketags( $dir, 1 );
1128
        foreach my $subdir (@{$Tags->{$dir}{subdirs}} )
1129
        {
1130
            UnSubMakeFiles( CleanDirName( "$dir/$subdir") );
1131
        }
1132
        UnMake( $dir );
1133
    }
1134
 
1135
    #
1136
    #   Delete makefiles in the current directory
1137
    #
1138
    sub UnMake
1139
    {
1140
        my ($dir) = @_;
1141
        Verbose("Unmake in $dir");
1142
        foreach my $tgt ( keys %{$Tags->{$dir}{platforms}}   )
1143
        {
1144
            Verbose2("Unmake. Delete ${tgt}.mk");
1145
            unlink ("$dir/${tgt}.mk");
1146
        }
1147
        unlink ("$dir/Makefile.gbe");
1148
        Verbose2("Unmake. Delete Makefile.gbe");
1149
    }
1150
 
1151
    #
1152
    #   Depth first recursion through the tree
1153
    #
1154
    UnSubMakeFiles ( $Cwd );
1155
}
1156
 
1157
#-------------------------------------------------------------------------------
1158
# Function        : TestParents
1159
#
1160
# Description     : Ensure that each makefile node has exactly one parent
1161
#                   Prevent the user from creating recursive loops
1162
#
1163
# Inputs          : 
1164
#
1165
# Returns         : 
1166
#
1167
my %parents;
1168
sub TestParents
1169
{
1170
    Verbose ("Test makefile parents");
1171
    #
1172
    #   Init the hash. Command may be invoked multiple times
1173
    #
1174
    %parents = ();
1175
 
1176
    #
1177
    #   Recurse down the tree
1178
    #   Recurse, then performs operations in the current directory
1179
    #
1180
    sub RecurseDown
1181
    {
1182
        my ($dir) = @_;
1183
        $Tags = ReadMaketags( $dir, 1 );
1184
        Verbose2("TestParents in $dir");
1185
        foreach my $subdir (@{$Tags->{$dir}{subdirs}} )
1186
        {
1187
            my $subdir = CleanDirName( "$dir/$subdir");
1188
            push @{$parents{$subdir}}, $dir;
1189
            RecurseDown( $subdir );
1190
        }
1191
    }
1192
 
1193
    #
1194
    #   Depth first recursion through the tree
1195
    #
1196
    RecurseDown ( $Cwd );
1197
 
1198
    #
1199
    #   Test for only one parent
1200
    #   The root makefile won't have any
1201
    #
1202
    foreach my $dir ( sort keys %{$Tags} )
1203
    {
1204
        my $count = $#{$parents{$dir}};
1205
        if ( $count > 0 )
1206
        {
1207
            if ( defined($GBE_ABT) )
1208
            {
1209
                Warning ("Error supressed by ABT");
1210
                Warning ("makefile.pl with multiple parents",
1211
                         "makefile.pl in: $dir",
1212
                         "Parented by:", @{$parents{$dir}} );
1213
            }
1214
            else
1215
            {
1216
                unlink $Tags->{$dir}{config};
1217
                Error ("makefile.pl with multiple parents",
1218
                       "makefile.pl in: $dir",
1219
                       "Parented by:", @{$parents{$dir}} );
1220
            }
1221
        }
1222
    }
1223
}
1224
 
1225
#-------------------------------------------------------------------------------
1226
# Function        : TestPackages
1227
#
1228
# Description     : Ensure that files that are packaged and installed are
1229
#                   only done from one makefile. Warn if the same file
1230
#                   is being packaged from multiple makefiles.
1231
#
1232
# Inputs          : 
1233
#
1234
# Returns         : 
1235
#
1236
my %test_packages;
1237
sub TestPackages
1238
{
1239
    Verbose ("Test packaged files");
1240
    #
1241
    #   Init the hash. Command may be invoked multiple times
1242
    #
1243
    %test_packages = ();
1244
 
1245
    #
1246
    #   Recurse down the tree
1247
    #   Recurse, then performs operations in the current directory
1248
    #
1249
    sub TRecurseDown
1250
    {
1251
        my ($dir) = @_;
1252
        Verbose2("TestPackages in $dir");
1253
        $Tags = ReadMaketags( $dir, 1 );
1254
        #
1255
        #   Process makefile
1256
        #   Examine all the %PACKAGE_xxx and %INSTALL_xxx fields thare listed
1257
        #   in the @PACKAGE_VARS and @INSTALL_VARS array
1258
        #
1259
        foreach my $target ( keys %{$Tags->{$dir}{platforms}}   )
1260
        {
285 dpurdie 1261
            next if ( %gbe_platform && ! exists $gbe_platform{$target} );
227 dpurdie 1262
            foreach my $field ( @{$Tags->{$dir}{full}{$target}{'@PACKAGE_VARS'}},
1263
                                @{$Tags->{$dir}{full}{$target}{'@INSTALL_VARS'}} )
1264
            {
1265
                foreach my $entry ( keys %{$Tags->{$dir}{full}{$target}{$field}} )
1266
                {
1267
                    Verbose3("TestPackages: $target, File: $entry");
1268
                    push @{$test_packages{$target}{$entry}}, $dir;
1269
                }
1270
            }
1271
        }
1272
 
1273
        #
1274
        #   Process subdirectories too
1275
        #
1276
        foreach my $subdir (@{$Tags->{$dir}{subdirs}} )
1277
        {
1278
            TRecurseDown( CleanDirName( "$dir/$subdir") );
1279
        }
1280
    }
1281
 
1282
 
1283
 
1284
    #
1285
    #   Depth first recursion through the tree
1286
    #
1287
    TRecurseDown ( $Cwd );
1288
 
1289
    #
1290
    #   Test and report files that are packaged in different makefiles
1291
    #   There are two issues:
1292
    #       1) Not good practice
1293
    #       2) May be different files
1294
    #   The warning message is a bit ugly - but it shouldn't pop up often.
1295
    #
1296
#    DebugDumpData ("test_packages", \%test_packages);
1297
 
1298
    foreach my $target ( sort keys %test_packages )
1299
    {
1300
        foreach my $file ( sort keys %{$test_packages{$target}} )
1301
        {
1302
            #
1303
            #   The descpkg file is known to be packaged from multiple dirs
1304
            #
1305
            next if ( $file =~ m~/descpkg~ );
1306
            if ( $#{$test_packages{$target}{$file}} > 0 )
1307
            {
1308
                Warning ("File is packaged or installed from multiple makefiles",
1309
                         "Target: $target, Packaged file: $file",
1310
                         "Packaged from the following directories:", @{$test_packages{$target}{$file}} );
1311
            }
1312
        }
1313
    }
1314
}
1315
 
1316
 
1317
#-------------------------------------------------------------------------------
1318
# Function        : DoHelp
1319
#
1320
# Description     : Display basic help information
1321
#
1322
# Inputs          : None
1323
#
1324
# Returns         :
1325
#
1326
sub DoHelp
1327
{
1328
 
1329
#
1330
#   Display basic usage information
1331
#
1332
    pod2usage(-verbose => 0,
1333
              -message => "Version: $VERSION",
1334
              -exitval => 'NOEXIT');
1335
 
363 dpurdie 1336
    ShowTargetsAlaises();
1337
}
1338
 
1339
#-------------------------------------------------------------------------------
1340
# Function        : ShowTargetsAlaises
1341
#
1342
# Description     : Display make targets and aliases
1343
#                   Used by 'show' and 'help'
1344
#
1345
# Inputs          : None
1346
#
1347
# Returns         : Nothing
1348
#                   Output via 'print'
1349
#
1350
sub ShowTargetsAlaises
1351
{
1352
    my @targets = sort keys %BUILDINFO;
1353
    my @alias = sort keys %ScmBuildAliases;
1354
 
1355
    #
1356
    #   Determine the max length of target or alias
1357
    #   Used to make pretty display
1358
    #
1359
    my $flen = 6;
1360
    foreach ( @alias, @targets )
227 dpurdie 1361
    {
363 dpurdie 1362
        my $len = length $_;
1363
        $flen = $len if ( $len > $flen );
1364
    }
1365
 
1366
    print "\nActive Platform targets\n";
1367
    foreach (@targets)
1368
    {
227 dpurdie 1369
        print "    $_\n";
1370
    }
1371
 
1372
    if ( $#alias >=0 )
1373
    {
363 dpurdie 1374
        print "\nAlias targets\n";
1375
 
1376
        #   Display aliases
1377
        #   Indent list by 4 spaces
1378
        #
227 dpurdie 1379
        foreach ( @alias )
1380
        {
363 dpurdie 1381
            print PrintList("    $_",4+$flen, split(' ', $ScmBuildAliases{$_}));
227 dpurdie 1382
        }
1383
    }
1384
}
1385
 
1386
#-------------------------------------------------------------------------------
363 dpurdie 1387
# Function        : PrintList
1388
#
6276 dpurdie 1389
# Description     : Pretty format an array to fit within 100 char line
363 dpurdie 1390
#                   Perform wrapping as required
1391
#
1392
# Inputs          : $title          - Title string
1393
#                   $len            - Desired length of title area
1394
#                   @list           - An array of items to print
1395
#
1396
# Returns         : string
1397
#
1398
sub PrintList
1399
{
1400
    my ($title, $llen, @list) = @_;
1401
    my $string = sprintf ("%-${llen}s :", $title);
1402
 
1403
    my $nlen = length($string);
1404
    my $nl = "\n" . (' ' x  $nlen );
1405
    $llen = $nlen;
1406
 
1407
    for my $k (sort @list)
1408
    {
1409
        my $klen = length($k);
6276 dpurdie 1410
        if ($llen + $klen >= 100 )
363 dpurdie 1411
        {
1412
            $string .= $nl;
1413
            $llen = $nlen;
1414
        }
1415
        $string .= ' ' .  $k;
1416
        $llen += $klen + 1;
1417
    }
1418
    return $string . "\n";
1419
}
1420
 
1421
#-------------------------------------------------------------------------------
227 dpurdie 1422
# Function        : ReadMaketags
1423
#
1424
# Description     : Read in the global make tags data base
1425
#                   This contains information on all the components within
1426
#                   the build. The tags allow recursive makes to be pruned.
1427
#
1428
#                   The file may change while the build is running
1429
#                   It can be read multiple times
1430
#
1431
# Inputs          : $dir            - Directory entry to read
321 dpurdie 1432
#                   $test           - 0: Read. Error if not available (default)
1433
#                                     1: Read if available
227 dpurdie 1434
#                                     2: Force read
1435
#
1436
# Returns         : Reference to the tag data for the requested directory
1437
#                   Will error if no available
1438
#
1439
our %cf_minfo;
1440
our %cf_minfo2;
1441
my %tag_data;
1442
sub ReadMaketags
1443
{
1444
    my ($dir, $test) = @_;
321 dpurdie 1445
    $test ||= 0;
227 dpurdie 1446
 
1447
    #
1448
    #   Force data re-aquisition
1449
    #
1450
    delete $tag_data{$dir}
321 dpurdie 1451
        if ( $test == 2 );
227 dpurdie 1452
 
1453
    #
1454
    #   Do we already have the entry
1455
    #
1456
    return \%tag_data
1457
        if ( exists ($tag_data{$dir} ));
1458
 
1459
    #
1460
    #   If the entry is not known, then re-read the index file
1461
    #
321 dpurdie 1462
#DebugDumpData ("ReadMaketags", \%::cf_filelist);
227 dpurdie 1463
    unless ( $::cf_filelist{$dir} )
1464
    {
1465
        my $index_file = "$::ScmRoot/$::ScmInterface/Makefile.cfg";
1466
        Error ("Makefile index missing. Rebuild required") unless ( -f $index_file );
1467
 
1468
        #
1469
        #   Kill the entry in %INC to force the file to be read in
1470
        #
1471
        $::cf_filelist = ();
1472
        delete $INC{ $index_file };
1473
        require $index_file;
1474
    }
1475
 
1476
    my $cfg_filen = $::cf_filelist{$dir};
1477
    unless ( $cfg_filen )
1478
    {
285 dpurdie 1479
        return if ( $test );
227 dpurdie 1480
        Error ("Makefile index entry missing: $dir. Rebuild required");
1481
    }
1482
 
1483
 
1484
    #
1485
    #   Read in all the Makefile_x.cfg files
1486
    #
1487
    %cf_minfo = ();
1488
    %cf_minfo2 = ();
1489
    my $cfg_file = "$::ScmRoot/$::ScmInterface/$cfg_filen";
1490
 
1491
    unless ( -f $cfg_file )
1492
    {
285 dpurdie 1493
        return if ( $test );
227 dpurdie 1494
        Error ("Make data file missing: $cfg_file. Rebuild required");
1495
    }
1496
 
1497
    delete $INC{ $cfg_file };
1498
    require $cfg_file;
1499
 
1500
    Error ("Makefile info2 not present")
1501
        unless ( keys %::cf_info2 );
1502
 
1503
    Error ("Makefile info2 incorrect version. Rebuild required")
285 dpurdie 1504
        unless ( exists $::cf_info2{version} && $::cf_info2{version} == 1 );
227 dpurdie 1505
 
1506
    %{$tag_data{$dir}} = %::cf_info2;
1507
    $tag_data{$dir}{config} = $cfg_file;
1508
    %{$tag_data{$dir}{full}} = %::cf_info;
1509
 
1510
#DebugDumpData ("ReadMaketags", $tag_data{$dir});
1511
    return \%tag_data;
1512
 
1513
}
1514
 
1515
#-------------------------------------------------------------------------------
1516
# Function        : ExpandComposite
1517
#
1518
# Description     : Expand a command via composite command expansion
1519
#                   A composite command may contain other composite commands
261 dpurdie 1520
#                   Detect, as an error, recursive expansions
227 dpurdie 1521
#
1522
# Inputs          : $cmd    - command to expand
1523
#
1524
# Returns         : An array of commands
1525
#
1526
sub ExpandComposite
1527
{
285 dpurdie 1528
    my @scmds = $_[0];
227 dpurdie 1529
    my @cmds;
261 dpurdie 1530
    my %seen;
227 dpurdie 1531
    while ( @scmds )
1532
    {
1533
        my $cmd = shift @scmds;
1534
        if ( exists $composite_commands{$cmd} )
1535
        {
261 dpurdie 1536
 
1537
            Error ("Internal. Recursion in composite command definitions: $cmd")
1538
                if ($seen{$cmd});
1539
 
227 dpurdie 1540
            @scmds = (@{$composite_commands{$cmd}}, @scmds);
261 dpurdie 1541
            $seen{$cmd} = 1;
227 dpurdie 1542
        }
1543
        else
1544
        {
1545
            push @cmds, $cmd;
1546
        }
1547
    }
1548
 
1549
    return @cmds;
1550
}
1551
 
1552
#-------------------------------------------------------------------------------
1553
#   Documentation
1554
#
1555
 
1556
=pod
1557
 
361 dpurdie 1558
=for htmltoc    JATS::make
1559
 
227 dpurdie 1560
=head1 NAME
1561
 
1562
jmake - JATS make support tool
1563
 
1564
=head1 SYNOPSIS
1565
 
1566
 Usage: jats make [options][targets][flags]
1567
 
1568
 Where options:
1569
    -h, -h -h, -man     - Help messages with increasing verbosity
1570
    -verbose            - Verbose operation
1571
    -debug              - Debug operation
1572
    -default=target     - Default 'target' if none is supplied
5695 dpurdie 1573
    -maxTime=duration   - Maximum allowed duration of any make command
367 dpurdie 1574
    -- make options     - [Advanced] Options passed directly to make
227 dpurdie 1575
 
1576
 Where flags are of the form Name=Value
1577
    SHOWENV=1           - Show make environment
1578
    LEAVETMP=1          - Leave temp working files
1579
    NODEPEND=1          - Ignore dependency checking
261 dpurdie 1580
    EXPERT=1            - Ignore dependency on makefiles
4782 dpurdie 1581
    UTF_POSTPROCESS=1   - Enable Unit Test Post Processing
227 dpurdie 1582
    OPTIONS=[opt]       - Maketime options [args,allargs,filter...]
1583
 
1584
 Valid targets include:
1585
    all                 - build and install everything(p*)
1586
    build               - build everything (pu)
1587
    debug               - build all things for debug (pu)
1588
    prod                - build all things for production (pu)
1589
    install             - install public components (pu*)
5073 dpurdie 1590
    ctags               - Generate ctags over the source (assumes debug)(p)
227 dpurdie 1591
    lint                - lints the source (assumes debug)(p)
1592
    package             - build all packages (pu*)
361 dpurdie 1593
    package-[set]       - build specific package (see below) (pu*)
227 dpurdie 1594
    run_tests           - Run the tests specified in the makefile
1595
    run_unit_tests      - Run the automatic unit tests specified in the makefile
1596
    deploy              - Run the deployment scripts (p*)
1597
    rebuild             - recursively rebuild makefiles
367 dpurdie 1598
    makefiles           - recursively rebuild makefiles, if needed (u)
227 dpurdie 1599
    depend              - construct the dependencies (u*)
1600
    rmlitter            - remove build litter (core, tmp and err) (*)
1601
    clean               - delete generate, obj, libraries and programs (p*)
1602
    clobber             - delete everything which can be remade (p*)
281 dpurdie 1603
    help                - A list of platforms and aliases
1604
    show                - A list of platforms, alias, and makefile paths
5073 dpurdie 1605
 Partial Builds
1606
    hdrs                - build to the headers phase (p*)
1607
    libs                - build to the static library stage (p*)
1608
    slibs               - build to the shared librray stage (p*)
1609
    progs               - build to the progs stage (p*)
227 dpurdie 1610
 
1611
      (u) undo target available (ie uninstall)
1612
      (p) optional [platform_] prefix targets (ie XXX_build)
1613
      (*) optional [_debug|_prod] postfix targets (ie clean_debug)
1614
 
1615
=head1 OPTIONS
1616
 
1617
=over 8
1618
 
1619
=item B<-help>
1620
 
1621
Print a brief help message and exits.
1622
 
1623
=item B<-help -help>
1624
 
1625
Print a detailed help message with an explanation for each option.
1626
 
1627
=item B<-man>
1628
 
1629
Prints the manual page and exits.
1630
 
1631
=item B<-verbose>
1632
 
1633
Increase the level of verbosity of the program execution
1634
 
1635
=item B<-debug>
1636
 
1637
Increase the debug output during program execution
1638
 
1639
=item B<-default=target>
1640
 
1641
This options specifies the default target if none is provided on the command
1642
line. Used by the jats wrapper to simplify processing.
1643
 
5695 dpurdie 1644
=item B<-maxTime=duration>
1645
 
1646
This option specifies the maximum allowed duration of any make sub command.
1647
 
1648
Some commands are composed of several subcommands, as are the production and 
1649
debug variants. The time lime is imposed on a sub commands and not the total
1650
collection of commands. The intent of the time limit is to prevent stalled builds 
1651
from hijacking the build process.
1652
 
5859 dpurdie 1653
The default value will be taken from the EnvVar L<GBE_MAXMAKE>, if present, or 4 hours
5695 dpurdie 1654
if the EnvVar is not present. A value of 0 (zero) will disable this feature.
1655
 
1656
The duration is specified as a positive floating point number with an optional
1657
modifing character. Valid modifiers are:
1658
 
1659
=over 4
1660
 
1661
=item   
1662
 
1663
B<s> - Seconds (default)
1664
 
1665
=item   
1666
 
1667
B<m> - Minutes
1668
 
1669
=item   
1670
 
1671
B<h> - hours
1672
 
1673
=item   
1674
 
1675
B<d> - Days
1676
 
1677
=back
1678
 
1679
Example: C<-MaxTime=5.h>. Will set a Maximum make time of 30 minutes.
1680
 
335 dpurdie 1681
=item B<-- Make Options>
1682
 
1683
Command line arguments that follow a '--' are passed directly to the GNU make
1684
program. This may be useful for advanced debugging of makefiles. These options
1685
include:
1686
 
1687
=over 8
1688
 
361 dpurdie 1689
=item
335 dpurdie 1690
 
361 dpurdie 1691
B<-h>     - Display Make's own help
335 dpurdie 1692
 
361 dpurdie 1693
=item
335 dpurdie 1694
 
361 dpurdie 1695
B<-d>     - Display diagnostic information
335 dpurdie 1696
 
361 dpurdie 1697
=item
1698
 
1699
B<-p>     - Print make's internal database.
1700
 
1701
=item
1702
 
1703
B<-k>     - Keep going when some targets can't be made.
1704
 
227 dpurdie 1705
=back
1706
 
335 dpurdie 1707
=back
1708
 
261 dpurdie 1709
=head1 TARGETS
227 dpurdie 1710
 
261 dpurdie 1711
Targets are described above.
1712
 
1713
Most targets support three modifiers. These can be used in conjunction with each
1714
other.
1715
 
227 dpurdie 1716
=over 8
1717
 
261 dpurdie 1718
=item undo
1719
 
1720
Many target operation can be undone by prefixing the tarhet with 'un' ie:
1721
uninstall.
1722
 
1723
=item platform prefix
1724
 
1725
Many target operations can be limited to one platform by prefixing the target
1726
with a valid platform name and an underscore. ie WIN32_all
1727
 
1728
=item build postfix. prod or debug
1729
 
1730
Many targets operations can be limited toi either production of debug by
1731
adding '_prod' or '_debug' to the target. ie 'install_debug'
1732
 
1733
=back
1734
 
5073 dpurdie 1735
=head1 PARTIAL BUILDS
1736
 
1737
Partial build targets allow the build process to be partialy completed. This may be of use during development.
1738
 
1739
The partial build phases are:
1740
 
1741
=over 4
1742
 
1743
=item hdrs
1744
 
1745
Generate header files. Install header files locally.
1746
 
1747
=item libs
1748
 
1749
Previous step plus build static libraries, merge static librarys and install static libraries locally.
1750
 
1751
=item slib
1752
 
1753
Previous step plus build shared libraries and install shared libraries.
1754
 
1755
=item progs
1756
 
1757
Previous step plus build programs and install programs (including test programs). This step is the same as 'build'.
1758
 
1759
=back
1760
 
261 dpurdie 1761
=head1 FLAGS
1762
 
227 dpurdie 1763
Flags are in the form TAG=value. This is a format that it used as they will be
1764
passed directly to the underlying makefiles. The recognised flags are:
1765
 
261 dpurdie 1766
=over 8
1767
 
227 dpurdie 1768
=item B<SHOWENV=1>
1769
 
1770
This flag will force the 'Environment' to be displayed before commands are executed
1771
 
1772
=item B<LEAVETMP=1>
1773
 
1774
This flag will cause temp files, created by the build process, to notr be deleted.
1775
 
1776
=item B<NODEPEND=1>
1777
 
1778
This flag will supress dependency checking. Makefiles will not be created when
1779
the makefile.pl is changed. Source files will not be scanned for header files.
1780
 
261 dpurdie 1781
=item B<EXPERT=1>
1782
 
1783
This flag will supress dependency checking between object files and the
1784
generated makefile. This option can be used while test building a large build
1785
when the makefile has been rebuilt but the user does not wish all the object
1786
files to be rebuilt.
1787
 
4782 dpurdie 1788
=item B<UTF_POSTPROCESS=1>
1789
 
1790
This flag will enable post processing of test results.
1791
 
1792
Post processing allows the details of the test results to be captured by the build system.
1793
 
1794
Post processing is normally only performed within the automated build environment. This flag 
1795
will force the processing within a user development environment.
1796
 
1797
UTF_POSTPROCESS=1   - Enable Unit Test Post Processing
1798
 
227 dpurdie 1799
=item B<OPTIONS=list,list>
1800
 
1801
This flags passes a list of comma seperated options into the makefile. The exact
1802
set of available options is target specific. Refer to the JATS manual.
1803
 
361 dpurdie 1804
=back
227 dpurdie 1805
 
361 dpurdie 1806
=head1 EXAMPLES
1807
 
1808
=over 4
1809
 
1810
=item jats all
1811
 
1812
This command will perform a B<jats build> if the build.pl file has been modified
1813
since the last build. It will then C<make> all the build targets.
1814
 
1815
=item jats make all
1816
 
1817
Same as C<jats all>
1818
 
1819
=item jats make debug
1820
 
1821
This command will create the B<debug> version of the make
1822
components in the current directory - and referenced sub components.
1823
 
1824
=item jats make debug NODEPEND=1
1825
 
1826
Same as C<jats make debug> but the dependency generation phase will be
1827
skipped. In a large build this will speed up the build, but there is an implicit
1828
assumption that file changes do not result in more header or library files being
1829
required. It will use the results of the previous C<make depend> phase.
1830
 
1831
=item jats make clean
1832
 
1833
This command will remove all object files, libraries, programs and any other
1834
build artifacts created by the B<make> process.
1835
 
1836
=item jats make clobber
1837
 
1838
Similar to C<jats make clean> but it will also delete build artifacts from the
1839
packaging directory.
1840
 
227 dpurdie 1841
=back
361 dpurdie 1842
 
1843
=cut
1844