Subversion Repositories DevTools

Rev

Rev 7309 | Rev 7311 | 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
    #
7310 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
 
7310 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
 
7310 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
 
7310 dpurdie 3276
 
227 dpurdie 3277
    #
305 dpurdie 3278
    #   Ensure directive is allowed
3279
    #       $BUILDPHASE >  1     - No more directives allowed
3280
    #       $BUILDPHASE == 1     - Allowed directive
3281
    #
3282
    if ( $BUILDPHASE > 1 )
3283
    {
3284
        my $function = (caller(1))[3];
3285
        $function =~ s~.*::~~;
3286
        Error ("Directive not allowed: $function","'BuildMake' must be the last directive in the build file");
3287
    }
3288
 
3289
    #
227 dpurdie 3290
    #   Only do it once
3291
    #
305 dpurdie 3292
    return if ( $BUILDPHASE  );
3293
    $BUILDPHASE = 1;
227 dpurdie 3294
 
3295
    #
341 dpurdie 3296
    #   If we are not performing a ForceBuild, then we don't need to continue
3297
    #   We have updated the interface directory with BuildPkgArchive
3298
    #   information.
3299
    #
3300
    TestForForcedBuild();
3301
 
3302
    #
6133 dpurdie 3303
    #   Calculate the aliases that are being extracted from targets
227 dpurdie 3304
    #
3305
    Process_TargetAlias();
3306
 
3307
    #
7307 dpurdie 3308
    #   Calculate defined aliases
6133 dpurdie 3309
    #       Limit the Aliases to active platforms
7307 dpurdie 3310
    #       ie: NATIVE INSTRUMENT PKG_WIN PKG_RPM PKG_DEB SK
4728 dpurdie 3311
    #
7310 dpurdie 3312
    my %activePlatformMap;
3313
#    foreach my $item (@BUILD_ACTIVEPLATFORMS) {
3314
    foreach my $item ( keys %BUILDINFO) {
3315
           my $pInfo = $BUILDINFO{$item};
3316
           next if $pInfo->{NOT_AVAILABLE} > 1; 
3317
           push @{$activePlatformMap{$pInfo->{TARGET}}}, $item;
3318
    }
3319
 
7307 dpurdie 3320
    foreach my $alias ( @PlatformConfig::BuildAliases )
4728 dpurdie 3321
    {
7310 dpurdie 3322
        if (exists $BUILDALIAS{$alias})  
4728 dpurdie 3323
        {
7307 dpurdie 3324
            # Will occur if GBE_ABT has been set, for backward compatibility
6133 dpurdie 3325
            Warning("User has manually specified a $alias alias",'Default alias will not be set.');
7310 dpurdie 3326
            #DebugDumpData("BUILDALIAS", \%BUILDALIAS);
4728 dpurdie 3327
        }
6133 dpurdie 3328
        else
3329
        {
3330
            my @activeAliases;
7309 dpurdie 3331
            foreach my $item (PlatformConfig::getTargetsByTag($alias)) {
7310 dpurdie 3332
                if (exists($activePlatformMap{$item})) {
3333
                    push (@activeAliases, @{$activePlatformMap{$item}});
3334
                }
6133 dpurdie 3335
            }
7310 dpurdie 3336
 
6133 dpurdie 3337
            $BUILDALIAS{$alias} = join(' ', @activeAliases) if (@activeAliases);
3338
 
3339
            #
3340
            #   Add to the build entry too
3341
            #
7310 dpurdie 3342
            foreach my $aliasTarget (@activeAliases) {
6133 dpurdie 3343
                push @{$BUILDINFO{$aliasTarget}{USERALIAS}}, $alias;
3344
            }
3345
        }
4728 dpurdie 3346
    }
6133 dpurdie 3347
    CleanUp_Aliases();
4728 dpurdie 3348
 
3349
    #
311 dpurdie 3350
    #   Create dummy package to describe the Interface directory
3351
    #
3352
    CreateInterfacePackage();
3353
 
3354
    #
227 dpurdie 3355
    #   Sanity test the users packages
6133 dpurdie 3356
    #       In a sandbox all bet are off
227 dpurdie 3357
    #
6133 dpurdie 3358
    PackageEntry::SanityTest() unless ($Clobber || $::GBE_SANDBOX);
227 dpurdie 3359
 
3360
    #
3361
    #   Validate the $Srcdir before its first real use
3362
    #   This is calculated from the user directives
3363
    #
3364
 
3365
    #.. Determine default "source" root
3366
    #
3367
    if ( $Srcdir eq "" )
3368
    {
3369
        Warning( "Both the directories 'src' and 'SRC' exist ....." )
3370
            if ( $ScmHost eq "Unix" && -e "src" && -e "SRC" );
3371
 
3372
        if ( -e "src" ) {
3373
            $Srcdir = "src";
3374
        } else {
3375
            ( -e "SRC" ) ||
3376
                Error( "Neither the directory 'src' nor 'SRC' exist ....." );
3377
            $Srcdir = "SRC";
3378
        }
3379
    }
3380
 
3381
    #
3382
    #   Must have a valid Srcdir
3383
    #
3384
    Error ("Source directory not found: $Srcdir")
3385
        unless ( $Srcdir && -d $Srcdir );
3386
 
305 dpurdie 3387
    #
3388
    #   Create source package
3389
    #
3390
    BuildSrcArchiveBody();
3391
 
227 dpurdie 3392
    return $Srcdir;
3393
}
3394
 
3395
#-------------------------------------------------------------------------------
341 dpurdie 3396
# Function        : TestForForcedBuild
3397
#
3398
# Description     : If a non-forced build has been requested, then see
3399
#                   if a build is required ( ie: build.pl modified )
6133 dpurdie 3400
#                   
3401
#                   Check:
3402
#                       Time stamp of build.pl
3403
#                       Time stamp of Makefile.gbe
3404
#                       BuildFilter has not changed
3405
#                       Signature of dependencies has not changed
3406
#                       No packages consumed from within the sandbox
341 dpurdie 3407
#
3408
# Inputs          : None
3409
#
3410
# Returns         : May not return
6133 dpurdie 3411
#                   Will return if we need to perform a build
341 dpurdie 3412
#
3413
sub TestForForcedBuild
3414
{
3415
    #
3416
    #   Always return if in clobber mode
3417
    #
3418
    return if ( $Clobber );
3419
 
3420
    if ( ! $ForceBuild  )
3421
    {
3422
        my @build_warn;
3423
        my $bstamp = -M "$Cwd/$ScmBuildSrc";
3424
        my $tstamp = -M "$Cwd/Makefile.gbe";
3425
 
3426
        push @build_warn, "Missing: Makefile.gbe" unless ( defined $tstamp );
3427
        push @build_warn, "Modified build file ($ScmBuildSrc)" if ( $tstamp && $bstamp < $tstamp );
3428
 
363 dpurdie 3429
        #
3430
        #   Ensure that the build filter has not changed
3431
        #   If the user has changed the buildfilter, then we need to
3432
        #   force a build.
3433
        #
6133 dpurdie 3434
        #   The root Makefile.gbe will have a $ScmBuildFilter entry
363 dpurdie 3435
        #
3436
        unless ( @build_warn )
3437
        {
3438
            use JatsMakeInfo;
3439
            ReadMakeInfo();
5726 dpurdie 3440
            my $line = $::ScmBuildFilter || '';
3441
            $line =~ s~\s+~ ~g;
363 dpurdie 3442
 
5726 dpurdie 3443
            my $filter = $::GBE_BUILDFILTER || '';
3444
            $filter =~ s~\s+~ ~g;
3445
            if ( $line ne $filter )
3446
            {
3447
                push @build_warn, "Build filter has changed";
3448
                Verbose2 ("Buildfilter Test: Was:$line, Is:$::GBE_BUILDFILTER");
3449
            }
363 dpurdie 3450
        }
3451
 
6133 dpurdie 3452
        #
7301 dpurdie 3453
        #   See if the dependencies have changed
3454
        #   
7310 dpurdie 3455
        my $BuildpkgSig = Digest::SHA::PurePerl->new;
7301 dpurdie 3456
        $BuildpkgSig->add("PKGNAME: $BUILDNAME_PACKAGE $BUILDNAME_VERSION $BUILDNAME_SUFFIX");
3457
 
3458
        #
3459
        #   Include the signature of ALL dependent packages
3460
        #   Ie: The build fingerprint is a function of the source and its dependents
3461
        #
3462
        my $depTagFile = catfile($ScmInterface, 'build.bfp');
3463
        unless (-f $depTagFile) {
3464
            push @build_warn, "Missing: $depTagFile";
3465
        }
3466
        else
3467
        {
3468
            foreach my $tag ( PackageEntry::GetPackageList() )
3469
            {
3470
                my $pkgSig = PackageEntry::GetPackageSignature($tag);
3471
                $BuildpkgSig->add("PKGSIGNATURE: $pkgSig");
3472
            }
3473
            my $depSha1 =  $BuildpkgSig->hexdigest;
3474
            Debug2("DepSha1: $depSha1");
3475
            unless (TagFileMatch ($depTagFile, $depSha1))
3476
            {
3477
                push @build_warn, "Dependency signatures have changed";
3478
            }
3479
        }
3480
 
3481
        #
6133 dpurdie 3482
        #   If any of the imported packages are from a sandbox, then we must force a build
3483
        #   and a make.
3484
        #
3485
        if ($pkgFromSandbox)
3486
        {
3487
            push @build_warn, "Consuming packages from within the sandbox";
3488
        }
3489
 
341 dpurdie 3490
        if ( @build_warn )
3491
        {
363 dpurdie 3492
            Verbose ("Forcing Build.", @build_warn );
341 dpurdie 3493
        }
3494
        else
3495
        {
3496
            Verbose ("No build performed. Build files up to date");
3497
            Log ("Build files up to date") if $::GBE_SANDBOX;
3498
            exit 0;
3499
        }
3500
    }
3501
}
3502
 
3503
#-------------------------------------------------------------------------------
305 dpurdie 3504
# Function        : LastBuildDirective
3505
#
3506
# Description     : No more build directives allowed
3507
#
3508
# Inputs          : 
3509
#
3510
# Returns         : 
3511
#
3512
sub LastBuildDirective
3513
{
3514
    $BUILDPHASE = 2;
3515
}
3516
 
