Subversion Repositories DevTools

Rev

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

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