Subversion Repositories DevTools

Rev

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

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