3517
#-------------------------------------------------------------------------------
227 dpurdie 3518
# Function        : BuildPackageLink
3519
#
3520
# Description     : Create a soft link from sandbox_dpkg_archive to the package
3521
#                   being created by this build
3522
#
3523
#                   For backward compatability.
3524
#                   If GBE_DPKG_SBOX is not defined, then use GBE_DPKG_LOCAL
3525
#
3526
#                   This will allow multiple components to work together
3527
#
3528
#                   Note: When called in Clobber-mode the link will be deleted
3529
#
3530
# Inputs          : $BUILDNAME              - The package name
3531
#                   $BUILDNAME_PROJECT      - Project extension
3532
#                   $::GBE_DPKG_SBOX        - Path of sandbox_dpkg_archive
3533
#                   $::GBE_DPKG_LOCAL       - Path of local_dpkg_archive
3534
#                   $::GBE_DPKG             - Main repository
3535
#
3536
# Returns         : Nothing
3537
#
3538
sub BuildPackageLink
3539
{
3540
    my $target_archive;
3541
    my $target_archive_name;
3542
    my $link_file;
3543
    my $tag;
371 dpurdie 3544
    my $root_path;
227 dpurdie 3545
 
3546
    #
3547
    #   Determine the path (and name) of the target archive
3548
    #   Use sandbox_dpkg_archive if it exists
3549
    #   Use local_dpkg_acrhive for backward compatability (should be removed after JATS 2.64.2+)
3550
    #
3551
    if ( $target_archive = $::GBE_DPKG_SBOX )
3552
    {
3553
        $target_archive_name = "sandbox_dpkg_archive";
3554
        $tag = "Sandbox";
7301 dpurdie 3555
        $link_file  = 'sandbox' . ${BUILDNAME_SUFFIX} . '.lnk';
371 dpurdie 3556
        $root_path = 'GBE_SANDBOX' . substr($Cwd, length($::GBE_SANDBOX));
3557
        Verbose2("Root Path: $::GBE_SANDBOX, $root_path");
227 dpurdie 3558
    }
3559
    elsif ( $target_archive = $::GBE_DPKG_LOCAL )
3560
    {
3561
        $target_archive_name = "local_dpkg_archive";
3562
        $link_file = "$BUILDVERSION.lnk";
3563
        $tag = "Local";
371 dpurdie 3564
        $root_path = $Cwd;
227 dpurdie 3565
    }
3566
    else
3567
    {
3568
        Verbose("Cannot locate local or sandbox archive")
3569
            unless $Clobber;
3570
        return;
3571
    }
3572
 
3573
    #
3574
    #   Santity test
3575
    #   Target must be a directory
3576
    #
3577
    unless ( -d $target_archive )
3578
    {
241 dpurdie 3579
        Warning("$target_archive_name is not a directory: $target_archive")
227 dpurdie 3580
            unless $Clobber;
3581
        return;
3582
    }
3583
 
3584
    my $link_dir = "$target_archive/$BUILDNAME_PACKAGE";
3585
    my $link_path = "$link_dir/$link_file";
3586
 
6133 dpurdie 3587
    if ( $Clobber || $NoBuild )
227 dpurdie 3588
    {
3589
        unlink $link_path;          # Delete the link
3590
        rmdir $link_dir;            # Delete only if empty
3591
    }
3592
    else
3593
    {
261 dpurdie 3594
        Log( "Local Link . $BUILDNAME_PACKAGE/$link_file ($tag)");
3595
        mkdir $link_dir unless -d $link_dir;
371 dpurdie 3596
        FileCreate ( $link_path, "$root_path/pkg/$BUILDNAME_PACKAGE");
227 dpurdie 3597
    }
3598
}
3599
 
3600
#-------------------------------------------------------------------------------
3601
# Function        : BuildSandboxData
3602
#
3603
# Description     : Create data structures to allow this package to be built
3604
#                   within a multi-package sandbox.
3605
#
3606
#                   This will allow multiple components to work together
6133 dpurdie 3607
#                   Creates:
3608
#                       sandbox.int     - Rel path to the packages interface
3609
#                       sandbox.ffp     - Fast FingerPrint over the package body
3610
#                       sandbox.nob     - No Build marker
227 dpurdie 3611
#
3612
#                   Note: When called in Clobber-mode the link will be deleted
3613
#
3614
# Inputs          : $BUILDNAME              - The package name
3615
#                   $BUILDNAME_PROJECT      - Project extension
3616
#                   $::GBE_DPKG_SBOX        - Path of sandbox_dpkg_archive
3617
#                   $::GBE_DPKG             - Main repository
3618
#
3619
# Returns         : Nothing
3620
#
3621
sub BuildSandboxData
3622
{
3623
    my $sandbox_dpkg_archive = $::GBE_DPKG_SBOX;
3624
    return unless ( $sandbox_dpkg_archive );
3625
 
3626
    unless ( -d $sandbox_dpkg_archive )
3627
    {
241 dpurdie 3628
        Error("sandbox_dpkg_archive is not a directory: $sandbox_dpkg_archive")
227 dpurdie 3629
            unless $Clobber;
3630
        return;
3631
    }
3632
 
3633
    #
3634
    #   Create a name for this package in the sandbox
3635
    #   Must use the package name and extension. Don't use the version
3636
    #   information as this will not be correct
3637
    #
3638
    #   PACKAGE/sandbox.PRJ.cfg
3639
    #
3640
    my $link_dir = "$sandbox_dpkg_archive/$BUILDNAME_PACKAGE";
6133 dpurdie 3641
    my $base = 'sandbox' . ${BUILDNAME_SUFFIX}; 
359 dpurdie 3642
 
6133 dpurdie 3643
    my $nob_path  = $base . ".nob";
3644
    my $ffp_path  = $base . ".ffp";
3645
    my $int_path  = $base . ".int";
227 dpurdie 3646
 
6133 dpurdie 3647
    $nob_path = "$link_dir/$nob_path";
3648
    $ffp_path = "$link_dir/$ffp_path";
3649
    $int_path = "$link_dir/$int_path";
3650
 
227 dpurdie 3651
    if ( $Clobber )
3652
    {
3653
        rmdir $link_dir;            # Delete only if empty
3654
    }
3655
    else
3656
    {
6133 dpurdie 3657
        ToolsetFiles::AddFile($nob_path);
3658
        ToolsetFiles::AddFile($ffp_path);
3659
        ToolsetFiles::AddFile($int_path);
3660
 
3661
        #Log( "Sandbox Data. $base");
3662
        unlink $int_path;
227 dpurdie 3663
        mkdir $link_dir;
3664
 
3665
        #
6133 dpurdie 3666
        #   File with path to the interface directory
3667
        #   Relative to the base of the sandbox
227 dpurdie 3668
        #
6133 dpurdie 3669
        FileCreate($int_path, catdir('GBE_SANDBOX',RelPath($Cwd,$::GBE_SANDBOX),$BUILDINTERFACE ));
227 dpurdie 3670
 
3671
        #
6133 dpurdie 3672
        #   Indicate packages not build on this machine
227 dpurdie 3673
        #
6133 dpurdie 3674
        unlink $nob_path;           # Delete the NoBuild marker
3675
        if ($NoBuild) {
3676
            TouchFile($nob_path);
3677
        }
227 dpurdie 3678
    }
3679
}
3680
 
3681
 
3682
#-------------------------------------------------------------------------------
3683
# Function        : BuildMake
3684
#
3685
# Description     : Generate the makefiles
3686
#                   This directive MUST be the last directive in the build.pl
3687
#                   file. The directive triggers the processing of all the
3688
#                   information that has been collected
3689
#
3690
#
3691
# Inputs          : None
3692
#
3693
# Returns         : Nothing
3694
#
3695
 
3696
sub BuildMake
3697
{
3698
    my( $argc, $platform );
3699
 
3700
    #
3701
    #   Must have a valid $BUILDINTERFACE
3702
    #   Normally this is held in the interface directory, but this is not
3703
    #   always created. If there is no $BUILDINTERFACE, then use the
3704
    #   build directory
3705
    #
6133 dpurdie 3706
    BuildInterfaceInternal($::ScmInterface) unless ( $BUILDINTERFACE );
227 dpurdie 3707
 
6133 dpurdie 3708
 
227 dpurdie 3709
    #.. Starting the build phase. No more data collection
3710
    #
305 dpurdie 3711
    StartBuildPhase();
3712
    LastBuildDirective();
227 dpurdie 3713
 
5109 dpurdie 3714
    #
3715
    #   Now that the bulk of the information has been displayed
3716
    #   we can display captured messages. These warnings will be 
3717
    #   at the end of the log so that users can see them.
3718
    DumpCapture();
3719
 
227 dpurdie 3720
    sub DeleteCfg
3721
    {
3722
        #
3723
        #   Delete files that will be re-created
3724
        #   Some of these files are read and written.
3725
        #   Errors in the files are solved by deleting the files now.
3726
        #
3727
        unlink "$BUILDINTERFACE/build.cfg";
3728
        unlink "$BUILDINTERFACE/Makefile.cfg";
3729
        unlink glob ("$BUILDINTERFACE/Makefile*.cfg");
3730
        unlink "$BUILDINTERFACE/Buildfile.cfg";
3731
        unlink "$BUILDINTERFACE/Dpackage.cfg";
3732
    }
3733
 
3734
    if ( $Clobber )                             # clobber mode ?
3735
    {
4003 dpurdie 3736
        #
3737
        #   Unmake all the makefiles
3738
        #   No longer needed as we track the file that are created
3739
        #
3740
        #if ( -e "Makefile.gbe" )
3741
        #{
3742
        #    JatsTool ( 'jmake.pl', 'unmakefiles');
3743
        #}
3744
 
3745
        #
3746
        #   Delete my own configuration files
3747
        #
227 dpurdie 3748
        DeleteCfg();
3749
 
3750
        #
3751
        #   JATS creates a 'pkg' directory for the target package
3752
        #
3753
        push @CLOBBERDIRS, "pkg";
3754
 
3755
        #
3756
        #   Deployment creates a 'build/deploy' directory
375 dpurdie 3757
        #   The 'build' directory may contain user files - only remove if empty
227 dpurdie 3758
        #
3759
        push @CLOBBERDIRS, "build/deploy";
375 dpurdie 3760
        push @REMOVEDIRS, "build";
227 dpurdie 3761
 
3762
        #
6133 dpurdie 3763
        #   List of files maintained by the build system
3764
        #
3765
        my @toolsetFiles = ToolsetFiles::GetFiles();
3766
 
3767
        #
227 dpurdie 3768
        #   Delete interface directories and other directories that have been
375 dpurdie 3769
        #   marked to be clobbered
227 dpurdie 3770
        #
3771
        foreach my $dir ( @CLOBBERDIRS )
3772
        {
3773
            next if ( $dir eq '.' );
3774
            next if ( $dir eq '..' );
3775
            if ( -d $dir )
3776
            {
361 dpurdie 3777
                RmDirTree ( $dir );
227 dpurdie 3778
            }
3779
        }
3780
 
375 dpurdie 3781
        foreach my $dir ( @REMOVEDIRS )
3782
        {
3783
            next if ( $dir eq '.' );
3784
            next if ( $dir eq '..' );
3785
            if ( -d $dir )
3786
            {
3787
                rmdir ( $dir ); # Only if empty
3788
            }
3789
        }
3790
 
6133 dpurdie 3791
        foreach my $file (@toolsetFiles)
227 dpurdie 3792
        {
6133 dpurdie 3793
            RmDirTree ( $file ) if ( -f $file );
227 dpurdie 3794
        }
3795
 
3796
        #
3797
        #   DPACKAGE may be a user file, Only delete it if we created it
3798
        #
299 dpurdie 3799
        unlink "$Srcdir/DPACKAGE.$::GBE_MACHTYPE" if $DeleteDPACKAGE;
227 dpurdie 3800
 
3801
        BuildPackageLink();
3802
        BuildSandboxData();
3803
        return;
3804
    }
3805
 
3806
    #.. Build support files
3807
    #
3808
    DeleteCfg();
3809
    BuildConfig();
3810
    BuildSharedLibFiles();
3811
    WriteParsedBuildConfig();
3812
    BuildPackageLink();
3813
    BuildSandboxData();
4003 dpurdie 3814
    NoBuildMarker();
227 dpurdie 3815
 
3816
    #
3817
    #  ONLY (re)building interface dir
3818
    #
3819
    return
3820
        if ( $Interface );
3821
 
3822
    #---------------------------------------------------------------------------
3823
    #
3824
    #.. Make bootstrap "makefile",
3825
    #   Simulate a top level makefile
3826
    #       Pass argumenst to makelib
3827
    #       Sumulate SubDir() operations
3828
    #       Sumulate a Platform(*);
3829
    #
3830
    #       Due to the normal way that makelib.pl is executed,
3831
    #       the following substitutions are done.
3832
    #
3833
    @ARGV = ();
3834
    $0 = "makefile.pl ";
3835
    push @ARGV, "$Cwd";                         # current working directory
331 dpurdie 3836
    push @ARGV, "$::GBE_TOOLS/makelib.pl";     # makelib.pl image
227 dpurdie 3837
    push @ARGV, "--interface=$BUILDINTERFACE"
261 dpurdie 3838
        if ($BUILDINTERFACE);
227 dpurdie 3839
 
3840
    Debug( "ARGV:      @ARGV" );
3841
 
3842
    #.. (re)Build root makefile
3843
    #
3844
    $ScmBuildlib = 0;                           # clear Buildlib flag for 'makelib.pl'
3845
    RootMakefile();                             # inform 'makelib.pl'
3846
    MakeLibInit();                              # run initialisation
3847
 
3848
    #.. Register subdir(s)
3849
    #
3850
    UniquePush (\@BUILDSUBDIRS, $Srcdir );
3851
    SubDir( @BUILDSUBDIRS );
3852
    Platform( @BUILD_ACTIVEPLATFORMS );
3853
 
3854
    #.. (re)build src makefiles and associated information
367 dpurdie 3855
    #   JatsTool will not return on error
227 dpurdie 3856
    #
263 dpurdie 3857
    my @cmds = ('jmake.pl', 'rebuild');
227 dpurdie 3858
    push @cmds, 'NORECURSE=1' if ( $RootOnly );
263 dpurdie 3859
    JatsTool ( @cmds);
305 dpurdie 3860
 
3861
    #
7301 dpurdie 3862
    #   Generate package signature
3863
    #
6133 dpurdie 3864
    ErrorConfig( 'name' => 'buildlib')   ;
7301 dpurdie 3865
    BuildSignature();
3866
 
3867
    #
305 dpurdie 3868
    #   Generate some warnings that will be seen at the end of the build
3869
    #
3870
    Warning ("BuildSrcArchive Directive Present","Read JATS Manual for correct usage")
3871
        if ($build_source_pkg);
227 dpurdie 3872
}
3873
 
