Subversion Repositories DevTools

Rev

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