Subversion Repositories DevTools

Rev

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

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