Subversion Repositories DevTools

Rev

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