Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
227 dpurdie 1
# -*- mode: perl; tabs: 8; indent-width: 4; show-tabs: yes; -*-
2
# Copyright 1995-2004 ERG Transit Systems, All Rights Reserved
3
#
4
# Module name   : buildlib.pl
5
# Module type   : Makefile system
6
# Compiler(s)   : ANSI C
7
# Environment(s): n/a
8
#
9
# Description:
10
#       This is the standard bootstrap script for sandboxs.
11
#
12
# Notes:
13
#
14
#                       *** DO NOT DETAB ***
15
#
16
#       Beware the use of space v's tab characters within the
17
#       makefile generation sessions.
18
#
19
#.........................................................................
20
#
21
 
22
use strict;
23
use warnings;
24
 
25
use BuildVersion;
26
use BuildName;
27
use PackageEntry;
28
use JatsEnv;
29
use JatsSystem;
30
use JatsVersionUtils;
31
use FileUtils;
32
use Pod::Usage;
261 dpurdie 33
use Getopt::Long;
305 dpurdie 34
use File::Path;
227 dpurdie 35
 
36
our $BuildVersion           = "2.1.0";
37
 
38
#.. Switchs
39
#
40
our $ScmBuildlib            = 0;
41
our $ScmBuildSrc            = "";
42
 
43
our $CmdSwitch              = "";
44
our $Clobber                = 0;
45
our $Archive                = 0;
46
our $Interface              = 0;
47
our $RootOnly               = 0;
48
our $Perms                  = 0;
49
our $Expert                 = 0;
50
our $All                    = 0;
51
our $Nolog                  = 0;
52
our $Cache                  = 0;
261 dpurdie 53
our $NoPackageError         = 0;
227 dpurdie 54
our $ForceBuildPkg          = 0;
55
our $Srcdir                 = "";               # default source root
331 dpurdie 56
our $ForceBuild             = 1;
227 dpurdie 57
 
58
#.. Public symbols, referenced by many build.pl implementations
59
#
60
our $BUILDPREVIOUSVERSION   = "0.0.0";          # BuildPreviousVersion()
61
our @BUILDPLATFORMS         = ();               # BuildPlatforms()
62
our %BUILDINFO              = ();               # BuildInfo
63
our @DEFBUILDPLATFORMS      = ();
64
our %BUILDPLATFORMARGS      = ();
65
our @BUILD_ACTIVEPLATFORMS  = ();
66
our @BUILDSUBDIRS           = ();               # BuildSubDir()
67
our @BUILDSETENV            = ();               # BuildSetenv()
68
our $BUILDINTERFACE         = "";               # BuildInterface()
69
our $BUILDLOCAL             = "";               # BuildInterface()
70
our $BUILDDIRTREE           = "";               # BuildDirTree()
241 dpurdie 71
our @BUILD_BADNAME          = ();               # Unknown platforms
227 dpurdie 72
 
73
our $BUILDNAME              = "";               # BuildName()
74
our $BUILDVERSION           = "";               # BuildName()
75
our $BUILDNAME_PACKAGE;                         # Name
76
our $BUILDNAME_VERSION;                         # Version
77
our $BUILDNAME_PROJECT;                         # Project(optional)
78
our $DEPLOY_PATCH           = 0;                # Deplyment patch number
79
 
80
our %BUILDALIAS_DELAY       = ();               # Delayed aliases
81
our %BUILDALIAS_TARGETS     = ();               # BuildAlias from --Targets
82
our %BUILDALIAS             = ();               # BuildAlias
83
our %BUILDPRODUCT           = ();               # BuildProduct
84
our %BUILDPRODUCT_PARTS     = ();               # BuildProduct parts
85
our %PKGRULES               = ();               # Package include and link rules
86
our @BUILDTOOLS             = ();               # Extended tool path
87
our $BUILDPHASE             = 0;                # In Build Phase
88
our @CLOBBERDIRS            = ();               # Directories to clobber
89
our @CLOBBERFILES           = ();               # Files to clobber
247 dpurdie 90
our %BUILD_KNOWNFILES       = ();               # Files that will be known
227 dpurdie 91
 
333 dpurdie 92
our $Makelib                = "";
263 dpurdie 93
our $GBE_CORE;                                  # Root of JATS
94
our $InterfaceVersion;                          # Interface directory format version
95
our $ScmInterface;                              # Interface directory
227 dpurdie 96
 
263 dpurdie 97
 
98
 
227 dpurdie 99
my  $DeleteDPACKAGE         = 0;                # Must clobber DPACKAGE
305 dpurdie 100
my  $build_source_pkg       = 0;                # Flag to build source package
227 dpurdie 101
my  $opt_help               = 0;
102
 
103
BuildLibInit();
104
 
105
sub BuildLibInit
106
{
107
 
108
#.. Set environment
109
#
331 dpurdie 110
    EnvImport( 'GBE_VERSION' );
111
    EnvImport( 'GBE_BIN' );
112
    EnvImport( 'GBE_CORE' );
113
    EnvImport( 'GBE_PERL' );
114
    EnvImport( 'GBE_TOOLS' );
115
    EnvImport( 'GBE_CONFIG' );
116
    EnvImport( 'GBE_DPKG' );
117
    EnvImport( 'GBE_MACHTYPE' );
118
    EnvImport( 'USER' );
119
    EnvImport( 'GBE_HOSTNAME');
120
    EnvImport( 'GBE_DRV' )
121
        if ( $ScmHost ne 'Unix' );            # DOS or WIN special
227 dpurdie 122
 
123
    EnvImportOptional ( 'GBE_DPKG_STORE','' );
124
    EnvImportOptional ( 'GBE_DPKG_CACHE','' );
125
    EnvImportOptional ( 'GBE_DPKG_LOCAL','' );
126
    EnvImportOptional ( 'GBE_DPKG_SBOX' ,'' );
313 dpurdie 127
    EnvImportOptional ( 'GBE_DPLY'      ,'' );
341 dpurdie 128
    EnvImportOptional ( 'GBE_SANDBOX'   ,'' );
227 dpurdie 129
 
130
    EnvImportOptional ( 'GBE_PLATFORM' );           # optional PLATFORM filter
131
    EnvImportOptional ( 'GBE_BUILDFILTER' );        # optional BUILD filter       
132
    EnvImportOptional ( 'GBE_ABT' );                # optional ABT flags          
133
 
134
#.. Common stuff
135
#
136
    require "$::GBE_TOOLS/common.pl";
331 dpurdie 137
    CommonInit( 'buildlib' );
227 dpurdie 138
    Debug( "Version:   $BuildVersion" );
279 dpurdie 139
    Require( "$::GBE_CONFIG/PLATFORM", "PLATFORM_CFG.PM"  );
227 dpurdie 140
 
141
#.. Parse command line
142
#
143
    $ScmBuildSrc = $0;                          # Name of the build file
331 dpurdie 144
    $Cwd = shift @ARGV;
227 dpurdie 145
    $Cwd =~ tr~\\/~/~s;;                        # Need / in path, Remove doubles
333 dpurdie 146
    $Makelib = shift @ARGV;                     # Only for legacy build.pl files
227 dpurdie 147
 
261 dpurdie 148
    Verbose ("Command Line: @ARGV");
313 dpurdie 149
    my $result = GetOptions( "help|h:+"      => \$opt_help,
150
                             "man:3"         => \$opt_help,
151
                             "debug:+"       => \$::ScmDebug,
152
                             "verbose:+"     => \$::ScmVerbose,
153
                             "expert:1"      => \$Expert,
154
                             "all"           => \$All,
155
                             "nolog"         => \$Nolog,
331 dpurdie 156
                             "cache:+"       => \$Cache,
313 dpurdie 157
                             "package"       => \$NoPackageError,
158
                             "forcebuildpkg" => \$ForceBuildPkg,
331 dpurdie 159
                             "force!"        => \$ForceBuild,
313 dpurdie 160
                             );
261 dpurdie 161
    Usage() if ( $opt_help || !$result );
227 dpurdie 162
 
331 dpurdie 163
    Debug( "Host:          ", $ScmHost );
164
    Debug( "Cwd:           ", $Cwd );
333 dpurdie 165
    Debug( "Makelib:       ", $Makelib );
331 dpurdie 166
    Debug( "BuildFile:     ", $ScmBuildSrc );
167
    Debug( "Debug:         ", $::ScmDebug );
168
    Debug( "Verbose:       ", $::ScmVerbose );
169
    Debug( "Expert:        ", $Expert );
170
    Debug( "All:           ", $All );
171
    Debug( "Nolog:         ", $Nolog );
172
    Debug( "Cache:         ", $Cache );
173
    Debug( "package:       ", $NoPackageError );
174
    Debug( "ForcePkg  :    ", $ForceBuildPkg );
175
    Debug( "ForceBuild :   ", $ForceBuild );
227 dpurdie 176
 
177
#.. Command
178
#
331 dpurdie 179
    $CmdSwitch = shift @ARGV;
180
    Debug( "CmdSwitch:     ", $CmdSwitch );
227 dpurdie 181
 
331 dpurdie 182
    if ( $CmdSwitch )
183
    {
184
        if ( $CmdSwitch eq "interface" ) {
185
            $Interface      = 1;
227 dpurdie 186
 
331 dpurdie 187
        } elsif ( $CmdSwitch eq "rootonly" ) {
188
            $RootOnly       = 1;
227 dpurdie 189
 
331 dpurdie 190
        } elsif ( $CmdSwitch eq "clobber" ) {
191
            $Clobber        = 1;
227 dpurdie 192
 
331 dpurdie 193
        } elsif ( $CmdSwitch eq "help" || $CmdSwitch eq "usage" ) {
194
            $opt_help = 1;
195
            Usage();
227 dpurdie 196
 
331 dpurdie 197
        } elsif ( $CmdSwitch eq "changelog" ) {
198
            if ( -d "CVS" )                         # CVS support subdir
199
            {
200
                System( "$::GBE_PERL $::GBE_TOOLS/cvs2cl.pl --tags --branches --revisions --day-of-week" )
201
            }
202
            exit(1);
227 dpurdie 203
 
331 dpurdie 204
        } else {
205
            Usage( "(E) build. Unknown command \"$CmdSwitch\"" );
206
        }
207
    }
227 dpurdie 208
 
331 dpurdie 209
    #
341 dpurdie 210
    #   If we are not performing a ForceBuild, then we don't need to continue
211
    #   We have updated the interface directory with BuildPkgArchive
212
    #   information.
331 dpurdie 213
    #
341 dpurdie 214
    unless ( $::GBE_SANDBOX )
331 dpurdie 215
    {
341 dpurdie 216
        TestForForcedBuild();
227 dpurdie 217
    }
218
 
219
    #
220
    #   Must inform makelib that its running under buildlib
221
    #
222
    $ScmBuildlib = 1;
223
 
224
    #
225
    #   In clobber mode System commands will not force termination
226
    #   otherwise, within build.pl, a failed system command will die.
227
    #
228
    SystemConfig ('UseShell' => 1,
283 dpurdie 229
                  'ExitOnError' => ($Clobber == 0) );
227 dpurdie 230
}
231
 
232
 
233
#-------------------------------------------------------------------------------
234
# Function        : Log
235
#
236
# Description     : Internal function to generate a log file of the build process
341 dpurdie 237
#                   The function will print its arguments to the screen and a log file
227 dpurdie 238
#
239
# Inputs          : Arguments will be printed
240
#
241
# Returns         : Nothing
242
#
243
sub Log
244
{
245
    if ( ! $Clobber )
246
    {
261 dpurdie 247
        print "@_\n";
248
        FileAppend ('build.log', \@_ );
227 dpurdie 249
    }
250
}
251
 
252
#-------------------------------------------------------------------------------
253
# Function        : BuildSubDir
254
#
255
# Description     : Specify one or more directories in which makefile.pl's can be
256
#                   found to be processed.
257
#
258
#                   This function will flag the build 'src' dir.
259
#                   This will be the first directory specified UNLESS there
260
#                   is a 'src' directory in the list
261
#
262
#                   The function may be called multiple times.
263
#
264
# Inputs          : NewDirs             - An array of directories
265
#
266
# Returns         : Nothing
267
#
268
 
269
sub BuildSubDir
270
{
271
    my( @NewDirs );
272
 
273
    @NewDirs = map { split /\s+/ } @_;
274
    @NewDirs = grep { defined $_ } @NewDirs;
275
 
276
    Debug( "BuildSubDir(@NewDirs)" );
277
 
278
    foreach my $ThisDir ( @NewDirs )
279
    {
280
        unless ( $Clobber )
281
        {
282
            if ( $ThisDir eq "." )
283
            {
284
                Error( "BuildSubDir() cannot specify the current directory (.)",
285
                       "The makefile.pl in the root directory is included in all makefile.pl's" );
286
            }
287
 
288
            if ( $ThisDir =~ m~\\~)
289
            {
290
                Warning ("BuildSubDir contains a '\\' character: $ThisDir" );
291
            }
292
            if ( grep /^$ThisDir$/, @BUILDSUBDIRS )
293
            {
294
                Warning( "BuildSubDir() duplicate subdirectory ignored '$ThisDir'." );
295
                next;
296
            }
297
            if ( ! ( -e $ThisDir and -d $ThisDir ) )
298
            {
299
                Error( "BuildSubDir() non-existent subdirectory: '$ThisDir'." );
300
            }
301
            if ( ! -f $ThisDir . '/makefile.pl' )
302
            {
303
                Error( "BuildSubDir() makefile.pl not found in subdirectory: '$ThisDir'." );
304
            }
305
 
306
            push( @BUILDSUBDIRS, $ThisDir );
307
        }
308
 
309
        #
310
        #   Capture the first source directory mentioned
311
        #   This will be used as the root of the build
312
        #
313
        #   If there is a Src directory then use this
314
        #
315
        $Srcdir = $ThisDir
316
            if ( $ThisDir =~ m/^src$/i );
317
        $Srcdir = $ThisDir
318
            unless ( $Srcdir );
319
    }
320
}
321
 
322
#-------------------------------------------------------------------------------
323
# Function        : BuildAlias
324
#
325
# Description     : Create an alias for multiple targets
326
#                   The default operations will:
327
#                       Add the alias as a default platform (* in the makefile.pl)
328
#                       Perform an implicit BuildPlatform for the alias targets
329
#
330
#                   In hindsight this was not good. Options modify the behaviour
331
#                   Options:
332
#                       --NotDefault    The alias will not be a part of the default
333
#                                       platform for the makefile.pls
334
#                       --Define        Simply define text substitution
335
#                                       Do not implicitly create platforms
336
#                       --Target        Accumulate platforms with specified targets
337
#                                       Complete alias determination is delayed
338
#                                       The named targets are specified as an alias
339
#                                       until the calculation is done
340
#
341
# Inputs          : alias[,--options]   comma seperated options
342
#                   arguments           alias arguments; platforms or targets
343
#
344
# Returns         : Nothing
345
#
346
sub BuildAlias
347
{
348
    my( $alias, @arguments ) = @_;
349
    my $notdefault;
350
    my $define;
351
    my $target_mode;
352
 
353
    Debug( "BuildAlias($alias, @arguments)" );
354
    Error ("BuildAlias: No platforms specified") unless ( @arguments );
355
    Error( "BuildAlias() must appear before BuildName()..." ) if ( $BUILDNAME );
356
 
357
    #   Parse attributes
358
    #
359
    my ( @attrs ) = split( ',', $alias );
360
 
361
    $alias = "";
362
    foreach ( @attrs ) {
363
        if ( /^--/ ) {
364
            if ( /^--NotDefault$/ ) {
365
                $notdefault = 1;
366
 
367
            } elsif ( /^--Define$/ ) {
368
                $define = 1;
369
 
370
            } elsif ( /^--Target$/ ) {
371
                $target_mode = 1;
372
 
373
            } else {
374
                Warning( "BuildAlias() unknown attribute: $_ -- ignored" );
375
            }
376
 
377
        } else {
378
            Error( "BuildAlias() multiple alias specifications -- ignored" )
379
                if ( $alias ne "" );
380
            $alias = $_;
381
        }
382
    }
383
    Error( "BuildAlias() missing alias specifications" )
384
        if ( $alias eq "" );
385
 
386
 
387
    #
388
    #   If we need to recalculate the alias based on targets, then tag the alias
389
    #   to be processed
390
    #
391
    $BUILDALIAS_TARGETS{ $alias } = ''
392
        if ( $target_mode );
393
 
394
    #   Define alias
395
    #
396
    if ( $alias eq "GENERIC" )
397
    {
398
        Error( "BuildAlias() cannot create a alias named GENERIC" );
399
    }
400
    elsif ( $alias ne quotemeta( $alias ) )
401
    {
402
        Warning( "BuildAlias() alias '$alias' contains invalid characters -- ignored" );
403
    }
404
    elsif ( $BUILDALIAS{ $alias } )
405
    {
406
        Warning( "BuildAlias() duplicate alias '$alias' -- alias ignored" );
407
    }
408
    else
409
    {
410
        #
411
        #   Expand alias UNLESS using --Target.
412
        #   The --Target is a real target and not a subject to alias expansion
413
        #   This solves order dependancy problems.
414
        #
415
        @arguments = ExpandPlatforms( @arguments )
416
            unless $target_mode;
417
 
418
        my $platform = "";                   # current platform
419
        my @pargs = ();                      # current args
420
 
421
        #
422
        #   Process the expanded arguments
423
        #   Collect arguments and process when a new platform is discovered
424
        #
425
        foreach my $arg ( @arguments, '++' )
426
        {
427
            if ( $arg =~ /^--/ )
428
            {
429
                push @pargs, $arg;
430
                next;
431
            }
432
            else
433
            {
434
                #
435
                #   Start of a platform
436
                #   Process previous data, once a platform has been seen
437
                #
438
                if ( $platform )
439
                {
440
                    #   Add arguments to BUILDALIAS as we see them
441
                    #
442
                    HashJoin( \%BUILDALIAS, ' ', $alias, $platform );
443
                    HashJoin( \%BUILDALIAS, ' ', $alias, grep(!/^--Uses=/, @pargs) );
444
 
445
                    #
446
                    #   The BuildAlias can also define a platform.
447
                    #   (Sounded like a good idea at the time!)
448
                    #
449
                    unless ( $define || $target_mode )
450
                    {
451
                        push @pargs, '--NotDefault' if ( $notdefault );
452
                        push @pargs, '--FunctionName=BuildAlias';
453
                        BuildPlatforms( $platform, @pargs );
454
                    }
455
                }
456
 
457
                #
458
                #   Start collecting args for the next platform
459
                #
460
                @pargs = ();
461
                $platform = $arg;
462
            }
463
        }
464
    }
465
}
466
 
467
 
468
#-------------------------------------------------------------------------------
469
# Function        : Process_TargetAlias
470
#
471
# Description     : Post Process the --Target option for the build alias
472
#                   Filter all platforms and extract those with a matching targets
473
#
474
# Inputs          : None
475
#
476
# Returns         : Nothing
477
#
478
sub Process_TargetAlias
479
{
480
 
481
    #
482
    #   Merge any delayed aliases with the complete set of alias
483
    #   Delayed alias are not used in expansions during the processing
484
    #   of platforms and targets, but can be used to pick up
485
    #
486
    while ( my($key,$value) = each(%BUILDALIAS_DELAY) )
487
    {
488
        if ( exists($BUILDALIAS{$key}) )
489
        {
490
            Warning( "BuildAlias() duplicates internal alias '$key' -- internal alias ignored" );
491
            next;
492
        }
493
        $BUILDALIAS{$key} = $value;
494
    }
495
 
496
    foreach my $alias ( keys %BUILDALIAS_TARGETS )
497
    {
498
        Debug( "BuildTargetAlias($alias)" );
499
 
500
        #
501
        #   Replace the existing alias - it has done its JOB
502
        #
503
        my $arguments = delete $BUILDALIAS{ $alias } ;
504
 
505
        foreach my $arg ( split / /, $arguments )
506
        {
507
            if ( $arg =~ /^--/ )                # argument
508
            {
509
                #   Add arguments to BUILDALIAS as we see them
510
                #
511
                HashJoin( \%BUILDALIAS, ' ', $alias, $arg );
512
                next;
513
            }
514
 
515
            foreach my $platform ( keys %BUILDINFO )
516
            {
517
                foreach my $element ( qw (TARGET BASE ) )
518
                {
519
                    my $target = $BUILDINFO{$platform}{$element};
520
                    if ( $target && $target eq $arg )
521
                    {
522
                        HashUniqueJoin( \%BUILDALIAS, ' ', $alias, $platform );
523
                        Debug( "BuildTargetAlias: $alias, $target -> $platform" );
524
                    }
525
                }
526
            }
527
        }
528
    }
529
}
530
 
