Subversion Repositories DevTools

Rev

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

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