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