Subversion Repositories DevTools

Rev

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