531
#-------------------------------------------------------------------------------
532
# Function        : BuildProduct
533
#
534
# Description     : Create a family of Platforms with a common product line
535
#                   ie: Create two flavors of the TP5, one based on the MOSF and
536
#                   the othe based on the MOS68 toolset.
537
#
538
# Inputs          : $product[,opts]+    The name of the product
539
#                                       This will be the base name for the family
540
#                                       Allowed options are:
541
#                                           --NotDefault    : This is not a default build platform
542
#                                           --Uses=xxx      : All use another platform
543
#
544
#                   platforms           One or more root platforms, with options
545
#                                       The platform is macro expanded.
546
#                                       Options may be a part of the platform or
547
#                                       distinct.
548
#
549
# Returns         :
550
#
551
 
552
sub BuildProduct
553
{
554
    my( $product, @arguments ) = @_;
555
    my $notdefault = 0;
556
    my @uses = ();
557
 
558
    Debug( "BuildProduct($product, @arguments)" );
559
    Error( "BuildProduct must appear before BuildName()..." )
560
        if ( $BUILDNAME ne "" );
561
 
562
    #   Parse attributes
563
    #
564
    my( @attrs ) = split( ',', $product );
565
 
566
    $product = "";
567
    foreach ( @attrs ) {
568
        if ( /^--/ ) {
569
            if ( /^--NotDefault$/ ) {
570
                $notdefault++;
571
 
572
            } elsif ( /^--Uses=(.*)/ ) {
573
                UniquePush (\@uses, $1);
574
 
575
            } else {
576
                Warning( "BuildProduct() unknown attribute: $_ -- ignored" );
577
            }
578
 
579
        } else {
580
            Error( "BuildProduct() multiple product specifications not allowed" )
581
                if ( $product ne "" );
582
            $product = $_;
583
        }
584
    }
585
 
586
    #
587
    #   Sanity test
588
    #
589
    Error( "BuildProduct() missing product specifications" )
590
        if ( $product eq "" );
591
 
592
    Error( "BuildProduct() product '$product' contains invalid characters" )
593
        if ( $product ne quotemeta( $product ) );
594
 
595
    Error( "BuildProduct() duplicate product '$product'" )
596
        if ( $BUILDPRODUCT{ $product } );
597
 
598
    Error( "BuildProduct() duplicate alias '$product'" )
599
        if ( $BUILDALIAS{ $product } );
600
 
601
    #
602
    #   Expand the user specified targets to allow the use of BuildAlias
603
    #   The (bad) side effect of this is that target options get reorganised
604
    #       PLATFORM,--Uses=ANOTHER  ==> PLATFORM --Uses=ANOTHER
605
    #
606
    #   Insert markers(++) into @aruments to mark when to process collected data
607
    #   Insert before each PLATFORM and at the end of the list
608
    #   platform specifier or the end of the list. Scan the arguments
609
    #
610
    @arguments = ExpandPlatforms( @arguments );
611
    my @new_args;
612
    foreach  ( @arguments )
613
    {
614
        push (@new_args, '++') unless ( m/^--/ );
615
        push (@new_args, $_ );
616
    }
617
    push (@new_args, '++');
618
    shift @new_args if $new_args[0] eq '++';
619
 
620
    my @targs = ();
621
    my $target;
622
    my @tuses = @uses;
623
    foreach my $arg ( @new_args )
624
    {
625
        #
626
        #   Collect per-platform arguments
627
        #
628
        if ( $arg =~ /^--Uses=(.*)/ ) {
629
            UniquePush (\@tuses, $1);
630
            next;
631
 
632
        } elsif ( $arg =~ /^--/ ) {
633
            push @targs, $arg;
634
            next;
635
        }
636
 
637
        #
638
        #   Collect target(platform) name
639
        #
640
        unless ( $arg eq '++' )
641
        {
642
            $target = $arg;
643
            Error( "BuildProduct() cannot create a product based on a GENERIC platform" )
644
                if ( $target eq "GENERIC" );
645
            next;
646
        }
647
 
648
        #
649
        #   Infer a BuildPlatform
650
        #   Do not provide a platform name. This will be created later when the
651
        #   full name is known - or can be calculated.
652
        #
653
        CreateBuildPlatformEntry('BuildProduct', $notdefault, $product, $target, \@tuses, \@targs );
654
 
655
        @targs = ();
656
        @tuses = @uses;
657
        $target = undef;
658
    }
659
}
660
 
661
#-------------------------------------------------------------------------------
662
# Function        : CreateBuildPlatformEntry
663
#
664
# Description     : Internal routine to create the Build Entry
665
#                   Single point to create a platform, whatever one of those is
666
#
667
# Inputs          : $fname                  - Name of invoking directive
668
#                   $notdefault             - True if the platform is not to be added to the
669
#                                             list of default platforms
670
#                   $product                - Optional product name
671
#                   $target                 - Target platform name
672
#                   $pUses                  - Ref to an array of 'Uses'
673
#                   $pArgs                  - Ref to an array of platform arguments
674
#
675
# Returns         :
676
#
677
 
678
my $have_generic;
679
my $have_no_generic;
680
sub CreateBuildPlatformEntry
681
{
682
    my ($fname, $notdefault, $product, $target, $pUses, $pArgs ) = @_;
683
    my %buildentry;
684
    my $platform;
685
 
686
    #
687
    #   Detect GENERIC platform
688
    #       Generic platforms force a build for all
689
    #       Don't mix generic with others
690
    #
691
    if ( $target eq "GENERIC" )
692
    {
693
        $All = 1;
694
        $have_generic = 1;
695
    }
696
    else
697
    {
698
        $have_no_generic = 1;
699
    }
700
    Error("Cannot use a 'GENERIC' platform with any other platform names")
701
        if ( $have_generic && $have_no_generic );
702
 
703
 
704
    #
705
    #   Create a basic BUILDINFO entry
706
    #
707
    $buildentry{FNAME} = $fname;
708
    $buildentry{NOT_DEFAULT} = $notdefault;
709
    $buildentry{PRODUCT} = $product;
710
    $buildentry{TARGET} = $target;
711
    $buildentry{BASE} = $target;
712
    $buildentry{USES} = [ @$pUses ] if $pUses;
713
    $buildentry{ARGS} = [ @$pArgs ] if $pArgs;
714
 
715
    #
716
    #   Allow per-platform processing to be alter the basic information
717
    #   Special processing may be perform to extend the information
718
    #   Allows special processing to be enabled on a per-target basis
719
    #
720
    #   There are three forms of processing that have been allowed for:
721
    #       1) None:        There is not platform specific extension
722
    #       2) Basic:       The extension will add or extend build information
723
    #       3) Advanced:    The extension will generate additional build information
724
    #                       structures.
725
    #
726
 
727
    #
728
    #   Locate the optional PLATFORM configuration file
729
    #   If it does exist then it can alter build-time information
730
    #
731
    if ( my $build_cfg = Require( "$::GBE_CONFIG/PLATFORM", "$target.cfg"  ) )
732
    {
733
        Verbose ("Processing(new) Platform Configuration file: $build_cfg");
734
 
297 dpurdie 735
        #
303 dpurdie 736
        #   Create package name with an uppercase target
737
        #   Target should be UC, but under windows its not detected
738
        #   at this time
739
        #
740
        my $package_name = uc($target) . '_Build';
741
 
742
        #
297 dpurdie 743
        #   Ensure that the CFG is correclt formed
744
        #       Perhaps the package that it implements was misnamed
745
        #
303 dpurdie 746
        Error ("INTERNAL: $target.cfg does not satisfy API " )
297 dpurdie 747
            unless ( $package_name->can('new_platform') || $package_name->can('add_platform') );
748
 
227 dpurdie 749
        if ( $package_name->can('new_platform') )
750
        {
751
            Verbose ("Processing(new) Platform Configuration: $package_name");
752
            $package_name->new_platform( \%buildentry );
753
        }
754
        else
755
        {
756
            Debug ("Processing(new) Platform Configuration: $package_name. 'new_platform' function not found");
757
        }
758
    }
759
 
760
    #
761
    #   Add the basic entry into the build system, unless its been
762
    #   flagged as a TEMPLATE
763
    #
764
    AddBuildPlatformEntry (\%buildentry )
765
        unless ( $buildentry{TEMPLATE} );
766
}
767
 
768
 
769
#-------------------------------------------------------------------------------
770
# Function        : AddBuildPlatformEntry
771
#
772
# Description     : Internal routine to add a Build Entry into the build system
773
#                   This function MAY be called from the build extensions
774
#
775
#                   NOTES:
776
#                   No processing of the info structure is performed. This MUST
777
#                   have been done before now.
778
#
779
#                   Additional information may be added to the structure.
780
#
781
#
782
# Inputs          : $pInfo              - Reference to a BuildInfo structure
783
#
784
# Returns         : Nothing
785
#
786
sub AddBuildPlatformEntry
787
{
788
    my ($pInfo) = @_;
789
    my $fname = $pInfo->{FNAME};
790
 
791
    #
792
    #   Locate the optional PLATFORM configuration file
793
    #   If it does exist then it can extend build-time information
794
    #
795
    my $target = $pInfo->{TARGET};
241 dpurdie 796
 
279 dpurdie 797
    #
798
    #   Yukky Kludge
799
    #   JATS has a mechanism whereby packages can create new platforms
800
    #   Luckily this has only been done for LMOS - don't every do it again
801
    #   One problem is that we can't validate the target name at this point
802
    #   in time: as the packages are loaded much later.
803
    #
804
    #   Kludge. Assume that a leading LMOS_ can be removed when determing
805
    #           validity of the target platform.
806
    #
807
    my $base_target = $target;
808
    $base_target =~ s~^LMOS_~~;
241 dpurdie 809
 
279 dpurdie 810
    #
811
    #   Ensure target is known to JATS
812
    #   Remove unknown targets from the build. Create a list of unknown
813
    #   targets and report them later.
814
    #
815
    #   If there are signs that the target has been processed, then it may be
816
    #   an alias that has not been expanded.
817
    #
818
    #   One result will be that alias platforms, such as DEVLINUX, that don't
819
    #   expand on WIN32 will be shown as DEVLINUX and not its components.
820
    #
281 dpurdie 821
    unless ( $pInfo->{NOT_AVAILABLE} || exists $BUILDINFO{$target} )
227 dpurdie 822
    {
279 dpurdie 823
        unless ( Exists( "$::GBE_CONFIG/PLATFORM", $base_target  ) )
824
        {
825
            UniquePush (\@BUILD_BADNAME, $target );
826
            $pInfo->{NOT_AVAILABLE} = 1;
827
        }
828
    }
829
 
830
    #
831
    #   Mark as NOT_AVAILABLE platforms that are not available on the machine
832
    #
833
    unless ($pInfo->{NOT_AVAILABLE} )
834
    {
835
        $pInfo->{NOT_AVAILABLE} = 1
836
            unless ( PlatformConfig::checkBuildAvailability( $base_target ) );
837
    }
838
 
839
    unless ($pInfo->{NOT_AVAILABLE} )
840
    {
317 dpurdie 841
        my $target_cfg = $pInfo->{TARGET_CFG} || $target ;
842
        if ( my $build_cfg = Require( "$::GBE_CONFIG/PLATFORM", "${target_cfg}.cfg"  ) )
227 dpurdie 843
        {
844
            Verbose ("Processing(add) Platform Configuration file: $build_cfg");
317 dpurdie 845
            my $package_name = "${target_cfg}_Build";
227 dpurdie 846
 
847
            if ( $package_name->can('add_platform') )
848
            {
849
                Verbose ("Processing(add) Platform Configuration: $package_name");
850
                $package_name->add_platform( $pInfo );
851
            }
852
            else
853
            {
854
                Debug ("Processing(add) Platform Configuration: $package_name. 'add_platform' function not found");
855
            }
856
        }
857
    }
858
 
859
    #
860
    #   If a product name has been provided then the platform is a product
861
    #   and will need additional processing
862
    #
863
    if ( $pInfo->{PRODUCT} )
864
    {
865
        #
866
        #   Create the platform name. Derived from the product and the target
867
        #
868
        $pInfo->{PLATFORM} = $pInfo->{PRODUCT} . '_' . $pInfo->{TARGET};
869
 
870
        #
871
        #   Remember the product name
872
        #
873
        $BUILDPRODUCT{ $pInfo->{PRODUCT} } = 1;
874
 
875
        #
876
        #   Add platform name to the alias explansion being created
877
        #   Allows the user to reference the entire FAMILY of platforms
878
        #
879
        HashJoin( \%BUILDALIAS, ' ', $pInfo->{PRODUCT}, $pInfo->{PLATFORM} );
880
 
881
        #
882
        #   Add arguments to the 'alias' based on the product
883
        #   Ensure they don't make it any further
884
        #
885
        HashJoin( \%BUILDALIAS, ' ', $pInfo->{PRODUCT}, @{$pInfo->{ARGS}} ) if ( $pInfo->{ARGS}  );
886
        $pInfo->{ARGS} = undef;
887
 
888
        #
889
        #   Create an element to assist in creating %ScmBuildProducts
890
        #
891
        $pInfo->{ISPRODUCT} = 1;
892
        $BUILDPRODUCT_PARTS{$pInfo->{PLATFORM}} = "$pInfo->{PRODUCT},$pInfo->{TARGET}";
893
    }
894
    else
895
    {
896
        $pInfo->{PRODUCT} = $pInfo->{TARGET};
897
        $pInfo->{PLATFORM} = $pInfo->{TARGET};
898
    }
899
 
900
    #---------------------------------------------------------------------------
901
    #   All the hard work has been done
902
    #   We now know the platforms full name
903
    #
904
    #   Ensure that the target platform has not been been specified
905
    #   Perhaps this should be an error
906
    #
907
    my $platform = $pInfo->{PLATFORM};
908
 
909
    if ( defined ( $BUILDINFO{$platform}) )
910
    {
911
        Warning( "$fname() duplicate platform '$platform' -- ignored" )
912
            unless $Clobber;
913
        return;
914
    }
915
 
916
    #
917
    #   Add platform (tag) to various lists
918
    #
919
    UniquePush( \@BUILDPLATFORMS, $platform );
920
    UniquePush( \@DEFBUILDPLATFORMS, $platform ) unless ( $pInfo->{NOT_DEFAULT} );
921
 
922
    #
923
    #   Create a simple alias if requested
924
    #   Used if a platform creates multiple entires
925
    #
926
    if ( $pInfo->{ALIAS} )
927
    {
317 dpurdie 928
        HashJoin( \%BUILDALIAS_DELAY, ' ', $_, $platform )
929
            foreach ( ArrayList($pInfo->{ALIAS}) );
227 dpurdie 930
    }
931
 
932
    #
933
    #   Create a HARDWARE type alias if requested
934
    #   ie: SOLARIS_SPARC or SOLARIS_X86
935
    #
936
    if ( $pInfo->{HARDWARE} )
937
    {
938
        HashJoin( \%BUILDALIAS_DELAY, ' ',  $pInfo->{BASE} . '_' . $pInfo->{HARDWARE}, $platform );
939
    }
940
 
941
    #
942
    #   Create the 'parts' of the platform. This is a list of unique
943
    #   bits to search. It will consist of:
944
    #       [0]     - platform
945
    #       [1]     - product
946
    #       ...     - Uses bits ...
947
    #       [last]  - target
948
    #
949
    my @parts;
950
    push @parts,    $platform;
951
 
952
    #
953
    #   Include all the product extensions
954
    #
955
    if ( $pInfo->{ISPRODUCT}  )
956
    {
957
        UniquePush (\@parts, map {+ "$pInfo->{PRODUCT}_${_}" } @{$pInfo->{USES}});
958
        UniquePush (\@parts, map {+ "$pInfo->{PRODUCT}_${_}" } @{$pInfo->{ALSO_USES}});
959
        UniquePush (\@parts, $pInfo->{PRODUCT} );
960
    }
961
 
962
    #
963
    #   Add in non-product expanded parts
964
    #
965
    UniquePush (\@parts, @{$pInfo->{EXTRA_USES}});
966
 
967
    #
968
    #   Create a structure to assist in search path resolution
969
    #   The order is important. It sets the include search order for include
970
    #   files and libraries
971
    #   If A uses B then search in A_B, A, B
972
    #       ie: GAK uses MOS68K Search stuff in GAK_MOS68K, GAK, MOS68K
973
    #
974
    #       Usage:  OBFTP uses TP5 on MOSCF(target)       (BuildProduct)
975
    #       Expansion: OBFTP, TP5_MOSCF, TP5
976
    #
977
    #       Usage: VS2003(target) also uses WIN32(uses)     (BuildPlatform)
978
    #       Expansion: VS2003, VS2003_WIN32, WIN32
979
    #
980
    if ( $pInfo->{ISPRODUCT}  )
981
    {
982
        UniquePush (\@parts, map {+ "${_}_$pInfo->{TARGET}", $_, $pInfo->{TARGET}} @{$pInfo->{USES}});
983
        UniquePush (\@parts, map {+ "${_}_$pInfo->{TARGET}", $_, $pInfo->{TARGET}} @{$pInfo->{ALSO_USES}});
984
    }
985
    else
986
    {
987
        UniquePush (\@parts, map {+ "$pInfo->{TARGET}_${_}", $pInfo->{TARGET}, $_} @{$pInfo->{USES}});
988
        UniquePush (\@parts, map {+ "$pInfo->{TARGET}_${_}", $pInfo->{TARGET}, $_} @{$pInfo->{ALSO_USES}});
989
    }
990
 
991
    #
992
    #   Finally - the target
993
    #
994
    UniquePush (\@parts, $pInfo->{TARGET} );
995
 
996
    #
997
    #   Save the PARTS
998
    #   Also saved as BUILDPLATFORM_PARTS for interface with older versions
999
    #   of the deployments scripts.
1000
    #
1001
    $pInfo->{PARTS} = \@parts;
1002
 
1003
    #
1004
    #   Add any arguments to the platforms argument list
1005
    #
1006
    PlatformArgument( $platform, @{$pInfo->{ARGS}} ) if ( $pInfo->{ARGS} );
1007
 
1008
    #
1009
    #   Clean up and save
1010
    #
1011
    delete $pInfo->{TEMPLATE};
1012
    delete $pInfo->{FNAME};
1013
    $BUILDINFO{$platform} = $pInfo;
1014
#    DebugDumpData("BUILDINFO", \%BUILDINFO );
1015
}
1016
 
1017
 
