Subversion Repositories DevTools

Rev

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