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} );
261 dpurdie 683
        push @args, "NOSCMDEPEND=1";
227 dpurdie 684
 
685
        my $cdir = CleanDirName ($dir);
686
        my @make_command;
687
        push @make_command, "$ENV{GBE_BIN}/xmake";
688
        push @make_command, "-s" if $opt_silent;
689
        push @make_command, "--no-print-directory";
690
        push @make_command, "-C", $cdir unless ( $cdir eq $::Cwd );
691
        push @make_command, "-f", "$target.mk";
692
        push @make_command, @args;
693
        push @make_command, 'make_dir' unless exists $commands{$cmd}{nomakecheck} ;
694
        push @make_command, $cmd;
695
 
696
        Message ( sprintf ("[$text] %-${tlen}s, $cmd, $cdir", $target ));
697
        System (@make_command, "DEBUG=$do_debug" );
698
    }
699
}
700
 
701
#-------------------------------------------------------------------------------
702
# Function        : TestMakeFiles
703
#
704
# Description     : Test all the makefile dependent files to see if any of the
705
#                   makefiles need to be rebuilt.
706
#
707
#                   Walk the directory tree looking for makefiles to be
708
#                   rebuilt.
709
#
710
# Inputs          : $cmd            - Current command
711
#                   $pref           - Ref to an array of platforms
712
#
713
# Returns         : 
714
#
715
sub TestMakeFiles
716
{
717
    my ( $cmd, $pref ) = @_;
718
    Verbose ("Test makefile dependencies");
719
 
720
    #
721
    #   Read in the Tag file for the current directory
722
    #   This will provide the current list of subdirectories
723
    #
724
    #   Process Test the current makefiles, then test any subdirs
725
    #
726
    TestSubMake( $cmd, $Cwd, $pref );
727
 
728
    #
729
    #   Report build errors
730
    #   Done after all makefiles have been processed
731
    #
732
    if ( $build_error )
733
    {
734
        Error ("Error creating makefiles. Errors previously reported");
735
    }
736
 
737
    #
738
    #   Post makefile build processing
739
    #   Only required if a files have been re-built
740
    #
741
    if ( $update )
742
    {
743
        #
744
        #   Sanity test the makefile structure
745
        #   Ensure that makefiles have only one parent.
746
        #
747
        TestParents();
748
 
749
        #
750
        #   Sanity test the installed and packaged files
751
        #   Generate warnings and errors if a file if packaged from two
752
        #   locations
753
        #
754
        TestPackages();
755
 
756
        #
757
        #   Generate DPACKAGE file if required
758
        #
759
        JatsDPackage::DPackageGenerate( $::ScmRoot, $::ScmInterface  );
760
    }
761
 
762
    #
763
    #
764
    #   Check that the build.pl file is not newer that the tags file
765
    #   This will not be an error, but it will be a nagging warning
766
    #
767
    my @build_warn;
768
    my $bstamp = -M "$::ScmRoot/$ScmBuildSrc";
769
    my $tstamp = -M "$::ScmRoot/Makefile.gbe";
770
 
771
    push @build_warn, "Missing: Makefile.gbe" unless ( defined $tstamp );
772
    push @build_warn, "Modified build file ($ScmBuildSrc)" if ( $tstamp && $bstamp < $tstamp );
773
    if ( @build_warn )
774
    {
775
        Warning ("The build file is newer than the generated files",
776
                 "The project needs to be built for these changes to be included",
777
                 @build_warn );
778
    }
779
}
780
 
781
#-------------------------------------------------------------------------------
782
# Function        : TestSubMake
783
#
784
# Description     : Test the makefiles in the current directory
785
#                   Recurse into subdirectories
786
#
787
# Inputs          : $cmd            - Current command
788
#                   $dir            - Directory to test
789
#                   $pref           - Ref to an array of platforms
790
#
791
# Returns         : 
792
#
793
sub TestSubMake
794
{
795
    my ($cmd, $dir, $pref ) = @_;
796
 
797
    $Tags = ReadMaketags( $dir, 1 );
798
    unless ( $Tags )
799
    {
800
        Verbose2 ("TestSubMake :Directory not in tag database", $dir );
801
        MakeBuild( $dir);
802
    }
803
    else
804
    {
805
        TestMake( $cmd, $dir, $pref );
806
    }
807
 
808
    #
809
    #   Recurse into any subdirectories that may be a part of the build
810
    #
811
    unless ( exists $defs{NORECURSE} && $defs{NORECURSE}  )
812
    {
813
        foreach my $subdir (@{$Tags->{$dir}{subdirs}} )
814
        {
815
            TestSubMake( $cmd, CleanDirName( "$dir/$subdir"), $pref );
816
        }
817
    }
818
}
819
 
