Subversion Repositories DevTools

Rev

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

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