Subversion Repositories DevTools

Rev

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

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