820
#-------------------------------------------------------------------------------
281 dpurdie 821
# Function        : ShowMakefiles
822
#
823
# Description     : Show the makefiles used in the build
824
#
825
# Inputs          : $cmd            - Current command
826
#                   $pref           - Ref to an array of platforms
827
#
828
# Returns         : 
829
#
830
sub ShowMakefiles
831
{
832
    my ( $cmd, $pref ) = @_;
833
    Verbose ("Show makefiles");
363 dpurdie 834
    ShowTargetsAlaises();
281 dpurdie 835
 
836
    #
837
    #   Read in the Tag file for the current directory
838
    #   This will provide the current list of subdirectories
839
    #
840
    #   Process Test the current makefiles, then any subdirs
841
    #
842
    ShowSubMake( $cmd, $Cwd, $pref, 0 );
843
}
844
 
845
#-------------------------------------------------------------------------------
846
# Function        : ShowSubMake
847
#
848
# Description     : Test the makefiles in the current directory
849
#                   Recurse into subdirectories
850
#
851
# Inputs          : $cmd            - Current command
852
#                   $dir            - Directory to test
853
#                   $pref           - Ref to an array of platforms
854
#                   $level          - Recursion depth
855
#
856
# Returns         : 
857
#
858
sub ShowSubMake
859
{
860
    my ($cmd, $dir, $pref, $level ) = @_;
861
 
862
    $Tags = ReadMaketags( $dir, 1 );
863
    unless ( $Tags )
864
    {
865
        Verbose2 ("ShowSubMake :Directory not in tag database", $dir );
866
        MakeBuild( $dir);
867
    }
868
    elsif ( $level )
869
    {
870
        print ("Makefile : " . ' ' x (4 * ($level - 1) ) . DisplayPath(RelPath($dir)) ,"\n");
871
    } else {
872
        print ("\nBuildfile: ", DisplayPath($dir), "\n" );
873
    }
874
 
875
    #
876
    #   Recurse into any subdirectories that may be a part of the build
877
    #
878
    foreach my $subdir (@{$Tags->{$dir}{subdirs}} )
879
    {
880
        ShowSubMake( $cmd, CleanDirName( "$dir/$subdir"), $pref, $level + 1 );
881
    }
882
}
883
 
