Subversion Repositories DevTools

Rev

Rev 5679 | Rev 5708 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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