1018
sub BuildArgument
1019
{
1020
    my( $platform, @arguments ) = @_;
1021
    my( @platforms );
1022
 
1023
    Debug( "BuildArgument($platform, @arguments)" );
1024
 
1025
    Error( "BuildArgument must appear before BuildName()..." )
1026
        if ( $BUILDNAME ne "" );
1027
 
1028
    #
1029
    #   Allow a wildcard to apply a single argument to all platforms
1030
    #   Should only be used AFTER all the platforms have been specified
1031
    #
1032
    if ( $platform eq '*' )
1033
    {
1034
        @platforms = @BUILDPLATFORMS;          # Simple Wildcard
1035
    }
1036
    else
1037
    {
1038
        @platforms = ExpandPlatforms( $platform );  # aliasing
1039
    }
1040
 
283 dpurdie 1041
    foreach my $platform ( @platforms )
227 dpurdie 1042
    {
1043
        next if ( $platform =~ /^--/ );         # argument, ignore
1044
 
1045
        PlatformArgument( $platform, @arguments );
1046
    }
1047
}
1048
 
1049
 
1050
sub BuildPlatforms
1051
{
1052
    my( @arguments ) = @_;
1053
    my $fname = "BuildPlatforms";
1054
 
1055
    Debug( "BuildPlatforms(@arguments)" );
1056
 
1057
    Error( "BuildPlatforms must appear before BuildName()..." )
1058
        if ( $BUILDNAME ne "" );
1059
 
1060
    #
1061
    #   Expand the user specified platforms to allow the use of BuildAlias
1062
    #   The (bad) side effect of this is that platform options get reorganised
1063
    #       PLATFORM,--Uses=ANOTHER  ==> PLATFORM --Uses=ANOTHER
1064
    #
1065
    #   Insert markers(++) into @aruments to mark when to process collected data
1066
    #   Insert before each PLATFORM and at the end of the list
1067
    #   platform specifier or the end of the list. Scan the arguments
1068
    #
1069
    @arguments = ExpandPlatforms( @arguments );
1070
    my @new_args;
1071
    foreach  ( @arguments )
1072
    {
1073
        push (@new_args, '++') unless ( m/^--/ );
1074
        push (@new_args, $_ );
1075
    }
1076
    push (@new_args, '++');
1077
    shift @new_args if $new_args[0] eq '++';
1078
 
1079
 
1080
    my $platform  = "";                         # current platform
1081
    my $notdefault  = 0;
1082
    my @uses = ();
1083
    my @pargs = ();
1084
 
1085
    foreach my $arg ( @new_args )
1086
    {
1087
        #
1088
        #   Extract known options
1089
        #   Unknown options bind to the current platform
1090
        #
1091
        if ( $arg =~ /^--/ ) {
1092
            if ( $arg =~ /^--NotDefault$/ ) {
1093
                $notdefault = 1;
1094
 
1095
            } elsif ( $arg =~/^--Uses=(.*)/ ) {
1096
                UniquePush (\@uses, $1);
1097
 
1098
            } elsif ( $arg =~/^--FunctionName=(.*)/ ) {
1099
                $fname = $1;
1100
 
1101
            } else {
1102
                push @pargs, $arg;
1103
            }
1104
            next;
1105
        }
1106
 
1107
        #
1108
        #   New platform. Save name for later. Collect arguments first
1109
        #
1110
        unless ( $arg eq '++' )
1111
        {
1112
            $platform = $arg;
1113
 
1114
            Error( "$fname() missing platform specification" )
1115
                unless ( $platform );
1116
 
1117
            Error( "$fname() product '$platform' contains invalid characters" )
1118
                unless ( $platform eq quotemeta( $platform ) );
1119
 
1120
            next;
1121
        }
1122
 
1123
        #
1124
        #   Create new platform
1125
        #   Have collected name and arguments
1126
        #
1127
        CreateBuildPlatformEntry($fname, $notdefault, undef, $platform, \@uses, \@pargs  );
1128
 
1129
        #
1130
        #   Reset collection variables for next platform
1131
        #
1132
        $platform = "";
1133
        $notdefault  = 0;
1134
        @uses = ();
1135
        @pargs = ();
1136
    }
1137
}
1138
 
1139
 
1140
#   PlatformArgument ---
1141
#       Append an argument list to the specified platform argument list.
1142
#       Internal use only
1143
#..
1144
 
1145
sub PlatformArgument
1146
{
1147
    my( $platform, @arguments ) = @_;
1148
 
1149
    Debug( "  PlatformArguments($platform, @arguments)" );
1150
 
1151
    HashJoin( \%BUILDPLATFORMARGS, $;, $platform, @arguments )
1152
        if ( $platform );
1153
}
1154
 
279 dpurdie 1155
#-------------------------------------------------------------------------------
1156
# Function        : BuildName
1157
#
1158
# Description     : Defines the package name and version
1159
#
1160
# Inputs          : build arguments
1161
#                   Various formats are allowed for backward compatability
1162
#                   Must support a number of different formats
1163
#                       "name nn.nn.nn prj"
1164
#                       "name nn.nn.nn.prj"
1165
#
1166
#                       "name nn.nn.nn prj", "nn.nn.nn"
1167
#                       "name nn.nn.nn.prj", "nn.nn.nn"
1168
#
1169
#                       "name", "nn.nn.nn.prj"
1170
#
1171
#                       "name", "nn.nn.nn", "prj", --RelaxedVersion
1172
#
1173
# Returns         : Nothing
1174
#
227 dpurdie 1175
sub BuildName
1176
{
1177
    my( @arguments ) = @_;
1178
    my $relaxed_version_name = 0;
1179
    my @args;
1180
 
1181
    Debug( "BuildName(@arguments)" );
1182
 
315 dpurdie 1183
    Error( "Platform(s) not defined.",
227 dpurdie 1184
            "BuildAlias, BuildProduct and BuildPlatform directives must be defined prior to BuildName()." )
1185
        unless( scalar @BUILDPLATFORMS );
1186
 
1187
#.. Parse arguments
1188
#.
1189
    my $build_info = parseBuildName( @arguments );
1190
 
1191
    $BUILDNAME_PACKAGE = $build_info->{BUILDNAME_PACKAGE};
1192
    $BUILDNAME_VERSION = $build_info->{BUILDNAME_VERSION};
1193
    $BUILDNAME_PROJECT = $build_info->{BUILDNAME_PROJECT};
1194
 
1195
    $BUILDNAME         = $build_info->{BUILDNAME};
1196
    $BUILDVERSION      = $build_info->{BUILDVERSION};
1197
 
1198
    $DEPLOY_PATCH      = $build_info->{DEPLOY_PATCH} || 0;
1199
 
1200
    #
1201
    #   Clobber processing done after values have been accumulated
1202
    #   as they may be used later
1203
    #
1204
    push @CLOBBERFILES, 'build.log';
1205
    push @CLOBBERFILES, 'ChangeLog', 'ChangeLog.bak' if ( $ScmHost eq "Unix" );
1206
    return if ( $Clobber );
1207
 
1208
#.. Create the ChangeLog
1209
#
1210
    if ( -d "CVS" )                             # CVS support subdir
1211
    {
1212
        System( "$::GBE_PERL $::GBE_TOOLS/cvs2cl.pl --tags --branches --revisions --day-of-week" )
1213
            if ( $Nolog == 0 && $ScmHost eq "Unix" );
1214
    }
1215
 
1216
 
1217
#.. Create build.log summary information
1218
#
261 dpurdie 1219
    my ($sep) = "\n".(" " x 11) . ". ";
227 dpurdie 1220
 
261 dpurdie 1221
    Log( "\nBuild configuration (version $::GBE_VERSION)" );
1222
    Log( "Name ....... $BUILDNAME ($ScmHost)" );
1223
    Log( "Version .... $BUILDNAME_VERSION" );
1224
    Log( "DeployPatch. $DEPLOY_PATCH" ) if ($DEPLOY_PATCH);
1225
    Log( "Project .... $BUILDNAME_PROJECT" )if ($BUILDNAME_PROJECT);
1226
    Log( "Project .... ****** Specifically supressed ******" )unless ($BUILDNAME_PROJECT);
1227
    Log( "DateTime ... $::CurrentTime" );
1228
    Log( "AutoBuild... Enabled:$::GBE_ABT" ) if defined($::GBE_ABT) ;
1229
    Log( "Build dir... $Cwd" ) if defined($::GBE_ABT) ;
227 dpurdie 1230
 
261 dpurdie 1231
    Log( "BIN  ....... $::GBE_BIN" );
1232
    Log( "PERL ....... $::GBE_PERL" );
1233
    Log( "TOOLS ...... $::GBE_TOOLS" );
1234
    Log( "CONFIG ..... $::GBE_CONFIG" );
1235
    Log( "MACHTYPE ... $::GBE_MACHTYPE" );
227 dpurdie 1236
 
261 dpurdie 1237
    Log( "PLATFORM ... " . PrintList([split(' ', $::GBE_PLATFORM)], $sep) )    if defined ($::GBE_PLATFORM);
1238
    Log( "BUILDFILTER. " . PrintList([split(' ', $::GBE_BUILDFILTER)], $sep) ) if defined ($::GBE_BUILDFILTER);
227 dpurdie 1239
 
261 dpurdie 1240
    Log( "DPKG_STORE.. $::GBE_DPKG_STORE" );
1241
    Log( "DPKG ....... $::GBE_DPKG" );
1242
    Log( "DPKG_CACHE . $::GBE_DPKG_CACHE" );
1243
    Log( "DPKG_LOCAL . $::GBE_DPKG_LOCAL" );
1244
    Log( "DPKG_SBOX .. $::GBE_DPKG_SBOX" );
227 dpurdie 1245
 
261 dpurdie 1246
    Log( "Platforms .. " . PrintPlatforms(\@BUILDPLATFORMS, $sep) );
227 dpurdie 1247
 
1248
    #
241 dpurdie 1249
    #   Generate a list of platforms that are completely unknown to JATS
1250
    #   May be the result of a user type or a guess
1251
    #
1252
    if ( @BUILD_BADNAME )
1253
    {
281 dpurdie 1254
        Log( "Unknown Pl . " . PrintPlatforms(\@BUILD_BADNAME, $sep) );
241 dpurdie 1255
         Warning ("The following platform names are not known to JATS", "@BUILD_BADNAME");
1256
    }
1257
 
1258
    #
227 dpurdie 1259
    #   Generate a list of active platforms
1260
    #   Ensure that there are some active platforms
1261
    #
1262
    GeneratePlatformList();
1263
    Error( "GBE_BUILDFILTER prevents any targets being built" )
1264
        unless( @BUILD_ACTIVEPLATFORMS );
261 dpurdie 1265
    Log( "Build for .. ". PrintPlatforms(\@BUILD_ACTIVEPLATFORMS, $sep));
227 dpurdie 1266
 
1267
    #
1268
    #   Generate an error if nothing can be done because the GBE_PLATFORM
1269
    #   masks any useful operation.
1270
    #
1271
    if ( $::GBE_PLATFORM )
1272
    {
1273
        my @MAKE_PLATFORMS;
1274
        my %active_platforms;
1275
 
239 dpurdie 1276
        #
1277
        #   Create a hash of active platforms based on the array of
1278
        #   active platforms to simplify testing
1279
        #
1280
        $active_platforms{$_} = 1 foreach ( @BUILD_ACTIVEPLATFORMS  );
227 dpurdie 1281
 
239 dpurdie 1282
        unless ( defined($active_platforms{GENERIC}) )
227 dpurdie 1283
        {
239 dpurdie 1284
            foreach  ( split( ' ', $::GBE_PLATFORM) )
1285
            {
1286
                push @MAKE_PLATFORMS, $_
1287
                    if ( $active_platforms{$_} );
1288
            }
227 dpurdie 1289
 
239 dpurdie 1290
            Error ("The GBE_PLATFORM filter prevents any targets being made",
1291
                   "GBE_PLATFORM: $::GBE_PLATFORM" ) unless ( @MAKE_PLATFORMS );
227 dpurdie 1292
 
261 dpurdie 1293
            Log( "Make for ... ". PrintPlatforms(\@MAKE_PLATFORMS, $sep));
239 dpurdie 1294
        }
227 dpurdie 1295
 
1296
    }
1297
 
1298
    return 1;
1299
}
1300
 
1301
 
1302
sub BuildPreviousVersion
1303
{
1304
    my( $version ) = shift;
1305
 
1306
    $BUILDPREVIOUSVERSION = $version;
261 dpurdie 1307
    Log( "Previous Version ... $BUILDPREVIOUSVERSION" );
227 dpurdie 1308
 
1309
    return 1;
1310
}
1311
 
1312
 
1313
sub BuildInterface
1314
{
1315
    my( $ifdirname ) = @_;
1316
 
1317
 
1318
    #
1319
    #   Clobber the directory - at the end.
1320
    #
1321
    if ( $Clobber )
1322
    {
1323
        #
1324
        #   If this Interface directory contains the Dpackage.cfg file
1325
        #   then JATS has created DPACKAGE and it needs to be clobbered
1326
        #   Flag that it needs to be done later - when we know where it is
1327
        #
1328
        $DeleteDPACKAGE = 1 if ( -f "$ifdirname/Dpackage.cfg" );
1329
 
1330
        push @CLOBBERDIRS, $ifdirname;
1331
        return;
1332
    }
1333
 
1334
    #
1335
    #   In AutoBuildTool mode the entire interface directory
1336
    #   will be deleted. This allows the build to be retried
1337
    #
1338
    if (  defined($::GBE_ABT) )   # clobber mode ?
1339
    {
1340
        if ( -d "$ifdirname" )
1341
        {
341 dpurdie 1342
                rmtree ( $ifdirname );
227 dpurdie 1343
        }
1344
    }
1345
 
1346
    if ( $ifdirname eq "local" ) {
341 dpurdie 1347
        mkpath ( "$ifdirname/inc" );
227 dpurdie 1348
        $BUILDLOCAL = "local";
1349
 
1350
    } else {
341 dpurdie 1351
        mkpath ( "$ifdirname/include" );
227 dpurdie 1352
        $BUILDINTERFACE = $ifdirname;
1353
        $::ScmInterface = $ifdirname;
1354
    }
341 dpurdie 1355
    mkpath ( "$ifdirname/bin" );
1356
    mkpath ( "$ifdirname/lib" );
227 dpurdie 1357
 
261 dpurdie 1358
    Log( "Interface .. $ifdirname" );
227 dpurdie 1359
    return 1;
1360
}
1361
 
1362
 
1363
sub BuildDirTree
1364
{
1365
    my( $dirfile, $dirhead ) = @_;
1366
    my( $dirname, $c );
1367
 
1368
    $dirhead = '.'
1369
        unless defined( $dirhead );
1370
 
1371
    if ( $Clobber )                             # clobber mode ?
1372
    {
1373
        push @CLOBBERDIRS, $dirhead unless $dirhead eq '.';
1374
        return;
1375
    }
1376
 
1377
    #
1378
    #   Allow for an empty "dirfile". This will allow a directory to be created
1379
    #   without the overhead of the file
1380
    #
1381
    if ( ! $dirfile )
1382
    {
261 dpurdie 1383
        Log( "DirTree .... $dirhead" );
341 dpurdie 1384
        mkpath ( $dirhead );
227 dpurdie 1385
    }
1386
    else
1387
    {
261 dpurdie 1388
        Log( "DirTree .... $dirfile within $dirhead" );
341 dpurdie 1389
        mkpath ( $dirhead );
1390
 
283 dpurdie 1391
        open( DIRFILE, '<' ,$dirfile ) ||
227 dpurdie 1392
            Error( "cannot open '$dirfile'" );
1393
 
1394
        while( $dirname = <DIRFILE> )
1395
        {
1396
            chop $dirname;
1397
            $dirname =~ s/#.*//;
1398
            $c = $dirname =~ s/\s*(\S+).*/$1/g;
1399
 
1400
            next unless ( $c == 1 );
1401
 
1402
            if ( ! -d "$dirhead/$dirname" )
1403
            {
261 dpurdie 1404
                Log( "Dir ........ $dirhead/$dirname" );
341 dpurdie 1405
                mkpath ( "$dirhead/$dirname" );
227 dpurdie 1406
            }
1407
        }
1408
 
1409
        close( DIRFILE );
1410
    }
1411
    $BUILDDIRTREE = $dirhead;
1412
}
1413
 
1414
#-------------------------------------------------------------------------------
1415
# Function        : IncludePkg
1416
#
1417
# Description     : Examine a fully specified package directory for a file
1418
#                   that will specify packages to be included. This allows
1419
#                   a package to be simply a package of other packages
1420
#
1421
#                   Internal function. Not to be used by users
1422
#
1423
# Inputs          : Name of the package
1424
#                   Full directory path of the package to examine
1425
#
1426
# Returns         : Nothing
1427
#
1428
sub IncludePkg
1429
{
1430
    my ($name, $pkg) = @_;
1431
    my $file = "$pkg/incpkg";
1432
 
1433
    Debug ("IncludePkg: $pkg" );
1434
 
1435
    #
1436
    #   Using a require will ensure that the package is only processed once
1437
    #   even though the function user may be called multiple times.
1438
    #   Also prevents recursion within included packages.
1439
    #
1440
    if ( -f $file  )
1441
    {
261 dpurdie 1442
        Log( "PackageIncludes. $name" ) unless ( $INC{$file} );
227 dpurdie 1443
        require $file;
1444
    }
1445
}
1446
 
1447
 