7301 dpurdie 3874
#-------------------------------------------------------------------------------
3875
# Function        : BuildSignature 
3876
#
3877
# Description     : Generate a package 'signature' for this package
3878
#               
3879
#                   The signature is used to bypass the entire Make processing in a sandbox
3880
#                   If we can find a matching package in the package store then we don't 
3881
#                   need to 'make' this package.
3882
#
3883
#                   There are two scenarios:
3884
#                       In a GIT enabled sandbox
3885
#                       Without GIT
3886
#                       
3887
#                   In a GIT enabled sandbox the signature allows the use of a pre-built 
3888
#                   package - even if the package has been built on a different branch.
3889
#                   
3890
#                       The signature includes:
3891
#                           The name of this package
3892
#                           The GIT sha1 of the directory trees that contain this package
3893
#                           The package signatures of all dependent packages
3894
#                           
3895
#                   In a Non-GIT enabled sandbox the package signature will be set such that
3896
#                   the package will never be found in the package store and the package MUST
3897
#                   be built within the sandbox.
3898
#                   
7302 dpurdie 3899
#                   The hard part is determing the directory trees that contains this package
7301 dpurdie 3900
#                   Ideally this is a single dir-tree, but this cannot be enforced.
3901
#                   
3902
#                   Source directories have been gathered during makefile generation
3903
#                   
3904
#                   This suits most cases, but there are a few where the user needs
3905
#                   to give JATS a hint. Use the AsdSrcDir directive to extend
3906
#                   the signature paths to directories not under the build.pl
3907
#                   or any makefile included by the build.pl
3908
#                       
3909
# Inputs          : 
3910
#
3911
# Returns         : 
3912
#
3913
sub BuildSignature
3914
{
3915
    my %sigExcludeDirs;
3916
    my %sigExcludeFiles;
3917
    my $BuildSignatureSha1;
3918
    my $signatureFile = catfile($Cwd, $BUILDINTERFACE, 'Package.sig');
3919
    my $sigDebugFile  = catfile($Cwd, $BUILDINTERFACE, 'Package.dsig');
3920
    my @sigList;
227 dpurdie 3921
 
7301 dpurdie 3922
    #
3923
    #   Only create the Signature file ONCE
3924
    #   Done on first build (after a clobber)
3925
    #
3926
#   if (-f $signatureFile)
3927
#   {
3928
#       Message("Generate Package Signature - Already generated");
3929
#       return;
3930
#   }
3931
 
3932
    Message("Generate Package Signature");
3933
 
3934
    #
3935
    #   Determine if this is a GIT enabled sandbox build
3936
    #   Need a .git directory or file in the root of the sandbox
3937
    #
3938
    my $gitEnabled;
3939
    if ($::GBE_SANDBOX && -e catfile ($::GBE_SANDBOX, '.git') )
3940
    {
3941
        $gitEnabled = 1;
3942
    }
3943
 
3944
    #
3945
    #   Start generating the signature
3946
    #       Include the package Name,Version and Project
3947
    #
7310 dpurdie 3948
    $BuildSignatureSha1 = Digest::SHA::PurePerl->new;
7301 dpurdie 3949
    $BuildSignatureSha1->add("PKGNAME: $BUILDNAME_PACKAGE $BUILDNAME_VERSION $BUILDNAME_SUFFIX");
3950
    push @sigList, "PKGNAME: $BUILDNAME_PACKAGE $BUILDNAME_VERSION $BUILDNAME_SUFFIX: " . $BuildSignatureSha1->clone->hexdigest;
3951
 
3952
    #
3953
    #   Include the signature of ALL dependent packages
3954
    #   Ie: The package signature is a function of the source and its dependents
3955
    #
3956
    foreach my $tag ( PackageEntry::GetPackageList() )
3957
    {
3958
        my $pkgSig = PackageEntry::GetPackageSignature($tag);
3959
        $BuildSignatureSha1->add("PKGSIGNATURE: $pkgSig");
7302 dpurdie 3960
        push @sigList, sprintf("PKGSIGNATURE: [%s] %s: %s", PackageEntry::GetNameVersion($tag), $pkgSig , $BuildSignatureSha1->clone->hexdigest);
7301 dpurdie 3961
    }
3962
 
3963
    #
3964
    #   Save the signature of the package header and the dependencies
3965
    #   This will be used for a simple test to see in we need to rebuild the build file 
3966
    #
3967
    my $depSha1 =  $BuildSignatureSha1->clone->hexdigest;
3968
    Debug2("DepSha1: $depSha1");
3969
    FileCreate( catfile($ScmInterface, 'build.bfp'), $depSha1 );
3970
 
3971
    if ($gitEnabled)
3972
    {
3973
        #
3974
        #   Include the sha1 of all 'git' tree items that form the complete source image
3975
        #
3976
        my @relDirList = map { my $relName = $_; $relName =~ s~^$::GBE_SANDBOX/~~; $relName  } ToolsetFiles::GetSubTrees(); 
3977
        my @cmdList = map { 'HEAD:' . $_  } @relDirList;
3978
Debug0(" GIT DIR: @relDirList" );
3979
Debug0(" GIT CMD: " . "git rev-parse @cmdList" );
3980
        my $index = 0;
3981
 
3982
        my $callback = sub {
3983
            my ($cdata, $line) = @_;
3984
            $line =~ s~\s+$~~;
3985
Debug0(" GIT OUT: " . $line  );
3986
            $BuildSignatureSha1->add($line);
3987
            push @sigList, "PKGSRC: $relDirList[$index++]: $line: " . $BuildSignatureSha1->clone->hexdigest;
3988
            return 0;
3989
        };
3990
 
3991
        GitCmd('rev-parse', @cmdList, { process => $callback } );
3992
        $BUILDSIGNATURE =  $BuildSignatureSha1->hexdigest;
3993
    }
3994
    else
3995
    {
7302 dpurdie 3996
        $BUILDSIGNATURE = 'MSG: Sandbox is not git enabled';
7301 dpurdie 3997
    }
3998
 
3999
    Message("Signature: $BUILDSIGNATURE");
4000
    push @sigList, "Signature: $BUILDSIGNATURE";
4001
    FileCreate( $signatureFile, $BUILDSIGNATURE );
4002
    FileCreate( $sigDebugFile, @sigList );
4003
Debug0("sigDebugFile: $sigDebugFile");
4004
 
4005
    #
4006
    #   Create the descpkg file - to include the signature
4007
    #
4008
    BuildDescpkg('Internal');
4009
}
4010
 
