Subversion Repositories DevTools

Rev

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