Subversion Repositories DevTools

Rev

Rev 4836 | Details | Compare with Previous | Last modification | View Log | RSS feed

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