884
#-------------------------------------------------------------------------------
227 dpurdie 885
# Function        : TestMake
886
#
887
# Description     : Test the makefiles component files
888
#                   and determine if the makefile(s) need to be rebuilt
889
#
890
# Inputs          : $cmd            - Current command
891
#                   $dir            - Directory to test
892
#                   $pref           - Ref to an array of platforms
893
#
894
# Returns         : 
895
#
896
sub TestMake
897
{
898
    my ( $cmd, $dir, $pref ) = @_;
899
    my @must_rebuild;
900
 
901
    if ( $cmd eq 'rebuild' )
902
    {
903
        MakeBuild( $dir);
904
        return;
905
    }
906
 
907
    #
908
    #   Check that the local makefile.pl is not newer than
909
    #   the Tags file. Not all makefile.pl's create .mk files
910
    #
911
    my $mstamp = -M "$dir/makefile.pl";
912
    my $tstamp = -M "$dir/Makefile.gbe";
913
 
914
    unless ( defined $tstamp )
915
    {
916
        UniquePush (\@must_rebuild, "Missing: $dir/Makefile.gbe");
917
    }
918
 
919
    if ( $mstamp && $mstamp < $tstamp  )
920
    {
921
        UniquePush (\@must_rebuild, "Updated: $dir/makefile.pl");
922
    }
923
    else
924
    {
925
        if ( $Tags->{$dir}{root} )
926
        {
927
            Verbose2 "TestMake: Root directory has no makefiles: $dir";
928
            return;
929
        }
930
 
931
        if ( $Tags->{$dir}{noplatforms} )
932
        {
933
            Verbose2 "TestMake: No make targets in $dir";
934
            return;
935
        }
936
 
937
        #
938
        #   Process only the required build targets
939
        #
940
        foreach my $tgt ( keys %{$Tags->{$dir}{platforms}}   )
941
        {
285 dpurdie 942
            next if ( %gbe_platform && ! exists $gbe_platform{$tgt} );
227 dpurdie 943
            #
944
            #   Locate all the makefile dependent files
945
            #
946
            my $data = $Tags->{$dir}{full}{$tgt}{'@ScmDepends'};
947
            if ( $data )
948
            {
949
                Verbose2 ("Processing: $dir : $tgt");
950
                my $base_stamp = -M "$dir/$tgt.mk";
951
                unless ( defined $base_stamp )
952
                {
953
                    UniquePush (\@must_rebuild, "Missing: $dir/$tgt.mk");
954
                }
955
                else
956
                {
957
                    foreach my $file ( "$dir/makefile.pl" ,@$data )
958
                    {
325 dpurdie 959
                        $file = FullPath ( $file, $dir );
227 dpurdie 960
                        my $stamp = -M $file;
961
                        if ( defined $stamp )
962
                        {
963
                            Verbose3 ("Timestamp: $stamp, $file");
964
                            if ( $stamp < $base_stamp  )
965
                            {
966
                                UniquePush (\@must_rebuild, $file);
967
                            }
968
                        }
969
                        else
970
                        {
971
                            UniquePush (\@must_rebuild, "Missing: $file");
972
                        }
973
                    }
974
                }
975
            }
976
            else
977
            {
978
                Warning ("No dependency information for: $tgt in $dir");
979
            }
980
        }
981
    }
982
 
983
    if ( @must_rebuild )
984
    {
985
        my @display;
986
        push (@display, CleanDirName($_) ) foreach ( @must_rebuild );
987
        Message ("One or more JATS source or internal files have changed, Makefiles will be rebuilt",
988
                  "Target is: $dir",
989
                  @display );
990
        MakeBuild ($dir);
991
    }
992
    return;
993
}
994
 
995
#-------------------------------------------------------------------------------
996
# Function        : MakeBuild
997
#
998
# Description     : Rebuild the makefiles in the specified directory
999
#                   This does not involve recursion - thats already been
1000
#                   done.
1001
#
1002
#                   Once the makefiles have been re-built the tags database
1003
#                   must be read in again as it may have changed.
1004
#
1005
# Inputs          : 
1006
#
1007
# Returns         : 
1008
#
1009
sub MakeBuild
1010
{
1011
    my ($dir) = @_;
1012
 
1013
    #
1014
    #   No makefiles to build in the root directory
1015
    #   Can't rebuild the top-level Makefile.gbe file
1016
    #
1017
    return if ( $Tags->{$dir}{root} );
1018
 
1019
    #
1020
    #   Try to rebuild the makefile
1021
    #
1022
    chdir $dir || Error ("Cannot change directory to $dir");
261 dpurdie 1023
    my $result = System ('--NoExit', $ENV{GBE_PERL}, 'makefile.pl',
1024
                            $::ScmRoot, $makelib, "--interface=$::ScmInterface" );
227 dpurdie 1025
    chdir $::Cwd || Error ("Cannot change directory to $::Cwd");
1026
 
1027
    #
1028
    #   Re-read the tags database
1029
    #
1030
    $Tags = ReadMaketags( $dir, 2 );
1031
 
1032
    #
1033
    #   Flag that makefiles have been modified
1034
    #
1035
    $update = 1;
261 dpurdie 1036
    $build_error = 1 if ( $result );
227 dpurdie 1037
}
1038
 