1448
sub LinkSandbox
1449
{
1450
    my( $name, $path, $platform ) = @_;
1451
    return if ( $Clobber );                     # clobber mode ?
1452
 
1453
    Error ("LinkSandbox() expects three arguments:  @_")
1454
        unless ( $#_ == 2 );
1455
 
299 dpurdie 1456
    Error ("LinkSandbox not allowed in ABT build")
1457
        if ( $::GBE_ABT );
1458
 
227 dpurdie 1459
    Debug( "LinkSandbox:" );
1460
    Debug( "Package:   $name" );
1461
    Debug( "Version:   $path" );
1462
 
1463
    DataDirective("LinkSandbox");               # This directive allowed here
1464
 
1465
#
1466
#   If GBE_BUILDFILTER exists, Import 'user' platform
1467
#   specification and filter against the BUILD_ACTIVEPLATFORMS.
1468
#
261 dpurdie 1469
    Log( "LinkSandbox. $name ($path)" );
227 dpurdie 1470
 
1471
    if ( ! -d $path )                           # sandbox exists ?
1472
    {
261 dpurdie 1473
        Log( "WARNING .... Sandbox $path not available" );
227 dpurdie 1474
    }
1475
    else
1476
    {
1477
        $path = Realpath( $path );
1478
 
1479
        if ( !defined($platform) || $platform eq "*" ) 
1480
        {
1481
            foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
1482
            {
331 dpurdie 1483
                LinkEntry( $platform, $path, $name, "!sandbox", 1, 1 );
227 dpurdie 1484
            }
1485
        }
1486
        else
1487
        {
1488
            my(@platforms) = split( ',', $platform );
1489
            @platforms = ExpandPlatforms( @platforms );
1490
 
1491
            foreach my $platform ( @platforms )
1492
            {
331 dpurdie 1493
                LinkEntry( $platform, $path, $name, "!sandbox", 1, 1 );
227 dpurdie 1494
            }
1495
        }
1496
    }
1497
}
1498
 
1499
 
1500
#-------------------------------------------------------------------------------
1501
# Function        : LinkPkgArchive
1502
#
1503
# Description     : Include an external package into the build sandbox
1504
#                   by extending the compiler and linker search paths to
1505
#                   include suitable directories found in the package
1506
#
1507
# Inputs          : package name
1508
#                   package version
1509
#
1510
sub LinkPkgArchive
1511
{
1512
    my( $name, $version ) = @_;
1513
 
1514
    return BuildPkgArchive( @_ )
1515
        if ( $ForceBuildPkg );                  # Forcing interface directory
1516
    return if ( $Clobber );                     # clobber mode ?
1517
 
1518
    Debug( "LinkPkgArchive:" );
1519
    Debug( "Name:      $name" );
1520
    Debug( "Version:   $version" );
1521
 
1522
    DataDirective("LinkPkgArchive");            # This directive allowed here
1523
 
1524
    #
1525
    #   Ensure that we have do not have multiple definitions
1526
    #
1527
    if ( PackageEntry::Exists( $name, $version ) )
1528
    {
261 dpurdie 1529
        Log( "Duplicate Package: $name, $version. Duplicate entry ignored" );
227 dpurdie 1530
        return;
1531
    }
1532
 
1533
    if ( $Cache && $::GBE_DPKG_CACHE )
1534
    {
1535
        my $mode = ($Cache > 1) ? "-refresh" : "";
331 dpurdie 1536
        Log( "LinkPkgArchive .. $name ($version) Update Cache" );
227 dpurdie 1537
        System('--NoExit', "$::GBE_PERL $::GBE_TOOLS/cache_dpkg.pl $mode -quiet $name/$version" );
1538
    }
1539
 
1540
    #
1541
    #   Locate the package ONCE
1542
    #
331 dpurdie 1543
    Log( "LinkPkgArchive .. $name ($version)" );
227 dpurdie 1544
    my ($pkg, $local ) = PackageLocate( $name, $version );
1545
    if ( $pkg )
1546
    {
1547
        #
1548
        #   Generate package rules for each active platform
1549
        #
1550
        foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
1551
        {
331 dpurdie 1552
            LinkEntry( $platform, $pkg, $name, $version, 0, $local );
227 dpurdie 1553
        }
1554
    }
1555
}
1556
 
1557
sub LinkClean
1558
{
343 dpurdie 1559
    if ( $BUILDINTERFACE )
227 dpurdie 1560
    {                                           # only once
1561
        Debug( "LinkClean" );
1562
 
1563
        foreach my $platform ( @BUILDPLATFORMS )
1564
        {                                       # remove generated images
341 dpurdie 1565
            rmtree( "$BUILDINTERFACE/$platform.rul" );
227 dpurdie 1566
        }
1567
    }
1568
}
1569
 
1570
 
1571
#-------------------------------------------------------------------------------
1572
# Function        : PackageLocate
1573
#
1574
# Description     : Locate a package
1575
#                   Once located a package will be processed for each
1576
#                   platform, but it need only be located ONCE
1577
#
1578
# Inputs          : package name
1579
#                   package version
1580
#
1581
# Returns         : path to the package
1582
#                   local       1 - From local package repository
1583
#
1584
sub PackageLocate
1585
{
1586
    my ($name, $uversion ) = @_;
283 dpurdie 1587
    my $pkg;
227 dpurdie 1588
    my $local = 1;
1589
    my $sandbox = 1;
1590
    my $isa_cache = 0;
1591
    my $version;
1592
    my ($pn, $pv, $ps ) = SplitPackage ($name, $uversion );
1593
 
1594
    Debug( "PackageLocate: ($name/$uversion)" );
1595
 
1596
    #
1597
    #   Look in each package archive directory
1598
    #
1599
    foreach my $dpkg ( split( $::ScmPathSep, $::GBE_DPKG_SBOX),
1600
                       '--NotSandbox',
1601
                       split( $::ScmPathSep, $::GBE_DPKG_LOCAL),
1602
                       '--NotLocal',
1603
                       split( $::ScmPathSep, $::GBE_DPKG_CACHE),
1604
                       '--NotCache',
1605
                       split( $::ScmPathSep, $::GBE_DPKG),
313 dpurdie 1606
                       split( $::ScmPathSep, $::GBE_DPLY),
227 dpurdie 1607
                       split( $::ScmPathSep, $::GBE_DPKG_STORE) )
1608
    {
1609
 
1610
        #
1611
        #   Detect various tags that have been placed in the search list
1612
        #   to flag the end of the sandbox search and the end of the local
1613
        #   archive search
1614
        #
1615
        if ( $dpkg eq '--NotSandbox' )
1616
        {
1617
            $sandbox = 0;
1618
            next;
1619
        }
1620
        if ( $dpkg eq '--NotLocal' )
1621
        {
1622
            $local = 0;
1623
            $isa_cache = 1;
1624
            next;
1625
        }
1626
        if ( $dpkg eq '--NotCache' )
1627
        {
1628
            $isa_cache = 0;
1629
            next;
1630
        }
1631
 
1632
 
1633
        #
1634
        #   If we are playing in a sandbox, then the version number is
1635
        #   not used. The Package suffix is still used so that we can
1636
        #   differentiate sysbasetypes.xxxxx.mas and sysbasetypes.xxxxx.syd
1637
        #
1638
        if ( $sandbox )
1639
        {
1640
            $version = 'sandbox';
1641
            $version .= '.' . $ps if ( $ps );
1642
        }
1643
        else
1644
        {
1645
            $version = $uversion;
1646
        }
1647
 
1648
        #
1649
        #   Alias support
1650
        #   If the 'version' is '!current' then use a version of:
1651
        #       current
1652
        #       current_<USER_NAME>
1653
        #   This is an old mechanism whose use should not be encouraged
1654
        #
1655
        #..
1656
        if ( $version eq "!current" )
331 dpurdie 1657
        {
1658
            Error ("Use of !version is not allowed in ABT build")
1659
                if ( $::GBE_ABT );
227 dpurdie 1660
 
331 dpurdie 1661
            $pkg = "$dpkg/$name/current";       # current
227 dpurdie 1662
            $pkg = "$dpkg/$name/current.lnk"
1663
                if ( -e "$dpkg/$name/current.lnk" );
1664
 
331 dpurdie 1665
                                                # USER specific current
1666
            EnvImport( "USER" );
227 dpurdie 1667
            $pkg = "$dpkg/$name/current_$::USER"
1668
                if ( -e "$dpkg/$name/current_$::USER" );
1669
 
1670
            $pkg = "$dpkg/$name/current_$::USER.lnk"
1671
                if ( -e "$dpkg/$name/current_$::USER.lnk" );
1672
        }
1673
        else
1674
        {                                       # standard
1675
            $pkg = "$dpkg/$name/$version";
1676
            $pkg = "$dpkg/$name/$version.lnk"
1677
                if ( -e "$dpkg/$name/$version.lnk" );
1678
        }
1679
 
1680
        #
1681
        #   Using a soft link
1682
        #   Emulate a link in software. The link file contains one line
1683
        #   which is the real pathname of the package
1684
        #
1685
        if ( $pkg =~ m~(.*)\.lnk$~  )
1686
        {
1687
            #
1688
            #   Warn the user if both a link and a real directory
1689
            #   are both present - the link may well be incorrect
1690
            #
1691
            my $non_link = $1;
1692
            Warning ("Suspect package link: $pkg",
1693
                     "Both a link and a package where found - using the link" )
1694
                                                            if ( -d $non_link );
1695
 
1696
            Debug( "           link found -> $pkg" );
1697
            my $link_src = $pkg;
283 dpurdie 1698
            open( LNKFILE, '<', "$pkg" ) || Error( "cannot open '$pkg'" );
227 dpurdie 1699
            $pkg = <LNKFILE>;                   # real path
1700
            close( LNKFILE );
1701
            $pkg = '' unless ( $pkg );
325 dpurdie 1702
            $pkg =~ s~\s+$~~;;
227 dpurdie 1703
 
1704
            Error ("Broken link: $pkg",
1705
                   "Source link: $link_src",
1706
                   "Try deleting the .lnk file" ) unless ( -d $pkg );
1707
        }
1708
 
1709
        Debug( "           searching $pkg" );
1710
 
1711
        #   Does the package directory exist?
1712
        #   Terminate the directory name with a "/" to detect hidden spaces
1713
        #..
1714
        $pkg =~ s~//~/~g;
1715
        next unless ( -d "$pkg/" );             # exists ?
1716
 
1717
        #
1718
        #   If the package exists within the dpkg_archive cache then mark the
1719
        #   version as having been used. Used by cache cleanup algorithms
1720
        #
1721
        if ( $isa_cache  )
1722
        {
1723
            TouchFile ( "$pkg/used.cache", "Marks the cache copy as being used");
1724
        }
1725
 
1726
        #
1727
        #   Use the first suitable package found
1728
        #..
1729
 
1730
        Debug( "           importing $pkg" );
1731
        return $pkg, $local;
1732
    }
1733
 
1734
    #
1735
    #   Package not found
1736
    #   This is an error, although it can be bypassed
1737
    #
261 dpurdie 1738
    Error ("Required package not found: '$name/$version'" ) unless ( $NoPackageError );
227 dpurdie 1739
 
261 dpurdie 1740
    Log( "WARNING .... Package not available: '$name/$version'" );
283 dpurdie 1741
    return;
227 dpurdie 1742
}
1743
 
1744
 
1745
#-------------------------------------------------------------------------------
1746
# Function        : LinkEntry
1747
#
1748
# Description     : Scan a package an locate platform specific directories
1749
#                   Create data structures to capture the information
1750
#                   This function is used by LinkPkgArchive and LinkSandbox
1751
#                   to perfom the bulk of package inclusion work.
1752
#
1753
# Inputs          : platform being processed
1754
#                   path to the package
1755
#                   name of the package
1756
#                   version of the package
1757
#                   sandbox support (non-zero)
331 dpurdie 1758
#                   local package
227 dpurdie 1759
#
1760
sub LinkEntry
1761
{
331 dpurdie 1762
    my( $platform, $pkg, $name, $version, $sandbox, $local ) = @_;
227 dpurdie 1763
    my( $entry );
1764
 
1765
    #   Create entry record
1766
    #
1767
    #..
331 dpurdie 1768
    $entry = PackageEntry::New( $pkg, $name, $version, $sandbox, 'link', $local );
227 dpurdie 1769
 
1770
    #   Populate includes:
1771
    #
1772
    #   - include/$platform                 (eg include/solaris)
1773
    #   - inc/$platform                     (eg inc/solaris)
1774
    #   - include.$platform                 (eg include.solaris)
1775
    #   - inc.$platform                     (eg inc.solaris)
1776
    #   - include                           (eg include)
1777
    #   - inc                               (eg inc)
1778
    #
1779
    #   plus, product specialisation directores
1780
    #
1781
    #   eg. BuildProduct( 'IDFC', 'WIN32' );
1782
    #
1783
    #   - inc/IDFC_WIN32                    <- derived platform
1784
    #   - inc/IDFC                          <- product
1785
    #   - inc/WIN32                         <- target
1786
    #..
1787
    my $parts = $BUILDINFO{$platform}{PARTS};
1788
 
1789
    foreach my $part ( @$parts )
1790
    {
1791
        $entry->RuleInc( "/include." . $part ) if ( !$sandbox );
1792
        $entry->RuleInc( "/inc." . $part )     if ( !$sandbox );
1793
        $entry->RuleInc( "/include/" . $part ) if ( !$sandbox );
1794
        $entry->RuleInc( "/inc/" . $part );
1795
    }
1796
 
1797
    #
1798
    #   Also search the root include directory - last
1799
    #
1800
    $entry->RuleInc( "/include" )               if ( !$sandbox );
1801
    $entry->RuleInc( "/inc" );
1802
 
1803
    #   Populate libraries:
1804
    #
1805
    #   - lib/lib.$platform[D|P]            (eg lib/lib.sparcD)
1806
    #   - lib/$platform[D|P]                (eg lib/lib.sparc)
1807
    #   - lib.$platform[D|P]                (eg lib.sparcD)
1808
    #
1809
    #   plus, product specialisation directores
1810
    #
1811
    #   eg. BuildProduct( 'IDFC', 'WIN32' );
1812
    #
1813
    #   - lib/IDFC_WIN32                    <- derived platform
1814
    #   - lib/IDFC                          <- product
1815
    #   - lib/WIN32                         <- target
1816
    #..
1817
    $parts = $BUILDINFO{$platform}{PARTS};
1818
 
1819
    foreach my $part ( @$parts )
1820
    {
1821
        $entry->RuleLib("/lib" . ".$part" )     if ( !$sandbox );
1822
        $entry->RuleLib("/lib" . "/lib.$part" ) if ( !$sandbox );
1823
        $entry->RuleLib("/lib" . "/$part" );
1824
    }
1825
 
1826
    #
1827
    #   Some extra places to search
1828
    #   None. This is good as it indicates that all locations are described in PARTS
1829
    #
1830
    #   Do NOT search in /lib. There are no libraries that work on all platforms
1831
    #   Libraries are binaries!
1832
    #
1833
    #    $entry->RuleLib( "/lib" );
1834
 
1835
    #   Tools:
1836
    #
1837
    #   Tools provide an extensible search path for tools and
1838
    #   utilities used to build programs. These are tools that
1839
    #   are executable on the current host machine and are
1840
    #   independent of the toolset.
1841
    #
1842
    #..
1843
    $entry->ExamineToolPath();
1844
    $entry->ExamineThxPath($platform);
1845
    IncludePkg ( $name, $pkg );
1846
    $entry->Cleanup();                          # cleanup tables
1847
 
1848
    #
1849
    #   Add the package entry to the array of such entries for
1850
    #   the current platform. Maintain the discovery order
1851
    #
1852
    #..
1853
    push ( @{$PKGRULES{$platform}}, $entry );
1854
}
1855
 
1856
 
1857
#-------------------------------------------------------------------------------
1858
# Function        : BuildPkgArchive
1859
#
1860
# Description     : Include an external package into the build sandbox
1861
#                   by copying the packages files into the interface directory
1862
#
1863
# Inputs          : package name
1864
#                   package version
1865
#
1866
sub BuildPkgArchive
1867
{
1868
    my( $name, $version ) = @_;
1869
 
1870
    return if ( $Clobber );                     # clobber mode ?
1871
 
1872
    Debug( "BuildPkgArchive:" );
1873
    Debug( "Name:      $name" );
1874
    Debug( "Version:   $version" );
1875
 
1876
    DataDirective("BuildPkgArchive");           # This directive allowed here
1877
 
1878
    #
1879
    #   Ensure that we have do not have multiple definitions
1880
    #
1881
    if ( PackageEntry::Exists( $name, $version ) )
1882
    {
261 dpurdie 1883
        Log( "Duplicate Package: $name, $version. Duplicate entry ignored" );
227 dpurdie 1884
        return;
1885
    }
1886
 
1887
    if ( $Cache && $::GBE_DPKG_CACHE )
1888
    {
1889
        my $mode = ($Cache > 1) ? "-refresh" : "";
261 dpurdie 1890
        Log( "BuildPkgArchive . $name ($version) Update Cache" );
227 dpurdie 1891
        System('--NoExit', "$::GBE_PERL $::GBE_TOOLS/cache_dpkg.pl $mode -quiet $name/$version" );
1892
    }
1893
 
1894
    #
1895
    #   Locate the package
1896
    #   Use the first instance of the package that it found
1897
    #
261 dpurdie 1898
    Log( "BuildPkgArchive . $name ($version)" );
227 dpurdie 1899
    my ( $pkg, $local ) = PackageLocate( $name, $version );
1900
    if ( $pkg )
1901
    {
1902
        #
1903
        #   Create a Package Entry
1904
        #
331 dpurdie 1905
        my $entry = PackageEntry::New( $pkg, $name, $version, 0, 'build', $local );
227 dpurdie 1906
 
1907
        #
1908
        #   Determine if the package needs to be installed:
1909
        #       If the package is a 'local' package then force transfer
1910
        #       If the user has specified --cache then force transfer
1911
        #       If package is newer that copy, then force transfer
1912
        #       If copy does not exist, then force a transfer
1913
        #
1914
        my $tag_dir = "$Cwd/$BUILDINTERFACE/BuildTags";
1915
        my $tag_file = "$tag_dir/${name}_${version}.tag";
1916
 
1917
        my $package_installed;
1918
        $package_installed = 1
1919
            if ( !$local &&
1920
                 !$Cache &&
1921
                 !FileIsNewer( $entry->GetBaseDir('descpkg'), $tag_file ) );
1922
 
1923
        #
1924
        #   Determine the package format and use the appropriate installer
1925
        #   Supported formats
1926
        #       1) Package has a descpkg file (new style)
1927
        #       2) Package has a InstallPkg.sh file (old style)
1928
        #       3) Package has a Install.sh file (old style is it used ??)
1929
        #
1930
        if ( $package_installed ) {
1931
            Verbose ("Package already installed: $name, $version");
1932
 
1933
        } else {
261 dpurdie 1934
            Log( "                . installing '$pkg'" );
1935
            Log( "                . -> " . readlink($pkg) ) if ( -l $pkg );
227 dpurdie 1936
 
1937
            if ( -e "$pkg/descpkg" )
1938
            {
1939
 
1940
                #
1941
                #   If forcing a BuildPkg, then don't use symlinks
1942
                #   to files in dpkg_archive
1943
                #
331 dpurdie 1944
                my @opts;
1945
                push @opts, "--NoSymlinks" if ( $ForceBuildPkg );
1946
                push @opts, "--AllowOverWrite" if ( $local );
227 dpurdie 1947
 
1948
                #
1949
                #   Determine all the Platforms, Products and Targets
1950
                #   that need to be installed
1951
                #
1952
                my $arglist = GenerateInstallArgumentList();
331 dpurdie 1953
                System( "cd $pkg; $::GBE_PERL $::GBE_TOOLS/installpkg.pl $Cwd/$BUILDINTERFACE $Cwd @opts $arglist");
227 dpurdie 1954
                Error( "Package installation error" ) if ( $? != 0 );
1955
            }
1956
            elsif ( -e "$pkg/InstallPkg.sh" )
1957
            {
1958
                System( "(cd $pkg; ./InstallPkg.sh $Cwd/$BUILDINTERFACE $Cwd)" );
1959
            }
1960
            elsif ( -e "$pkg/Install.sh" )
1961
            {
1962
                System( "(cd $pkg; ./Install.sh $Cwd/$BUILDINTERFACE $Cwd)" );
1963
            }
1964
            else
1965
            {
1966
                Error ("Unknown package format for package $name/$version found in $pkg");
1967
            }
1968
 
1969
            #
1970
            #   Tag the package as installed - after it has been transferred
1971
            #
1972
            mkdir ( $tag_dir );
1973
            TouchFile( $tag_file );
1974
        }
1975
 
1976
        #
1977
        #   Process package
1978
        #
1979
        IncludePkg ( $name, $pkg );
1980
 
1981
        #
1982
        #   Complete the creation of the package entry
1983
        #   Add the information for all platforms
1984
        #
1985
        $entry->Cleanup();
1986
        for my $platform (@BUILD_ACTIVEPLATFORMS)
1987
        {
1988
            $entry->ExamineToolPath();
1989
            $entry->ExamineThxPath($platform);
1990
            push ( @{$PKGRULES{$platform}}, $entry );
1991
        }
1992
    }
1993
}
1994
 
1995
#-------------------------------------------------------------------------------
311 dpurdie 1996
# Function        : CreateInterfacePackage
1997
#
1998
# Description     : Create a dummy package entry to describe the Interface
1999
#                   This is done AFTER all the BuildPkgArchive directives have
2000
#                   been processed so that the interface directory is fully
2001
#                   processed
2002
#
2003
# Inputs          : None
2004
#
2005
# Returns         : 
2006
#
2007
sub CreateInterfacePackage
2008
{
2009
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
2010
    {
2011
        my $entry = PackageEntry::Interface( "$::Cwd/$BUILDINTERFACE" );
2012
 
2013
        #
2014
        #   Locate include and lib bits within the interface
2015
        #   This is much simpler than for a LinkPkgArchive as the form
2016
        #   has been sanitized
2017
        #
2018
        my $parts = $BUILDINFO{$platform}{PARTS};
2019
 
2020
        foreach my $part ( @$parts )
2021
        {
2022
            $entry->RuleInc( "/include/" . $part );
2023
        }
2024
        $entry->RuleInc( "/include" );
2025
 
2026
        foreach my $part ( @$parts )
2027
        {
2028
            $entry->RuleLib("/lib/" . $part );
2029
        }
2030
 
2031
        $entry->ExamineToolPath();
2032
        $entry->ExamineThxPath($platform);
2033
        $entry->Cleanup();
2034
 
2035
        #
2036
        #   Add the package entry to the array of such entries for
2037
        #   the current platform. Force it to be the first one as
2038
        #   the interface directory will be scanned first
2039
        #
2040
        unshift ( @{$PKGRULES{$platform}}, $entry );
2041
    }
2042
}
2043
 
2044
#-------------------------------------------------------------------------------
227 dpurdie 2045
# Function        : GenerateInstallArgumentList
2046
#
2047
# Description     : Generate an argument list for the installpkg.pl script
2048
#                   The argument list is of the form
2049
#                       --Platform:xx[:xx[:xx]] --Platform:yy[:yy[:yy]] ...
2050
#                   Where xx is:
2051
#                       * a 'part' of the target platform
2052
#                         Order is: platform, product, ...  target( in that order )
2053
#                       * --Option[=yyy]
2054
#                        An option to be passed to the script. These are bound only
2055
#                        to the enclosed platform.
2056
# Inputs          :
2057
#
2058
# Returns         : See above
2059
#
2060
sub GenerateInstallArgumentList
2061
{
2062
    my @arglist;
2063
 
2064
    #
2065
    #   Generate the argument list as an array
2066
    #
2067
    for (@BUILD_ACTIVEPLATFORMS)
2068
    {
2069
        my @args = '--Platform';
2070
        push @args, @{$BUILDINFO{$_}{PARTS}};
2071
        push @arglist, join (":" , @args );
2072
    }
2073
 
2074
    return "@arglist";
2075
}
2076
 
2077
#-------------------------------------------------------------------------------
2078
# Function        : GeneratePlatformList
2079
#
2080
# Description     : Return a list of platforms that should particiate in this
2081
#                   build. This is a function of
2082
#                       1) Platforms defined in the build.pl file
2083
#                       2) User filter defined in GBE_BUILDFILTER
2084
#
2085
#                   The primary use of this function is to limit the creation
2086
#                   of makefiles to those that have supported compilers on
2087
#                   the underlying machine.
2088
#
2089
#                   GBE_BUILDFILTER is a space seperated string of words
2090
#                   Each word may be one of
2091
#                       OPTION=TAG or OPTION=!TAG
2092
#                       TAG or !TAG. This is the same as --TARGET=TAG
2093
#
2094
#                   Bare tags are taken to be TARGETS.
2095
#
2096
#                   Where OPTION may be one of
2097
#                       --PLATFORM
2098
#                       --PRODUCT
2099
#                       --TARGET
2100
#
2101
#                   Special cases
2102
#                   1) If GBE_BUILDFILTER is empty, then all available platforms are used
2103
#                      The global $All is set, then all available platforms are used
2104
#                   2) If the first word of GBE_BUILDFILTER is a negative filter,
2105
#                      ie is used the !xxxx or yyy=!xxxx construct, then it is assumed
2106
#                      that the filter will start with all available platforms
2107
#                   3) The special word --ALL forces selection of ALL platforms
2108
#                      and may reset any existing scanning
2109
#                   4) GBE_BUILDFILTER is parsed left to right. It is possible to add and
2110
#                      subtract items from the list.
2111
#                   5) OPTIONS are case insensitive
2112
#                      TAGS are case sensitive
2113
#
2114
#
2115
# Inputs          : GBE_BUILDFILTER from the environment
2116
#
2117
# Returns         : An array of platforms to include in the build
2118
#                   Maintains @BUILD_ACTIVEPLATFORMS  - the last calculated result
2119
#                   Ensures that @DEFBUILDPLATFORMS is a subset of @BUILD_ACTIVEPLATFORMS
2120
#
2121
sub GeneratePlatformList
2122
{
2123
    #
2124
    #   Return the cached result for speed
2125
    #   The value need only be calculated once
2126
    #
2127
    unless ( defined @BUILD_ACTIVEPLATFORMS )
2128
    {
2129
        my ($platform_filter);
2130
        my %result;
2131
        my %part_to_platform;
2132
 
2133
        #
2134
        #   Create a data structure to assist in the production of the platform list
2135
        #   The structure will be a hash of hashes of arrays
2136
        #
2137
        #   The first level hash will be keyed by the word TARGET, PRODUCT or PLATFORM
2138
        #   The second level of the hash will keyed by available targets, products or platforms
2139
        #   The value of the field will be an array of platforms that match the keyword
2140
        #
2141
        for my $platform (keys (%::BUILDINFO))
2142
        {
2143
            my $pParts = $::BUILDINFO{$platform};
2144
 
2145
            #
2146
            #   Skip platforms that are known to be unavailable on this build
2147
            #   machine. Self configure
2148
            #
2149
            next if ( $pParts->{NOT_AVAILABLE} );
2150
 
2151
            my $target  = $pParts->{TARGET};
2152
            my $product = $pParts->{PRODUCT};
2153
 
2154
            push @{$part_to_platform{'PLATFORM'}{$platform}}, $platform;
2155
            push @{$part_to_platform{'TARGET'}  {$target}}  , $platform;
2156
            push @{$part_to_platform{'PRODUCT'} {$product}} , $platform;
2157
        }
2158
        #
2159
        #   Determine the source of the filter
2160
        #   If the user provides one, then use it.
2161
        #   Otherwise its taken from the environment.
2162
        #
2163
        #   Global build all platforms - Kill any user filter
2164
        #
2165
        if ( $All )
2166
        {
2167
            $platform_filter = "";
2168
        }
2169
        else
2170
        {
2171
            $platform_filter = "";
2172
            $platform_filter = $::GBE_BUILDFILTER
2173
                if ( defined($::GBE_BUILDFILTER) );
2174
        }
2175
        Debug( "GeneratePlatformList: Filter:$platform_filter" );
2176
 
2177
        #
2178
        #   Detect the special cases
2179
        #       1) No user definition - assume all platforms
2180
        #       2) First word contains a subtractive element
2181
        #
2182
        my (@filter) = split( ' ', $platform_filter );
2183
 
2184
        if ( !scalar @filter || $filter[0] =~ m/^$/ || $filter[0] =~ m/!/ )
2185
        {
2186
            %result = %{$part_to_platform{'PLATFORM'}}
2187
                if exists $part_to_platform{'PLATFORM'} ;
2188
        }
2189
#DebugDumpData( "PartToPlatform", \%part_to_platform );
2190
 
2191
        #
2192
        #   Process each element in the user filter list
2193
        #   Expand platforms into known aliases
2194
        #
2195
        for my $word (@filter)
2196
        {
2197
            my $platform;
2198
 
2199
            if ( $word =~ m/^--ALL/i )
2200
            {
2201
                %result = %{$part_to_platform{'PLATFORM'}};
2202
            }
2203
            elsif ( $word =~ m/^--(TARGET)=(!?)(.*)/i ||
2204
                    $word =~ m/^--(PRODUCT)=(!?)(.*)/i ||
2205
                    $word =~ m/^--(PLATFORM)=(!?)(.*)/i ||
2206
                    ( $word !~ m/^-/ && $word =~ m/()(!?)(.*)/ )
2207
                )
2208
            {
2209
                my $table = uc($1);
2210
                $table = "TARGET"
2211
                    unless ( $1 );
2212
 
2213
                #
2214
                #   Expand PLATFORMs into known aliases
2215
                #   Alias will expand to PLATFORMs so it won't work unless we are
2216
                #   processing PALTFORMs.
2217
                #
2218
                my @taglist = ( $table eq "PLATFORM" ) ? ExpandPlatforms($3) : $3;
2219
 
2220
                #
2221
                #   Add / Remove items from the result
2222
                #
2223
                for my $item ( @taglist )
2224
                {
2225
                    my $plist = $part_to_platform{$table}{$item};
2226
                    for ( @{$plist})
2227
                    {
2228
                        if ( $2 )
2229
                        {
2230
                            delete $result{$_};
2231
                        }
2232
                        else
2233
                        {
2234
                            $result{$_} = 1;
2235
                        }
2236
                    }
2237
                }
2238
            }
2239
            else
2240
            {
2241
                print "GBE_BUILDFILTER filter term not understood: $word\n";
2242
            }
2243
        }
2244
 
2245
        #
2246
        #   Return an array of platforms to process
2247
        #
2248
        @BUILD_ACTIVEPLATFORMS = sort keys %result;
2249
 
2250
        #
2251
        #   Ensure that DEFBUILDPLATFORMS is a subset of build active platforms
2252
        #
2253
        my @NEW_DEFBUILDPLATFORMS;
2254
        foreach ( @DEFBUILDPLATFORMS )
2255
        {
2256
            push @NEW_DEFBUILDPLATFORMS, $_
2257
                if ( exists $result{$_} );
2258
        }
2259
        @DEFBUILDPLATFORMS = @NEW_DEFBUILDPLATFORMS;
2260
    }
2261
 
2262
    Debug("GeneratePlatformList: Result:@BUILD_ACTIVEPLATFORMS");
2263
    return @BUILD_ACTIVEPLATFORMS;
2264
}
2265
 
2266
#-------------------------------------------------------------------------------
2267
# Function        : PrintPlatforms
2268
#
2269
# Description     : Petty print the specified platform list, breaking line
2270
#                   on either a primary key change or length width >78.
2271
#
2272
# Returns         : Formated string
2273
#
2274
# Example Output :
2275
#
2276
#           DDU_LMOS_WIN32 DDU_LMOS_linux_armv4 DDU_LMOS_linux_i386
2277
#           IDFC_LMOS_WIN32 IDFC_LMOS_linux_armv4 IDFC_LMOS_linux_i386
2278
#           LMOS_WCEPSPC_ARM LMOS_WCEPSPC_EMU LMOS_WIN32 LMOS_linux_armv4
2279
#           LMOS_linux_i386
2280
#..
2281
sub PrintPlatforms
2282
{
2283
    my ($platforms, $nl) = @_;
2284
    my ($string) = "";                          # result
2285
 
2286
    if ( defined(@$platforms) )
2287
    {
2288
        my ($key_run) = 0;
2289
        my ($pkey);                             # previous key
2290
 
2291
        #   Perform a simple formatting and determine if there is key 
2292
        #   change greater then 1 or whether the total length exceeds 78.
2293
        #
2294
        #   If the line exceeds 78, the printer shall then reformat 
2295
        #   breaking based on line length and possiblity keys.
2296
        #
2297
        $pkey = "";
2298
        for my $k (sort @$platforms) 
2299
        {
2300
            my ($d);                            # delimitor
2301
 
2302
            if (($d = index( $k, '_' )) != index( $pkey, '_' ) ||
2303
                    substr( $k, 0, $d ) ne substr( $pkey, 0, $d )) {
2304
                $key_run = 1
2305
                    if ($key_run <= 1);         # change, reset run if <= 1
2306
            } else {
2307
                $key_run++;                     # same primary key
2308
            }
2309
 
2310
            $string .= " " if ($pkey);
2311
            $string .= $k;
2312
            $pkey = $k;
2313
        }
2314
 
2315
        #   Reprint if required.
2316
        #
2317
        if (length($nl)+length($string) > 78)
2318
        {
2319
            my ($llen);                         # line length
2320
 
2321
            $llen = length($nl);
2322
 
2323
            $pkey = "";
2324
            $string = "";
2325
 
2326
            for my $k (sort @$platforms)
2327
            {
2328
                my ($klen, $d);                 # key length, delimitor
2329
 
2330
                $klen = length($k);
2331
                if ($pkey ne "")
2332
                {
2333
                    if ($llen + $klen > 78 ||
2334
                        ($key_run > 1 && (
2335
                            ($d = index( $k, '_' )) != index( $pkey, '_' ) ||
2336
                            substr( $k, 0, $d ) ne substr( $pkey, 0, $d ) )) )
2337
                    {                           # line >70 or key change
2338
                        $string .= $nl;
2339
                        $llen = length($nl);
2340
                    }
2341
                    else
2342
                    {
2343
                        $string .= " ";
2344
                        $llen++;
2345
                    }
2346
                }
2347
                $string .= $k;
2348
                $pkey = $k;
2349
                $llen += $klen;
2350
            }
2351
        }    
2352
    }
2353
    return $string;
2354
}
241 dpurdie 2355
#-------------------------------------------------------------------------------
2356
# Function        : PrintList
2357
#
2358
# Description     : Pretty format an array to fit within 80 char line
2359
#                   Perform wrapping as required
2360
#
2361
# Inputs          : $list           - Reference to an array
2362
#                   $nl             - New line stuff.
2363
#                                     Use to prefix new lines
2364
#
2365
# Returns         : string
2366
#
2367
sub PrintList
2368
{
2369
    my ($list, $nl) = @_;
2370
    my ($string) = '';                          # result
2371
    my $sep;
227 dpurdie 2372
 
241 dpurdie 2373
    if ( @$list )
2374
    {
2375
        my ($llen) = length($nl);
227 dpurdie 2376
 
241 dpurdie 2377
        for my $k (@$list)
2378
        {
2379
            my $klen = length($k);
2380
            if ($llen + $klen > 78 )
2381
            {
2382
                $string .= $nl;
2383
                $llen = length($nl);
2384
            }
2385
            else
2386
            {
2387
                if ( $sep )
2388
                {
2389
                    $string .= $sep;
2390
                    $llen++;
2391
                }
2392
                else
2393
                {
2394
                    $sep = ' ';
2395
                }
2396
            }
2397
            $string .= $k;
2398
            $llen += $klen;
2399
        }
2400
    }
2401
    return $string;
2402
}
2403
 
305 dpurdie 2404
#-------------------------------------------------------------------------------
2405
# Function        : BuildReleaseFile
2406
#
2407
# Description     : Legacy function
2408
#                   Don't know what it was meant to do
2409
#                   Unfortunately it is present in a lot of build.pl files
2410
#
2411
#                   Not well supported on all machine types
2412
#
331 dpurdie 2413
# Inputs          : None that are used
305 dpurdie 2414
#
331 dpurdie 2415
# Returns         : Undefined
305 dpurdie 2416
#
227 dpurdie 2417
sub BuildReleaseFile
2418
{
2419
}
2420
 
305 dpurdie 2421
#-------------------------------------------------------------------------------
2422
# Function        : BuildSnapshot
2423
#
2424
# Description     : Legacy function
2425
#                   Don't know what it was meant to do
2426
#                   Unfortunately it is present in a lot of build.pl files
2427
#
2428
# Inputs          : None that are used
2429
#
2430
# Returns         : Undefined
2431
#
227 dpurdie 2432
sub BuildSnapshot
2433
{
2434
}
2435
 
305 dpurdie 2436
#-------------------------------------------------------------------------------
2437
# Function        : BuildSrcArchive
2438
#
2439
# Description     : Create a source snapshot of the build source
2440
#                   Designed to provide a source image for packaging
2441
#                   examples
2442
#
2443
#                   Should be platform independent
2444
#
2445
#                   Creates an archive file and places it into the
2446
#                   interface directory. The archive will be packaged
2447
#                   automatically by the build process
2448
#
2449
#                   Use the 'pax' utility
2450
#                       1) Can massage the file path such that the stored
2451
#                          directory image contains the package name and version
2452
#
2453
#                   Directive can be used at any time before the BuildMake
2454
#
2455
#                   Will handle the existence of an auto.pl file by inserting
2456
#                   it as build.pl.
2457
#
2458
# Inputs          : Options
2459
#
2460
#
2461
# Returns         : 
2462
#
2463
sub BuildSrcArchive
2464
{
2465
    #
2466
    #   If we are clobbering, then there is nothing to do
2467
    #   The generated file is placed within the interface
2468
    #   directory and that directory will be deleted during the clobber
2469
    #
2470
    return if ( $Clobber );
2471
    DataDirective("BuildSrcArchive");
227 dpurdie 2472
 
305 dpurdie 2473
    #
2474
    #   Currently this operation is only supported of some platforms
2475
    #   Only supported on Unix platforms
2476
    #   Uses the 'pax' utility
2477
    #
2478
    unless ( LocateProgInPath ( 'pax', '--All' ) && ( $ScmHost eq "Unix" ) )
2479
    {
2480
        Log( "SrcPackage . Not supported" );
2481
        return;
2482
    }
2483
 
2484
    #
2485
    #   Only allow one instance of the directive
2486
    #
2487
    Error ("Multiple BuildSrcArchive directives not supported")
2488
        if ( $build_source_pkg );
2489
 
2490
    #
2491
    #   Create the name of the archive
2492
    #       Based on the package name and version
2493
    #       Has no spaces
2494
    #
2495
    my $build_name = $BUILDNAME;
2496
    $build_name =~ s~\s+~_~g;
2497
 
2498
    #
2499
    #   Create the archive in the interface directory
2500
    #   Don't need to clobber it as the entire interface directory
2501
    #   will be clobbered
2502
    #
2503
    $build_source_pkg = $build_name;
2504
}
2505
 
2506
#-------------------------------------------------------------------------------
2507
# Function        : BuildSrcArchiveBody
227 dpurdie 2508
#
305 dpurdie 2509
# Description     : Function to implement the body of the BuildSrcArchive
2510
#                   operation. Will be invoked during BuildMake
2511
#
2512
# Inputs          : None
2513
#
2514
# Returns         : 
2515
#
2516
sub BuildSrcArchiveBody
2517
{
2518
    return unless ( $build_source_pkg );
2519
 
2520
    my $archive_dir = "pkg/$BUILDNAME_PACKAGE/src";
2521
    my $archive_file = "$build_source_pkg" . '.tar';
2522
 
2523
    Log( "SrcPackage . $archive_file.gz" );
2524
    unlink "$archive_dir/$archive_file";
2525
    unlink "$archive_dir/$archive_file.gz";
2526
    mkpath($archive_dir, 0, 0775);
2527
 
2528
    #
2529
    #   Create a list of files and top-level dirs to add to source archive
2530
    #   Many files are ignored
2531
    #   Should only be executed on the first 'build' thus many internal
2532
    #   directories will not be present
2533
    #
2534
    my @flist;
2535
    my $auto_pl;
2536
    opendir (my $tp, '.' ) or Error ("Cannot read current directory");
2537
    while ( $_ = readdir($tp) )
2538
    {
2539
        next if ( m/^\.$/ );
2540
        next if ( m'^\.\.$' );
2541
        next if ( m'^build\.log$' );
2542
        next if ( m'\.gbe$' );
2543
        next if ( m'^local$' );
2544
        next if ( m'^pkg$' );
2545
        next if ( m/^$BUILDINTERFACE$/ );
2546
        $auto_pl = 1, next  if ( m'^auto\.pl$' );
2547
        next if (  m'^build\.pl$' );
2548
        next if ( m/^$build_source_pkg$/ );
2549
        push @flist, $_;
2550
    }
2551
    closedir $tp;
2552
 
2553
    #
2554
    #   If we don't have an auto.pl, then we add the build.pl file
2555
    #   If we do have a auto.pl - it gets tricky. Its don't after the
2556
    #   initial pax command
2557
    #
2558
    unless ( $auto_pl )
2559
    {
2560
        push @flist, 'build.pl';
2561
    }
2562
 
2563
    #
2564
    #   Create the command to be executed
2565
    #   Prefix archive paths with build_name
2566
    #
2567
    my @command = ( 'pax', '-w', '-f', "$archive_dir/$archive_file" );
2568
    System( '--NoShell' , @command, '-s', "~^~$build_source_pkg/~", @flist );
2569
 
2570
    #
2571
    #   If we have an auto.pl file, then we need to add it to the archive
2572
    #   but it needs to be called build.pl
2573
    #
2574
    if ( $auto_pl )
2575
    {
2576
        System( '--NoShell' , @command, '-a', '-s', "~^auto.pl~$build_source_pkg/build.pl~" , 'auto.pl' );
2577
    }
2578
 
2579
    #
2580
    #   Must now zip the file
2581
    #   Can't zip and append at the same time
2582
    #
2583
    System( '--NoShell' , 'gzip', "$archive_dir/$archive_file" );
2584
 
2585
    #
2586
    #   Display the results
2587
    #
2588
    System ('--NoShell', 'pax', '-z', "-f$archive_dir/$archive_file.gz")
2589
        if (IsVerbose (1));
2590
}
2591
 
2592
#-------------------------------------------------------------------------------
2593
# Function        : BuildAccessPerms
2594
#
2595
# Description     : Check if access/permissions setting requested...
2596
#                   Legacy
2597
#
331 dpurdie 2598
#                   Don't know what it was meant to do
2599
#                   Unfortunately it is present in a lot of build.pl files
305 dpurdie 2600
#
331 dpurdie 2601
# Inputs          : None that are used
305 dpurdie 2602
#
331 dpurdie 2603
# Returns         : Undefined
2604
#
227 dpurdie 2605
sub BuildAccessPerms
2606
{
2607
}
2608
 
2609
 
2610
sub BuildSetenv
2611
{
2612
    push( @BUILDSETENV, @_ );
2613
}
2614
 
2615
#-------------------------------------------------------------------------------
2616
# Function        : DataDirective
2617
#
2618
# Description     : Called by data collection directives to ensure that we are
2619
#                   still collecting data and that we have collected other data
2620
#
2621
# Inputs          : $dname              - Directive Name
2622
#
2623
# Returns         : Will error if we are not
2624
#
2625
sub DataDirective
2626
{
2627
    my ($dname) = @_;
2628
 
2629
    Error( "$dname() must appear after BuildName()...")
2630
        if ( $BUILDNAME eq "" );
2631
 
2632
    Error( "$dname() must appear after BuildInterface()...")
2633
        unless( $BUILDINTERFACE );
2634
 
2635
    Error( "$dname() not allowed after BuildDescpkg, BuildIncpkg, BuildVersion or BuildMake")
2636
        if( $BUILDPHASE);
2637
}
2638
 
2639
#-------------------------------------------------------------------------------
2640
# Function        : StartBuildPhase
2641
#
2642
# Description     : Called by directives that deal with the building phases
2643
#                   to perform common initialisation and to ensure that
2644
#                   directives that collect data are no longer called
2645
#
305 dpurdie 2646
# Inputs          : last                - True: Last directive expected
227 dpurdie 2647
#
2648
# Returns         : May generate an error
2649
#
2650
sub StartBuildPhase
2651
{
305 dpurdie 2652
    my ($last) = @_;
2653
 
227 dpurdie 2654
    #
305 dpurdie 2655
    #   Ensure directive is allowed
2656
    #       $BUILDPHASE >  1     - No more directives allowed
2657
    #       $BUILDPHASE == 1     - Allowed directive
2658
    #
2659
    if ( $BUILDPHASE > 1 )
2660
    {
2661
        my $function = (caller(1))[3];
2662
        $function =~ s~.*::~~;
2663
        Error ("Directive not allowed: $function","'BuildMake' must be the last directive in the build file");
2664
    }
2665
 
2666
    #
227 dpurdie 2667
    #   Only do it once
2668
    #
305 dpurdie 2669
    return if ( $BUILDPHASE  );
2670
    $BUILDPHASE = 1;
227 dpurdie 2671
 
2672
    #
341 dpurdie 2673
    #   If we are not performing a ForceBuild, then we don't need to continue
2674
    #   We have updated the interface directory with BuildPkgArchive
2675
    #   information.
2676
    #
2677
    TestForForcedBuild();
2678
 
2679
    #
227 dpurdie 2680
    #   Calcuate the aliases that are being extracted from targets
2681
    #
2682
    Process_TargetAlias();
2683
 
2684
    #
311 dpurdie 2685
    #   Create dummy package to describe the Interface directory
2686
    #
2687
    CreateInterfacePackage();
2688
 
2689
    #
227 dpurdie 2690
    #   Sanity test the users packages
2691
    #
2692
    PackageEntry::SanityTest() unless $Clobber;
2693
 
2694
    #
2695
    #   Validate the $Srcdir before its first real use
2696
    #   This is calculated from the user directives
2697
    #
2698
 
2699
    #.. Determine default "source" root
2700
    #
2701
    if ( $Srcdir eq "" )
2702
    {
2703
        Warning( "Both the directories 'src' and 'SRC' exist ....." )
2704
            if ( $ScmHost eq "Unix" && -e "src" && -e "SRC" );
2705
 
2706
        if ( -e "src" ) {
2707
            $Srcdir = "src";
2708
        } else {
2709
            ( -e "SRC" ) ||
2710
                Error( "Neither the directory 'src' nor 'SRC' exist ....." );
2711
            $Srcdir = "SRC";
2712
        }
2713
    }
2714
 
2715
    #
2716
    #   Must have a valid Srcdir
2717
    #
2718
    Error ("Source directory not found: $Srcdir")
2719
        unless ( $Srcdir && -d $Srcdir );
2720
 
305 dpurdie 2721
    #
2722
    #   Create source package
2723
    #
2724
    BuildSrcArchiveBody();
2725
 
227 dpurdie 2726
    return $Srcdir;
2727
}
2728
 
2729
#-------------------------------------------------------------------------------
341 dpurdie 2730
# Function        : TestForForcedBuild
2731
#
2732
# Description     : If a non-forced build has been requested, then see
2733
#                   if a build is required ( ie: build.pl modified )
2734
#
2735
#
2736
# Inputs          : None
2737
#
2738
# Returns         : May not return
2739
#
2740
sub TestForForcedBuild
2741
{
2742
    #
2743
    #   Always return if in clobber mode
2744
    #
2745
    return if ( $Clobber );
2746
 
2747
    if ( ! $ForceBuild  )
2748
    {
2749
        my @build_warn;
2750
        my $bstamp = -M "$Cwd/$ScmBuildSrc";
2751
        my $tstamp = -M "$Cwd/Makefile.gbe";
2752
 
2753
        push @build_warn, "Missing: Makefile.gbe" unless ( defined $tstamp );
2754
        push @build_warn, "Modified build file ($ScmBuildSrc)" if ( $tstamp && $bstamp < $tstamp );
2755
 
2756
        if ( @build_warn )
2757
        {
2758
            Verbose ("Forcing Build", @build_warn );
2759
        }
2760
        else
2761
        {
2762
            Verbose ("No build performed. Build files up to date");
2763
            Log ("Build files up to date") if $::GBE_SANDBOX;
2764
            exit 0;
2765
        }
2766
    }
2767
}
2768
 
2769
#-------------------------------------------------------------------------------
305 dpurdie 2770
# Function        : LastBuildDirective
2771
#
2772
# Description     : No more build directives allowed
2773
#
2774
# Inputs          : 
2775
#
2776
# Returns         : 
2777
#
2778
sub LastBuildDirective
2779
{
2780
    $BUILDPHASE = 2;
2781
}
2782
 
2783
#-------------------------------------------------------------------------------
227 dpurdie 2784
# Function        : BuildPackageLink
2785
#
2786
# Description     : Create a soft link from sandbox_dpkg_archive to the package
2787
#                   being created by this build
2788
#
2789
#                   For backward compatability.
2790
#                   If GBE_DPKG_SBOX is not defined, then use GBE_DPKG_LOCAL
2791
#
2792
#                   This will allow multiple components to work together
2793
#
2794
#                   Note: When called in Clobber-mode the link will be deleted
2795
#
2796
# Inputs          : $BUILDNAME              - The package name
2797
#                   $BUILDNAME_PROJECT      - Project extension
2798
#                   $::GBE_DPKG_SBOX        - Path of sandbox_dpkg_archive
2799
#                   $::GBE_DPKG_LOCAL       - Path of local_dpkg_archive
2800
#                   $::GBE_DPKG             - Main repository
2801
#
2802
# Returns         : Nothing
2803
#
2804
sub BuildPackageLink
2805
{
2806
    my $target_archive;
2807
    my $target_archive_name;
2808
    my $link_file;
2809
    my $tag;
2810
 
2811
    #
2812
    #   Determine the path (and name) of the target archive
2813
    #   Use sandbox_dpkg_archive if it exists
2814
    #   Use local_dpkg_acrhive for backward compatability (should be removed after JATS 2.64.2+)
2815
    #
2816
    if ( $target_archive = $::GBE_DPKG_SBOX )
2817
    {
2818
        $target_archive_name = "sandbox_dpkg_archive";
2819
        $tag = "Sandbox";
2820
 
2821
        $link_file  = 'sandbox';
2822
        $link_file .= '.' . $BUILDNAME_PROJECT if ( $BUILDNAME_PROJECT );
2823
        $link_file .= '.lnk';
2824
    }
2825
    elsif ( $target_archive = $::GBE_DPKG_LOCAL )
2826
    {
2827
        $target_archive_name = "local_dpkg_archive";
2828
        $link_file = "$BUILDVERSION.lnk";
2829
        $tag = "Local";
2830
    }
2831
    else
2832
    {
2833
        Verbose("Cannot locate local or sandbox archive")
2834
            unless $Clobber;
2835
        return;
2836
    }
2837
 
2838
    #
2839
    #   Santity test
2840
    #   Target must be a directory
2841
    #
2842
    unless ( -d $target_archive )
2843
    {
241 dpurdie 2844
        Warning("$target_archive_name is not a directory: $target_archive")
227 dpurdie 2845
            unless $Clobber;
2846
        return;
2847
    }
2848
 
2849
    my $link_dir = "$target_archive/$BUILDNAME_PACKAGE";
2850
    my $link_path = "$link_dir/$link_file";
2851
 
2852
    if ( $Clobber )
2853
    {
2854
        unlink $link_path;          # Delete the link
2855
        rmdir $link_dir;            # Delete only if empty
2856
    }
2857
    else
2858
    {
261 dpurdie 2859
        Log( "Local Link . $BUILDNAME_PACKAGE/$link_file ($tag)");
2860
        mkdir $link_dir unless -d $link_dir;
2861
        FileCreate ( $link_path, "$Cwd/pkg/$BUILDNAME_PACKAGE");
227 dpurdie 2862
    }
2863
}
2864
 
2865
#-------------------------------------------------------------------------------
2866
# Function        : BuildSandboxData
2867
#
2868
# Description     : Create data structures to allow this package to be built
2869
#                   within a multi-package sandbox.
2870
#
2871
#                   This will allow multiple components to work together
2872
#
2873
#                   Note: When called in Clobber-mode the link will be deleted
2874
#
2875
# Inputs          : $BUILDNAME              - The package name
2876
#                   $BUILDNAME_PROJECT      - Project extension
2877
#                   $::GBE_DPKG_SBOX        - Path of sandbox_dpkg_archive
2878
#                   $::GBE_DPKG             - Main repository
2879
#
2880
# Returns         : Nothing
2881
#
2882
sub BuildSandboxData
2883
{
2884
    my $sandbox_dpkg_archive = $::GBE_DPKG_SBOX;
2885
    return unless ( $sandbox_dpkg_archive );
2886
 
2887
    unless ( -d $sandbox_dpkg_archive )
2888
    {
241 dpurdie 2889
        Error("sandbox_dpkg_archive is not a directory: $sandbox_dpkg_archive")
227 dpurdie 2890
            unless $Clobber;
2891
        return;
2892
    }
2893
 
2894
    #
2895
    #   Create a name for this package in the sandbox
2896
    #   Must use the package name and extension. Don't use the version
2897
    #   information as this will not be correct
2898
    #
2899
    #   PACKAGE/sandbox.PRJ.cfg
2900
    #
2901
    my $link_dir = "$sandbox_dpkg_archive/$BUILDNAME_PACKAGE";
2902
    my $link_file = 'sandbox';
2903
       $link_file .= '.' . $BUILDNAME_PROJECT if ( $BUILDNAME_PROJECT );
2904
       $link_file .= '.cfg';
2905
    my $link_path = "$link_dir/$link_file";
2906
 
2907
    if ( $Clobber )
2908
    {
2909
        unlink $link_path;          # Delete the link
2910
        rmdir $link_dir;            # Delete only if empty
2911
    }
2912
    else
2913
    {
261 dpurdie 2914
        Log( "Sandbox cfg. $link_file");
227 dpurdie 2915
        unlink $link_path;
2916
        mkdir $link_dir;
2917
 
2918
        #
2919
        #   Create the sandbox config data structure
2920
        #
2921
        my %sandbox_info = (
2922
            BUILDDIR     => $Cwd,
2923
            INTERFACEDIR => $BUILDINTERFACE,
2924
            );
2925
 
2926
        #
2927
        #   Write out the Parsed Config File with new information
2928
        #
2929
        my $fh = ConfigurationFile::New( $link_path );
2930
        $fh->Header( "buildlib (version $::BuildVersion)",
2931
                                  "Sandbox configuration" );
2932
 
2933
        #
2934
        #   Dump out the configuration information
2935
        #
2936
        $fh->Dump( [\%sandbox_info], [qw(*sandbox_info)] );
2937
        $fh->Close();
2938
    }
2939
}
2940
 
2941
 
2942
#-------------------------------------------------------------------------------
2943
# Function        : BuildMake
2944
#
2945
# Description     : Generate the makefiles
2946
#                   This directive MUST be the last directive in the build.pl
2947
#                   file. The directive triggers the processing of all the
2948
#                   information that has been collected
2949
#
2950
#
2951
# Inputs          : None
2952
#
2953
# Returns         : Nothing
2954
#
2955
 
2956
sub BuildMake
2957
{
2958
    my( $argc, $platform );
2959
 
2960
    #
2961
    #   Must have a valid $BUILDINTERFACE
2962
    #   Normally this is held in the interface directory, but this is not
2963
    #   always created. If there is no $BUILDINTERFACE, then use the
2964
    #   build directory
2965
    #
2966
    $BUILDINTERFACE = "." unless ( $BUILDINTERFACE );
2967
 
2968
    #.. Starting the build phase. No more data collection
2969
    #
305 dpurdie 2970
    StartBuildPhase();
2971
    LastBuildDirective();
227 dpurdie 2972
 
2973
    sub DeleteCfg
2974
    {
2975
        #
2976
        #   Delete files that will be re-created
2977
        #   Some of these files are read and written.
2978
        #   Errors in the files are solved by deleting the files now.
2979
        #
2980
        unlink "$BUILDINTERFACE/build.cfg";
2981
        unlink "$BUILDINTERFACE/Makefile.cfg";
2982
        unlink glob ("$BUILDINTERFACE/Makefile*.cfg");
2983
        unlink "$BUILDINTERFACE/Buildfile.cfg";
2984
        unlink "$BUILDINTERFACE/Dpackage.cfg";
2985
    }
2986
 
2987
    if ( $Clobber )                             # clobber mode ?
2988
    {
2989
        if ( -e "Makefile.gbe" )
2990
        {
263 dpurdie 2991
            JatsTool ( 'jmake.pl', 'unmakefiles');
227 dpurdie 2992
            unlink "Makefile.gbe";
2993
        }
2994
 
2995
        DeleteCfg();
343 dpurdie 2996
        LinkClean();
227 dpurdie 2997
 
2998
        #
2999
        #   JATS creates a 'pkg' directory for the target package
3000
        #
3001
        push @CLOBBERDIRS, "pkg";
3002
 
3003
        #
3004
        #   Deployment creates a 'build/deploy' directory
3005
        #
3006
        push @CLOBBERDIRS, "build/deploy";
3007
 
3008
        #
3009
        #   Delete interface directories and other directories that have been
3010
        #   marked to be clobberd
3011
        #
3012
        foreach my $dir ( @CLOBBERDIRS )
3013
        {
3014
            next if ( $dir eq '.' );
3015
            next if ( $dir eq '..' );
3016
            if ( -d $dir )
3017
            {
341 dpurdie 3018
                rmtree ( $dir );
227 dpurdie 3019
            }
3020
        }
3021
 
3022
        foreach my $file ( @CLOBBERFILES )
3023
        {
3024
            if ( -f $file )
3025
            {
341 dpurdie 3026
                rmtree ( $file );
227 dpurdie 3027
            }
3028
        }
3029
 
3030
        #
3031
        #   DPACKAGE may be a user file, Only delete it if we created it
3032
        #
299 dpurdie 3033
        unlink "$Srcdir/DPACKAGE.$::GBE_MACHTYPE" if $DeleteDPACKAGE;
227 dpurdie 3034
 
3035
        BuildPackageLink();
3036
        BuildSandboxData();
3037
        return;
3038
    }
3039
 
3040
    #.. Build support files
3041
    #
3042
    DeleteCfg();
3043
    BuildConfig();
343 dpurdie 3044
    LinkClean();                                # clean previous images
227 dpurdie 3045
    BuildRuleFiles();
3046
    BuildSharedLibFiles();
3047
    WriteParsedBuildConfig();
3048
    BuildPackageLink();
3049
    BuildSandboxData();
3050
 
3051
    #
3052
    #  ONLY (re)building interface dir
3053
    #
3054
    return
3055
        if ( $Interface );
3056
 
3057
    #---------------------------------------------------------------------------
3058
    #
3059
    #.. Make bootstrap "makefile",
3060
    #   Simulate a top level makefile
3061
    #       Pass argumenst to makelib
3062
    #       Sumulate SubDir() operations
3063
    #       Sumulate a Platform(*);
3064
    #
3065
    #       Due to the normal way that makelib.pl is executed,
3066
    #       the following substitutions are done.
3067
    #
3068
    @ARGV = ();
3069
    $0 = "makefile.pl ";
3070
    push @ARGV, "$Cwd";                         # current working directory
331 dpurdie 3071
    push @ARGV, "$::GBE_TOOLS/makelib.pl";     # makelib.pl image
227 dpurdie 3072
    push @ARGV, "--interface=$BUILDINTERFACE"
261 dpurdie 3073
        if ($BUILDINTERFACE);
227 dpurdie 3074
 
3075
    Debug( "ARGV:      @ARGV" );
3076
 
3077
    #.. (re)Build root makefile
3078
    #
3079
    $ScmBuildlib = 0;                           # clear Buildlib flag for 'makelib.pl'
3080
    RootMakefile();                             # inform 'makelib.pl'
3081
    MakeLibInit();                              # run initialisation
3082
 
3083
 
3084
    #.. Register subdir(s)
3085
    #
3086
    UniquePush (\@BUILDSUBDIRS, $Srcdir );
3087
    SubDir( @BUILDSUBDIRS );
3088
    Platform( @BUILD_ACTIVEPLATFORMS );
3089
 
3090
    #.. (re)build src makefiles and associated information
3091
    #
263 dpurdie 3092
    my @cmds = ('jmake.pl', 'rebuild');
227 dpurdie 3093
    push @cmds, 'NORECURSE=1' if ( $RootOnly );
3094
 
263 dpurdie 3095
    JatsTool ( @cmds);
305 dpurdie 3096
 
3097
    #
3098
    #   Generate some warnings that will be seen at the end of the build
3099
    #
3100
    Warning ("BuildSrcArchive Directive Present","Read JATS Manual for correct usage")
3101
        if ($build_source_pkg);
227 dpurdie 3102
}
3103
 
3104
 
3105
#-------------------------------------------------------------------------------
3106
# Function        : BuildVersion
3107
#
3108
# Description     : Generate version.c and version.h files
3109
#
3110
# Inputs          : Options
3111
#                       --Prefix=prefix         Text prepended to variables created
3112
#                                               as a part of the "C" versions
3113
#                       --Type=type             Type of "C" style data
3114
#                                               Allowed types are: array
3115
#                       --Defs=name             Generate a "C" definitions file.
3116
#                                               This file simply contains definitions
3117
#                       --Defs                  Same as --Defs=defs
3118
#                       --Style=style           Output file style
3119
#                                               Supported styles:
3120
#                                                   "C" - Default
3121
#                                                   "CSharp"
3122
#                                                   "WinRC"
289 dpurdie 3123
#                                                   "Delphi"
315 dpurdie 3124
#                                                   "VB"
227 dpurdie 3125
#                       --File=name             Specifies the output file name
3126
#                                               Default is determined by the style
3127
#
3128
#                   Also allows for an 'old' style format in which
3129
#                   the first three arguments are prefix,type and defs
3130
# Returns         :
3131
#
3132
 
3133
sub BuildVersion
3134
{
3135
    my ( $Prefix, $Type, $Mode ) = @_;
3136
    my $ModePrefix;
3137
    my $Style = "C";
3138
    my $FileName;
3139
    my $VersionFiles;
267 dpurdie 3140
    my @opts;
3141
    my $supports_opts;
227 dpurdie 3142
 
3143
    StartBuildPhase();                          # Starting the build phase. No more data collection
3144
 
279 dpurdie 3145
    if ( defined($Prefix) && $Prefix =~ /^-/ )
227 dpurdie 3146
    {
3147
        $Prefix = undef;
3148
        $Type = undef;
3149
        $Mode = undef;
3150
        foreach  ( @_ )
3151
        {
3152
            if (      /^--Prefix=(.*)/ ) {
3153
                $Prefix = $1;
3154
                $VersionFiles = 1;
3155
 
3156
            } elsif ( /^--Type=(.*)/ ) {
3157
                $Type = $1;
3158
                $VersionFiles = 1;
3159
 
3160
            } elsif ( /^--Defs=(.*)/ ) {
3161
                $Mode = $1;
3162
                $ModePrefix = "_$1";
3163
 
3164
            } elsif ( /^--Defs$/ ) {
3165
                $Mode = 'defs';
3166
                $ModePrefix = "";
3167
 
3168
            } elsif ( /^--Style=(.*)/ ) {
3169
                $Style = $1;
279 dpurdie 3170
                $VersionFiles = 1;
267 dpurdie 3171
                $supports_opts = 1 if ( $Style =~ /^WinRC/i );
227 dpurdie 3172
 
3173
            } elsif ( /^--File=(.*)/ ) {
3174
                $FileName = $1;
3175
 
267 dpurdie 3176
            } elsif ($supports_opts ) {
3177
                push @opts, $_;
235 dpurdie 3178
 
227 dpurdie 3179
            } else {
3180
                Error ("BuildVersion: Unknown option: $_");
3181
 
3182
            }
3183
        }
3184
    }
3185
    else
3186
    {
3187
        #
3188
        #   Old style positional arguments.
3189
        #
3190
        $VersionFiles = 1;
3191
        if ( defined( $Mode ) )
3192
        {
3193
            if ( $Mode =~ m/^defs(=(.*))?$/i )
3194
            {
3195
                $Mode       = $2 ? $2    : 'defs';
3196
                $ModePrefix = $2 ? "_$2" : "";
3197
            }
3198
            else
3199
            {
3200
                Error ("BuildVersion: Bad Mode argument. Need 'defs' or 'defs=name'");
3201
            }
3202
        }
3203
    }
3204
 
3205
    #
3206
    #   Determine the style of version file to create
3207
    #
3208
    if ( $Style =~ /^CSharp/i ) {
3209
        BuildVersionCSharp( $FileName );
3210
 
229 dpurdie 3211
    } elsif ( $Style =~ /^Properties/i ) {
3212
        BuildVersionProperties( $FileName, $Prefix );
3213
 
227 dpurdie 3214
    } elsif ( $Style =~ /^WinRC/i ) {
267 dpurdie 3215
        BuildVersionWinRC( $FileName, @opts );
227 dpurdie 3216
 
289 dpurdie 3217
    } elsif ( $Style =~ /^Delphi/i ) {
3218
        BuildVersionDelphi( $FileName, $Prefix );
315 dpurdie 3219
 
3220
    } elsif ( $Style =~ /^VB/i ) {
3221
        BuildVersionVB( $FileName, $Prefix );
289 dpurdie 3222
 
227 dpurdie 3223
    } elsif ( $Style eq "C" ) {
289 dpurdie 3224
        BuildVersionC    ( $FileName, $Prefix, $Type )     if ( $VersionFiles );
3225
        BuildVersionCdefs( $FileName, $Mode, $ModePrefix ) if ( $Mode );
227 dpurdie 3226
 
3227
    } else {
3228
        Error("BuildVersion: Unknown style: $Style");
3229
    }
3230
}
3231
 
3232
#-------------------------------------------------------------------------------
3233
# Function        : BuildDescpkg
3234
#
3235
# Description     : Create a package description file
3236
#                   The format of this file matches that generated by JANTS
3237
#                   Take care when extending the format
3238
#
3239
#                   NOTE: It turns out that JANTS is not a standard and the
3240
#                         implementors (of JANTS) kept on changing it.
3241
#
3242
# Inputs          :
3243
#
3244
# Returns         :
3245
#
3246
sub BuildDescpkg
3247
{
3248
    StartBuildPhase();                          # Starting the build phase. No more data collection
3249
 
247 dpurdie 3250
    #
3251
    #   Store the files location for use at runtime
3252
    #   It will be a file that is 'known' to JATS
3253
    #
3254
    my $pkgfile = BuildAddKnownFile ( $Srcdir, 'descpkg' );
3255
    return if ( $Clobber );                 # clobber mode ?
227 dpurdie 3256
 
261 dpurdie 3257
    my @desc;
279 dpurdie 3258
    push @desc, "Package Name:  $BUILDNAME_PACKAGE";
3259
    push @desc, "Version:       $BUILDVERSION";
3260
    push @desc, "Released By:   $::USER";
3261
    push @desc, "Released On:   $::CurrentTime";
3262
    push @desc, "Build Machine: $::GBE_HOSTNAME";
3263
    push @desc, "Path:          $Cwd";
3264
    push @desc, "Jats Version:  $::GBE_VERSION";
3265
    push @desc, "Jats Path:     $::GBE_CORE";
261 dpurdie 3266
    push @desc, "";
3267
    push @desc, "Build Dependencies:";
3268
    push @desc, "";
227 dpurdie 3269
 
3270
    foreach my $tag ( PackageEntry::GetPackageList )
3271
    {
3272
        my ($name, $version, $type) = PackageEntry::GetPackageData($tag);
3273
 
3274
        my @attributes;
3275
 
3276
        push @attributes, "name=\"$name\"";
3277
        push @attributes, "version=\"$version\"";
3278
        push @attributes, "build=\"true\"" if $type =~ /Build/i;
3279
 
261 dpurdie 3280
        push @desc, "<sandbox @attributes/>";
227 dpurdie 3281
    }
247 dpurdie 3282
 
261 dpurdie 3283
    FileCreate ($pkgfile, \@desc );
227 dpurdie 3284
}
3285
 
3286
#-------------------------------------------------------------------------------
3287
# Function        : BuildIncpkg
3288
#
3289
# Description     : Create a package inclusion file
3290
#
3291
# Inputs          :
3292
#
3293
# Returns         :
3294
#
3295
sub BuildIncpkg
3296
{
3297
    StartBuildPhase();                          # Starting the build phase. No more data collection
3298
    if ( $Clobber )                             # clobber mode ?
3299
    {
341 dpurdie 3300
        rmtree( "$Srcdir/incpkg" );
227 dpurdie 3301
        return;
3302
    }
3303
 
3304
    my $fh = ConfigurationFile::New( "$Srcdir/incpkg" );
3305
    $fh->Header( "buildlib (Version $BuildVersion)",
3306
                              "Package inclusion list" );
3307
 
3308
    foreach my $tag ( PackageEntry::GetPackageList )
3309
    {
3310
        my ($name, $version, $type) = PackageEntry::GetPackageData($tag);
3311
        $type = ($type =~ /build/i) ? "Build" : "Link";
3312
 
3313
        $fh->Write( "${type}PkgArchive( '$name', '$version' );\n" );
3314
    }
3315
 
3316
    $fh->Close();
3317
}
3318
 
3319
#-------------------------------------------------------------------------------
3320
# Function        : BuildConfig
3321
#
3322
# Description     : Create the file interface/build.cfg
3323
#                   This file contains information gathered by the build process
3324
#                   that is to be used when makefiles are created and re-created
3325
#
3326
# Inputs          : None
3327
#
3328
# Returns         : Nothing
3329
#
283 dpurdie 3330
sub BuildConfig
227 dpurdie 3331
{
3332
    Error( "No BuildInterface directive encountered\n" )
3333
        unless ($BUILDINTERFACE);
3334
 
3335
    my $fh = ConfigurationFile::New( "$BUILDINTERFACE/build.cfg");
3336
    $fh->Header( "buildlib (Version $BuildVersion)",
3337
                              "Makelib configuration file", "
3338
\$ScmBuildMachType              = \"$::GBE_MACHTYPE\";
3339
\$ScmInterfaceVersion           = \"$::InterfaceVersion\";
3340
\$ScmBuildName                  = \"$BUILDNAME\";
3341
\$ScmBuildPackage               = \"$BUILDNAME_PACKAGE\";
3342
\$ScmBuildVersion               = \"$BUILDNAME_VERSION\";
3343
\$ScmBuildProject               = \"$BUILDNAME_PROJECT\";
3344
\$ScmBuildVersionFull           = \"$BUILDVERSION\";
3345
\$ScmBuildPreviousVersion       = \"$BUILDPREVIOUSVERSION\";
3346
\$ScmLocal                      = \"$BUILDLOCAL\";
3347
\$ScmDeploymentPatch            = \"$DEPLOY_PATCH\";
3348
\$ScmSrcDir                     = \"$Srcdir\";
3349
\$ScmBuildSrc                   = \"$ScmBuildSrc\";
3350
\$ScmExpert                     = \"$Expert\";
261 dpurdie 3351
\$ScmAll                        = \"$All\";
227 dpurdie 3352
");
3353
 
3354
#.. Alias
3355
#
3356
    $fh->DumpData(
3357
        "\n# Aliases.\n#\n",
3358
        "ScmBuildAliases", \%BUILDALIAS );
3359
 
3360
#.. Products
3361
#
3362
    $fh->DumpData(
3363
        "# Product mapping.\n#\n",
3364
        "ScmBuildProducts", \%BUILDPRODUCT_PARTS );
3365
 
3366
#.. Create ScmBuildPlatforms
3367
#
3368
    my( @platforms_merged, %platform_args ) = ();
3369
 
3370
    UniquePush ( \@platforms_merged, @BUILDPLATFORMS );
3371
 
3372
    foreach my $key ( keys %BUILDPRODUCT ) {
3373
        my( @list ) = split( ' ', $BUILDALIAS{ $key } || '' );
3374
        my( $platform );
3375
 
3376
        foreach my $elem ( @list ) {
3377
            if ( $elem =~ /^--/ ) {             # argument
3378
                HashJoin( \%platform_args, $;, $platform, $elem )
3379
                    if ( defined($platform) );
3380
                next;
3381
            }
3382
            $platform = $elem;                  # platform
3383
            UniquePush( \@platforms_merged, $elem );
3384
        }
3385
    }
3386
 
3387
#.. Create ScmBuildPlatforms
3388
#   Contains per platform options extracted from alias and platform args
3389
#
3390
    my %ScmBuildPlatforms;
3391
    foreach my $key ( @platforms_merged ) {
3392
 
3393
        my( @arguments ) = ();
3394
        UniquePush( \@arguments, split( /$;/, $BUILDPLATFORMARGS{ $key } ))
3395
            if ( exists $BUILDPLATFORMARGS{ $key } );
3396
 
3397
        UniquePush( \@arguments, split( /$;/, $platform_args{ $key } ))
3398
            if ( exists $platform_args{ $key } );
3399
 
3400
        $ScmBuildPlatforms{$key} = join "$;", @arguments;
3401
    }
3402
 
3403
    $fh->DumpData(
3404
        "# Platform and global argument list.\n#\n",
3405
        "ScmBuildPlatforms", \%ScmBuildPlatforms );
3406
 
3407
 
3408
# .. Create BuildPkgRules
3409
#
3410
#    This most of the information contained within %PKGRULES, which
3411
#    requires additional processing within makelib.
3412
#
3413
    my %ScmBuildPkgRules;
3414
    foreach my $platform ( keys %PKGRULES )
3415
    {
3416
        foreach my $package ( @{$PKGRULES{$platform}} )
3417
        {
3418
            my %entry;
3419
 
3420
            $entry{ROOT}     = $package->{'base'};
3421
            $entry{NAME}     = $package->{'name'};
3422
            $entry{VERSION}  = $package->{'version'};
3423
            $entry{DNAME}    = $package->{'dname'};
3424
            $entry{DVERSION} = $package->{'dversion'};
3425
            $entry{DPROJ}    = $package->{'dproj'};
3426
            $entry{TYPE}     = $package->{'type'};
3427
            $entry{CFGDIR}   = $package->{'cfgdir'} if ( defined( $package->{'cfgdir'} ) );
3428
 
3429
 
3430
            foreach my $dir (qw (PINCDIRS PLIBDIRS TOOLDIRS THXDIRS) )
3431
            {
3432
                $entry{$dir} = $package->{$dir} ;
3433
            }
3434
 
3435
            push @{$ScmBuildPkgRules{$platform}}, \%entry;
3436
        }
3437
    }
3438
 
3439
    $fh->DumpData(
3440
        "# Imported packages.\n#\n",
3441
        "ScmBuildPkgRules", \%ScmBuildPkgRules );
3442
 
3443
#
3444
#   BUILDPLATFORMS,
3445
#       The value that is saved only contains the active platforms
3446
#
3447
#   DEFBUILDPLATFORMS,
3448
#       The value that is matchs the wildcard specification for Platform 
3449
#       directives.
3450
#
3451
    $fh->DumpData(
3452
        "# A list of platforms active within the view.\n#\n",
3453
        "BUILDPLATFORMS", \@BUILD_ACTIVEPLATFORMS );
3454
 
3455
    $fh->DumpData(
3456
        "# A list of default platforms within the view.\n#\n",
3457
        "DEFBUILDPLATFORMS", \@DEFBUILDPLATFORMS );
3458
 
3459
#
3460
#   BUILDTOOLS
3461
#       A list of toolset extension paths
3462
#
3463
    $fh->DumpData(
3464
        "# A list of paths with toolset extension programs.\n#\n",
3465
        "BUILDTOOLSPATH", \@BUILDTOOLS );
3466
 
3467
#
3468
#   BUILDPLATFORM_PARTS
3469
#       A subset of BUILDINFO exported as BUILDPLATFORM_PARTS
3470
#       This exists only for backward compatability with existing code
3471
#       in external packages ( deployfiles).
3472
#
3473
#   Only save those parts that are part of the current build
3474
#   This will prevent users attempting to build for platforms that have not
3475
#   been correctly constructed.
3476
#
3477
    my %active =  map { ${_} => 1 } @BUILD_ACTIVEPLATFORMS;
3478
    my %active_buildplatform_parts;
3479
    my %active_build_info;
3480
    foreach ( keys %BUILDINFO )
3481
    {
3482
        next unless ( $active{$_} );
3483
        $active_buildplatform_parts{$_} = $BUILDINFO{$_}{PARTS};
3484
        $active_build_info{$_}          = $BUILDINFO{$_};
3485
    }
3486
 
3487
    $fh->DumpData(
3488
        "# Parts of all platforms.\n#\n",
3489
        "BUILDPLATFORM_PARTS", \%active_buildplatform_parts );
3490
#
3491
#   BUILDINFO
3492
#       Complete TARGET Information
3493
#
3494
    $fh->DumpData(
3495
        "# Extended build information.\n#\n",
3496
        "BUILDINFO", \%active_build_info );
3497
 
3498
#
247 dpurdie 3499
#   BUILD_KNOWNFILES
3500
#       All paths are relative to the project root directory
3501
#       ie: The directory that conatins the build.pl file
3502
#
3503
    $fh->DumpData(
3504
        "# Generated Files that may be known when used as Src files.\n#\n",
3505
        "BUILD_KNOWNFILES", \%BUILD_KNOWNFILES );
3506
 
3507
#
227 dpurdie 3508
#   Close out the file
3509
#
3510
    $fh->Close();
3511
}
3512
 
3513
#-------------------------------------------------------------------------------
3514
# Function        : WriteParsedBuildConfig
3515
#
3516
# Description     : Write all the parsed build.pl data to a single file
3517
#                   Its all in there for use
3518
#
3519
# Inputs          : 
3520
#
3521
# Returns         : 
3522
#
3523
sub WriteParsedBuildConfig
3524
{
3525
    my $cfg_file = "$::BUILDINTERFACE/Buildfile.cfg";
3526
    my %cf_build_info = ();
3527
 
3528
    #
3529
    #   Examine the symbol table and capture most of the entries
3530
    #
3531
    foreach my $symname (keys %main::)
3532
    {
3533
        next if ( $symname =~ m/::/  );                 # No Typeglobs
3534
        next if ( $symname =~ m/^cf_build_info/  );     # Not myself
3535
        next unless ( $symname =~ m/^[A-Za-z]/  );      # No system type names
3536
        next if ( $symname =~ m/^SIG$/  );              # Useless
3537
        next if ( $symname =~ m/^ENV$/  );              # Don't keep the user ENV
3538
        next if ( $symname =~ m/^INC$/  );              # Don't keep the INC paths
3539
        next if ( $symname =~ m/^DEFINES/  );           # Don't keep
3540
        next if ( $symname =~ m/^TOOLSETRULES/  );      # Don't keep
3541
 
331 dpurdie 3542
        no strict 'vars';
227 dpurdie 3543
        local *sym = $main::{$symname};
3544
 
331 dpurdie 3545
        $cf_build_info{"\$$symname"} =  $sym if defined $sym;
3546
        $cf_build_info{"\@$symname"} = \@sym if defined @sym;
3547
        $cf_build_info{"\%$symname"} = \%sym if defined %sym;
3548
        use strict 'vars';
227 dpurdie 3549
    }
3550
 
3551
    #
3552
    #   Dump out the configuration information
3553
    #
3554
    my $fh = ConfigurationFile::New( "$cfg_file" );
3555
    $fh->Header( "buildlib (version $::BuildVersion)",
3556
                              "Buildfile configuration" );
3557
    $fh->Dump( [\%cf_build_info], [qw(*cf_build_info)] );
3558
    $fh->Close();
3559
}
3560
 
3561
 
3562
#-------------------------------------------------------------------------------
3563
# Function        : BuildRuleFiles
3564
#
3565
# Description     : Create a set of rule files in the interface directory
3566
#                   These will be included directly into makefiles to
3567
#                   extend library and header search paths to the Linked
3568
#                   archives
3569
#
3570
#                   One file is created for each platform to simplify the
3571
#                   inclusion rules
3572
#
3573
#
3574
#                   The PKGRULES data structure is of the form:
3575
#
3576
#                   A hash, by platform, of an array of package information
3577
#                   Each block of package information is a hash containing
3578
#                       'name'      -  short name of the package
3579
#                       'version'   -  short name of the package
3580
#                       'base'      - path of the package root
3581
#                       'PINCDIRS'  - Array of included directories
3582
#                       'PLIBDIRS'  - Array of library directories
3583
#
3584
#                   Arrays are used to preserve the user specified search
3585
#                   order, both of packages and directories within each
3586
#                   package
3587
#
3588
# Inputs          :
3589
#
3590
# Returns         :
3591
#
3592
sub BuildRuleFiles
3593
{
3594
    #
3595
    #   A file is generated for each platform
3596
    #   Within this lines are generated for each package
3597
    #
3598
    foreach my $platform ( keys %PKGRULES )
3599
    {
3600
        my $pPlatform = $PKGRULES{$platform};
3601
 
3602
        my $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/$platform.rul", '--NoEof', '--Type=mak' );
3603
        $fh->Header( "Buildlib ($BuildVersion)","Package import specification" );
3604
 
3605
        $fh->Write ( "PINCDIRS\t=\t\t" . "# includes\n" );
3606
        $fh->Write ( "PLIBDIRS\t=\t\t" . "# libraries\n" );
3607
        $fh->Write ( "\n" );
3608
 
3609
        #
3610
        #   For each Available package accessable to this platform
3611
        #
3612
        foreach my $package ( @{$pPlatform} )
3613
        {
311 dpurdie 3614
            #
3615
            #   Skip the pseudo package that encapsulates the interface
3616
            #   directory. Currently the makefiles do this in a different
3617
            #   manner - to be resolved
3618
            #
3619
            #   Just comment out the lines so that the data is visible
3620
            #   Its a hint to make use of the data
3621
            #
3622
            my $prefix = '';
3623
            $prefix = '# ' if ( $package->{'type'} eq 'interface' );
3624
 
3625
 
227 dpurdie 3626
            my $name = $package->{'name'} . '/' . $package->{'version'};
3627
            my $base = $package->{'base'};
3628
 
3629
            $fh->Write ( "##########################################################\n");
3630
            $fh->Write ( "# Source:  $name\n" );
3631
            $fh->Write ( "#\n" );
3632
 
3633
            #
3634
            #   List include and library directories
257 dpurdie 3635
            #   Need the True Path for windows.
3636
            #       Some makefile functions (wildcard) only work as expected
3637
            #       if the case of the pathname is correct. Really only a problem
3638
            #       with badly formed legecy packages where the Windows user
3639
            #       guessed at the package format.
227 dpurdie 3640
            #
257 dpurdie 3641
            #
227 dpurdie 3642
            for my $type (qw (PINCDIRS PLIBDIRS) )
3643
            {
3644
                for my $path ( @{$package->{$type}} )
3645
                {
311 dpurdie 3646
                    $fh->Write ( "$prefix$type\t+= " . TruePath($base . $path) . "\n" );
227 dpurdie 3647
                }
3648
            }
3649
            $fh->Write ( "\n" );
3650
        }
3651
        $fh->Close();
3652
    }
3653
}
3654
 
3655
#-------------------------------------------------------------------------------
3656
# Function        : BuildSharedLibFiles
3657
#
3658
# Description     : Create a file in the interface directory that will specify
3659
#                   the locations of shared libraries.
3660
#
3661
#                   Note: Always create a file as makefile targets depend on it.
3662
#
3663
#                   This is a bit ugly.
3664
#
3665
#                   There needs be an association between the build machine and
3666
#                   the target platform. Need to know if the current target is
3667
#                   native to the current build machine. If it is then we can
3668
#                   run tests on the machine and we then need to extend the
3669
#                   search path for the target.
3670
#
3671
#                   The BUILDINFO{EXT_SHARED} is used to control the creation of
3672
#                   the files by specifying the extension of the file.
3673
#
3674
# Inputs          : None
3675
#
3676
# Returns         :
3677
#
3678
sub BuildSharedLibFiles
3679
{
3680
    if ( $ScmHost eq "DOS" || $ScmHost eq "WIN" ) {
3681
        BuildSharedLibFiles_WIN(@_);
3682
 
3683
    } elsif ( $ScmHost eq "Unix" ) {
3684
        BuildSharedLibFiles_Unix(@_);
3685
 
3686
    } else {
3687
        Error("Cannot build. Unknown machine type: $ScmHost",
3688
              "Need WIN, DOS or Unix" );
3689
    }
3690
}
3691
 
3692
#-------------------------------------------------------------------------------
3693
# Function        : BuildSharedLibFiles_WIN
3694
#
3695
# Description     : Implementation of BuildSharedLibFiles for Windows
3696
#
3697
# Inputs          : None
3698
#
3699
sub BuildSharedLibFiles_WIN
3700
{
3701
 
3702
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
3703
    {
3704
        next unless ( exists $BUILDINFO{$platform}{EXT_SHARED} );
3705
        my @dos_paths = BuildSharedLibFiles_list( $platform, $BUILDINFO{$platform}{EXT_SHARED} );
3706
 
3707
        #
3708
        #   Create a .bat file for WIN32
3709
        #   This may be consumed by user wrapper programs
3710
        #
229 dpurdie 3711
        #   Features: No Echo
3712
        #             Use of SETLOCAL to prevent pollution of environment
3713
        #
227 dpurdie 3714
        my $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/set_$platform.bat", '--NoEof', '--Type=bat' );
229 dpurdie 3715
        $fh->Write ( "\@echo off\n");
227 dpurdie 3716
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
229 dpurdie 3717
        $fh->Write ( "\nSETLOCAL\n");
227 dpurdie 3718
        foreach ( reverse @dos_paths )
3719
        {
3720
            $_ =~ s~/~\\~g;
3721
            $fh->Write ( "PATH=$_;\%PATH\%\n" );
3722
        }
3723
        $fh->Write ( "\n%*\n" );
229 dpurdie 3724
        $fh->Write ( "\nENDLOCAL\n");
231 dpurdie 3725
        $fh->Write ( "EXIT /B %ERRORLEVEL%\n");
227 dpurdie 3726
        $fh->Close();
3727
 
3728
        #
3729
        #   Create a .sh file for WIN32
3730
        #   This may be consumed by a shell - as used within JATS
3731
        #
3732
        $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/set_$platform.sh", '--NoEof', '--Type=sh' );
3733
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
3734
        foreach ( reverse @dos_paths )
3735
        {
3736
            tr~\\/~/~s;
3737
            $fh->Write ( "PATH=$_\\;\$PATH\n" );
3738
        }
287 dpurdie 3739
        $fh->Write ( "\n" . '[ -n "$*" ] && "$@"'  ."\n" );
227 dpurdie 3740
        $fh->Close();
3741
    }
3742
}
3743
 
3744
#-------------------------------------------------------------------------------
3745
# Function        : BuildSharedLibFiles_Unix
3746
#
3747
# Description     : Implementation of BuildSharedLibFiles for Unix
3748
#                   Extend the Shared Library search path via LD_LIBRARY_PATH
3749
#
3750
# Inputs          : None
3751
#
3752
sub BuildSharedLibFiles_Unix
3753
{
3754
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
3755
    {
3756
        next unless ( exists $BUILDINFO{$platform}{EXT_SHARED} );
3757
        my @unix_paths = BuildSharedLibFiles_list( $platform, $BUILDINFO{$platform}{EXT_SHARED} );
3758
 
3759
        #
3760
        #   Create a .sh file for Unix
3761
        #
229 dpurdie 3762
        my $file = "$BUILDINTERFACE/set_$platform.sh";
3763
        my $fh = ::ConfigurationFile::New( $file , '--NoEof', '--Type=sh' );
227 dpurdie 3764
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
3765
        foreach ( reverse @unix_paths )
3766
        {
3767
            $fh->Write ( "export LD_LIBRARY_PATH=$_:\$LD_LIBRARY_PATH\n" );
3768
        }
275 dpurdie 3769
        $fh->Write ( "\n\"\$\@\"\n" );
227 dpurdie 3770
        $fh->Close();
229 dpurdie 3771
 
3772
        #
3773
        #   Make the file executable under unix
3774
        #
3775
        chmod 0755, $file;
227 dpurdie 3776
    }
3777
}
3778
 
3779
#-------------------------------------------------------------------------------
3780
# Function        : BuildSharedLibFiles_list
3781
#
3782
# Description     : Determine a list of Shared Library paths that can be used
3783
#                   by the current target
3784
#
3785
# Inputs          : $platform       - Current platform
3786
#                   $so             - Shared object extensions
3787
#
3788
# Returns         : List of search paths
3789
#
3790
sub BuildSharedLibFiles_list
3791
{
3792
    my ($platform, $so ) = @_;
3793
    my @paths;
3794
    my @parts = @{$BUILDINFO{$platform}{PARTS}};
3795
 
3796
    #
3797
    #   Paths from the current build
3798
    #       Local directory         - for installed components
3799
    #       Interface directory     - for BuildPkgArchives
3800
    #
3801
    if ( $BUILDLOCAL )
3802
    {
3803
        foreach ( @parts )
3804
        {
3805
            push @paths, AbsPath("$BUILDLOCAL/lib/$_");
3806
        }
3807
    }
3808
 
3809
    foreach ( @parts )
3810
    {
3811
            push @paths, AbsPath("$BUILDINTERFACE/lib/$_");
3812
    }
3813
 
3814
    #
3815
    #   For each LinkPkgArchive
3816
    #
3817
    foreach my $package ( @{$PKGRULES{$platform}} )
3818
    {
3819
        next unless ( $package->{'type'} eq 'link' );
3820
 
3821
        my $base = $package->{'base'};
3822
        for my $path ( @{$package->{'PLIBDIRS'}} )
3823
        {
289 dpurdie 3824
            my @so_libs;
317 dpurdie 3825
            push @so_libs, glob ( "$base$path/*$_") foreach ( ArrayList($so) );
227 dpurdie 3826
            next unless scalar @so_libs;
3827
            push @paths, $base . $path;;
3828
        }
3829
    }
3830
 
3831
    #
3832
    #   Returns paths found
3833
    #
3834
    return @paths;
3835
}
3836
 
3837
#-------------------------------------------------------------------------------
247 dpurdie 3838
# Function        : BuildAddKnownFile
3839
#
3840
# Description     : Save the file as a file that will be known  to the JATS
3841
#                   makefiles. It will be available SRCS, but will not be a
3842
#                   part of any object list.
3843
#
3844
#                   Known Files will be deleted on clobber
3845
#
3846
# Inputs          : $path
3847
#                   $file
289 dpurdie 3848
#                   $noadd                    - Don't add to known
247 dpurdie 3849
#
3850
# Returns         : Path and filename
3851
#
3852
 
3853
sub BuildAddKnownFile
3854
{
289 dpurdie 3855
    my ($path, $file, $noadd) = @_;
247 dpurdie 3856
    $path .= '/'. $file;
289 dpurdie 3857
    $BUILD_KNOWNFILES {$file} = $path
3858
        unless ( defined($noadd) && $noadd);
247 dpurdie 3859
    push @CLOBBERFILES, $path;
3860
 
3861
    return $path;
3862
}
3863
 
3864
#-------------------------------------------------------------------------------
227 dpurdie 3865
# Function        : Usage
3866
#
3867
# Description     : Display program usage information
3868
#
3869
# Inputs          : args            - Text message to display
3870
#
3871
#                   $opt_help       - Level of verbose ness
3872
#
3873
# Returns         : Does not return
3874
#                   This function will exit
3875
#
3876
sub Usage
3877
{
3878
    my( $msg ) = @_;
3879
    my %usage_args;
3880
 
3881
    #
3882
    #   Create a hash of arguments for the pod2usage function
3883
    #
3884
    $usage_args{'-input'} = __FILE__;
3885
    $usage_args{'-exitval'} = 42;
3886
    $usage_args{'-message'} = "\nbuildlib $msg\n" if $msg;
3887
    $usage_args{'-verbose'} = $opt_help < 3 ? $opt_help - 1 : 3 if ( $opt_help );
3888
 
3889
    #
3890
    #   Generate nice help
3891
    #
3892
    pod2usage(\%usage_args);
3893
}
3894
 
3895
#-------------------------------------------------------------------------------
3896
#   Documentation
3897
#
3898
 
3899
=pod
3900
 
3901
=head1 NAME
3902
 
3903
jats sandbox bootstrap
3904
 
3905
=head1 SYNOPSIS
3906
 
3907
jats build [options] [command]
3908
 
3909
     [perl buildlib.pl [options] PWD [command]]
3910
 
3911
 
3912
 Options:
331 dpurdie 3913
    -help          - Display terse usage
3914
    -help -help   - Display verbose usage
3915
    -man           - Display internal manual
3916
    -verbose[=n]   - Set level of progress verbosity
3917
    -debug[=n]     - Set the debug level
3918
    -nolog         - Do not generate/update Changelog
3919
    -cache         - Cache packages in the local dpkg_package cache
3920
    -cache -cache - Forced refresh dependent packages in the local cache
3921
    -package       - Ignore packages that are not available and continue
3922
    -forcebuildpkg - Treat LinkPkgArchive directives as BuildPkgArchive
227 dpurdie 3923
                      Also suppress the use of symlinks so that the phsical
3924
                      file will be copied locally.
331 dpurdie 3925
    -[no]force     - Force build even if build.pl is not newer
3926
                      Default: -force
227 dpurdie 3927
 
3928
 Sticky settings:
331 dpurdie 3929
    -all           - Build for all platforms ignoring GBE_BUILDFILTER
3930
    -expert[=n]    - Relaxing dependency checks on the user makefiles
227 dpurdie 3931
 
3932
 Commands:
3933
    changelog       - Only update ChangeLog.
3934
    interface       - Only (re)build the interface tree, including ChangeLog.
3935
    rootonly        - Only (re)build the root directory.
3936
    clobber         - Remove generated build system (eg Makefiles).
3937
 
3938
 
3939
=head1 OPTIONS
3940
 
3941
=over 8
3942
 
331 dpurdie 3943
=item B<-help>
227 dpurdie 3944
 
3945
Print a brief help message and exits.
3946
 
3947
=item B<-help -help>
3948
 
3949
Print a detailed help message with an explanation for each option.
3950
 
3951
=item B<-man>
3952
 
3953
Prints the manual page and exits.
3954
 
331 dpurdie 3955
=item B<-verbose[=n]>
227 dpurdie 3956
 
261 dpurdie 3957
Increases program output.
227 dpurdie 3958
 
261 dpurdie 3959
If an argument is provided, then it will be used to set the level, otherwise the
3960
existing level will be incremented. This option may be specified multiple times.
227 dpurdie 3961
 
261 dpurdie 3962
=item B<-debug>
3963
 
227 dpurdie 3964
Increases program output. Enable internal debugging messages to generate detailed
3965
progress information.
3966
 
261 dpurdie 3967
If an argument is provided, then it will be used to set the level, otherwise the
3968
existing level will be incremented. This option may be specified multiple times.
3969
 
331 dpurdie 3970
=item B<-nolog>
227 dpurdie 3971
 
3972
Do not generate or update the ChangeLog maintained when a CVS directory is detected
3973
in the build directory.
3974
 
331 dpurdie 3975
=item B<-cache>
227 dpurdie 3976
 
3977
This option will cause dependent packages to be cached in the local
3978
dpkg_archive cache.
3979
 
3980
If the option is used twice then the packages will be forcibly refreshed.
3981
 
331 dpurdie 3982
=item B<-package>
227 dpurdie 3983
 
3984
This option will cause the build process to ignore packages that cannot be
3985
located. The package build may fail at a later stage.
3986
 
3987
This option is used by the Auto Build Tool to handle packages that may not be
3988
needed in all builds.
3989
 
331 dpurdie 3990
=item B<-forcebuildpkg>
227 dpurdie 3991
 
3992
This option will force LinkPkgArchive directives to be treated as
3993
BuildPkgArchive directives. The result is that the 'interface' directory will be
3994
populated with the contents of all dependent packages. Moreover, on a Unix
3995
machine, the files will be copied and not referenced with a soft link.
3996
 
3997
This may be useful for:
3998
 
3999
=over 8
4000
 
4001
=item * Remote Development
4002
 
4003
=item * Collecting header files for scanning
4004
 
4005
=item * Local modification of files for test/debug/development
4006
 
4007
=back
4008
 
331 dpurdie 4009
=item B<-[no]force>
227 dpurdie 4010
 
331 dpurdie 4011
The '-noforce' option will only perform a build, if the build.pl file
4012
has build.pl file has been modified since the last build.
4013
 
4014
The default operation will alwars force a build.
4015
 
4016
=item B<-all>
4017
 
227 dpurdie 4018
This option will cause the build process to generate makefiles for all
4019
possible build targets ignoring the use of GBE_BUILDFILTER.
4020
 
4021
This option is sticky. Once used in a build it will be retained when makefiles
4022
are rebuilt.
4023
 
331 dpurdie 4024
=item B<-expert[=n]>
227 dpurdie 4025
 
4026
This option causes the generation of makefiles with relaxed dependancy checks.
4027
 
261 dpurdie 4028
If an argument is provided, then it will be used to set the level, otherwise a
4029
level of '1' will be set.
4030
 
227 dpurdie 4031
The makefiles will have no dependancy between the makefiles and the JATS build
4032
files or the users makefile. If the user's makefile.pl is changed then JATS
4033
will not detect the change and will not rebuild the makefiles. The user manually
4034
force the rebuild with the command 'jats rebuild'.
4035
 
4036
This option should be used with care and with full knowledge of its impact.
4037
 
4038
This option is sticky. Once used in a build it will be retained when makefiles
261 dpurdie 4039
are rebuilt. It will only be lost when the next 'jats build' is perfromed.
227 dpurdie 4040
 
261 dpurdie 4041
The effect of the option can be changed when the makefiles are processed. This
4042
option simply sets the default' mode of operation.
4043
 
227 dpurdie 4044
=item B<changelog>
4045
 
4046
This command will only update the CVS change log.
4047
 
4048
=item B<interface>
4049
 
4050
This command will only build, or rebuild, the 'interface' directory and the
4051
changelog ( if required ).
4052
 
261 dpurdie 4053
This command will not build, or rebuild, the root directory. The build
227 dpurdie 4054
process will not recurse through the subdirectories creating makefiles.
4055
 
261 dpurdie 4056
=item B<rootonly>
4057
 
4058
This command will only build, or rebuild, the 'interface' directory, the
4059
changelog (if required) and the root-level makefiles.
4060
 
4061
The build process will not recurse through the subdirectories creating
4062
makefiles. These can be made on-demand by jats if a 'make' command is issued.
4063
 
227 dpurdie 4064
=item B<clobber>
4065
 
4066
This command will remove generated build system files and directories.
4067
 
4068
=back
4069
 
4070
=head1 DESCRIPTION
4071
 
4072
The default build process will parse the user's build.pl file and create the
4073
'interface' directory before creating makefiles for each target platform.
4074
 
4075
The 'build' process simply generates the build sandbox. It does not invoke the
4076
generated makefiles. This must be done by the user in a different phase.
4077
 
4078
The 'build' process need only be invoked if the build.pl file has changed. The
4079
generated makefiles will detected changes to the makefile.pl's and cause them to
4080
be generated as required. The 'build' step sets up the sandboxes external
4081
environment.
4082
 
4083
=head1 INVOCATION
4084
 
4085
This perl library (buildlib.pl) is not designed to be invoked directly by the
4086
user. It should be invoked through a 'build.pl' file. Moreover, for historical
4087
reasons, the build.pl is not easily invoked. It is best to only invoke the
4088
'build' process via the JATS wrapper scripts : jats.bat or jats.sh.
4089
 
331 dpurdie 4090
The build.pl file must be invoked with one fixed arguments, followed by user
227 dpurdie 4091
options and subcommands
4092
 
4093
=over 8
4094
 
4095
=item   1 The current working directory
4096
 
4097
This could have been derived directly by the program, rather than having it
4098
passed in.
4099
 
331 dpurdie 4100
=item   2 Options and commands may follow the first two mandatory arguments.
227 dpurdie 4101
 
4102
=back
4103
 
4104
The build.pl file must 'require' the buildlib.pl and makelib.pl. The preferred
4105
code is:
4106
 
4107
=over 8
4108
 
4109
    build.pl: First statements
4110
    $MAKELIB_PL     = "$ENV{ GBE_TOOLS }/makelib.pl";
4111
    $BUILDLIB_PL    = "$ENV{ GBE_TOOLS }/buildlib.pl";
4112
 
4113
    require         "$BUILDLIB_PL";
4114
    require         "$MAKELIB_PL";
4115
 
4116
=back
4117
 
4118
=cut
4119
 
4120
1;