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