1039
#-------------------------------------------------------------------------------
1040
# Function        : UnMakeFiles
1041
#
1042
# Description     : Delete generated makefiles and control files
1043
#
1044
# Inputs          : $cmd            - Current command
1045
#                   $pref           - Ref to an array of platforms
1046
#
1047
# Returns         : 
1048
#
1049
sub UnMakeFiles
1050
{
1051
    #
1052
    #   Recurse down the tree
1053
    #   Recurse, then performs operations in the current directory
1054
    #
1055
    sub UnSubMakeFiles
1056
    {
1057
        my ($dir) = @_;
1058
        $Tags = ReadMaketags( $dir, 1 );
1059
        foreach my $subdir (@{$Tags->{$dir}{subdirs}} )
1060
        {
1061
            UnSubMakeFiles( CleanDirName( "$dir/$subdir") );
1062
        }
1063
        UnMake( $dir );
1064
    }
1065
 
1066
    #
1067
    #   Delete makefiles in the current directory
1068
    #
1069
    sub UnMake
1070
    {
1071
        my ($dir) = @_;
1072
        Verbose("Unmake in $dir");
1073
        foreach my $tgt ( keys %{$Tags->{$dir}{platforms}}   )
1074
        {
1075
            Verbose2("Unmake. Delete ${tgt}.mk");
1076
            unlink ("$dir/${tgt}.mk");
1077
        }
1078
        unlink ("$dir/Makefile.gbe");
1079
        Verbose2("Unmake. Delete Makefile.gbe");
1080
    }
1081
 
1082
    #
1083
    #   Depth first recursion through the tree
1084
    #
1085
    UnSubMakeFiles ( $Cwd );
1086
}
1087
 
1088
#-------------------------------------------------------------------------------
1089
# Function        : TestParents
1090
#
1091
# Description     : Ensure that each makefile node has exactly one parent
1092
#                   Prevent the user from creating recursive loops
1093
#
1094
# Inputs          : 
1095
#
1096
# Returns         : 
1097
#
1098
my %parents;
1099
sub TestParents
1100
{
1101
    Verbose ("Test makefile parents");
1102
    #
1103
    #   Init the hash. Command may be invoked multiple times
1104
    #
1105
    %parents = ();
1106
 
1107
    #
1108
    #   Recurse down the tree
1109
    #   Recurse, then performs operations in the current directory
1110
    #
1111
    sub RecurseDown
1112
    {
1113
        my ($dir) = @_;
1114
        $Tags = ReadMaketags( $dir, 1 );
1115
        Verbose2("TestParents in $dir");
1116
        foreach my $subdir (@{$Tags->{$dir}{subdirs}} )
1117
        {
1118
            my $subdir = CleanDirName( "$dir/$subdir");
1119
            push @{$parents{$subdir}}, $dir;
1120
            RecurseDown( $subdir );
1121
        }
1122
    }
1123
 
1124
    #
1125
    #   Depth first recursion through the tree
1126
    #
1127
    RecurseDown ( $Cwd );
1128
 
1129
    #
1130
    #   Test for only one parent
1131
    #   The root makefile won't have any
1132
    #
1133
    foreach my $dir ( sort keys %{$Tags} )
1134
    {
1135
        my $count = $#{$parents{$dir}};
1136
        if ( $count > 0 )
1137
        {
1138
            if ( defined($GBE_ABT) )
1139
            {
1140
                Warning ("Error supressed by ABT");
1141
                Warning ("makefile.pl with multiple parents",
1142
                         "makefile.pl in: $dir",
1143
                         "Parented by:", @{$parents{$dir}} );
1144
            }
1145
            else
1146
            {
1147
                unlink $Tags->{$dir}{config};
1148
                Error ("makefile.pl with multiple parents",
1149
                       "makefile.pl in: $dir",
1150
                       "Parented by:", @{$parents{$dir}} );
1151
            }
1152
        }
1153
    }
1154
}
1155
 
