Subversion Repositories DevTools

Rev

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