Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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