Subversion Repositories DevTools

Rev

Rev 5986 | Rev 6133 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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