Subversion Repositories DevTools

Rev

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