227 dpurdie 4011
#-------------------------------------------------------------------------------
7301 dpurdie 4012
# Function        : GitCmd
4013
#
4014
# Description     : Run a Git Command and capture/process the output
4015
#
4016
#                   Based on JatsSvnCore:GitCmd
4017
#
4018
# Inputs          : Command
4019
#                   Command arguments
4020
#                   Last argument may be a hash of options.
4021
#                       nosavedata  - Don't save the data
4022
#                       process     - Callback function
4023
#                       printdata   - Print data
4024
#                       error       - Error Message
4025
#                                     Used as first line of an Error call
4026
#
4027
# Returns         : non-zero on errors detected
4028
#
4029
sub GitCmd
4030
{
4031
    my $self;           # Local storage
4032
    Debug ("GitCmd");
4033
 
4034
    #
4035
    #   Locate essential tools
4036
    #
4037
    our $GBE_SVN_PATH;
4038
    EnvImportOptional('GBE_GIT_PATH', '');
4039
    Debug ("GBE_GIT_PATH", $::GBE_GIT_PATH);
4040
 
4041
    my $stdmux = LocateProgInPath ( 'stdmux');
4042
    my $git    = LocateProgInPath ( 'git', '--All', '--Path=' . $::GBE_GIT_PATH );
4043
 
4044
    #
4045
    #   Extract arguments and options
4046
    #   If last argument is a hash, then its a hash of options
4047
    #
4048
    my $opt;
4049
    $opt = pop @_
4050
        if (@_ > 0 and UNIVERSAL::isa($_[-1],'HASH'));
4051
 
4052
    $self->{PRINTDATA} = $opt->{'printdata'} if ( exists $opt->{'printdata'} );
4053
 
4054
    Verbose2 "GitCmd $git @_";
4055
 
4056
    #
4057
    # Useful debugging
4058
    #
4059
    # $self->{LAST_CMD} = [$svn, @_];
4060
 
4061
    #
4062
    #   Reset command output data
4063
    #
4064
    $self->{ERROR_LIST} = [];
4065
    $self->{RESULT_LIST} = [];
4066
#    $self->{LAST_CMD} = \@_;
4067
 
4068
    #
4069
    #   Make use of a wrapper program to mux the STDERR and STDOUT into
4070
    #   one stream (STDOUT). #   This solves a lot of problems
4071
    #
4072
    #   Do not use IO redirection of STDERR because as this will cause a
4073
    #   shell (sh or cmd.exe) to be invoked and this makes it much
4074
    #   harder to kill on all platforms.
4075
    #
4076
    #   Use open3 as it allows the arguments to be passed
4077
    #   directly without escaping and without any shell in the way
4078
    #
4079
    local (*CHLD_OUT, *CHLD_IN);
4080
    my $pid = open3( \*CHLD_IN, \*CHLD_OUT, '>&STDERR', $stdmux, $git, @_);
4081
 
4082
    #
4083
    #   Looks as though we always get a PID - even if the process dies
4084
    #   straight away or can't be found. I suspect that open3 doesn't set
4085
    #   $! anyway. I know it doesn't set $?
4086
    #
4087
    Debug ("Pid: $pid");
4088
    Error ("Can't run command: $!") unless $pid;
4089
 
4090
    #
4091
    #   Close the input handle
4092
    #   We don't have anything to send to this program
4093
    #
4094
    close(CHLD_IN);
4095
 
4096
    #
4097
    #   Monitor the output from the utility
4098
    #   Have used stdmux to multiplex stdout and stderr
4099
    #
4100
    #   Note: IO::Select doesn't work on Windows :(
4101
    #   Note: Open3 will cause blocking unless both streams are read
4102
    #         Can read both streams becsue IO::Select doesn't work
4103
    #
4104
    #   Observation:
4105
    #       svn puts errors to STDERR
4106
    #       svn puts status to STDOUT
4107
    #
4108
    while (<CHLD_OUT>)
4109
    {
4110
        s~\s+$~~;
4111
        tr~\\/~/~;
4112
 
4113
 
4114
        Verbose3 ( "GitCmd:" . $_);
4115
        m~^STD(...):(.+)~;
4116
        my $data = $1 ? $2 : $_;
4117
        next unless ( $data );
4118
 
4119
        if ( $1 && $1 eq 'ERR' )
4120
        {
4121
            #
4122
            #   Process STDERR output
4123
            #
4124
            push @{$self->{ERROR_LIST}}, $data;
4125
        }
4126
        else
4127
        {
4128
            #
4129
            #   Process STDOUT data
4130
            #
4131
            push @{$self->{RESULT_LIST}}, $data unless ($opt->{'nosavedata'});
4132
 
4133
            #
4134
            #   If the user has specified a processing function then pass each
4135
            #   line to the specified function.  A non-zero return will
4136
            #   be taken as a signal to kill the command.
4137
            #
4138
            if ( exists ($opt->{'process'}) && $opt->{'process'}($self, $data) )
4139
            {
4140
                kill 9, $pid;
4141
                sleep(1);
4142
                last;
4143
            }
4144
        }
4145
    }
4146
 
4147
    close(CHLD_OUT);
4148
 
4149
    #
4150
    #   MUST wait for the process
4151
    #   Under Windows if this is not done then we eventually fill up some
4152
    #   perl-internal structure and can't spawn anymore processes.
4153
    #
4154
    my $rv = waitpid ( $pid, 0);
4155
 
4156
    #
4157
    #   If an error condition was detected and the user has provided
4158
    #   an error message, then display the error
4159
    #
4160
    #   This simplifies the user error processing
4161
    #
4162
    if ( @{$self->{ERROR_LIST}} && $opt->{'error'}  )
4163
    {
4164
        Error ( $opt->{'error'}, @{$self->{ERROR_LIST}} );
4165
    }
4166
 
4167
    #
4168
    #   Exit status has no meaning since open3 has been used
4169
    #   This is because perl does not treat the opened process as a child
4170
    #   Not too sure it makes any difference anyway
4171
    #
4172
    #
4173
    Debug ("Useless Exit Status: $rv");
4174
    my $result = @{$self->{ERROR_LIST}} ? 1 : 0;
4175
    Verbose3 ("Exit Code: $result");
4176
 
4177
    return $result;
4178
}
4179
 
4180
 
4181
#-------------------------------------------------------------------------------
227 dpurdie 4182
# Function        : BuildVersion
4183
#
4184
# Description     : Generate version.c and version.h files
4185
#
4186
# Inputs          : Options
4187
#                       --Prefix=prefix         Text prepended to variables created
4188
#                                               as a part of the "C" versions
4189
#                       --Type=type             Type of "C" style data
4190
#                                               Allowed types are: array
4191
#                       --Defs=name             Generate a "C" definitions file.
4192
#                                               This file simply contains definitions
4193
#                       --Defs                  Same as --Defs=defs
4194
#                       --Style=style           Output file style
4195
#                                               Supported styles:
4196
#                                                   "C" - Default
4197
#                                                   "CSharp"
4198
#                                                   "WinRC"
289 dpurdie 4199
#                                                   "Delphi"
315 dpurdie 4200
#                                                   "VB"
227 dpurdie 4201
#                       --File=name             Specifies the output file name
4202
#                                               Default is determined by the style
4203
#
4204
#                   Also allows for an 'old' style format in which
4205
#                   the first three arguments are prefix,type and defs
4206
# Returns         :
4207
#
4208
 
4209
sub BuildVersion
4210
{
4211
    my ( $Prefix, $Type, $Mode ) = @_;
4212
    my $ModePrefix;
4213
    my $Style = "C";
4214
    my $FileName;
4215
    my $VersionFiles;
267 dpurdie 4216
    my @opts;
4217
    my $supports_opts;
227 dpurdie 4218
 
4219
    StartBuildPhase();                          # Starting the build phase. No more data collection
4220
 
279 dpurdie 4221
    if ( defined($Prefix) && $Prefix =~ /^-/ )
227 dpurdie 4222
    {
4223
        $Prefix = undef;
4224
        $Type = undef;
4225
        $Mode = undef;
4226
        foreach  ( @_ )
4227
        {
4228
            if (      /^--Prefix=(.*)/ ) {
4229
                $Prefix = $1;
4230
                $VersionFiles = 1;
4231
 
4232
            } elsif ( /^--Type=(.*)/ ) {
4233
                $Type = $1;
4234
                $VersionFiles = 1;
4235
 
4236
            } elsif ( /^--Defs=(.*)/ ) {
4237
                $Mode = $1;
4238
                $ModePrefix = "_$1";
4239
 
4240
            } elsif ( /^--Defs$/ ) {
4241
                $Mode = 'defs';
4242
                $ModePrefix = "";
4243
 
4244
            } elsif ( /^--Style=(.*)/ ) {
4245
                $Style = $1;
279 dpurdie 4246
                $VersionFiles = 1;
267 dpurdie 4247
                $supports_opts = 1 if ( $Style =~ /^WinRC/i );
227 dpurdie 4248
 
4249
            } elsif ( /^--File=(.*)/ ) {
4250
                $FileName = $1;
4251
 
267 dpurdie 4252
            } elsif ($supports_opts ) {
4253
                push @opts, $_;
235 dpurdie 4254
 
227 dpurdie 4255
            } else {
4256
                Error ("BuildVersion: Unknown option: $_");
4257
 
4258
            }
4259
        }
4260
    }
4261
    else
4262
    {
4263
        #
4264
        #   Old style positional arguments.
4265
        #
4266
        $VersionFiles = 1;
4267
        if ( defined( $Mode ) )
4268
        {
4269
            if ( $Mode =~ m/^defs(=(.*))?$/i )
4270
            {
4271
                $Mode       = $2 ? $2    : 'defs';
4272
                $ModePrefix = $2 ? "_$2" : "";
4273
            }
4274
            else
4275
            {
4276
                Error ("BuildVersion: Bad Mode argument. Need 'defs' or 'defs=name'");
4277
            }
4278
        }
4279
    }
4280
 
4281
    #
4282
    #   Determine the style of version file to create
4283
    #
4284
    if ( $Style =~ /^CSharp/i ) {
4285
        BuildVersionCSharp( $FileName );
4286
 
229 dpurdie 4287
    } elsif ( $Style =~ /^Properties/i ) {
4288
        BuildVersionProperties( $FileName, $Prefix );
4289
 
227 dpurdie 4290
    } elsif ( $Style =~ /^WinRC/i ) {
267 dpurdie 4291
        BuildVersionWinRC( $FileName, @opts );
227 dpurdie 4292
 
289 dpurdie 4293
    } elsif ( $Style =~ /^Delphi/i ) {
4294
        BuildVersionDelphi( $FileName, $Prefix );
315 dpurdie 4295
 
4296
    } elsif ( $Style =~ /^VB/i ) {
4297
        BuildVersionVB( $FileName, $Prefix );
289 dpurdie 4298
 
227 dpurdie 4299
    } elsif ( $Style eq "C" ) {
289 dpurdie 4300
        BuildVersionC    ( $FileName, $Prefix, $Type )     if ( $VersionFiles );
4301
        BuildVersionCdefs( $FileName, $Mode, $ModePrefix ) if ( $Mode );
227 dpurdie 4302
 
4303
    } else {
4304
        Error("BuildVersion: Unknown style: $Style");
4305
    }
4306
}
4307
 
4308
#-------------------------------------------------------------------------------
4309
# Function        : BuildDescpkg
4310
#
4311
# Description     : Create a package description file
4312
#                   The format of this file matches that generated by JANTS
4313
#                   Take care when extending the format
4314
#
4315
#                   NOTE: It turns out that JANTS is not a standard and the
4316
#                         implementors (of JANTS) kept on changing it.
4317
#
7301 dpurdie 4318
# Inputs          : $mode - 'Internal' - Skip sanity test
227 dpurdie 4319
#
4320
# Returns         :
4321
#
4322
sub BuildDescpkg
4323
{
7301 dpurdie 4324
    my ($mode) = @_;
4325
    unless ($mode && $mode eq 'Internal')
4326
    {
4327
        StartBuildPhase();                  # Starting the build phase. No more data collection
4328
    }
4003 dpurdie 4329
    return if ( $Clobber );                 # clobber mode ?
227 dpurdie 4330
 
247 dpurdie 4331
    #
4332
    #   Store the files location for use at runtime
4333
    #   It will be a file that is 'known' to JATS
4334
    #
4003 dpurdie 4335
    my $pkgfile = BuildAddKnownFile ( $NoBuild ? $Cwd : $Srcdir, 'descpkg' );
227 dpurdie 4336
 
261 dpurdie 4337
    my @desc;
279 dpurdie 4338
    push @desc, "Package Name:  $BUILDNAME_PACKAGE";
4339
    push @desc, "Version:       $BUILDVERSION";
7301 dpurdie 4340
    push @desc, "Signature:     $BUILDSIGNATURE" if defined $BUILDSIGNATURE;
279 dpurdie 4341
    push @desc, "Released By:   $::USER";
4342
    push @desc, "Released On:   $::CurrentTime";
4343
    push @desc, "Build Machine: $::GBE_HOSTNAME";
4344
    push @desc, "Path:          $Cwd";
4345
    push @desc, "Jats Version:  $::GBE_VERSION";
4346
    push @desc, "Jats Path:     $::GBE_CORE";
261 dpurdie 4347
    push @desc, "";
4348
    push @desc, "Build Dependencies:";
4349
    push @desc, "";
227 dpurdie 4350
 
4351
    foreach my $tag ( PackageEntry::GetPackageList )
4352
    {
4353
        my ($name, $version, $type) = PackageEntry::GetPackageData($tag);
4354
 
4355
        my @attributes;
4356
 
4357
        push @attributes, "name=\"$name\"";
4358
        push @attributes, "version=\"$version\"";
4359
        push @attributes, "build=\"true\"" if $type =~ /Build/i;
4360
 
261 dpurdie 4361
        push @desc, "<sandbox @attributes/>";
227 dpurdie 4362
    }
247 dpurdie 4363
 
261 dpurdie 4364
    FileCreate ($pkgfile, \@desc );
227 dpurdie 4365
}
4366
 
