Subversion Repositories DevTools

Rev

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