Subversion Repositories DevTools

Rev

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

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