4367
#-------------------------------------------------------------------------------
4003 dpurdie 4368
# Function        : NoBuildMarker
4369
#
4370
# Description     : Maintain the nobuild marker
4371
#                   This is file placed in the interface directory simply
4372
#                   to indicate to the 'create_dpkg' utility that this build
4373
#                   does not do anything useful.
4374
#
6133 dpurdie 4375
#                   It will only be used on a build machine by the build daemon
4003 dpurdie 4376
#
4377
#                   Its not placed in the interface directory as it would be
4378
#                   harder for create_dpkg to find it.
4379
#
4380
# Inputs          : None
4381
# Globals         : $NoBuild, $Clobber
4382
#
4383
# Returns         : Nothing
4384
#
4385
sub NoBuildMarker
4386
{
4387
    return if ( $Clobber );
4388
 
4389
    # Always delete the file - in case we toggle build forms
4390
    #
5986 dpurdie 4391
    my $markerFile = BuildAddKnownFile( $::ScmRoot, 'noBuild.gbe');
4003 dpurdie 4392
    unlink($markerFile);
4393
 
4394
    TouchFile($markerFile)
4395
        if ($NoBuild);
4396
}
4397
 
4398
#-------------------------------------------------------------------------------
227 dpurdie 4399
# Function        : BuildIncpkg
4400
#
4401
# Description     : Create a package inclusion file
4402
#
4403
# Inputs          :
4404
#
4405
# Returns         :
4406
#
4407
sub BuildIncpkg
4408
{
4409
    StartBuildPhase();                          # Starting the build phase. No more data collection
4410
    if ( $Clobber )                             # clobber mode ?
4411
    {
361 dpurdie 4412
        RmDirTree( "$Srcdir/incpkg" );
227 dpurdie 4413
        return;
4414
    }
4415
 
4416
    my $fh = ConfigurationFile::New( "$Srcdir/incpkg" );
4417
    $fh->Header( "buildlib (Version $BuildVersion)",
4418
                              "Package inclusion list" );
4419
 
4420
    foreach my $tag ( PackageEntry::GetPackageList )
4421
    {
4422
        my ($name, $version, $type) = PackageEntry::GetPackageData($tag);
4423
        $type = ($type =~ /build/i) ? "Build" : "Link";
4424
 
4425
        $fh->Write( "${type}PkgArchive( '$name', '$version' );\n" );
4426
    }
4427
 
4428
    $fh->Close();
4429
}
4430
 
