Subversion Repositories DevTools

Rev

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