Subversion Repositories DevTools

Rev

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

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