4431
#-------------------------------------------------------------------------------
4432
# Function        : BuildConfig
4433
#
4434
# Description     : Create the file interface/build.cfg
4435
#                   This file contains information gathered by the build process
4436
#                   that is to be used when makefiles are created and re-created
4437
#
4438
# Inputs          : None
4439
#
4440
# Returns         : Nothing
4441
#
283 dpurdie 4442
sub BuildConfig
227 dpurdie 4443
{
4444
    Error( "No BuildInterface directive encountered\n" )
4445
        unless ($BUILDINTERFACE);
4446
 
4447
    my $fh = ConfigurationFile::New( "$BUILDINTERFACE/build.cfg");
4448
    $fh->Header( "buildlib (Version $BuildVersion)",
4449
                              "Makelib configuration file", "
4450
\$ScmBuildMachType              = \"$::GBE_MACHTYPE\";
4451
\$ScmInterfaceVersion           = \"$::InterfaceVersion\";
4452
\$ScmBuildName                  = \"$BUILDNAME\";
4453
\$ScmBuildPackage               = \"$BUILDNAME_PACKAGE\";
4454
\$ScmBuildVersion               = \"$BUILDNAME_VERSION\";
4455
\$ScmBuildProject               = \"$BUILDNAME_PROJECT\";
4456
\$ScmBuildVersionFull           = \"$BUILDVERSION\";
4457
\$ScmBuildPreviousVersion       = \"$BUILDPREVIOUSVERSION\";
4458
\$ScmLocal                      = \"$BUILDLOCAL\";
4459
\$ScmDeploymentPatch            = \"$DEPLOY_PATCH\";
4460
\$ScmSrcDir                     = \"$Srcdir\";
4461
\$ScmBuildSrc                   = \"$ScmBuildSrc\";
4462
\$ScmExpert                     = \"$Expert\";
261 dpurdie 4463
\$ScmAll                        = \"$All\";
4003 dpurdie 4464
\$ScmNoBuild                    = \"$NoBuild\";
7300 dpurdie 4465
\$ScmBuildUuid                  = \"$BUILD_UUID\";
227 dpurdie 4466
");
4467
 
4468
#.. Alias
4469
#
4470
    $fh->DumpData(
4471
        "\n# Aliases.\n#\n",
4472
        "ScmBuildAliases", \%BUILDALIAS );
4473
 
4474
#.. Products
4475
#
4476
    $fh->DumpData(
4477
        "# Product mapping.\n#\n",
4478
        "ScmBuildProducts", \%BUILDPRODUCT_PARTS );
4479
 
4480
#.. Create ScmBuildPlatforms
4481
#
4482
    my( @platforms_merged, %platform_args ) = ();
4483
 
4484
    UniquePush ( \@platforms_merged, @BUILDPLATFORMS );
4485
 
4486
    foreach my $key ( keys %BUILDPRODUCT ) {
4487
        my( @list ) = split( ' ', $BUILDALIAS{ $key } || '' );
4488
        my( $platform );
4489
 
4490
        foreach my $elem ( @list ) {
4491
            if ( $elem =~ /^--/ ) {             # argument
4492
                HashJoin( \%platform_args, $;, $platform, $elem )
4493
                    if ( defined($platform) );
4494
                next;
4495
            }
4496
            $platform = $elem;                  # platform
4497
            UniquePush( \@platforms_merged, $elem );
4498
        }
4499
    }
4500
 
4501
#.. Create ScmBuildPlatforms
4502
#   Contains per platform options extracted from alias and platform args
4503
#
4504
    my %ScmBuildPlatforms;
4505
    foreach my $key ( @platforms_merged ) {
4506
 
7310 dpurdie 4507
        my $pInfo = $BUILDINFO{$key};
4508
        next if ($pInfo->{NOT_AVAILABLE});
4509
 
227 dpurdie 4510
        my( @arguments ) = ();
4511
        UniquePush( \@arguments, split( /$;/, $BUILDPLATFORMARGS{ $key } ))
4512
            if ( exists $BUILDPLATFORMARGS{ $key } );
4513
 
4514
        UniquePush( \@arguments, split( /$;/, $platform_args{ $key } ))
4515
            if ( exists $platform_args{ $key } );
4516
 
4517
        $ScmBuildPlatforms{$key} = join "$;", @arguments;
4518
    }
4519
 
4520
    $fh->DumpData(
4521
        "# Platform and global argument list.\n#\n",
4522
        "ScmBuildPlatforms", \%ScmBuildPlatforms );
4523
 
7310 dpurdie 4524
#.. Create ScmBuildMatrix
4525
#   Contains information on all the platforms that the package builds for and target machines
4526
#   
4527
    my %ScmBuildMatrix;
4528
    foreach my $key ( keys %BUILDINFO ) {
4529
        my $pInfo = $BUILDINFO{$key};
4530
        next if exists ($pInfo->{BADNAME});
4531
        next if ($pInfo->{NOT_AVAILABLE} > 1);
4532
        Error ("Internal: No MACHTYPE provided for $key") unless exists $pInfo->{MACHTYPE};
4533
        $ScmBuildMatrix{$key} = $pInfo->{MACHTYPE};
4534
    }
227 dpurdie 4535
 
7310 dpurdie 4536
    $fh->DumpData(
4537
        "# Build Matrix.\n#\n",
4538
        "ScmBuildMatrix", \%ScmBuildMatrix );
4539
 
227 dpurdie 4540
# .. Create BuildPkgRules
4541
#
367 dpurdie 4542
#    This is most of the information contained within %PKGRULES, which
227 dpurdie 4543
#    requires additional processing within makelib.
4544
#
367 dpurdie 4545
#   Need the True Path for windows.
4546
#       Some makefile functions (wildcard) only work as expected
4547
#       if the case of the pathname is correct. Really only a problem
4548
#       with badly formed legecy packages where the Windows user
4549
#       guessed at the package format.
4550
#
227 dpurdie 4551
    my %ScmBuildPkgRules;
4552
    foreach my $platform ( keys %PKGRULES )
4553
    {
4554
        foreach my $package ( @{$PKGRULES{$platform}} )
4555
        {
4556
            my %entry;
4557
 
367 dpurdie 4558
            $entry{ROOT}     = TruePath( $package->{'base'} );
227 dpurdie 4559
            $entry{NAME}     = $package->{'name'};
4560
            $entry{VERSION}  = $package->{'version'};
4561
            $entry{DNAME}    = $package->{'dname'};
4562
            $entry{DVERSION} = $package->{'dversion'};
4563
            $entry{DPROJ}    = $package->{'dproj'};
4564
            $entry{TYPE}     = $package->{'type'};
4565
            $entry{CFGDIR}   = $package->{'cfgdir'} if ( defined( $package->{'cfgdir'} ) );
4566
 
367 dpurdie 4567
            foreach my $dir (qw (TOOLDIRS) )
227 dpurdie 4568
            {
4569
                $entry{$dir} = $package->{$dir} ;
4570
            }
4571
 
367 dpurdie 4572
            my $baselen = length($package->{'base'});
4573
            foreach my $dir (qw (PINCDIRS PLIBDIRS THXDIRS) )
4574
            {
4575
                $entry{$dir} = [];
4576
                foreach my $file ( @{$package->{$dir}} )
4577
                {
4578
                    push @{$entry{$dir}}, substr TruePath($package->{'base'} . $file ), $baselen;
4579
                }
4580
            }
4581
 
227 dpurdie 4582
            push @{$ScmBuildPkgRules{$platform}}, \%entry;
4583
        }
4584
    }
4585
 
4586
    $fh->DumpData(
4587
        "# Imported packages.\n#\n",
4588
        "ScmBuildPkgRules", \%ScmBuildPkgRules );
4589
 
4590
#
4591
#   BUILDPLATFORMS,
4592
#       The value that is saved only contains the active platforms
4593
#
4594
#   DEFBUILDPLATFORMS,
4595
#       The value that is matchs the wildcard specification for Platform 
4596
#       directives.
4597
#
4598
    $fh->DumpData(
4599
        "# A list of platforms active within the view.\n#\n",
4600
        "BUILDPLATFORMS", \@BUILD_ACTIVEPLATFORMS );
4601
 
4602
    $fh->DumpData(
4603
        "# A list of default platforms within the view.\n#\n",
4604
        "DEFBUILDPLATFORMS", \@DEFBUILDPLATFORMS );
4605
 
4606
#
4607
#   BUILDTOOLS
4608
#       A list of toolset extension paths
4609
#
4610
    $fh->DumpData(
4611
        "# A list of paths with toolset extension programs.\n#\n",
4612
        "BUILDTOOLSPATH", \@BUILDTOOLS );
4613
 
4614
#
4615
#   BUILDPLATFORM_PARTS
4616
#       A subset of BUILDINFO exported as BUILDPLATFORM_PARTS
4617
#       This exists only for backward compatability with existing code
4618
#       in external packages ( deployfiles).
4619
#
4620
#   Only save those parts that are part of the current build
4621
#   This will prevent users attempting to build for platforms that have not
4622
#   been correctly constructed.
4623
#
4624
    my %active =  map { ${_} => 1 } @BUILD_ACTIVEPLATFORMS;
4625
    my %active_buildplatform_parts;
4626
    my %active_build_info;
4627
    foreach ( keys %BUILDINFO )
4628
    {
4629
        next unless ( $active{$_} );
4630
        $active_buildplatform_parts{$_} = $BUILDINFO{$_}{PARTS};
4631
        $active_build_info{$_}          = $BUILDINFO{$_};
4632
    }
4633
 
4634
    $fh->DumpData(
4635
        "# Parts of all platforms.\n#\n",
4636
        "BUILDPLATFORM_PARTS", \%active_buildplatform_parts );
4637
#
4638
#   BUILDINFO
4639
#       Complete TARGET Information
4640
#
4641
    $fh->DumpData(
4642
        "# Extended build information.\n#\n",
4643
        "BUILDINFO", \%active_build_info );
4644
 
4645
#
247 dpurdie 4646
#   BUILD_KNOWNFILES
4647
#       All paths are relative to the project root directory
4648
#       ie: The directory that conatins the build.pl file
4649
#
4650
    $fh->DumpData(
4651
        "# Generated Files that may be known when used as Src files.\n#\n",
4652
        "BUILD_KNOWNFILES", \%BUILD_KNOWNFILES );
4653
 
4654
#
227 dpurdie 4655
#   Close out the file
4656
#
4657
    $fh->Close();
363 dpurdie 4658
 
227 dpurdie 4659
}
4660
 
4661
#-------------------------------------------------------------------------------
4662
# Function        : WriteParsedBuildConfig
4663
#
4664
# Description     : Write all the parsed build.pl data to a single file
4665
#                   Its all in there for use
4666
#
4667
# Inputs          : 
4668
#
4669
# Returns         : 
4670
#
4671
sub WriteParsedBuildConfig
4672
{
4673
    my $cfg_file = "$::BUILDINTERFACE/Buildfile.cfg";
4674
    my %cf_build_info = ();
4675
 
4676
    #
4677
    #   Examine the symbol table and capture most of the entries
4678
    #
4679
    foreach my $symname (keys %main::)
4680
    {
4681
        next if ( $symname =~ m/::/  );                 # No Typeglobs
4682
        next if ( $symname =~ m/^cf_build_info/  );     # Not myself
4683
        next unless ( $symname =~ m/^[A-Za-z]/  );      # No system type names
4684
        next if ( $symname =~ m/^SIG$/  );              # Useless
4685
        next if ( $symname =~ m/^ENV$/  );              # Don't keep the user ENV
4686
        next if ( $symname =~ m/^INC$/  );              # Don't keep the INC paths
4687
        next if ( $symname =~ m/^DEFINES/  );           # Don't keep
4688
        next if ( $symname =~ m/^TOOLSETRULES/  );      # Don't keep
4689
 
331 dpurdie 4690
        no strict 'vars';
227 dpurdie 4691
        local *sym = $main::{$symname};
4692
 
331 dpurdie 4693
        $cf_build_info{"\$$symname"} =  $sym if defined $sym;
369 dpurdie 4694
        $cf_build_info{"\@$symname"} = \@sym if @sym;
4695
        $cf_build_info{"\%$symname"} = \%sym if %sym;
331 dpurdie 4696
        use strict 'vars';
227 dpurdie 4697
    }
4698
 
4699
    #
4700
    #   Dump out the configuration information
4701
    #
4702
    my $fh = ConfigurationFile::New( "$cfg_file" );
4703
    $fh->Header( "buildlib (version $::BuildVersion)",
4704
                              "Buildfile configuration" );
4705
    $fh->Dump( [\%cf_build_info], [qw(*cf_build_info)] );
4706
    $fh->Close();
4707
}
4708
 
4709
 
4710
#-------------------------------------------------------------------------------
4711
# Function        : BuildSharedLibFiles
4712
#
4713
# Description     : Create a file in the interface directory that will specify
4714
#                   the locations of shared libraries.
4715
#
4716
#                   Note: Always create a file as makefile targets depend on it.
4717
#
4718
#                   This is a bit ugly.
4719
#
4720
#                   There needs be an association between the build machine and
4721
#                   the target platform. Need to know if the current target is
4722
#                   native to the current build machine. If it is then we can
4723
#                   run tests on the machine and we then need to extend the
4724
#                   search path for the target.
4725
#
4726
#                   The BUILDINFO{EXT_SHARED} is used to control the creation of
4727
#                   the files by specifying the extension of the file.
4728
#
4729
# Inputs          : None
4730
#
4731
# Returns         :
4732
#
4733
sub BuildSharedLibFiles
4734
{
4735
    if ( $ScmHost eq "DOS" || $ScmHost eq "WIN" ) {
4736
        BuildSharedLibFiles_WIN(@_);
4737
 
4738
    } elsif ( $ScmHost eq "Unix" ) {
4739
        BuildSharedLibFiles_Unix(@_);
4740
 
4741
    } else {
4742
        Error("Cannot build. Unknown machine type: $ScmHost",
4743
              "Need WIN, DOS or Unix" );
4744
    }
4745
}
4746
 
4747
#-------------------------------------------------------------------------------
4748
# Function        : BuildSharedLibFiles_WIN
4749
#
4750
# Description     : Implementation of BuildSharedLibFiles for Windows
4751
#
4752
# Inputs          : None
4753
#
4754
sub BuildSharedLibFiles_WIN
4755
{
4756
 
4757
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
4758
    {
4759
        next unless ( exists $BUILDINFO{$platform}{EXT_SHARED} );
4760
        my @dos_paths = BuildSharedLibFiles_list( $platform, $BUILDINFO{$platform}{EXT_SHARED} );
4761
 
4762
        #
4763
        #   Create a .bat file for WIN32
4764
        #   This may be consumed by user wrapper programs
4765
        #
229 dpurdie 4766
        #   Features: No Echo
4767
        #             Use of SETLOCAL to prevent pollution of environment
4768
        #
227 dpurdie 4769
        my $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/set_$platform.bat", '--NoEof', '--Type=bat' );
229 dpurdie 4770
        $fh->Write ( "\@echo off\n");
227 dpurdie 4771
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
229 dpurdie 4772
        $fh->Write ( "\nSETLOCAL\n");
227 dpurdie 4773
        foreach ( reverse @dos_paths )
4774
        {
4775
            $_ =~ s~/~\\~g;
4776
            $fh->Write ( "PATH=$_;\%PATH\%\n" );
4777
        }
4778
        $fh->Write ( "\n%*\n" );
229 dpurdie 4779
        $fh->Write ( "\nENDLOCAL\n");
231 dpurdie 4780
        $fh->Write ( "EXIT /B %ERRORLEVEL%\n");
227 dpurdie 4781
        $fh->Close();
4782
 
4783
        #
4784
        #   Create a .sh file for WIN32
4785
        #   This may be consumed by a shell - as used within JATS
4786
        #
4787
        $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/set_$platform.sh", '--NoEof', '--Type=sh' );
4788
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
4789
        foreach ( reverse @dos_paths )
4790
        {
4791
            tr~\\/~/~s;
4792
            $fh->Write ( "PATH=$_\\;\$PATH\n" );
4793
        }
287 dpurdie 4794
        $fh->Write ( "\n" . '[ -n "$*" ] && "$@"'  ."\n" );
227 dpurdie 4795
        $fh->Close();
4796
    }
4797
}
4798
 
4799
#-------------------------------------------------------------------------------
4800
# Function        : BuildSharedLibFiles_Unix
4801
#
4802
# Description     : Implementation of BuildSharedLibFiles for Unix
4803
#                   Extend the Shared Library search path via LD_LIBRARY_PATH
5877 dpurdie 4804
#                   
4805
#                   Create sonames for all external shared libraries
227 dpurdie 4806
#
4807
# Inputs          : None
4808
#
4809
sub BuildSharedLibFiles_Unix
4810
{
4811
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
4812
    {
4813
        next unless ( exists $BUILDINFO{$platform}{EXT_SHARED} );
4814
        my @unix_paths = BuildSharedLibFiles_list( $platform, $BUILDINFO{$platform}{EXT_SHARED} );
4815
 
4816
        #
5877 dpurdie 4817
        #   Create sonames for all shared libraries
4818
        #   Append to the begging of the search list - so that it will rendered last
4819
        #   
4820
        my $sodir = BuildSoNameLinks_Unix($platform, @unix_paths);
4821
        unshift( @unix_paths, $sodir ) if defined $sodir;
4822
 
4823
        #
227 dpurdie 4824
        #   Create a .sh file for Unix
4825
        #
229 dpurdie 4826
        my $file = "$BUILDINTERFACE/set_$platform.sh";
4827
        my $fh = ::ConfigurationFile::New( $file , '--NoEof', '--Type=sh' );
227 dpurdie 4828
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
4829
        foreach ( reverse @unix_paths )
4830
        {
4831
            $fh->Write ( "export LD_LIBRARY_PATH=$_:\$LD_LIBRARY_PATH\n" );
4832
        }
275 dpurdie 4833
        $fh->Write ( "\n\"\$\@\"\n" );
227 dpurdie 4834
        $fh->Close();
229 dpurdie 4835
 
4836
        #
4837
        #   Make the file executable under unix
4838
        #
4839
        chmod 0755, $file;
227 dpurdie 4840
    }
4841
}
4842
 
4843
#-------------------------------------------------------------------------------
5877 dpurdie 4844
# Function        : BuildSoNameLinks_Unix 
4845
#
4846
# Description     : Generate soname links for all shared libraries from external
4847
#                   packages.
4848
#                   
4849
#                   There is a bit of a cheat. We don't examine the library to determine
4850
#                   the soname. We simple create all possible sonames to the library
4851
#
4852
# Inputs          : $platform       - Target platform
4853
#                   @paths          - Array of paths to scan for libraries 
4854
#
4855
# Returns         : soLinkDir       - Absolute path to the directory of gernerated
4856
#                                     symlinks
4857
#
4858
sub BuildSoNameLinks_Unix
4859
{
4860
    my ($platform, @paths) = @_;
4861
    my $soLinkDir = catdir($BUILDINTERFACE, 'soLinks', $platform );
4862
 
4863
    Verbose("Create Unix SoName links - $soLinkDir");
4864
    RmDirTree( $soLinkDir );
4865
 
4866
    #
4867
    #   Search provided library paths for shared libaries
4868
    #       These are names of the form *.so.* ie : libz.so.1.2.5
4869
    #
4870
    foreach my $path (@paths)
4871
    {
4872
        foreach my $file (glob(catdir($path, '*.so.*')))
4873
        {
4874
            #
4875
            #   Skip the debug symbol files
4876
            #
4877
            next if $file =~ m~\.debug$~;
4878
            next if $file =~ m~\.dbg$~;
4879
 
4880
            #
4881
            #   Generate all possible sonames by removing .nnnn from the 
4882
            #   end of the file name
4883
            #   
4884
            my $sofile = $file;
4885
            while ($sofile =~ m~(.*)\.\d+$~)
4886
            {
4887
                $sofile = $1;
4888
                unless (-f $sofile) {
4889
                    Verbose2("Need Soname: $sofile");
4890
 
4891
                    #
4892
                    #   Create link from soname to full name
4893
                    #   
4894
                    mkpath ( $soLinkDir ) unless -d $soLinkDir;
4895
                    my $sofilename = $sofile;
4896
                    $sofilename =~ s~.*/~~;
4897
                    $sofilename = catdir($soLinkDir, $sofilename);
4898
                    unless (-f $sofilename) {
4899
                        symlink ($file, $sofilename) || Error ("Cannot create symlink to $sofilename. $!"); 
4900
                    }
4901
                }
4902
            }
4903
        }
4904
    }
4905
 
4906
    #
4907
    #   Return the path the generated soLink dir
4908
    #
4909
    return AbsPath($soLinkDir) if (-d $soLinkDir);
4910
    return undef;
4911
}
4912
 
4913
#-------------------------------------------------------------------------------
227 dpurdie 4914
# Function        : BuildSharedLibFiles_list
4915
#
4916
# Description     : Determine a list of Shared Library paths that can be used
4917
#                   by the current target
4918
#
4919
# Inputs          : $platform       - Current platform
4920
#                   $so             - Shared object extensions
4921
#
4922
# Returns         : List of search paths
4923
#
4924
sub BuildSharedLibFiles_list
4925
{
4926
    my ($platform, $so ) = @_;
4927
    my @paths;
4928
    my @parts = @{$BUILDINFO{$platform}{PARTS}};
4929
 
4930
    #
4931
    #   Paths from the current build
4932
    #       Local directory         - for installed components
4933
    #       Interface directory     - for BuildPkgArchives
4934
    #
4935
    if ( $BUILDLOCAL )
4936
    {
5986 dpurdie 4937
        my @localParts;
4938
        UniquePush \@localParts, $BUILDINFO{$platform}{PLATFORM} , $BUILDINFO{$platform}{PRODUCT}, $BUILDINFO{$platform}{TARGET};
4939
        foreach ( @localParts )
227 dpurdie 4940
        {
4941
            push @paths, AbsPath("$BUILDLOCAL/lib/$_");
4942
        }
4943
    }
4944
 
4945
    foreach ( @parts )
4946
    {
4947
            push @paths, AbsPath("$BUILDINTERFACE/lib/$_");
4948
    }
4949
 
4950
    #
4951
    #   For each LinkPkgArchive
4952
    #
4953
    foreach my $package ( @{$PKGRULES{$platform}} )
4954
    {
4955
        next unless ( $package->{'type'} eq 'link' );
4956
 
4957
        my $base = $package->{'base'};
4958
        for my $path ( @{$package->{'PLIBDIRS'}} )
4959
        {
289 dpurdie 4960
            my @so_libs;
317 dpurdie 4961
            push @so_libs, glob ( "$base$path/*$_") foreach ( ArrayList($so) );
227 dpurdie 4962
            next unless scalar @so_libs;
4963
            push @paths, $base . $path;;
4964
        }
4965
    }
4966
 
4967
    #
4968
    #   Returns paths found
4969
    #
4970
    return @paths;
4971
}
4972
 
4973
#-------------------------------------------------------------------------------
247 dpurdie 4974
# Function        : BuildAddKnownFile
4975
#
4976
# Description     : Save the file as a file that will be known  to the JATS
4977
#                   makefiles. It will be available SRCS, but will not be a
4978
#                   part of any object list.
4979
#
4980
#                   Known Files will be deleted on clobber
4981
#
4982
# Inputs          : $path
4983
#                   $file
289 dpurdie 4984
#                   $noadd                    - Don't add to known
247 dpurdie 4985
#
4986
# Returns         : Path and filename
4987
#
4988
 
4989
sub BuildAddKnownFile
4990
{
289 dpurdie 4991
    my ($path, $file, $noadd) = @_;
247 dpurdie 4992
    $path .= '/'. $file;
2450 dpurdie 4993
    $path =~ tr~/~/~s;
289 dpurdie 4994
    $BUILD_KNOWNFILES {$file} = $path
4995
        unless ( defined($noadd) && $noadd);
4003 dpurdie 4996
 
6133 dpurdie 4997
    ToolsetFiles::AddFile( $path )
3967 dpurdie 4998
        unless ($Clobber);
4999
 
247 dpurdie 5000
    return $path;
5001
}
5002
 
5003
#-------------------------------------------------------------------------------
5969 dpurdie 5004
# Function        : WinPath 
5005
#
5006
# Description     : Covert path to a windows formatted path
5007
#
5008
# Inputs          : One path element
5009
#
5010
# Returns         : One ugly path element
5011
#
5012
 
5013
sub WinFullPath
5014
{
5015
    my ($path) = @_;
5016
    $path = FullPath($path);
5017
    $path =~ tr~\\/~\\~s;
5018
    return $path;
5019
}
5020
 
5021
#-------------------------------------------------------------------------------
5022
# Function        : BuildPropertyPages 
5023
#
5024
# Description     : Create a props file suitable for use by VS2010, VS2012 (possibly others)
5025
#                   Only supported for C/C++ projects
5026
#                   Provide info for:
5027
#                       Include Search paths
5028
#                       Library search paths
5029
#                       Nice Macros 
5030
#
5031
# Inputs          : 
5032
#
5033
# Returns         : 
5034
#
5035
sub BuildPropertyPages
5036
{
5037
    StartBuildPhase();                      # Starting the build phase. No more data collection
5986 dpurdie 5038
    return if $Clobber;
5969 dpurdie 5039
    foreach my $platform ( keys %BUILDINFO )
5040
    {
5041
        next unless $BUILDINFO{$platform}{MSBUILDPROPS};
5986 dpurdie 5042
        my $propsFile = BuildAddKnownFile ($Srcdir, 'jats_'. $BUILDINFO{$platform}{TARGET} . '.props');
5043
 
5969 dpurdie 5044
        Message("BuildPropertyPages: $propsFile");
5045
 
5046
        my %macros;
5047
        my @libpaths;
5048
        my @incpaths;
5049
        my @parts = @{$BUILDINFO{$platform}{PARTS}};
5050
 
5051
        #
5052
        #   Basic definitions
5053
        #   
5054
        $macros{'GBE_ROOT'}     = WinFullPath(".");
5055
        $macros{'GBE_PLATFORM'} = $BUILDINFO{$platform}{PLATFORM};
5056
        $macros{'GBE_PRODUCT'}  = $BUILDINFO{$platform}{PRODUCT};
5057
        $macros{'GBE_TARGET'}   = $BUILDINFO{$platform}{TARGET};
5058
        $macros{'GBE_MACHTYPE'} = $::GBE_MACHTYPE;
5059
        $macros{'GBE_PKGDIR'}   = WinFullPath('./pkg/' . $BUILDNAME_PACKAGE);
5060
        $macros{'GBE_BUILDNAME'}= $BUILDNAME_PACKAGE;
5061
 
5062
        #
5063
        #   Paths from the current build
5064
        #       Local directory         - for installed components
5065
        #       Interface directory     - for BuildPkgArchives
5066
        #
5067
        if ( $BUILDLOCAL )
5068
        {
5069
            my $macroName = 'GBE_LOCALDIR';
5070
            $macros{$macroName} = WinFullPath("$BUILDLOCAL") ;
5071
            $macroName = '$(' . $macroName . ')';
5986 dpurdie 5072
            my @localParts;
5073
            UniquePush \@localParts, $BUILDINFO{$platform}{PLATFORM} , $BUILDINFO{$platform}{PRODUCT}, $BUILDINFO{$platform}{TARGET};
5074
            foreach ( @localParts )
5969 dpurdie 5075
            {
5076
                push @libpaths, catdir($macroName, 'lib', $_);
5077
                push @incpaths, catdir($macroName ,'include' ,$_);
5078
            }
5079
            push @incpaths, catdir($macroName ,'include');
5080
        }
5081
 
5082
        my $macroName = 'GBE_INTERFACEDIR';
5083
        $macros{$macroName} = WinFullPath("$BUILDINTERFACE") ;
5084
        $macroName = '$(' . $macroName . ')';
5085
 
5086
        foreach ( @parts )
5087
        {
5088
                push @libpaths, catdir($macroName, 'lib' , $_);
5089
                push @incpaths, catdir($macroName ,'include' ,$_);
5090
        }
5091
        push @incpaths, catdir($macroName ,'include');
5092
 
5093
        #
5094
        #   For each LinkPkgArchive
5095
        #
5096
        foreach my $package ( @{$PKGRULES{$platform}} )
5097
        {
5098
            next unless ( $package->{'type'} eq 'link' );
5099
 
5100
            my $macroName = 'GBE_PACKAGE_'.$package->{'name'};
5101
            $macros{$macroName} = WinFullPath($package->{'base'}) ;
5102
            $macroName = '$(' . $macroName . ')';
5103
 
5104
            for my $path ( @{$package->{'PLIBDIRS'}} )
5105
            {
5106
                push @libpaths, catdir($macroName, $path);
5107
            }
5108
            for my $path ( @{$package->{'PINCDIRS'}} )
5109
            {
5110
                push @incpaths, catdir($macroName, $path);
5111
            }
5112
        }
5113
 
5114
        my $AdditionalIncludeDirectories = join(';', @incpaths );
5115
        my $AdditionalLibraryDirectories = join(';', @libpaths);
5116
        my $PreprocessorDefinitions = 'JATS=1';
5117
 
5118
        #
5119
        #   Create a props file formatted for VS2012
5120
        #
5121
        open (my $XML, '>', $propsFile) || Error ("Cannot create output file: $propsFile", $!);
5122
 
5123
        my $writer = XML::Writer->new(OUTPUT => $XML, UNSAFE => 0, DATA_INDENT => 4, DATA_MODE => 1);
5124
        $writer->xmlDecl("UTF-8");
5125
        $writer->comment('This file is generated by JATS build');
5126
        $writer->comment('Do not edit this file');
5127
        $writer->comment('Do not version control this file');
5128
        $writer->startTag('Project', "ToolsVersion", "4.0", "xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
5129
        $writer->emptyTag('ImportGroup', 'Label' , "PropertySheets");
5130
 
5131
        #
5132
        #   Special Macro for handling production/debug libraries
5133
        #
5134
        $writer->startTag('PropertyGroup', 'Label' , "UserMacros", 'Condition', "'\$(Configuration)' == 'Debug'");
5135
        $writer->dataElement('GBE_TYPE', 'D');
5136
        $writer->endTag('PropertyGroup');
5137
 
5138
        $writer->startTag('PropertyGroup', 'Label' , "UserMacros", 'Condition', "'\$(Configuration)' != 'Debug'");
5139
        $writer->dataElement('GBE_TYPE', 'P');
5140
        $writer->endTag('PropertyGroup');
5141
 
5142
        #
5143
        #   Define macros
5144
        #   
5145
        $writer->startTag('PropertyGroup', 'Label' , "UserMacros");
5146
        foreach my $key ( sort keys %macros)
5147
        {
5148
            $writer->dataElement($key, $macros{$key});
5149
        }
5150
        $writer->endTag('PropertyGroup');
5151
        $macros{'GBE_TYPE'}     = 1;
5152
 
5153
        #
5154
        #   Extend the search paths for includes and libaraies
5155
        #   
5156
        #$writer->emptyTag('ItemDefinitionGroup');
5157
        $writer->startTag('ItemDefinitionGroup');
5158
 
5159
        $writer->startTag('ClCompile');
5160
        $writer->dataElement('AdditionalIncludeDirectories', $AdditionalIncludeDirectories . ';%(AdditionalIncludeDirectories)');
5161
        $writer->dataElement('PreprocessorDefinitions', $PreprocessorDefinitions . ';%(PreprocessorDefinitions)');
5162
        $writer->endTag('ClCompile');
5163
 
5164
        $writer->startTag('Link');
5165
        $writer->dataElement('AdditionalLibraryDirectories', $AdditionalLibraryDirectories . ';%(AdditionalLibraryDirectories)');
5166
        $writer->endTag('Link');
5167
        $writer->endTag('ItemDefinitionGroup');
5168
 
5169
        #
5170
        #   Specify all macro names
5171
        #
5172
        $writer->startTag('ItemGroup');
5173
        foreach my $key ( sort keys %macros)
5174
        {
5175
            $writer->startTag('BuildMacro', 'Include' , $key);
5176
            $writer->dataElement('Value', '$(' . $key . ')');
5177
            $writer->endTag('BuildMacro');
5178
        }
5179
 
5180
        #
5181
        #   Close tags and write the XML file
5182
        #
5183
        $writer->endTag('ItemGroup');
5184
        $writer->endTag('Project');
5185
        $writer->end();
5186
    }
5187
}
5188
 
5189
 
5190
#-------------------------------------------------------------------------------
227 dpurdie 5191
# Function        : Usage
5192
#
5193
# Description     : Display program usage information
5194
#
5195
# Inputs          : args            - Text message to display
5196
#
5197
#                   $opt_help       - Level of verbose ness
5198
#
5199
# Returns         : Does not return
5200
#                   This function will exit
5201
#
5202
sub Usage
5203
{
5204
    my( $msg ) = @_;
5205
    my %usage_args;
5206
 
5207
    #
5208
    #   Create a hash of arguments for the pod2usage function
5209
    #
5210
    $usage_args{'-input'} = __FILE__;
5211
    $usage_args{'-exitval'} = 42;
5212
    $usage_args{'-message'} = "\nbuildlib $msg\n" if $msg;
5213
    $usage_args{'-verbose'} = $opt_help < 3 ? $opt_help - 1 : 3 if ( $opt_help );
5214
 
5215
    #
5216
    #   Generate nice help
5217
    #
5218
    pod2usage(\%usage_args);
5219
}
5220
 
5221
#-------------------------------------------------------------------------------
5222
#   Documentation
5223
#
5224
 
5225
=pod
5226
 
361 dpurdie 5227
=for htmltoc    JATS::build
5228
 
227 dpurdie 5229
=head1 NAME
5230
 
361 dpurdie 5231
build - Build Environment and Makefiles
227 dpurdie 5232
 
5233
=head1 SYNOPSIS
5234
 
5235
jats build [options] [command]
5236
 
5237
     [perl buildlib.pl [options] PWD [command]]
5238
 
5239
 Options:
331 dpurdie 5240
    -help          - Display terse usage
361 dpurdie 5241
    -help -help    - Display verbose usage
331 dpurdie 5242
    -man           - Display internal manual
5243
    -verbose[=n]   - Set level of progress verbosity
5244
    -debug[=n]     - Set the debug level
5245
    -cache         - Cache packages in the local dpkg_package cache
361 dpurdie 5246
    -cache -cache  - Forced refresh dependent packages in the local cache
331 dpurdie 5247
    -package       - Ignore packages that are not available and continue
2078 dpurdie 5248
    -nopackages    - Ignore package processing directives
331 dpurdie 5249
    -forcebuildpkg - Treat LinkPkgArchive directives as BuildPkgArchive
361 dpurdie 5250
                     Also suppress the use of symlinks so that the physical
5251
                     file will be copied locally.
331 dpurdie 5252
    -[no]force     - Force build even if build.pl is not newer
363 dpurdie 5253
                     Default: -force
4778 dpurdie 5254
    -[no]generic   - Build system sanity test
5255
                     Default: Do not test
227 dpurdie 5256
 
5257
 Sticky settings:
331 dpurdie 5258
    -all           - Build for all platforms ignoring GBE_BUILDFILTER
5259
    -expert[=n]    - Relaxing dependency checks on the user makefiles
227 dpurdie 5260
 
5261
 Commands:
2078 dpurdie 5262
    clobber        - Remove generated build system (eg Makefiles).
6133 dpurdie 5263
    interface      - Only (re)build the interface tree.
361 dpurdie 5264
    rootonly       - Only (re)build the root directory.
227 dpurdie 5265
 
5266
=head1 OPTIONS
5267
 
5268
=over 8
5269
 
331 dpurdie 5270
=item B<-help>
227 dpurdie 5271
 
5272
Print a brief help message and exits.
5273
 
5274
=item B<-help -help>
5275
 
5276
Print a detailed help message with an explanation for each option.
5277
 
5278
=item B<-man>
5279
 
5280
Prints the manual page and exits.
5281
 
331 dpurdie 5282
=item B<-verbose[=n]>
227 dpurdie 5283
 
261 dpurdie 5284
Increases program output.
227 dpurdie 5285
 
261 dpurdie 5286
If an argument is provided, then it will be used to set the level, otherwise the
5287
existing level will be incremented. This option may be specified multiple times.
227 dpurdie 5288
 
261 dpurdie 5289
=item B<-debug>
5290
 
227 dpurdie 5291
Increases program output. Enable internal debugging messages to generate detailed
5292
progress information.
5293
 
261 dpurdie 5294
If an argument is provided, then it will be used to set the level, otherwise the
5295
existing level will be incremented. This option may be specified multiple times.
5296
 
331 dpurdie 5297
=item B<-cache>
227 dpurdie 5298
 
5299
This option will cause dependent packages to be cached in the local
5300
dpkg_archive cache.
5301
 
5302
If the option is used twice then the packages will be forcibly refreshed.
5303
 
331 dpurdie 5304
=item B<-package>
227 dpurdie 5305
 
5306
This option will cause the build process to ignore packages that cannot be
5307
located. The package build may fail at a later stage.
5308
 
5309
This option is used by the Auto Build Tool to handle packages that may not be
5310
needed in all builds.
5311
 
2078 dpurdie 5312
=item B<-nopackage>
5313
 
5314
This options will cause all the directives that process external packages to be
5315
ignored.
5316
 
5317
This directive has limited use. It can be used in conjunction with the
5318
'interface' build command in order to create Version Information files in a
5319
sandbox where the required packages do not yet exist.
5320
 
331 dpurdie 5321
=item B<-forcebuildpkg>
227 dpurdie 5322
 
5323
This option will force LinkPkgArchive directives to be treated as
5324
BuildPkgArchive directives. The result is that the 'interface' directory will be
5325
populated with the contents of all dependent packages. Moreover, on a Unix
5326
machine, the files will be copied and not referenced with a soft link.
5327
 
5328
This may be useful for:
5329
 
5330
=over 8
5331
 
361 dpurdie 5332
=item *
227 dpurdie 5333
 
361 dpurdie 5334
Remote Development
227 dpurdie 5335
 
361 dpurdie 5336
=item *
227 dpurdie 5337
 
361 dpurdie 5338
Collecting header files for scanning
5339
 
5340
=item *
5341
 
5342
Local modification of files for test/debug/development
5343
 
227 dpurdie 5344
=back
5345
 
331 dpurdie 5346
=item B<-[no]force>
227 dpurdie 5347
 
331 dpurdie 5348
The '-noforce' option will only perform a build, if the build.pl file
363 dpurdie 5349
has been modified, or the buildfilter has changed, since the last build.
331 dpurdie 5350
 
363 dpurdie 5351
The default operation will always force a build.
331 dpurdie 5352
 
4778 dpurdie 5353
=item B<-[no]generic>
5354
 
5355
If used, this option will perform a sanity test on the build type. If set to 
5356
Generic then the build must be a GENERIC build. If set to noGeneric then the build
5357
must not be a GENERIC build.
5358
 
5359
The default is to not perform the test.
5360
 
5361
This option is intended to be used by the automated build system.
5362
 
331 dpurdie 5363
=item B<-all>
5364
 
227 dpurdie 5365
This option will cause the build process to generate makefiles for all
5366
possible build targets ignoring the use of GBE_BUILDFILTER.
5367
 
5368
This option is sticky. Once used in a build it will be retained when makefiles
5369
are rebuilt.
5370
 
331 dpurdie 5371
=item B<-expert[=n]>
227 dpurdie 5372
 
5373
This option causes the generation of makefiles with relaxed dependancy checks.
5374
 
261 dpurdie 5375
If an argument is provided, then it will be used to set the level, otherwise a
5376
level of '1' will be set.
5377
 
227 dpurdie 5378
The makefiles will have no dependancy between the makefiles and the JATS build
5379
files or the users makefile. If the user's makefile.pl is changed then JATS
5380
will not detect the change and will not rebuild the makefiles. The user manually
5381
force the rebuild with the command 'jats rebuild'.
5382
 
5383
This option should be used with care and with full knowledge of its impact.
5384
 
5385
This option is sticky. Once used in a build it will be retained when makefiles
363 dpurdie 5386
are rebuilt. It will only be lost when the next 'jats build' is performed.
227 dpurdie 5387
 
261 dpurdie 5388
The effect of the option can be changed when the makefiles are processed. This
5389
option simply sets the default' mode of operation.
5390
 
227 dpurdie 5391
=item B<interface>
5392
 
6133 dpurdie 5393
This command will only build, or rebuild, the 'interface' directory.
227 dpurdie 5394
 
261 dpurdie 5395
This command will not build, or rebuild, the root directory. The build
227 dpurdie 5396
process will not recurse through the subdirectories creating makefiles.
5397
 
261 dpurdie 5398
=item B<rootonly>
5399
 
6133 dpurdie 5400
This command will only build, or rebuild, the 'interface' directory and 
5401
the root-level makefiles.
261 dpurdie 5402
 
5403
The build process will not recurse through the subdirectories creating
5404
makefiles. These can be made on-demand by jats if a 'make' command is issued.
5405
 
227 dpurdie 5406
=item B<clobber>
5407
 
5408
This command will remove generated build system files and directories.
5409
 
5410
=back
5411
 
5412
=head1 DESCRIPTION
5413
 
5414
The default build process will parse the user's build.pl file and create the
5415
'interface' directory before creating makefiles for each target platform.
5416
 
5417
The 'build' process simply generates the build sandbox. It does not invoke the
5418
generated makefiles. This must be done by the user in a different phase.
5419
 
5420
The 'build' process need only be invoked if the build.pl file has changed. The
5421
generated makefiles will detected changes to the makefile.pl's and cause them to
5422
be generated as required. The 'build' step sets up the sandboxes external
5423
environment.
5424
 
5425
=head1 INVOCATION
5426
 
5427
This perl library (buildlib.pl) is not designed to be invoked directly by the
5428
user. It should be invoked through a 'build.pl' file. Moreover, for historical
5429
reasons, the build.pl is not easily invoked. It is best to only invoke the
5430
'build' process via the JATS wrapper scripts : jats.bat or jats.sh.
5431
 
331 dpurdie 5432
The build.pl file must be invoked with one fixed arguments, followed by user
227 dpurdie 5433
options and subcommands
5434
 
5435
=over 8
5436
 
361 dpurdie 5437
=item   1
227 dpurdie 5438
 
361 dpurdie 5439
The current working directory
5440
 
227 dpurdie 5441
This could have been derived directly by the program, rather than having it
5442
passed in.
5443
 
361 dpurdie 5444
=item   2
227 dpurdie 5445
 
361 dpurdie 5446
Options and commands may follow the first two mandatory arguments.
5447
 
227 dpurdie 5448
=back
5449
 
5450
The build.pl file must 'require' the buildlib.pl and makelib.pl. The preferred
5451
code is:
5452
 
5453
=over 8
5454
 
5455
    build.pl: First statements
5456
    $MAKELIB_PL     = "$ENV{ GBE_TOOLS }/makelib.pl";
5457
    $BUILDLIB_PL    = "$ENV{ GBE_TOOLS }/buildlib.pl";
5458
 
5459
    require         "$BUILDLIB_PL";
5460
    require         "$MAKELIB_PL";
5461
 
5462
=back
5463
 
5464
=cut
5465
 
5466
1;