Subversion Repositories DevTools

Rev

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