Subversion Repositories DevTools

Rev

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

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