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