1156
#-------------------------------------------------------------------------------
1157
# Function        : TestPackages
1158
#
1159
# Description     : Ensure that files that are packaged and installed are
1160
#                   only done from one makefile. Warn if the same file
1161
#                   is being packaged from multiple makefiles.
1162
#
1163
# Inputs          : 
1164
#
1165
# Returns         : 
1166
#
1167
my %test_packages;
1168
sub TestPackages
1169
{
1170
    Verbose ("Test packaged files");
1171
    #
1172
    #   Init the hash. Command may be invoked multiple times
1173
    #
1174
    %test_packages = ();
1175
 
1176
    #
1177
    #   Recurse down the tree
1178
    #   Recurse, then performs operations in the current directory
1179
    #
1180
    sub TRecurseDown
1181
    {
1182
        my ($dir) = @_;
1183
        Verbose2("TestPackages in $dir");
1184
        $Tags = ReadMaketags( $dir, 1 );
1185
        #
1186
        #   Process makefile
1187
        #   Examine all the %PACKAGE_xxx and %INSTALL_xxx fields thare listed
1188
        #   in the @PACKAGE_VARS and @INSTALL_VARS array
1189
        #
1190
        foreach my $target ( keys %{$Tags->{$dir}{platforms}}   )
1191
        {
285 dpurdie 1192
            next if ( %gbe_platform && ! exists $gbe_platform{$target} );
227 dpurdie 1193
            foreach my $field ( @{$Tags->{$dir}{full}{$target}{'@PACKAGE_VARS'}},
1194
                                @{$Tags->{$dir}{full}{$target}{'@INSTALL_VARS'}} )
1195
            {
1196
                foreach my $entry ( keys %{$Tags->{$dir}{full}{$target}{$field}} )
1197
                {
1198
                    Verbose3("TestPackages: $target, File: $entry");
1199
                    push @{$test_packages{$target}{$entry}}, $dir;
1200
                }
1201
            }
1202
        }
1203
 
1204
        #
1205
        #   Process subdirectories too
1206
        #
1207
        foreach my $subdir (@{$Tags->{$dir}{subdirs}} )
1208
        {
1209
            TRecurseDown( CleanDirName( "$dir/$subdir") );
1210
        }
1211
    }
1212
 
1213
 
1214
 
1215
    #
1216
    #   Depth first recursion through the tree
1217
    #
1218
    TRecurseDown ( $Cwd );
1219
 
1220
    #
1221
    #   Test and report files that are packaged in different makefiles
1222
    #   There are two issues:
1223
    #       1) Not good practice
1224
    #       2) May be different files
1225
    #   The warning message is a bit ugly - but it shouldn't pop up often.
1226
    #
1227
#    DebugDumpData ("test_packages", \%test_packages);
1228
 
1229
    foreach my $target ( sort keys %test_packages )
1230
    {
1231
        foreach my $file ( sort keys %{$test_packages{$target}} )
1232
        {
1233
            #
1234
            #   The descpkg file is known to be packaged from multiple dirs
1235
            #
1236
            next if ( $file =~ m~/descpkg~ );
1237
            if ( $#{$test_packages{$target}{$file}} > 0 )
1238
            {
1239
                Warning ("File is packaged or installed from multiple makefiles",
1240
                         "Target: $target, Packaged file: $file",
1241
                         "Packaged from the following directories:", @{$test_packages{$target}{$file}} );
1242
            }
1243
        }
1244
    }
1245
}
1246
 
1247
 
1248
#-------------------------------------------------------------------------------
1249
# Function        : DoHelp
1250
#
1251
# Description     : Display basic help information
1252
#
1253
# Inputs          : None
1254
#
1255
# Returns         :
1256
#
1257
sub DoHelp
1258
{
1259
 
1260
#
1261
#   Display basic usage information
1262
#
1263
    pod2usage(-verbose => 0,
1264
              -message => "Version: $VERSION",
1265
              -exitval => 'NOEXIT');
1266
 
363 dpurdie 1267
    ShowTargetsAlaises();
1268
}
1269
 
1270
#-------------------------------------------------------------------------------
1271
# Function        : ShowTargetsAlaises
1272
#
1273
# Description     : Display make targets and aliases
1274
#                   Used by 'show' and 'help'
1275
#
1276
# Inputs          : None
1277
#
1278
# Returns         : Nothing
1279
#                   Output via 'print'
1280
#
1281
sub ShowTargetsAlaises
1282
{
1283
    my @targets = sort keys %BUILDINFO;
1284
    my @alias = sort keys %ScmBuildAliases;
1285
 
1286
    #
1287
    #   Determine the max length of target or alias
1288
    #   Used to make pretty display
1289
    #
1290
    my $flen = 6;
1291
    foreach ( @alias, @targets )
227 dpurdie 1292
    {
363 dpurdie 1293
        my $len = length $_;
1294
        $flen = $len if ( $len > $flen );
1295
    }
1296
 
1297
    print "\nActive Platform targets\n";
1298
    foreach (@targets)
1299
    {
227 dpurdie 1300
        print "    $_\n";
1301
    }
1302
 
1303
    if ( $#alias >=0 )
1304
    {
363 dpurdie 1305
        print "\nAlias targets\n";
1306
 
1307
        #   Display aliases
1308
        #   Indent list by 4 spaces
1309
        #
227 dpurdie 1310
        foreach ( @alias )
1311
        {
363 dpurdie 1312
            print PrintList("    $_",4+$flen, split(' ', $ScmBuildAliases{$_}));
227 dpurdie 1313
        }
1314
    }
1315
}
1316
 
1317
#-------------------------------------------------------------------------------
363 dpurdie 1318
# Function        : PrintList
1319
#
1320
# Description     : Pretty format an array to fit within 80 char line
1321
#                   Perform wrapping as required
1322
#
1323
# Inputs          : $title          - Title string
1324
#                   $len            - Desired length of title area
1325
#                   @list           - An array of items to print
1326
#
1327
# Returns         : string
1328
#
1329
sub PrintList
1330
{
1331
    my ($title, $llen, @list) = @_;
1332
    my $string = sprintf ("%-${llen}s :", $title);
1333
 
1334
    my $nlen = length($string);
1335
    my $nl = "\n" . (' ' x  $nlen );
1336
    $llen = $nlen;
1337
 
1338
    for my $k (sort @list)
1339
    {
1340
        my $klen = length($k);
1341
        if ($llen + $klen > 78 )
1342
        {
1343
            $string .= $nl;
1344
            $llen = $nlen;
1345
        }
1346
        $string .= ' ' .  $k;
1347
        $llen += $klen + 1;
1348
    }
1349
    return $string . "\n";
1350
}
1351
 
1352
#-------------------------------------------------------------------------------
227 dpurdie 1353
# Function        : ReadMaketags
1354
#
1355
# Description     : Read in the global make tags data base
1356
#                   This contains information on all the components within
1357
#                   the build. The tags allow recursive makes to be pruned.
1358
#
1359
#                   The file may change while the build is running
1360
#                   It can be read multiple times
1361
#
1362
# Inputs          : $dir            - Directory entry to read
321 dpurdie 1363
#                   $test           - 0: Read. Error if not available (default)
1364
#                                     1: Read if available
227 dpurdie 1365
#                                     2: Force read
1366
#
1367
# Returns         : Reference to the tag data for the requested directory
1368
#                   Will error if no available
1369
#
1370
our %cf_minfo;
1371
our %cf_minfo2;
1372
my %tag_data;
1373
sub ReadMaketags
1374
{
1375
    my ($dir, $test) = @_;
321 dpurdie 1376
    $test ||= 0;
227 dpurdie 1377
 
1378
    #
1379
    #   Force data re-aquisition
1380
    #
1381
    delete $tag_data{$dir}
321 dpurdie 1382
        if ( $test == 2 );
227 dpurdie 1383
 
1384
    #
1385
    #   Do we already have the entry
1386
    #
1387
    return \%tag_data
1388
        if ( exists ($tag_data{$dir} ));
1389
 
1390
    #
1391
    #   If the entry is not known, then re-read the index file
1392
    #
321 dpurdie 1393
#DebugDumpData ("ReadMaketags", \%::cf_filelist);
227 dpurdie 1394
    unless ( $::cf_filelist{$dir} )
1395
    {
1396
        my $index_file = "$::ScmRoot/$::ScmInterface/Makefile.cfg";
1397
        Error ("Makefile index missing. Rebuild required") unless ( -f $index_file );
1398
 
1399
        #
1400
        #   Kill the entry in %INC to force the file to be read in
1401
        #
1402
        $::cf_filelist = ();
1403
        delete $INC{ $index_file };
1404
        require $index_file;
1405
    }
1406
 
1407
    my $cfg_filen = $::cf_filelist{$dir};
1408
    unless ( $cfg_filen )
1409
    {
285 dpurdie 1410
        return if ( $test );
227 dpurdie 1411
        Error ("Makefile index entry missing: $dir. Rebuild required");
1412
    }
1413
 
1414
 
1415
    #
1416
    #   Read in all the Makefile_x.cfg files
1417
    #
1418
    %cf_minfo = ();
1419
    %cf_minfo2 = ();
1420
    my $cfg_file = "$::ScmRoot/$::ScmInterface/$cfg_filen";
1421
 
1422
    unless ( -f $cfg_file )
1423
    {
285 dpurdie 1424
        return if ( $test );
227 dpurdie 1425
        Error ("Make data file missing: $cfg_file. Rebuild required");
1426
    }
1427
 
1428
    delete $INC{ $cfg_file };
1429
    require $cfg_file;
1430
 
1431
    Error ("Makefile info2 not present")
1432
        unless ( keys %::cf_info2 );
1433
 
1434
    Error ("Makefile info2 incorrect version. Rebuild required")
285 dpurdie 1435
        unless ( exists $::cf_info2{version} && $::cf_info2{version} == 1 );
227 dpurdie 1436
 
1437
    %{$tag_data{$dir}} = %::cf_info2;
1438
    $tag_data{$dir}{config} = $cfg_file;
1439
    %{$tag_data{$dir}{full}} = %::cf_info;
1440
 
1441
#DebugDumpData ("ReadMaketags", $tag_data{$dir});
1442
    return \%tag_data;
1443
 
1444
}
1445
 
1446
#-------------------------------------------------------------------------------
1447
# Function        : ExpandComposite
1448
#
1449
# Description     : Expand a command via composite command expansion
1450
#                   A composite command may contain other composite commands
261 dpurdie 1451
#                   Detect, as an error, recursive expansions
227 dpurdie 1452
#
1453
# Inputs          : $cmd    - command to expand
1454
#
1455
# Returns         : An array of commands
1456
#
1457
sub ExpandComposite
1458
{
285 dpurdie 1459
    my @scmds = $_[0];
227 dpurdie 1460
    my @cmds;
261 dpurdie 1461
    my %seen;
227 dpurdie 1462
    while ( @scmds )
1463
    {
1464
        my $cmd = shift @scmds;
1465
        if ( exists $composite_commands{$cmd} )
1466
        {
261 dpurdie 1467
 
1468
            Error ("Internal. Recursion in composite command definitions: $cmd")
1469
                if ($seen{$cmd});
1470
 
227 dpurdie 1471
            @scmds = (@{$composite_commands{$cmd}}, @scmds);
261 dpurdie 1472
            $seen{$cmd} = 1;
227 dpurdie 1473
        }
1474
        else
1475
        {
1476
            push @cmds, $cmd;
1477
        }
1478
    }
1479
 
1480
    return @cmds;
1481
}
1482
 
1483
 
1484
#-------------------------------------------------------------------------------
1485
#   Documentation
1486
#
1487
 
1488
=pod
1489
 
361 dpurdie 1490
=for htmltoc    JATS::make
1491
 
227 dpurdie 1492
=head1 NAME
1493
 
1494
jmake - JATS make support tool
1495
 
1496
=head1 SYNOPSIS
1497
 
1498
 Usage: jats make [options][targets][flags]
1499
 
1500
 Where options:
1501
    -h, -h -h, -man     - Help messages with increasing verbosity
1502
    -verbose            - Verbose operation
1503
    -debug              - Debug operation
1504
    -default=target     - Default 'target' if none is supplied
335 dpurdie 1505
    -- make options     - [Advanved] Options passed directly to make
227 dpurdie 1506
 
1507
 Where flags are of the form Name=Value
1508
    SHOWENV=1           - Show make environment
1509
    LEAVETMP=1          - Leave temp working files
1510
    NODEPEND=1          - Ignore dependency checking
261 dpurdie 1511
    EXPERT=1            - Ignore dependency on makefiles
227 dpurdie 1512
    OPTIONS=[opt]       - Maketime options [args,allargs,filter...]
1513
 
1514
 Valid targets include:
1515
    all                 - build and install everything(p*)
1516
    build               - build everything (pu)
1517
    debug               - build all things for debug (pu)
1518
    prod                - build all things for production (pu)
1519
    install             - install public components (pu*)
1520
    lint                - lints the source (assumes debug)(p)
1521
    package             - build all packages (pu*)
361 dpurdie 1522
    package-[set]       - build specific package (see below) (pu*)
227 dpurdie 1523
    run_tests           - Run the tests specified in the makefile
1524
    run_unit_tests      - Run the automatic unit tests specified in the makefile
1525
    deploy              - Run the deployment scripts (p*)
1526
    rebuild             - recursively rebuild makefiles
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