Subversion Repositories DevTools

Rev

Rev 5969 | Rev 6073 | 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";
2091
 
2092
        my $package_installed;
2093
        $package_installed = 1
2094
            if ( !$local &&
2095
                 !$Cache &&
2096
                 !FileIsNewer( $entry->GetBaseDir('descpkg'), $tag_file ) );
2097
 
2098
        #
2099
        #   Determine the package format and use the appropriate installer
2100
        #   Supported formats
2101
        #       1) Package has a descpkg file (new style)
2102
        #       2) Package has a InstallPkg.sh file (old style)
2103
        #       3) Package has a Install.sh file (old style is it used ??)
2104
        #
2105
        if ( $package_installed ) {
2106
            Verbose ("Package already installed: $name, $version");
2107
 
2108
        } else {
261 dpurdie 2109
            Log( "                . installing '$pkg'" );
2110
            Log( "                . -> " . readlink($pkg) ) if ( -l $pkg );
227 dpurdie 2111
 
2112
            if ( -e "$pkg/descpkg" )
2113
            {
2114
 
2115
                #
2116
                #   If forcing a BuildPkg, then don't use symlinks
2117
                #   to files in dpkg_archive
2118
                #
331 dpurdie 2119
                my @opts;
2120
                push @opts, "--NoSymlinks" if ( $ForceBuildPkg );
2121
                push @opts, "--AllowOverWrite" if ( $local );
227 dpurdie 2122
 
2123
                #
2124
                #   Determine all the Platforms, Products and Targets
2125
                #   that need to be installed
2126
                #
2127
                my $arglist = GenerateInstallArgumentList();
331 dpurdie 2128
                System( "cd $pkg; $::GBE_PERL $::GBE_TOOLS/installpkg.pl $Cwd/$BUILDINTERFACE $Cwd @opts $arglist");
227 dpurdie 2129
                Error( "Package installation error" ) if ( $? != 0 );
2130
            }
2131
            elsif ( -e "$pkg/InstallPkg.sh" )
2132
            {
2133
                System( "(cd $pkg; ./InstallPkg.sh $Cwd/$BUILDINTERFACE $Cwd)" );
2134
            }
2135
            elsif ( -e "$pkg/Install.sh" )
2136
            {
2137
                System( "(cd $pkg; ./Install.sh $Cwd/$BUILDINTERFACE $Cwd)" );
2138
            }
2139
            else
2140
            {
2141
                Error ("Unknown package format for package $name/$version found in $pkg");
2142
            }
2143
 
2144
            #
2145
            #   Tag the package as installed - after it has been transferred
2146
            #
2147
            mkdir ( $tag_dir );
2148
            TouchFile( $tag_file );
2149
        }
2150
 
2151
        #
2152
        #   Process package
2153
        #
2154
        IncludePkg ( $name, $pkg );
2155
 
2156
        #
2157
        #   Complete the creation of the package entry
2158
        #   Add the information for all platforms
2159
        #
2160
        $entry->Cleanup();
2161
        for my $platform (@BUILD_ACTIVEPLATFORMS)
2162
        {
2163
            $entry->ExamineToolPath();
2164
            $entry->ExamineThxPath($platform);
2165
            push ( @{$PKGRULES{$platform}}, $entry );
2166
        }
2167
    }
2168
}
2169
 
2170
#-------------------------------------------------------------------------------
311 dpurdie 2171
# Function        : CreateInterfacePackage
2172
#
2173
# Description     : Create a dummy package entry to describe the Interface
2174
#                   This is done AFTER all the BuildPkgArchive directives have
2175
#                   been processed so that the interface directory is fully
2176
#                   processed
2177
#
2178
# Inputs          : None
2179
#
2180
# Returns         : 
2181
#
2182
sub CreateInterfacePackage
2183
{
2184
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
2185
    {
2186
        my $entry = PackageEntry::Interface( "$::Cwd/$BUILDINTERFACE" );
2187
 
2188
        #
2189
        #   Locate include and lib bits within the interface
2190
        #   This is much simpler than for a LinkPkgArchive as the form
2191
        #   has been sanitized
2192
        #
2193
        my $parts = $BUILDINFO{$platform}{PARTS};
2194
 
2195
        foreach my $part ( @$parts )
2196
        {
2197
            $entry->RuleInc( "/include/" . $part );
2198
        }
2199
        $entry->RuleInc( "/include" );
2200
 
2201
        foreach my $part ( @$parts )
2202
        {
2203
            $entry->RuleLib("/lib/" . $part );
2204
        }
2205
 
2206
        $entry->ExamineToolPath();
2207
        $entry->ExamineThxPath($platform);
2208
        $entry->Cleanup();
2209
 
2210
        #
2211
        #   Add the package entry to the array of such entries for
2212
        #   the current platform. Force it to be the first one as
2213
        #   the interface directory will be scanned first
2214
        #
2215
        unshift ( @{$PKGRULES{$platform}}, $entry );
2216
    }
2217
}
2218
 
2219
#-------------------------------------------------------------------------------
227 dpurdie 2220
# Function        : GenerateInstallArgumentList
2221
#
2222
# Description     : Generate an argument list for the installpkg.pl script
2223
#                   The argument list is of the form
2224
#                       --Platform:xx[:xx[:xx]] --Platform:yy[:yy[:yy]] ...
2225
#                   Where xx is:
2226
#                       * a 'part' of the target platform
2227
#                         Order is: platform, product, ...  target( in that order )
2228
#                       * --Option[=yyy]
2229
#                        An option to be passed to the script. These are bound only
2230
#                        to the enclosed platform.
2231
# Inputs          :
2232
#
2233
# Returns         : See above
2234
#
2235
sub GenerateInstallArgumentList
2236
{
2237
    my @arglist;
2238
 
2239
    #
2240
    #   Generate the argument list as an array
2241
    #
2242
    for (@BUILD_ACTIVEPLATFORMS)
2243
    {
2244
        my @args = '--Platform';
2245
        push @args, @{$BUILDINFO{$_}{PARTS}};
2246
        push @arglist, join (":" , @args );
2247
    }
2248
 
2249
    return "@arglist";
2250
}
2251
 
2252
#-------------------------------------------------------------------------------
2253
# Function        : GeneratePlatformList
2254
#
2255
# Description     : Return a list of platforms that should particiate in this
2256
#                   build. This is a function of
2257
#                       1) Platforms defined in the build.pl file
5679 dpurdie 2258
#                       2) Platforms excluded in the build.pl file
2259
#                       3) User filter defined in GBE_BUILDFILTER
227 dpurdie 2260
#
2261
#                   The primary use of this function is to limit the creation
2262
#                   of makefiles to those that have supported compilers on
2263
#                   the underlying machine.
2264
#
2265
#                   GBE_BUILDFILTER is a space seperated string of words
2266
#                   Each word may be one of
2267
#                       OPTION=TAG or OPTION=!TAG
2268
#                       TAG or !TAG. This is the same as --TARGET=TAG
2269
#
2270
#                   Bare tags are taken to be TARGETS.
2271
#
2272
#                   Where OPTION may be one of
2273
#                       --PLATFORM
2274
#                       --PRODUCT
2275
#                       --TARGET
5679 dpurdie 2276
#                   For a BuildProduct( AA,BB,CC)
2277
#                       Product     - AA
2278
#                       Targets     - BB, CC
2279
#                       Platforms   - AA_BB, AA_CC
227 dpurdie 2280
#
2281
#                   Special cases
2282
#                   1) If GBE_BUILDFILTER is empty, then all available platforms are used
2283
#                      The global $All is set, then all available platforms are used
2284
#                   2) If the first word of GBE_BUILDFILTER is a negative filter,
2285
#                      ie is used the !xxxx or yyy=!xxxx construct, then it is assumed
2286
#                      that the filter will start with all available platforms
2287
#                   3) The special word --ALL forces selection of ALL platforms
2288
#                      and may reset any existing scanning
2289
#                   4) GBE_BUILDFILTER is parsed left to right. It is possible to add and
2290
#                      subtract items from the list.
2291
#                   5) OPTIONS are case insensitive
2292
#                      TAGS are case sensitive
2293
#
2294
#
2295
# Inputs          : GBE_BUILDFILTER from the environment
2296
#
2297
# Returns         : An array of platforms to include in the build
2298
#                   Maintains @BUILD_ACTIVEPLATFORMS  - the last calculated result
2299
#                   Ensures that @DEFBUILDPLATFORMS is a subset of @BUILD_ACTIVEPLATFORMS
2300
#
2301
sub GeneratePlatformList
2302
{
2303
    #
2304
    #   Return the cached result for speed
2305
    #   The value need only be calculated once
2306
    #
2931 dpurdie 2307
    unless ( @BUILD_ACTIVEPLATFORMS )
227 dpurdie 2308
    {
2309
        my ($platform_filter);
2310
        my %result;
2311
        my %part_to_platform;
2312
 
2313
        #
2314
        #   Create a data structure to assist in the production of the platform list
2315
        #   The structure will be a hash of hashes of arrays
2316
        #
2317
        #   The first level hash will be keyed by the word TARGET, PRODUCT or PLATFORM
2318
        #   The second level of the hash will keyed by available targets, products or platforms
2319
        #   The value of the field will be an array of platforms that match the keyword
2320
        #
2321
        for my $platform (keys (%::BUILDINFO))
2322
        {
2323
            my $pParts = $::BUILDINFO{$platform};
2324
 
2325
            #
2326
            #   Skip platforms that are known to be unavailable on this build
2327
            #   machine. Self configure
2328
            #
2329
            next if ( $pParts->{NOT_AVAILABLE} );
2330
 
2331
            my $target  = $pParts->{TARGET};
2332
            my $product = $pParts->{PRODUCT};
2333
 
2334
            push @{$part_to_platform{'PLATFORM'}{$platform}}, $platform;
2335
            push @{$part_to_platform{'TARGET'}  {$target}}  , $platform;
2336
            push @{$part_to_platform{'PRODUCT'} {$product}} , $platform;
2337
        }
2338
        #
2339
        #   Determine the source of the filter
2340
        #   If the user provides one, then use it.
2341
        #   Otherwise its taken from the environment.
2342
        #
2343
        #   Global build all platforms - Kill any user filter
2344
        #
2345
        if ( $All )
2346
        {
2347
            $platform_filter = "";
2348
        }
2349
        else
2350
        {
2351
            $platform_filter = "";
2352
            $platform_filter = $::GBE_BUILDFILTER
2353
                if ( defined($::GBE_BUILDFILTER) );
2354
        }
2355
        Debug( "GeneratePlatformList: Filter:$platform_filter" );
2356
 
2357
        #
2358
        #   Detect the special cases
5679 dpurdie 2359
        #       1) No user definition
227 dpurdie 2360
        #       2) First word contains a subtractive element
5679 dpurdie 2361
        #   And assume all platforms    
227 dpurdie 2362
        #
2363
        my (@filter) = split( ' ', $platform_filter );
2364
 
2365
        if ( !scalar @filter || $filter[0] =~ m/^$/ || $filter[0] =~ m/!/ )
2366
        {
2367
            %result = %{$part_to_platform{'PLATFORM'}}
2368
                if exists $part_to_platform{'PLATFORM'} ;
2369
        }
5679 dpurdie 2370
 
227 dpurdie 2371
#DebugDumpData( "PartToPlatform", \%part_to_platform );
2372
 
2373
        #
2374
        #   Process each element in the user filter list
2375
        #   Expand platforms into known aliases
2376
        #
2377
        for my $word (@filter)
2378
        {
2379
            my $platform;
2380
 
2381
            if ( $word =~ m/^--ALL/i )
2382
            {
2383
                %result = %{$part_to_platform{'PLATFORM'}};
2384
            }
2385
            elsif ( $word =~ m/^--(TARGET)=(!?)(.*)/i ||
2386
                    $word =~ m/^--(PRODUCT)=(!?)(.*)/i ||
2387
                    $word =~ m/^--(PLATFORM)=(!?)(.*)/i ||
2388
                    ( $word !~ m/^-/ && $word =~ m/()(!?)(.*)/ )
2389
                )
2390
            {
2391
                my $table = uc($1);
2392
                $table = "TARGET"
2393
                    unless ( $1 );
2394
 
2395
                #
2396
                #   Expand PLATFORMs into known aliases
2397
                #   Alias will expand to PLATFORMs so it won't work unless we are
2398
                #   processing PALTFORMs.
2399
                #
2400
                my @taglist = ( $table eq "PLATFORM" ) ? ExpandPlatforms($3) : $3;
2401
 
2402
                #
2403
                #   Add / Remove items from the result
2404
                #
2405
                for my $item ( @taglist )
2406
                {
2407
                    my $plist = $part_to_platform{$table}{$item};
2408
                    for ( @{$plist})
2409
                    {
2410
                        if ( $2 )
2411
                        {
2412
                            delete $result{$_};
2413
                        }
2414
                        else
2415
                        {
2416
                            $result{$_} = 1;
2417
                        }
2418
                    }
2419
                }
2420
            }
2421
            else
2422
            {
2423
                print "GBE_BUILDFILTER filter term not understood: $word\n";
2424
            }
2425
        }
2426
 
2427
        #
5679 dpurdie 2428
        #   Process BuildExclude
2429
        #   A list of 
2430
        #
2431
        for my $word (@BUILDEXCLUDE)
2432
        {
2433
            my $platform;
2434
 
2435
            Error('BuildExclude: Unknown option: ' . $word) if ($word =~ m~^-~);
2436
            Error('BuildExclude: Invalid format: ' . $word) if ($word =~ m~^!~);
2437
 
2438
            #
2439
            #   Remove items from the result
2440
            #
2441
            my $table = "TARGET";
2442
            my $plist = $part_to_platform{$table}{$word};
2443
            Warning('BuildExclude: Unknown target:' . $word ) unless $plist;
2444
            for ( @{$plist})
2445
            {
2446
                delete $result{$_};
2447
            }
2448
        }
2449
 
2450
        #
227 dpurdie 2451
        #   Return an array of platforms to process
2452
        #
2453
        @BUILD_ACTIVEPLATFORMS = sort keys %result;
2454
 
2455
        #
2456
        #   Ensure that DEFBUILDPLATFORMS is a subset of build active platforms
2457
        #
2458
        my @NEW_DEFBUILDPLATFORMS;
2459
        foreach ( @DEFBUILDPLATFORMS )
2460
        {
2461
            push @NEW_DEFBUILDPLATFORMS, $_
2462
                if ( exists $result{$_} );
2463
        }
2464
        @DEFBUILDPLATFORMS = @NEW_DEFBUILDPLATFORMS;
2465
    }
2466
 
2467
    Debug("GeneratePlatformList: Result:@BUILD_ACTIVEPLATFORMS");
2468
    return @BUILD_ACTIVEPLATFORMS;
2469
}
2470
 
2471
#-------------------------------------------------------------------------------
2472
# Function        : PrintPlatforms
2473
#
2474
# Description     : Petty print the specified platform list, breaking line
2475
#                   on either a primary key change or length width >78.
2476
#
2477
# Returns         : Formated string
2478
#
2479
# Example Output :
2480
#
2481
#           DDU_LMOS_WIN32 DDU_LMOS_linux_armv4 DDU_LMOS_linux_i386
2482
#           IDFC_LMOS_WIN32 IDFC_LMOS_linux_armv4 IDFC_LMOS_linux_i386
2483
#           LMOS_WCEPSPC_ARM LMOS_WCEPSPC_EMU LMOS_WIN32 LMOS_linux_armv4
2484
#           LMOS_linux_i386
2485
#..
2486
sub PrintPlatforms
2487
{
2488
    my ($platforms, $nl) = @_;
2489
    my ($string) = "";                          # result
2490
 
2931 dpurdie 2491
    if ( @$platforms )
227 dpurdie 2492
    {
2493
        my ($key_run) = 0;
2494
        my ($pkey);                             # previous key
2495
 
2496
        #   Perform a simple formatting and determine if there is key 
2497
        #   change greater then 1 or whether the total length exceeds 78.
2498
        #
2499
        #   If the line exceeds 78, the printer shall then reformat 
2500
        #   breaking based on line length and possiblity keys.
2501
        #
2502
        $pkey = "";
2503
        for my $k (sort @$platforms) 
2504
        {
2505
            my ($d);                            # delimitor
2506
 
2507
            if (($d = index( $k, '_' )) != index( $pkey, '_' ) ||
2508
                    substr( $k, 0, $d ) ne substr( $pkey, 0, $d )) {
2509
                $key_run = 1
2510
                    if ($key_run <= 1);         # change, reset run if <= 1
2511
            } else {
2512
                $key_run++;                     # same primary key
2513
            }
2514
 
2515
            $string .= " " if ($pkey);
2516
            $string .= $k;
2517
            $pkey = $k;
2518
        }
2519
 
2520
        #   Reprint if required.
2521
        #
2522
        if (length($nl)+length($string) > 78)
2523
        {
2524
            my ($llen);                         # line length
2525
 
2526
            $llen = length($nl);
2527
 
2528
            $pkey = "";
2529
            $string = "";
2530
 
2531
            for my $k (sort @$platforms)
2532
            {
2533
                my ($klen, $d);                 # key length, delimitor
2534
 
2535
                $klen = length($k);
2536
                if ($pkey ne "")
2537
                {
2538
                    if ($llen + $klen > 78 ||
2539
                        ($key_run > 1 && (
2540
                            ($d = index( $k, '_' )) != index( $pkey, '_' ) ||
2541
                            substr( $k, 0, $d ) ne substr( $pkey, 0, $d ) )) )
2542
                    {                           # line >70 or key change
2543
                        $string .= $nl;
2544
                        $llen = length($nl);
2545
                    }
2546
                    else
2547
                    {
2548
                        $string .= " ";
2549
                        $llen++;
2550
                    }
2551
                }
2552
                $string .= $k;
2553
                $pkey = $k;
2554
                $llen += $klen;
2555
            }
2556
        }    
2557
    }
2558
    return $string;
2559
}
241 dpurdie 2560
#-------------------------------------------------------------------------------
2561
# Function        : PrintList
2562
#
2563
# Description     : Pretty format an array to fit within 80 char line
2564
#                   Perform wrapping as required
2565
#
2566
# Inputs          : $list           - Reference to an array
2567
#                   $nl             - New line stuff.
2568
#                                     Use to prefix new lines
2569
#
2570
# Returns         : string
2571
#
2572
sub PrintList
2573
{
2574
    my ($list, $nl) = @_;
2575
    my ($string) = '';                          # result
2576
    my $sep;
227 dpurdie 2577
 
241 dpurdie 2578
    if ( @$list )
2579
    {
2580
        my ($llen) = length($nl);
227 dpurdie 2581
 
241 dpurdie 2582
        for my $k (@$list)
2583
        {
2584
            my $klen = length($k);
2585
            if ($llen + $klen > 78 )
2586
            {
2587
                $string .= $nl;
2588
                $llen = length($nl);
2589
            }
2590
            else
2591
            {
2592
                if ( $sep )
2593
                {
2594
                    $string .= $sep;
2595
                    $llen++;
2596
                }
2597
                else
2598
                {
2599
                    $sep = ' ';
2600
                }
2601
            }
2602
            $string .= $k;
2603
            $llen += $klen;
2604
        }
2605
    }
2606
    return $string;
2607
}
2608
 
305 dpurdie 2609
#-------------------------------------------------------------------------------
2610
# Function        : BuildReleaseFile
2611
#
2612
# Description     : Legacy function
2613
#                   Don't know what it was meant to do
2614
#                   Unfortunately it is present in a lot of build.pl files
2615
#
2616
#                   Not well supported on all machine types
2617
#
331 dpurdie 2618
# Inputs          : None that are used
305 dpurdie 2619
#
331 dpurdie 2620
# Returns         : Undefined
305 dpurdie 2621
#
227 dpurdie 2622
sub BuildReleaseFile
2623
{
2624
}
2625
 
305 dpurdie 2626
#-------------------------------------------------------------------------------
2627
# Function        : BuildSnapshot
2628
#
2629
# Description     : Legacy function
2630
#                   Don't know what it was meant to do
2631
#                   Unfortunately it is present in a lot of build.pl files
2632
#
2633
# Inputs          : None that are used
2634
#
2635
# Returns         : Undefined
2636
#
227 dpurdie 2637
sub BuildSnapshot
2638
{
2639
}
2640
 
305 dpurdie 2641
#-------------------------------------------------------------------------------
2642
# Function        : BuildSrcArchive
2643
#
2644
# Description     : Create a source snapshot of the build source
2645
#                   Designed to provide a source image for packaging
2646
#                   examples
2647
#
2648
#                   Should be platform independent
2649
#
2650
#                   Creates an archive file and places it into the
2651
#                   interface directory. The archive will be packaged
2652
#                   automatically by the build process
2653
#
2654
#                   Use the 'pax' utility
2655
#                       1) Can massage the file path such that the stored
2656
#                          directory image contains the package name and version
2657
#
2658
#                   Directive can be used at any time before the BuildMake
2659
#
2660
#                   Will handle the existence of an auto.pl file by inserting
2661
#                   it as build.pl.
2662
#
2663
# Inputs          : Options
2664
#
2665
#
2666
# Returns         : 
2667
#
2668
sub BuildSrcArchive
2669
{
2670
    #
2671
    #   If we are clobbering, then there is nothing to do
2672
    #   The generated file is placed within the interface
2673
    #   directory and that directory will be deleted during the clobber
2674
    #
2675
    return if ( $Clobber );
2676
    DataDirective("BuildSrcArchive");
227 dpurdie 2677
 
305 dpurdie 2678
    #
2679
    #   Currently this operation is only supported of some platforms
2680
    #   Only supported on Unix platforms
2681
    #   Uses the 'pax' utility
2682
    #
2683
    unless ( LocateProgInPath ( 'pax', '--All' ) && ( $ScmHost eq "Unix" ) )
2684
    {
2685
        Log( "SrcPackage . Not supported" );
2686
        return;
2687
    }
2688
 
2689
    #
2690
    #   Only allow one instance of the directive
2691
    #
2692
    Error ("Multiple BuildSrcArchive directives not supported")
2693
        if ( $build_source_pkg );
2694
 
2695
    #
2696
    #   Create the name of the archive
2697
    #       Based on the package name and version
2698
    #       Has no spaces
2699
    #
2700
    my $build_name = $BUILDNAME;
2701
    $build_name =~ s~\s+~_~g;
2702
 
2703
    #
2704
    #   Create the archive in the interface directory
2705
    #   Don't need to clobber it as the entire interface directory
2706
    #   will be clobbered
2707
    #
2708
    $build_source_pkg = $build_name;
2709
}
2710
 
2711
#-------------------------------------------------------------------------------
2712
# Function        : BuildSrcArchiveBody
227 dpurdie 2713
#
305 dpurdie 2714
# Description     : Function to implement the body of the BuildSrcArchive
2715
#                   operation. Will be invoked during BuildMake
2716
#
2717
# Inputs          : None
2718
#
2719
# Returns         : 
2720
#
2721
sub BuildSrcArchiveBody
2722
{
2723
    return unless ( $build_source_pkg );
2724
 
2725
    my $archive_dir = "pkg/$BUILDNAME_PACKAGE/src";
2726
    my $archive_file = "$build_source_pkg" . '.tar';
2727
 
2728
    Log( "SrcPackage . $archive_file.gz" );
2729
    unlink "$archive_dir/$archive_file";
2730
    unlink "$archive_dir/$archive_file.gz";
2731
    mkpath($archive_dir, 0, 0775);
2732
 
2733
    #
2734
    #   Create a list of files and top-level dirs to add to source archive
2735
    #   Many files are ignored
2736
    #   Should only be executed on the first 'build' thus many internal
2737
    #   directories will not be present
2738
    #
2739
    my @flist;
2740
    my $auto_pl;
2741
    opendir (my $tp, '.' ) or Error ("Cannot read current directory");
2742
    while ( $_ = readdir($tp) )
2743
    {
2744
        next if ( m/^\.$/ );
2745
        next if ( m'^\.\.$' );
2746
        next if ( m'^build\.log$' );
2747
        next if ( m'\.gbe$' );
2748
        next if ( m'^local$' );
2749
        next if ( m'^pkg$' );
2750
        next if ( m/^$BUILDINTERFACE$/ );
2751
        $auto_pl = 1, next  if ( m'^auto\.pl$' );
2752
        next if (  m'^build\.pl$' );
2753
        next if ( m/^$build_source_pkg$/ );
2754
        push @flist, $_;
2755
    }
2756
    closedir $tp;
2757
 
2758
    #
2759
    #   If we don't have an auto.pl, then we add the build.pl file
2760
    #   If we do have a auto.pl - it gets tricky. Its don't after the
2761
    #   initial pax command
2762
    #
2763
    unless ( $auto_pl )
2764
    {
2765
        push @flist, 'build.pl';
2766
    }
2767
 
2768
    #
2769
    #   Create the command to be executed
2770
    #   Prefix archive paths with build_name
2771
    #
2772
    my @command = ( 'pax', '-w', '-f', "$archive_dir/$archive_file" );
2773
    System( '--NoShell' , @command, '-s', "~^~$build_source_pkg/~", @flist );
2774
 
2775
    #
2776
    #   If we have an auto.pl file, then we need to add it to the archive
2777
    #   but it needs to be called build.pl
2778
    #
2779
    if ( $auto_pl )
2780
    {
2781
        System( '--NoShell' , @command, '-a', '-s', "~^auto.pl~$build_source_pkg/build.pl~" , 'auto.pl' );
2782
    }
2783
 
2784
    #
2785
    #   Must now zip the file
2786
    #   Can't zip and append at the same time
2787
    #
2788
    System( '--NoShell' , 'gzip', "$archive_dir/$archive_file" );
2789
 
2790
    #
2791
    #   Display the results
2792
    #
2793
    System ('--NoShell', 'pax', '-z', "-f$archive_dir/$archive_file.gz")
2794
        if (IsVerbose (1));
2795
}
2796
 
2797
#-------------------------------------------------------------------------------
2798
# Function        : BuildAccessPerms
2799
#
2800
# Description     : Check if access/permissions setting requested...
2801
#                   Legacy
2802
#
331 dpurdie 2803
#                   Don't know what it was meant to do
2804
#                   Unfortunately it is present in a lot of build.pl files
305 dpurdie 2805
#
331 dpurdie 2806
# Inputs          : None that are used
305 dpurdie 2807
#
331 dpurdie 2808
# Returns         : Undefined
2809
#
227 dpurdie 2810
sub BuildAccessPerms
2811
{
2812
}
2813
 
2814
 
2815
sub BuildSetenv
2816
{
2817
    push( @BUILDSETENV, @_ );
2818
}
2819
 
2820
#-------------------------------------------------------------------------------
2821
# Function        : DataDirective
2822
#
2823
# Description     : Called by data collection directives to ensure that we are
2824
#                   still collecting data and that we have collected other data
2825
#
2826
# Inputs          : $dname              - Directive Name
2827
#
2828
# Returns         : Will error if we are not
2829
#
2830
sub DataDirective
2831
{
2832
    my ($dname) = @_;
2833
 
2834
    Error( "$dname() must appear after BuildName()...")
2835
        if ( $BUILDNAME eq "" );
2836
 
2837
    Error( "$dname() must appear after BuildInterface()...")
2838
        unless( $BUILDINTERFACE );
2839
 
2840
    Error( "$dname() not allowed after BuildDescpkg, BuildIncpkg, BuildVersion or BuildMake")
2841
        if( $BUILDPHASE);
2842
}
2843
 
2844
#-------------------------------------------------------------------------------
2845
# Function        : StartBuildPhase
2846
#
2847
# Description     : Called by directives that deal with the building phases
2848
#                   to perform common initialisation and to ensure that
2849
#                   directives that collect data are no longer called
2850
#
305 dpurdie 2851
# Inputs          : last                - True: Last directive expected
227 dpurdie 2852
#
2853
# Returns         : May generate an error
2854
#
2855
sub StartBuildPhase
2856
{
305 dpurdie 2857
    my ($last) = @_;
2858
 
227 dpurdie 2859
    #
305 dpurdie 2860
    #   Ensure directive is allowed
2861
    #       $BUILDPHASE >  1     - No more directives allowed
2862
    #       $BUILDPHASE == 1     - Allowed directive
2863
    #
2864
    if ( $BUILDPHASE > 1 )
2865
    {
2866
        my $function = (caller(1))[3];
2867
        $function =~ s~.*::~~;
2868
        Error ("Directive not allowed: $function","'BuildMake' must be the last directive in the build file");
2869
    }
2870
 
2871
    #
227 dpurdie 2872
    #   Only do it once
2873
    #
305 dpurdie 2874
    return if ( $BUILDPHASE  );
2875
    $BUILDPHASE = 1;
227 dpurdie 2876
 
2877
    #
341 dpurdie 2878
    #   If we are not performing a ForceBuild, then we don't need to continue
2879
    #   We have updated the interface directory with BuildPkgArchive
2880
    #   information.
2881
    #
2882
    TestForForcedBuild();
2883
 
2884
    #
227 dpurdie 2885
    #   Calcuate the aliases that are being extracted from targets
2886
    #
2887
    Process_TargetAlias();
2888
 
2889
    #
4728 dpurdie 2890
    #   Calculate NATIVE alaias
2891
    #   Limit the Native Alias to active platforms
2892
    #
2893
    if (exists $BUILDALIAS{NATIVE})
2894
    {
2895
        Warning('User has manually specified a NATIVE alias','Default alias will not be set.');
2896
    }
2897
    else
2898
    {
2899
        my %activePatformMap = map {$_ => 1} @BUILD_ACTIVEPLATFORMS;
2900
        my @activeNatives;
2901
        foreach my $item (PlatformConfig::getNativeTargets())
2902
        {
2903
            push (@activeNatives, $item) if exists($activePatformMap{$item});
2904
        }
2905
 
2906
        $BUILDALIAS{NATIVE} = join(' ', @activeNatives);
2907
    }
2908
 
2909
    #
311 dpurdie 2910
    #   Create dummy package to describe the Interface directory
2911
    #
2912
    CreateInterfacePackage();
2913
 
2914
    #
227 dpurdie 2915
    #   Sanity test the users packages
2916
    #
2917
    PackageEntry::SanityTest() unless $Clobber;
2918
 
2919
    #
2920
    #   Validate the $Srcdir before its first real use
2921
    #   This is calculated from the user directives
2922
    #
2923
 
2924
    #.. Determine default "source" root
2925
    #
2926
    if ( $Srcdir eq "" )
2927
    {
2928
        Warning( "Both the directories 'src' and 'SRC' exist ....." )
2929
            if ( $ScmHost eq "Unix" && -e "src" && -e "SRC" );
2930
 
2931
        if ( -e "src" ) {
2932
            $Srcdir = "src";
2933
        } else {
2934
            ( -e "SRC" ) ||
2935
                Error( "Neither the directory 'src' nor 'SRC' exist ....." );
2936
            $Srcdir = "SRC";
2937
        }
2938
    }
2939
 
2940
    #
2941
    #   Must have a valid Srcdir
2942
    #
2943
    Error ("Source directory not found: $Srcdir")
2944
        unless ( $Srcdir && -d $Srcdir );
2945
 
305 dpurdie 2946
    #
2947
    #   Create source package
2948
    #
2949
    BuildSrcArchiveBody();
2950
 
227 dpurdie 2951
    return $Srcdir;
2952
}
2953
 
2954
#-------------------------------------------------------------------------------
341 dpurdie 2955
# Function        : TestForForcedBuild
2956
#
2957
# Description     : If a non-forced build has been requested, then see
2958
#                   if a build is required ( ie: build.pl modified )
2959
#
2960
#
2961
# Inputs          : None
2962
#
2963
# Returns         : May not return
2964
#
2965
sub TestForForcedBuild
2966
{
2967
    #
2968
    #   Always return if in clobber mode
2969
    #
2970
    return if ( $Clobber );
2971
 
2972
    if ( ! $ForceBuild  )
2973
    {
2974
        my @build_warn;
2975
        my $bstamp = -M "$Cwd/$ScmBuildSrc";
2976
        my $tstamp = -M "$Cwd/Makefile.gbe";
2977
 
2978
        push @build_warn, "Missing: Makefile.gbe" unless ( defined $tstamp );
2979
        push @build_warn, "Modified build file ($ScmBuildSrc)" if ( $tstamp && $bstamp < $tstamp );
2980
 
363 dpurdie 2981
        #
2982
        #   Ensure that the build filter has not changed
2983
        #   If the user has changed the buildfilter, then we need to
2984
        #   force a build.
2985
        #
2986
        #   The root Makefile.bge will have a $ScmBuildFilter entry
2987
        #
2988
        unless ( @build_warn )
2989
        {
2990
            use JatsMakeInfo;
2991
            ReadMakeInfo();
5726 dpurdie 2992
            my $line = $::ScmBuildFilter || '';
2993
            $line =~ s~\s+~ ~g;
363 dpurdie 2994
 
5726 dpurdie 2995
            my $filter = $::GBE_BUILDFILTER || '';
2996
            $filter =~ s~\s+~ ~g;
2997
            if ( $line ne $filter )
2998
            {
2999
                push @build_warn, "Build filter has changed";
3000
                Verbose2 ("Buildfilter Test: Was:$line, Is:$::GBE_BUILDFILTER");
3001
            }
363 dpurdie 3002
        }
3003
 
341 dpurdie 3004
        if ( @build_warn )
3005
        {
363 dpurdie 3006
            Verbose ("Forcing Build.", @build_warn );
341 dpurdie 3007
        }
3008
        else
3009
        {
3010
            Verbose ("No build performed. Build files up to date");
3011
            Log ("Build files up to date") if $::GBE_SANDBOX;
3012
            exit 0;
3013
        }
3014
    }
3015
}
3016
 
3017
#-------------------------------------------------------------------------------
305 dpurdie 3018
# Function        : LastBuildDirective
3019
#
3020
# Description     : No more build directives allowed
3021
#
3022
# Inputs          : 
3023
#
3024
# Returns         : 
3025
#
3026
sub LastBuildDirective
3027
{
3028
    $BUILDPHASE = 2;
3029
}
3030
 
3031
#-------------------------------------------------------------------------------
227 dpurdie 3032
# Function        : BuildPackageLink
3033
#
3034
# Description     : Create a soft link from sandbox_dpkg_archive to the package
3035
#                   being created by this build
3036
#
3037
#                   For backward compatability.
3038
#                   If GBE_DPKG_SBOX is not defined, then use GBE_DPKG_LOCAL
3039
#
3040
#                   This will allow multiple components to work together
3041
#
3042
#                   Note: When called in Clobber-mode the link will be deleted
3043
#
3044
# Inputs          : $BUILDNAME              - The package name
3045
#                   $BUILDNAME_PROJECT      - Project extension
3046
#                   $::GBE_DPKG_SBOX        - Path of sandbox_dpkg_archive
3047
#                   $::GBE_DPKG_LOCAL       - Path of local_dpkg_archive
3048
#                   $::GBE_DPKG             - Main repository
3049
#
3050
# Returns         : Nothing
3051
#
3052
sub BuildPackageLink
3053
{
3054
    my $target_archive;
3055
    my $target_archive_name;
3056
    my $link_file;
3057
    my $tag;
371 dpurdie 3058
    my $root_path;
227 dpurdie 3059
 
3060
    #
3061
    #   Determine the path (and name) of the target archive
3062
    #   Use sandbox_dpkg_archive if it exists
3063
    #   Use local_dpkg_acrhive for backward compatability (should be removed after JATS 2.64.2+)
3064
    #
3065
    if ( $target_archive = $::GBE_DPKG_SBOX )
3066
    {
3067
        $target_archive_name = "sandbox_dpkg_archive";
3068
        $tag = "Sandbox";
359 dpurdie 3069
        if ( $sandbox_exact )
3070
        {
3071
            $link_file = "$BUILDVERSION.lnk";
3072
        }
3073
        else
3074
        {
3075
            $link_file  = 'sandbox' . ${BUILDNAME_SUFFIX} . '.lnk';
3076
        }
371 dpurdie 3077
        $root_path = 'GBE_SANDBOX' . substr($Cwd, length($::GBE_SANDBOX));
3078
        Verbose2("Root Path: $::GBE_SANDBOX, $root_path");
227 dpurdie 3079
    }
3080
    elsif ( $target_archive = $::GBE_DPKG_LOCAL )
3081
    {
3082
        $target_archive_name = "local_dpkg_archive";
3083
        $link_file = "$BUILDVERSION.lnk";
3084
        $tag = "Local";
371 dpurdie 3085
        $root_path = $Cwd;
227 dpurdie 3086
    }
3087
    else
3088
    {
3089
        Verbose("Cannot locate local or sandbox archive")
3090
            unless $Clobber;
3091
        return;
3092
    }
3093
 
3094
    #
3095
    #   Santity test
3096
    #   Target must be a directory
3097
    #
3098
    unless ( -d $target_archive )
3099
    {
241 dpurdie 3100
        Warning("$target_archive_name is not a directory: $target_archive")
227 dpurdie 3101
            unless $Clobber;
3102
        return;
3103
    }
3104
 
3105
    my $link_dir = "$target_archive/$BUILDNAME_PACKAGE";
3106
    my $link_path = "$link_dir/$link_file";
3107
 
3108
    if ( $Clobber )
3109
    {
3110
        unlink $link_path;          # Delete the link
3111
        rmdir $link_dir;            # Delete only if empty
3112
    }
3113
    else
3114
    {
261 dpurdie 3115
        Log( "Local Link . $BUILDNAME_PACKAGE/$link_file ($tag)");
3116
        mkdir $link_dir unless -d $link_dir;
371 dpurdie 3117
        FileCreate ( $link_path, "$root_path/pkg/$BUILDNAME_PACKAGE");
227 dpurdie 3118
    }
3119
}
3120
 
3121
#-------------------------------------------------------------------------------
3122
# Function        : BuildSandboxData
3123
#
3124
# Description     : Create data structures to allow this package to be built
3125
#                   within a multi-package sandbox.
3126
#
3127
#                   This will allow multiple components to work together
3128
#
3129
#                   Note: When called in Clobber-mode the link will be deleted
3130
#
3131
# Inputs          : $BUILDNAME              - The package name
3132
#                   $BUILDNAME_PROJECT      - Project extension
3133
#                   $::GBE_DPKG_SBOX        - Path of sandbox_dpkg_archive
3134
#                   $::GBE_DPKG             - Main repository
3135
#
3136
# Returns         : Nothing
3137
#
3138
sub BuildSandboxData
3139
{
3140
    my $sandbox_dpkg_archive = $::GBE_DPKG_SBOX;
3141
    return unless ( $sandbox_dpkg_archive );
3142
 
3143
    unless ( -d $sandbox_dpkg_archive )
3144
    {
241 dpurdie 3145
        Error("sandbox_dpkg_archive is not a directory: $sandbox_dpkg_archive")
227 dpurdie 3146
            unless $Clobber;
3147
        return;
3148
    }
3149
 
3150
    #
3151
    #   Create a name for this package in the sandbox
3152
    #   Must use the package name and extension. Don't use the version
3153
    #   information as this will not be correct
3154
    #
3155
    #   PACKAGE/sandbox.PRJ.cfg
3156
    #
3157
    my $link_dir = "$sandbox_dpkg_archive/$BUILDNAME_PACKAGE";
359 dpurdie 3158
    my $link_file;
3159
 
3160
    if ( $sandbox_exact )
3161
    {
3162
        $link_file = "$BUILDVERSION.cfg";
3163
    }
3164
    else
3165
    {
3166
        $link_file  = 'sandbox' . ${BUILDNAME_SUFFIX} . '.cfg';
3167
    }
227 dpurdie 3168
    my $link_path = "$link_dir/$link_file";
3169
 
3170
    if ( $Clobber )
3171
    {
3172
        unlink $link_path;          # Delete the link
3173
        rmdir $link_dir;            # Delete only if empty
3174
    }
3175
    else
3176
    {
261 dpurdie 3177
        Log( "Sandbox cfg. $link_file");
227 dpurdie 3178
        unlink $link_path;
3179
        mkdir $link_dir;
3180
 
3181
        #
3182
        #   Create the sandbox config data structure
3183
        #
3184
        my %sandbox_info = (
3185
            BUILDDIR     => $Cwd,
3186
            INTERFACEDIR => $BUILDINTERFACE,
3187
            );
3188
 
3189
        #
3190
        #   Write out the Parsed Config File with new information
3191
        #
3192
        my $fh = ConfigurationFile::New( $link_path );
3193
        $fh->Header( "buildlib (version $::BuildVersion)",
3194
                                  "Sandbox configuration" );
3195
 
3196
        #
3197
        #   Dump out the configuration information
3198
        #
3199
        $fh->Dump( [\%sandbox_info], [qw(*sandbox_info)] );
3200
        $fh->Close();
3201
    }
3202
}
3203
 
3204
 
3205
#-------------------------------------------------------------------------------
3206
# Function        : BuildMake
3207
#
3208
# Description     : Generate the makefiles
3209
#                   This directive MUST be the last directive in the build.pl
3210
#                   file. The directive triggers the processing of all the
3211
#                   information that has been collected
3212
#
3213
#
3214
# Inputs          : None
3215
#
3216
# Returns         : Nothing
3217
#
3218
 
3219
sub BuildMake
3220
{
3221
    my( $argc, $platform );
3222
 
3223
    #
3224
    #   Must have a valid $BUILDINTERFACE
3225
    #   Normally this is held in the interface directory, but this is not
3226
    #   always created. If there is no $BUILDINTERFACE, then use the
3227
    #   build directory
3228
    #
3229
    $BUILDINTERFACE = "." unless ( $BUILDINTERFACE );
3230
 
3231
    #.. Starting the build phase. No more data collection
3232
    #
305 dpurdie 3233
    StartBuildPhase();
3234
    LastBuildDirective();
227 dpurdie 3235
 
5109 dpurdie 3236
    #
3237
    #   Now that the bulk of the information has been displayed
3238
    #   we can display captured messages. These warnings will be 
3239
    #   at the end of the log so that users can see them.
3240
    DumpCapture();
3241
 
227 dpurdie 3242
    sub DeleteCfg
3243
    {
3244
        #
3245
        #   Delete files that will be re-created
3246
        #   Some of these files are read and written.
3247
        #   Errors in the files are solved by deleting the files now.
3248
        #
3249
        unlink "$BUILDINTERFACE/build.cfg";
3250
        unlink "$BUILDINTERFACE/Makefile.cfg";
3251
        unlink glob ("$BUILDINTERFACE/Makefile*.cfg");
3252
        unlink "$BUILDINTERFACE/Buildfile.cfg";
3253
        unlink "$BUILDINTERFACE/Dpackage.cfg";
3254
    }
3255
 
3256
    if ( $Clobber )                             # clobber mode ?
3257
    {
4003 dpurdie 3258
        #
3259
        #   Read in toolset files - a list of files collected during
3260
        #   previous builds
3261
        #
3262
        ToolsetFile();
227 dpurdie 3263
 
4003 dpurdie 3264
        #
3265
        #   Unmake all the makefiles
3266
        #   No longer needed as we track the file that are created
3267
        #
3268
        #if ( -e "Makefile.gbe" )
3269
        #{
3270
        #    JatsTool ( 'jmake.pl', 'unmakefiles');
3271
        #}
3272
 
3273
        #
3274
        #   Delete my own configuration files
3275
        #
227 dpurdie 3276
        DeleteCfg();
3277
 
3278
        #
3279
        #   JATS creates a 'pkg' directory for the target package
3280
        #
3281
        push @CLOBBERDIRS, "pkg";
3282
 
3283
        #
3284
        #   Deployment creates a 'build/deploy' directory
375 dpurdie 3285
        #   The 'build' directory may contain user files - only remove if empty
227 dpurdie 3286
        #
3287
        push @CLOBBERDIRS, "build/deploy";
375 dpurdie 3288
        push @REMOVEDIRS, "build";
227 dpurdie 3289
 
3290
        #
3291
        #   Delete interface directories and other directories that have been
375 dpurdie 3292
        #   marked to be clobbered
227 dpurdie 3293
        #
3294
        foreach my $dir ( @CLOBBERDIRS )
3295
        {
3296
            next if ( $dir eq '.' );
3297
            next if ( $dir eq '..' );
3298
            if ( -d $dir )
3299
            {
361 dpurdie 3300
                RmDirTree ( $dir );
227 dpurdie 3301
            }
3302
        }
3303
 
375 dpurdie 3304
        foreach my $dir ( @REMOVEDIRS )
3305
        {
3306
            next if ( $dir eq '.' );
3307
            next if ( $dir eq '..' );
3308
            if ( -d $dir )
3309
            {
3310
                rmdir ( $dir ); # Only if empty
3311
            }
3312
        }
3313
 
4003 dpurdie 3314
        if ( exists $::GBE_TOOLSETFiles{Files} )
227 dpurdie 3315
        {
4007 dpurdie 3316
            foreach my $file (keys %{$::GBE_TOOLSETFiles{Files}})
227 dpurdie 3317
            {
4003 dpurdie 3318
                if ( -f $file )
3319
                {
3320
                    RmDirTree ( $file );
3321
                }
227 dpurdie 3322
            }
3323
        }
3324
 
3325
        #
3326
        #   DPACKAGE may be a user file, Only delete it if we created it
3327
        #
299 dpurdie 3328
        unlink "$Srcdir/DPACKAGE.$::GBE_MACHTYPE" if $DeleteDPACKAGE;
227 dpurdie 3329
 
3330
        BuildPackageLink();
3331
        BuildSandboxData();
3332
        return;
3333
    }
3334
 
3335
    #.. Build support files
3336
    #
3337
    DeleteCfg();
3338
    BuildConfig();
3339
    BuildSharedLibFiles();
3340
    WriteParsedBuildConfig();
3341
    BuildPackageLink();
3342
    BuildSandboxData();
4003 dpurdie 3343
    NoBuildMarker();
227 dpurdie 3344
 
3345
    #
3346
    #  ONLY (re)building interface dir
3347
    #
3348
    return
3349
        if ( $Interface );
3350
 
3351
    #---------------------------------------------------------------------------
3352
    #
3353
    #.. Make bootstrap "makefile",
3354
    #   Simulate a top level makefile
3355
    #       Pass argumenst to makelib
3356
    #       Sumulate SubDir() operations
3357
    #       Sumulate a Platform(*);
3358
    #
3359
    #       Due to the normal way that makelib.pl is executed,
3360
    #       the following substitutions are done.
3361
    #
3362
    @ARGV = ();
3363
    $0 = "makefile.pl ";
3364
    push @ARGV, "$Cwd";                         # current working directory
331 dpurdie 3365
    push @ARGV, "$::GBE_TOOLS/makelib.pl";     # makelib.pl image
227 dpurdie 3366
    push @ARGV, "--interface=$BUILDINTERFACE"
261 dpurdie 3367
        if ($BUILDINTERFACE);
227 dpurdie 3368
 
3369
    Debug( "ARGV:      @ARGV" );
3370
 
3371
    #.. (re)Build root makefile
3372
    #
3373
    $ScmBuildlib = 0;                           # clear Buildlib flag for 'makelib.pl'
3374
    RootMakefile();                             # inform 'makelib.pl'
3375
    MakeLibInit();                              # run initialisation
3376
 
3377
    #.. Register subdir(s)
3378
    #
3379
    UniquePush (\@BUILDSUBDIRS, $Srcdir );
3380
    SubDir( @BUILDSUBDIRS );
3381
    Platform( @BUILD_ACTIVEPLATFORMS );
3382
 
3383
    #.. (re)build src makefiles and associated information
367 dpurdie 3384
    #   JatsTool will not return on error
227 dpurdie 3385
    #
263 dpurdie 3386
    my @cmds = ('jmake.pl', 'rebuild');
227 dpurdie 3387
    push @cmds, 'NORECURSE=1' if ( $RootOnly );
263 dpurdie 3388
    JatsTool ( @cmds);
305 dpurdie 3389
 
3390
    #
3391
    #   Generate some warnings that will be seen at the end of the build
3392
    #
3393
    Warning ("BuildSrcArchive Directive Present","Read JATS Manual for correct usage")
3394
        if ($build_source_pkg);
227 dpurdie 3395
}
3396
 
3397
 
3398
#-------------------------------------------------------------------------------
3399
# Function        : BuildVersion
3400
#
3401
# Description     : Generate version.c and version.h files
3402
#
3403
# Inputs          : Options
3404
#                       --Prefix=prefix         Text prepended to variables created
3405
#                                               as a part of the "C" versions
3406
#                       --Type=type             Type of "C" style data
3407
#                                               Allowed types are: array
3408
#                       --Defs=name             Generate a "C" definitions file.
3409
#                                               This file simply contains definitions
3410
#                       --Defs                  Same as --Defs=defs
3411
#                       --Style=style           Output file style
3412
#                                               Supported styles:
3413
#                                                   "C" - Default
3414
#                                                   "CSharp"
3415
#                                                   "WinRC"
289 dpurdie 3416
#                                                   "Delphi"
315 dpurdie 3417
#                                                   "VB"
227 dpurdie 3418
#                       --File=name             Specifies the output file name
3419
#                                               Default is determined by the style
3420
#
3421
#                   Also allows for an 'old' style format in which
3422
#                   the first three arguments are prefix,type and defs
3423
# Returns         :
3424
#
3425
 
3426
sub BuildVersion
3427
{
3428
    my ( $Prefix, $Type, $Mode ) = @_;
3429
    my $ModePrefix;
3430
    my $Style = "C";
3431
    my $FileName;
3432
    my $VersionFiles;
267 dpurdie 3433
    my @opts;
3434
    my $supports_opts;
227 dpurdie 3435
 
3436
    StartBuildPhase();                          # Starting the build phase. No more data collection
3437
 
279 dpurdie 3438
    if ( defined($Prefix) && $Prefix =~ /^-/ )
227 dpurdie 3439
    {
3440
        $Prefix = undef;
3441
        $Type = undef;
3442
        $Mode = undef;
3443
        foreach  ( @_ )
3444
        {
3445
            if (      /^--Prefix=(.*)/ ) {
3446
                $Prefix = $1;
3447
                $VersionFiles = 1;
3448
 
3449
            } elsif ( /^--Type=(.*)/ ) {
3450
                $Type = $1;
3451
                $VersionFiles = 1;
3452
 
3453
            } elsif ( /^--Defs=(.*)/ ) {
3454
                $Mode = $1;
3455
                $ModePrefix = "_$1";
3456
 
3457
            } elsif ( /^--Defs$/ ) {
3458
                $Mode = 'defs';
3459
                $ModePrefix = "";
3460
 
3461
            } elsif ( /^--Style=(.*)/ ) {
3462
                $Style = $1;
279 dpurdie 3463
                $VersionFiles = 1;
267 dpurdie 3464
                $supports_opts = 1 if ( $Style =~ /^WinRC/i );
227 dpurdie 3465
 
3466
            } elsif ( /^--File=(.*)/ ) {
3467
                $FileName = $1;
3468
 
267 dpurdie 3469
            } elsif ($supports_opts ) {
3470
                push @opts, $_;
235 dpurdie 3471
 
227 dpurdie 3472
            } else {
3473
                Error ("BuildVersion: Unknown option: $_");
3474
 
3475
            }
3476
        }
3477
    }
3478
    else
3479
    {
3480
        #
3481
        #   Old style positional arguments.
3482
        #
3483
        $VersionFiles = 1;
3484
        if ( defined( $Mode ) )
3485
        {
3486
            if ( $Mode =~ m/^defs(=(.*))?$/i )
3487
            {
3488
                $Mode       = $2 ? $2    : 'defs';
3489
                $ModePrefix = $2 ? "_$2" : "";
3490
            }
3491
            else
3492
            {
3493
                Error ("BuildVersion: Bad Mode argument. Need 'defs' or 'defs=name'");
3494
            }
3495
        }
3496
    }
3497
 
3498
    #
3499
    #   Determine the style of version file to create
3500
    #
3501
    if ( $Style =~ /^CSharp/i ) {
3502
        BuildVersionCSharp( $FileName );
3503
 
229 dpurdie 3504
    } elsif ( $Style =~ /^Properties/i ) {
3505
        BuildVersionProperties( $FileName, $Prefix );
3506
 
227 dpurdie 3507
    } elsif ( $Style =~ /^WinRC/i ) {
267 dpurdie 3508
        BuildVersionWinRC( $FileName, @opts );
227 dpurdie 3509
 
289 dpurdie 3510
    } elsif ( $Style =~ /^Delphi/i ) {
3511
        BuildVersionDelphi( $FileName, $Prefix );
315 dpurdie 3512
 
3513
    } elsif ( $Style =~ /^VB/i ) {
3514
        BuildVersionVB( $FileName, $Prefix );
289 dpurdie 3515
 
227 dpurdie 3516
    } elsif ( $Style eq "C" ) {
289 dpurdie 3517
        BuildVersionC    ( $FileName, $Prefix, $Type )     if ( $VersionFiles );
3518
        BuildVersionCdefs( $FileName, $Mode, $ModePrefix ) if ( $Mode );
227 dpurdie 3519
 
3520
    } else {
3521
        Error("BuildVersion: Unknown style: $Style");
3522
    }
3523
}
3524
 
3525
#-------------------------------------------------------------------------------
3526
# Function        : BuildDescpkg
3527
#
3528
# Description     : Create a package description file
3529
#                   The format of this file matches that generated by JANTS
3530
#                   Take care when extending the format
3531
#
3532
#                   NOTE: It turns out that JANTS is not a standard and the
3533
#                         implementors (of JANTS) kept on changing it.
3534
#
3535
# Inputs          :
3536
#
3537
# Returns         :
3538
#
3539
sub BuildDescpkg
3540
{
4003 dpurdie 3541
    StartBuildPhase();                      # Starting the build phase. No more data collection
3542
    return if ( $Clobber );                 # clobber mode ?
227 dpurdie 3543
 
247 dpurdie 3544
    #
3545
    #   Store the files location for use at runtime
3546
    #   It will be a file that is 'known' to JATS
3547
    #
4003 dpurdie 3548
    my $pkgfile = BuildAddKnownFile ( $NoBuild ? $Cwd : $Srcdir, 'descpkg' );
227 dpurdie 3549
 
261 dpurdie 3550
    my @desc;
279 dpurdie 3551
    push @desc, "Package Name:  $BUILDNAME_PACKAGE";
3552
    push @desc, "Version:       $BUILDVERSION";
3553
    push @desc, "Released By:   $::USER";
3554
    push @desc, "Released On:   $::CurrentTime";
3555
    push @desc, "Build Machine: $::GBE_HOSTNAME";
3556
    push @desc, "Path:          $Cwd";
3557
    push @desc, "Jats Version:  $::GBE_VERSION";
3558
    push @desc, "Jats Path:     $::GBE_CORE";
261 dpurdie 3559
    push @desc, "";
3560
    push @desc, "Build Dependencies:";
3561
    push @desc, "";
227 dpurdie 3562
 
3563
    foreach my $tag ( PackageEntry::GetPackageList )
3564
    {
3565
        my ($name, $version, $type) = PackageEntry::GetPackageData($tag);
3566
 
3567
        my @attributes;
3568
 
3569
        push @attributes, "name=\"$name\"";
3570
        push @attributes, "version=\"$version\"";
3571
        push @attributes, "build=\"true\"" if $type =~ /Build/i;
3572
 
261 dpurdie 3573
        push @desc, "<sandbox @attributes/>";
227 dpurdie 3574
    }
247 dpurdie 3575
 
261 dpurdie 3576
    FileCreate ($pkgfile, \@desc );
227 dpurdie 3577
}
3578
 
3579
#-------------------------------------------------------------------------------
4003 dpurdie 3580
# Function        : NoBuildMarker
3581
#
3582
# Description     : Maintain the nobuild marker
3583
#                   This is file placed in the interface directory simply
3584
#                   to indicate to the 'create_dpkg' utility that this build
3585
#                   does not do anything useful.
3586
#
3587
#                   It will only be used on a build machine by the buid daemon
3588
#
3589
#                   Its not placed in the interface directory as it would be
3590
#                   harder for create_dpkg to find it.
3591
#
3592
# Inputs          : None
3593
# Globals         : $NoBuild, $Clobber
3594
#
3595
# Returns         : Nothing
3596
#
3597
sub NoBuildMarker
3598
{
3599
    return if ( $Clobber );
3600
 
3601
    # Always delete the file - in case we toggle build forms
3602
    #
5986 dpurdie 3603
    my $markerFile = BuildAddKnownFile( $::ScmRoot, 'noBuild.gbe');
4003 dpurdie 3604
    unlink($markerFile);
3605
 
3606
    TouchFile($markerFile)
3607
        if ($NoBuild);
3608
}
3609
 
3610
#-------------------------------------------------------------------------------
227 dpurdie 3611
# Function        : BuildIncpkg
3612
#
3613
# Description     : Create a package inclusion file
3614
#
3615
# Inputs          :
3616
#
3617
# Returns         :
3618
#
3619
sub BuildIncpkg
3620
{
3621
    StartBuildPhase();                          # Starting the build phase. No more data collection
3622
    if ( $Clobber )                             # clobber mode ?
3623
    {
361 dpurdie 3624
        RmDirTree( "$Srcdir/incpkg" );
227 dpurdie 3625
        return;
3626
    }
3627
 
3628
    my $fh = ConfigurationFile::New( "$Srcdir/incpkg" );
3629
    $fh->Header( "buildlib (Version $BuildVersion)",
3630
                              "Package inclusion list" );
3631
 
3632
    foreach my $tag ( PackageEntry::GetPackageList )
3633
    {
3634
        my ($name, $version, $type) = PackageEntry::GetPackageData($tag);
3635
        $type = ($type =~ /build/i) ? "Build" : "Link";
3636
 
3637
        $fh->Write( "${type}PkgArchive( '$name', '$version' );\n" );
3638
    }
3639
 
3640
    $fh->Close();
3641
}
3642
 
3643
#-------------------------------------------------------------------------------
3644
# Function        : BuildConfig
3645
#
3646
# Description     : Create the file interface/build.cfg
3647
#                   This file contains information gathered by the build process
3648
#                   that is to be used when makefiles are created and re-created
3649
#
3650
# Inputs          : None
3651
#
3652
# Returns         : Nothing
3653
#
283 dpurdie 3654
sub BuildConfig
227 dpurdie 3655
{
3656
    Error( "No BuildInterface directive encountered\n" )
3657
        unless ($BUILDINTERFACE);
3658
 
3659
    my $fh = ConfigurationFile::New( "$BUILDINTERFACE/build.cfg");
3660
    $fh->Header( "buildlib (Version $BuildVersion)",
3661
                              "Makelib configuration file", "
3662
\$ScmBuildMachType              = \"$::GBE_MACHTYPE\";
3663
\$ScmInterfaceVersion           = \"$::InterfaceVersion\";
3664
\$ScmBuildName                  = \"$BUILDNAME\";
3665
\$ScmBuildPackage               = \"$BUILDNAME_PACKAGE\";
3666
\$ScmBuildVersion               = \"$BUILDNAME_VERSION\";
3667
\$ScmBuildProject               = \"$BUILDNAME_PROJECT\";
3668
\$ScmBuildVersionFull           = \"$BUILDVERSION\";
3669
\$ScmBuildPreviousVersion       = \"$BUILDPREVIOUSVERSION\";
3670
\$ScmLocal                      = \"$BUILDLOCAL\";
3671
\$ScmDeploymentPatch            = \"$DEPLOY_PATCH\";
3672
\$ScmSrcDir                     = \"$Srcdir\";
3673
\$ScmBuildSrc                   = \"$ScmBuildSrc\";
3674
\$ScmExpert                     = \"$Expert\";
261 dpurdie 3675
\$ScmAll                        = \"$All\";
4003 dpurdie 3676
\$ScmNoBuild                    = \"$NoBuild\";
227 dpurdie 3677
");
3678
 
3679
#.. Alias
3680
#
3681
    $fh->DumpData(
3682
        "\n# Aliases.\n#\n",
3683
        "ScmBuildAliases", \%BUILDALIAS );
3684
 
3685
#.. Products
3686
#
3687
    $fh->DumpData(
3688
        "# Product mapping.\n#\n",
3689
        "ScmBuildProducts", \%BUILDPRODUCT_PARTS );
3690
 
3691
#.. Create ScmBuildPlatforms
3692
#
3693
    my( @platforms_merged, %platform_args ) = ();
3694
 
3695
    UniquePush ( \@platforms_merged, @BUILDPLATFORMS );
3696
 
3697
    foreach my $key ( keys %BUILDPRODUCT ) {
3698
        my( @list ) = split( ' ', $BUILDALIAS{ $key } || '' );
3699
        my( $platform );
3700
 
3701
        foreach my $elem ( @list ) {
3702
            if ( $elem =~ /^--/ ) {             # argument
3703
                HashJoin( \%platform_args, $;, $platform, $elem )
3704
                    if ( defined($platform) );
3705
                next;
3706
            }
3707
            $platform = $elem;                  # platform
3708
            UniquePush( \@platforms_merged, $elem );
3709
        }
3710
    }
3711
 
3712
#.. Create ScmBuildPlatforms
3713
#   Contains per platform options extracted from alias and platform args
3714
#
3715
    my %ScmBuildPlatforms;
3716
    foreach my $key ( @platforms_merged ) {
3717
 
3718
        my( @arguments ) = ();
3719
        UniquePush( \@arguments, split( /$;/, $BUILDPLATFORMARGS{ $key } ))
3720
            if ( exists $BUILDPLATFORMARGS{ $key } );
3721
 
3722
        UniquePush( \@arguments, split( /$;/, $platform_args{ $key } ))
3723
            if ( exists $platform_args{ $key } );
3724
 
3725
        $ScmBuildPlatforms{$key} = join "$;", @arguments;
3726
    }
3727
 
3728
    $fh->DumpData(
3729
        "# Platform and global argument list.\n#\n",
3730
        "ScmBuildPlatforms", \%ScmBuildPlatforms );
3731
 
3732
 
3733
# .. Create BuildPkgRules
3734
#
367 dpurdie 3735
#    This is most of the information contained within %PKGRULES, which
227 dpurdie 3736
#    requires additional processing within makelib.
3737
#
367 dpurdie 3738
#   Need the True Path for windows.
3739
#       Some makefile functions (wildcard) only work as expected
3740
#       if the case of the pathname is correct. Really only a problem
3741
#       with badly formed legecy packages where the Windows user
3742
#       guessed at the package format.
3743
#
227 dpurdie 3744
    my %ScmBuildPkgRules;
3745
    foreach my $platform ( keys %PKGRULES )
3746
    {
3747
        foreach my $package ( @{$PKGRULES{$platform}} )
3748
        {
3749
            my %entry;
3750
 
367 dpurdie 3751
            $entry{ROOT}     = TruePath( $package->{'base'} );
227 dpurdie 3752
            $entry{NAME}     = $package->{'name'};
3753
            $entry{VERSION}  = $package->{'version'};
3754
            $entry{DNAME}    = $package->{'dname'};
3755
            $entry{DVERSION} = $package->{'dversion'};
3756
            $entry{DPROJ}    = $package->{'dproj'};
3757
            $entry{TYPE}     = $package->{'type'};
3758
            $entry{CFGDIR}   = $package->{'cfgdir'} if ( defined( $package->{'cfgdir'} ) );
3759
 
367 dpurdie 3760
            foreach my $dir (qw (TOOLDIRS) )
227 dpurdie 3761
            {
3762
                $entry{$dir} = $package->{$dir} ;
3763
            }
3764
 
367 dpurdie 3765
            my $baselen = length($package->{'base'});
3766
            foreach my $dir (qw (PINCDIRS PLIBDIRS THXDIRS) )
3767
            {
3768
                $entry{$dir} = [];
3769
                foreach my $file ( @{$package->{$dir}} )
3770
                {
3771
                    push @{$entry{$dir}}, substr TruePath($package->{'base'} . $file ), $baselen;
3772
                }
3773
            }
3774
 
227 dpurdie 3775
            push @{$ScmBuildPkgRules{$platform}}, \%entry;
3776
        }
3777
    }
3778
 
3779
    $fh->DumpData(
3780
        "# Imported packages.\n#\n",
3781
        "ScmBuildPkgRules", \%ScmBuildPkgRules );
3782
 
3783
#
3784
#   BUILDPLATFORMS,
3785
#       The value that is saved only contains the active platforms
3786
#
3787
#   DEFBUILDPLATFORMS,
3788
#       The value that is matchs the wildcard specification for Platform 
3789
#       directives.
3790
#
3791
    $fh->DumpData(
3792
        "# A list of platforms active within the view.\n#\n",
3793
        "BUILDPLATFORMS", \@BUILD_ACTIVEPLATFORMS );
3794
 
3795
    $fh->DumpData(
3796
        "# A list of default platforms within the view.\n#\n",
3797
        "DEFBUILDPLATFORMS", \@DEFBUILDPLATFORMS );
3798
 
3799
#
3800
#   BUILDTOOLS
3801
#       A list of toolset extension paths
3802
#
3803
    $fh->DumpData(
3804
        "# A list of paths with toolset extension programs.\n#\n",
3805
        "BUILDTOOLSPATH", \@BUILDTOOLS );
3806
 
3807
#
3808
#   BUILDPLATFORM_PARTS
3809
#       A subset of BUILDINFO exported as BUILDPLATFORM_PARTS
3810
#       This exists only for backward compatability with existing code
3811
#       in external packages ( deployfiles).
3812
#
3813
#   Only save those parts that are part of the current build
3814
#   This will prevent users attempting to build for platforms that have not
3815
#   been correctly constructed.
3816
#
3817
    my %active =  map { ${_} => 1 } @BUILD_ACTIVEPLATFORMS;
3818
    my %active_buildplatform_parts;
3819
    my %active_build_info;
3820
    foreach ( keys %BUILDINFO )
3821
    {
3822
        next unless ( $active{$_} );
3823
        $active_buildplatform_parts{$_} = $BUILDINFO{$_}{PARTS};
3824
        $active_build_info{$_}          = $BUILDINFO{$_};
3825
    }
3826
 
3827
    $fh->DumpData(
3828
        "# Parts of all platforms.\n#\n",
3829
        "BUILDPLATFORM_PARTS", \%active_buildplatform_parts );
3830
#
3831
#   BUILDINFO
3832
#       Complete TARGET Information
3833
#
3834
    $fh->DumpData(
3835
        "# Extended build information.\n#\n",
3836
        "BUILDINFO", \%active_build_info );
3837
 
3838
#
247 dpurdie 3839
#   BUILD_KNOWNFILES
3840
#       All paths are relative to the project root directory
3841
#       ie: The directory that conatins the build.pl file
3842
#
3843
    $fh->DumpData(
3844
        "# Generated Files that may be known when used as Src files.\n#\n",
3845
        "BUILD_KNOWNFILES", \%BUILD_KNOWNFILES );
3846
 
3847
#
227 dpurdie 3848
#   Close out the file
3849
#
3850
    $fh->Close();
363 dpurdie 3851
 
227 dpurdie 3852
}
3853
 
3854
#-------------------------------------------------------------------------------
3855
# Function        : WriteParsedBuildConfig
3856
#
3857
# Description     : Write all the parsed build.pl data to a single file
3858
#                   Its all in there for use
3859
#
3860
# Inputs          : 
3861
#
3862
# Returns         : 
3863
#
3864
sub WriteParsedBuildConfig
3865
{
3866
    my $cfg_file = "$::BUILDINTERFACE/Buildfile.cfg";
3867
    my %cf_build_info = ();
3868
 
3869
    #
3870
    #   Examine the symbol table and capture most of the entries
3871
    #
3872
    foreach my $symname (keys %main::)
3873
    {
3874
        next if ( $symname =~ m/::/  );                 # No Typeglobs
3875
        next if ( $symname =~ m/^cf_build_info/  );     # Not myself
3876
        next unless ( $symname =~ m/^[A-Za-z]/  );      # No system type names
3877
        next if ( $symname =~ m/^SIG$/  );              # Useless
3878
        next if ( $symname =~ m/^ENV$/  );              # Don't keep the user ENV
3879
        next if ( $symname =~ m/^INC$/  );              # Don't keep the INC paths
3880
        next if ( $symname =~ m/^DEFINES/  );           # Don't keep
3881
        next if ( $symname =~ m/^TOOLSETRULES/  );      # Don't keep
3882
 
331 dpurdie 3883
        no strict 'vars';
227 dpurdie 3884
        local *sym = $main::{$symname};
3885
 
331 dpurdie 3886
        $cf_build_info{"\$$symname"} =  $sym if defined $sym;
369 dpurdie 3887
        $cf_build_info{"\@$symname"} = \@sym if @sym;
3888
        $cf_build_info{"\%$symname"} = \%sym if %sym;
331 dpurdie 3889
        use strict 'vars';
227 dpurdie 3890
    }
3891
 
3892
    #
3893
    #   Dump out the configuration information
3894
    #
3895
    my $fh = ConfigurationFile::New( "$cfg_file" );
3896
    $fh->Header( "buildlib (version $::BuildVersion)",
3897
                              "Buildfile configuration" );
3898
    $fh->Dump( [\%cf_build_info], [qw(*cf_build_info)] );
3899
    $fh->Close();
3900
}
3901
 
3902
 
3903
#-------------------------------------------------------------------------------
3904
# Function        : BuildSharedLibFiles
3905
#
3906
# Description     : Create a file in the interface directory that will specify
3907
#                   the locations of shared libraries.
3908
#
3909
#                   Note: Always create a file as makefile targets depend on it.
3910
#
3911
#                   This is a bit ugly.
3912
#
3913
#                   There needs be an association between the build machine and
3914
#                   the target platform. Need to know if the current target is
3915
#                   native to the current build machine. If it is then we can
3916
#                   run tests on the machine and we then need to extend the
3917
#                   search path for the target.
3918
#
3919
#                   The BUILDINFO{EXT_SHARED} is used to control the creation of
3920
#                   the files by specifying the extension of the file.
3921
#
3922
# Inputs          : None
3923
#
3924
# Returns         :
3925
#
3926
sub BuildSharedLibFiles
3927
{
3928
    if ( $ScmHost eq "DOS" || $ScmHost eq "WIN" ) {
3929
        BuildSharedLibFiles_WIN(@_);
3930
 
3931
    } elsif ( $ScmHost eq "Unix" ) {
3932
        BuildSharedLibFiles_Unix(@_);
3933
 
3934
    } else {
3935
        Error("Cannot build. Unknown machine type: $ScmHost",
3936
              "Need WIN, DOS or Unix" );
3937
    }
3938
}
3939
 
3940
#-------------------------------------------------------------------------------
3941
# Function        : BuildSharedLibFiles_WIN
3942
#
3943
# Description     : Implementation of BuildSharedLibFiles for Windows
3944
#
3945
# Inputs          : None
3946
#
3947
sub BuildSharedLibFiles_WIN
3948
{
3949
 
3950
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
3951
    {
3952
        next unless ( exists $BUILDINFO{$platform}{EXT_SHARED} );
3953
        my @dos_paths = BuildSharedLibFiles_list( $platform, $BUILDINFO{$platform}{EXT_SHARED} );
3954
 
3955
        #
3956
        #   Create a .bat file for WIN32
3957
        #   This may be consumed by user wrapper programs
3958
        #
229 dpurdie 3959
        #   Features: No Echo
3960
        #             Use of SETLOCAL to prevent pollution of environment
3961
        #
227 dpurdie 3962
        my $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/set_$platform.bat", '--NoEof', '--Type=bat' );
229 dpurdie 3963
        $fh->Write ( "\@echo off\n");
227 dpurdie 3964
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
229 dpurdie 3965
        $fh->Write ( "\nSETLOCAL\n");
227 dpurdie 3966
        foreach ( reverse @dos_paths )
3967
        {
3968
            $_ =~ s~/~\\~g;
3969
            $fh->Write ( "PATH=$_;\%PATH\%\n" );
3970
        }
3971
        $fh->Write ( "\n%*\n" );
229 dpurdie 3972
        $fh->Write ( "\nENDLOCAL\n");
231 dpurdie 3973
        $fh->Write ( "EXIT /B %ERRORLEVEL%\n");
227 dpurdie 3974
        $fh->Close();
3975
 
3976
        #
3977
        #   Create a .sh file for WIN32
3978
        #   This may be consumed by a shell - as used within JATS
3979
        #
3980
        $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/set_$platform.sh", '--NoEof', '--Type=sh' );
3981
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
3982
        foreach ( reverse @dos_paths )
3983
        {
3984
            tr~\\/~/~s;
3985
            $fh->Write ( "PATH=$_\\;\$PATH\n" );
3986
        }
287 dpurdie 3987
        $fh->Write ( "\n" . '[ -n "$*" ] && "$@"'  ."\n" );
227 dpurdie 3988
        $fh->Close();
3989
    }
3990
}
3991
 
3992
#-------------------------------------------------------------------------------
3993
# Function        : BuildSharedLibFiles_Unix
3994
#
3995
# Description     : Implementation of BuildSharedLibFiles for Unix
3996
#                   Extend the Shared Library search path via LD_LIBRARY_PATH
5877 dpurdie 3997
#                   
3998
#                   Create sonames for all external shared libraries
227 dpurdie 3999
#
4000
# Inputs          : None
4001
#
4002
sub BuildSharedLibFiles_Unix
4003
{
4004
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
4005
    {
4006
        next unless ( exists $BUILDINFO{$platform}{EXT_SHARED} );
4007
        my @unix_paths = BuildSharedLibFiles_list( $platform, $BUILDINFO{$platform}{EXT_SHARED} );
4008
 
4009
        #
5877 dpurdie 4010
        #   Create sonames for all shared libraries
4011
        #   Append to the begging of the search list - so that it will rendered last
4012
        #   
4013
        my $sodir = BuildSoNameLinks_Unix($platform, @unix_paths);
4014
        unshift( @unix_paths, $sodir ) if defined $sodir;
4015
 
4016
        #
227 dpurdie 4017
        #   Create a .sh file for Unix
4018
        #
229 dpurdie 4019
        my $file = "$BUILDINTERFACE/set_$platform.sh";
4020
        my $fh = ::ConfigurationFile::New( $file , '--NoEof', '--Type=sh' );
227 dpurdie 4021
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
4022
        foreach ( reverse @unix_paths )
4023
        {
4024
            $fh->Write ( "export LD_LIBRARY_PATH=$_:\$LD_LIBRARY_PATH\n" );
4025
        }
275 dpurdie 4026
        $fh->Write ( "\n\"\$\@\"\n" );
227 dpurdie 4027
        $fh->Close();
229 dpurdie 4028
 
4029
        #
4030
        #   Make the file executable under unix
4031
        #
4032
        chmod 0755, $file;
227 dpurdie 4033
    }
4034
}
4035
 
4036
#-------------------------------------------------------------------------------
5877 dpurdie 4037
# Function        : BuildSoNameLinks_Unix 
4038
#
4039
# Description     : Generate soname links for all shared libraries from external
4040
#                   packages.
4041
#                   
4042
#                   There is a bit of a cheat. We don't examine the library to determine
4043
#                   the soname. We simple create all possible sonames to the library
4044
#
4045
# Inputs          : $platform       - Target platform
4046
#                   @paths          - Array of paths to scan for libraries 
4047
#
4048
# Returns         : soLinkDir       - Absolute path to the directory of gernerated
4049
#                                     symlinks
4050
#
4051
sub BuildSoNameLinks_Unix
4052
{
4053
    my ($platform, @paths) = @_;
4054
    my $soLinkDir = catdir($BUILDINTERFACE, 'soLinks', $platform );
4055
 
4056
    Verbose("Create Unix SoName links - $soLinkDir");
4057
    RmDirTree( $soLinkDir );
4058
 
4059
    #
4060
    #   Search provided library paths for shared libaries
4061
    #       These are names of the form *.so.* ie : libz.so.1.2.5
4062
    #
4063
    foreach my $path (@paths)
4064
    {
4065
        foreach my $file (glob(catdir($path, '*.so.*')))
4066
        {
4067
            #
4068
            #   Skip the debug symbol files
4069
            #
4070
            next if $file =~ m~\.debug$~;
4071
            next if $file =~ m~\.dbg$~;
4072
 
4073
            #
4074
            #   Generate all possible sonames by removing .nnnn from the 
4075
            #   end of the file name
4076
            #   
4077
            my $sofile = $file;
4078
            while ($sofile =~ m~(.*)\.\d+$~)
4079
            {
4080
                $sofile = $1;
4081
                unless (-f $sofile) {
4082
                    Verbose2("Need Soname: $sofile");
4083
 
4084
                    #
4085
                    #   Create link from soname to full name
4086
                    #   
4087
                    mkpath ( $soLinkDir ) unless -d $soLinkDir;
4088
                    my $sofilename = $sofile;
4089
                    $sofilename =~ s~.*/~~;
4090
                    $sofilename = catdir($soLinkDir, $sofilename);
4091
                    unless (-f $sofilename) {
4092
                        symlink ($file, $sofilename) || Error ("Cannot create symlink to $sofilename. $!"); 
4093
                    }
4094
                }
4095
            }
4096
        }
4097
    }
4098
 
4099
    #
4100
    #   Return the path the generated soLink dir
4101
    #
4102
    return AbsPath($soLinkDir) if (-d $soLinkDir);
4103
    return undef;
4104
}
4105
 
4106
#-------------------------------------------------------------------------------
227 dpurdie 4107
# Function        : BuildSharedLibFiles_list
4108
#
4109
# Description     : Determine a list of Shared Library paths that can be used
4110
#                   by the current target
4111
#
4112
# Inputs          : $platform       - Current platform
4113
#                   $so             - Shared object extensions
4114
#
4115
# Returns         : List of search paths
4116
#
4117
sub BuildSharedLibFiles_list
4118
{
4119
    my ($platform, $so ) = @_;
4120
    my @paths;
4121
    my @parts = @{$BUILDINFO{$platform}{PARTS}};
4122
 
4123
    #
4124
    #   Paths from the current build
4125
    #       Local directory         - for installed components
4126
    #       Interface directory     - for BuildPkgArchives
4127
    #
4128
    if ( $BUILDLOCAL )
4129
    {
5986 dpurdie 4130
        my @localParts;
4131
        UniquePush \@localParts, $BUILDINFO{$platform}{PLATFORM} , $BUILDINFO{$platform}{PRODUCT}, $BUILDINFO{$platform}{TARGET};
4132
        foreach ( @localParts )
227 dpurdie 4133
        {
4134
            push @paths, AbsPath("$BUILDLOCAL/lib/$_");
4135
        }
4136
    }
4137
 
4138
    foreach ( @parts )
4139
    {
4140
            push @paths, AbsPath("$BUILDINTERFACE/lib/$_");
4141
    }
4142
 
4143
    #
4144
    #   For each LinkPkgArchive
4145
    #
4146
    foreach my $package ( @{$PKGRULES{$platform}} )
4147
    {
4148
        next unless ( $package->{'type'} eq 'link' );
4149
 
4150
        my $base = $package->{'base'};
4151
        for my $path ( @{$package->{'PLIBDIRS'}} )
4152
        {
289 dpurdie 4153
            my @so_libs;
317 dpurdie 4154
            push @so_libs, glob ( "$base$path/*$_") foreach ( ArrayList($so) );
227 dpurdie 4155
            next unless scalar @so_libs;
4156
            push @paths, $base . $path;;
4157
        }
4158
    }
4159
 
4160
    #
4161
    #   Returns paths found
4162
    #
4163
    return @paths;
4164
}
4165
 
4166
#-------------------------------------------------------------------------------
247 dpurdie 4167
# Function        : BuildAddKnownFile
4168
#
4169
# Description     : Save the file as a file that will be known  to the JATS
4170
#                   makefiles. It will be available SRCS, but will not be a
4171
#                   part of any object list.
4172
#
4173
#                   Known Files will be deleted on clobber
4174
#
4175
# Inputs          : $path
4176
#                   $file
289 dpurdie 4177
#                   $noadd                    - Don't add to known
247 dpurdie 4178
#
4179
# Returns         : Path and filename
4180
#
4181
 
4182
sub BuildAddKnownFile
4183
{
289 dpurdie 4184
    my ($path, $file, $noadd) = @_;
247 dpurdie 4185
    $path .= '/'. $file;
2450 dpurdie 4186
    $path =~ tr~/~/~s;
289 dpurdie 4187
    $BUILD_KNOWNFILES {$file} = $path
4188
        unless ( defined($noadd) && $noadd);
4003 dpurdie 4189
 
3967 dpurdie 4190
    ToolsetFile( $path )
4191
        unless ($Clobber);
4192
 
247 dpurdie 4193
    return $path;
4194
}
4195
 
4196
#-------------------------------------------------------------------------------
5969 dpurdie 4197
# Function        : WinPath 
4198
#
4199
# Description     : Covert path to a windows formatted path
4200
#
4201
# Inputs          : One path element
4202
#
4203
# Returns         : One ugly path element
4204
#
4205
 
4206
sub WinFullPath
4207
{
4208
    my ($path) = @_;
4209
    $path = FullPath($path);
4210
    $path =~ tr~\\/~\\~s;
4211
    return $path;
4212
}
4213
 
4214
#-------------------------------------------------------------------------------
4215
# Function        : BuildPropertyPages 
4216
#
4217
# Description     : Create a props file suitable for use by VS2010, VS2012 (possibly others)
4218
#                   Only supported for C/C++ projects
4219
#                   Provide info for:
4220
#                       Include Search paths
4221
#                       Library search paths
4222
#                       Nice Macros 
4223
#
4224
# Inputs          : 
4225
#
4226
# Returns         : 
4227
#
4228
sub BuildPropertyPages
4229
{
4230
    StartBuildPhase();                      # Starting the build phase. No more data collection
5986 dpurdie 4231
    return if $Clobber;
5969 dpurdie 4232
    foreach my $platform ( keys %BUILDINFO )
4233
    {
4234
        next unless $BUILDINFO{$platform}{MSBUILDPROPS};
5986 dpurdie 4235
        my $propsFile = BuildAddKnownFile ($Srcdir, 'jats_'. $BUILDINFO{$platform}{TARGET} . '.props');
4236
 
5969 dpurdie 4237
        Message("BuildPropertyPages: $propsFile");
4238
 
4239
        my %macros;
4240
        my @libpaths;
4241
        my @incpaths;
4242
        my @parts = @{$BUILDINFO{$platform}{PARTS}};
4243
 
4244
        #
4245
        #   Basic definitions
4246
        #   
4247
        $macros{'GBE_ROOT'}     = WinFullPath(".");
4248
        $macros{'GBE_PLATFORM'} = $BUILDINFO{$platform}{PLATFORM};
4249
        $macros{'GBE_PRODUCT'}  = $BUILDINFO{$platform}{PRODUCT};
4250
        $macros{'GBE_TARGET'}   = $BUILDINFO{$platform}{TARGET};
4251
        $macros{'GBE_MACHTYPE'} = $::GBE_MACHTYPE;
4252
        $macros{'GBE_PKGDIR'}   = WinFullPath('./pkg/' . $BUILDNAME_PACKAGE);
4253
        $macros{'GBE_BUILDNAME'}= $BUILDNAME_PACKAGE;
4254
 
4255
        #
4256
        #   Paths from the current build
4257
        #       Local directory         - for installed components
4258
        #       Interface directory     - for BuildPkgArchives
4259
        #
4260
        if ( $BUILDLOCAL )
4261
        {
4262
            my $macroName = 'GBE_LOCALDIR';
4263
            $macros{$macroName} = WinFullPath("$BUILDLOCAL") ;
4264
            $macroName = '$(' . $macroName . ')';
5986 dpurdie 4265
            my @localParts;
4266
            UniquePush \@localParts, $BUILDINFO{$platform}{PLATFORM} , $BUILDINFO{$platform}{PRODUCT}, $BUILDINFO{$platform}{TARGET};
4267
            foreach ( @localParts )
5969 dpurdie 4268
            {
4269
                push @libpaths, catdir($macroName, 'lib', $_);
4270
                push @incpaths, catdir($macroName ,'include' ,$_);
4271
            }
4272
            push @incpaths, catdir($macroName ,'include');
4273
        }
4274
 
4275
        my $macroName = 'GBE_INTERFACEDIR';
4276
        $macros{$macroName} = WinFullPath("$BUILDINTERFACE") ;
4277
        $macroName = '$(' . $macroName . ')';
4278
 
4279
        foreach ( @parts )
4280
        {
4281
                push @libpaths, catdir($macroName, 'lib' , $_);
4282
                push @incpaths, catdir($macroName ,'include' ,$_);
4283
        }
4284
        push @incpaths, catdir($macroName ,'include');
4285
 
4286
        #
4287
        #   For each LinkPkgArchive
4288
        #
4289
        foreach my $package ( @{$PKGRULES{$platform}} )
4290
        {
4291
            next unless ( $package->{'type'} eq 'link' );
4292
 
4293
            my $macroName = 'GBE_PACKAGE_'.$package->{'name'};
4294
            $macros{$macroName} = WinFullPath($package->{'base'}) ;
4295
            $macroName = '$(' . $macroName . ')';
4296
 
4297
            for my $path ( @{$package->{'PLIBDIRS'}} )
4298
            {
4299
                push @libpaths, catdir($macroName, $path);
4300
            }
4301
            for my $path ( @{$package->{'PINCDIRS'}} )
4302
            {
4303
                push @incpaths, catdir($macroName, $path);
4304
            }
4305
        }
4306
 
4307
        my $AdditionalIncludeDirectories = join(';', @incpaths );
4308
        my $AdditionalLibraryDirectories = join(';', @libpaths);
4309
        my $PreprocessorDefinitions = 'JATS=1';
4310
 
4311
        #
4312
        #   Create a props file formatted for VS2012
4313
        #
4314
        open (my $XML, '>', $propsFile) || Error ("Cannot create output file: $propsFile", $!);
4315
 
4316
        my $writer = XML::Writer->new(OUTPUT => $XML, UNSAFE => 0, DATA_INDENT => 4, DATA_MODE => 1);
4317
        $writer->xmlDecl("UTF-8");
4318
        $writer->comment('This file is generated by JATS build');
4319
        $writer->comment('Do not edit this file');
4320
        $writer->comment('Do not version control this file');
4321
        $writer->startTag('Project', "ToolsVersion", "4.0", "xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
4322
        $writer->emptyTag('ImportGroup', 'Label' , "PropertySheets");
4323
 
4324
        #
4325
        #   Special Macro for handling production/debug libraries
4326
        #
4327
        $writer->startTag('PropertyGroup', 'Label' , "UserMacros", 'Condition', "'\$(Configuration)' == 'Debug'");
4328
        $writer->dataElement('GBE_TYPE', 'D');
4329
        $writer->endTag('PropertyGroup');
4330
 
4331
        $writer->startTag('PropertyGroup', 'Label' , "UserMacros", 'Condition', "'\$(Configuration)' != 'Debug'");
4332
        $writer->dataElement('GBE_TYPE', 'P');
4333
        $writer->endTag('PropertyGroup');
4334
 
4335
        #
4336
        #   Define macros
4337
        #   
4338
        $writer->startTag('PropertyGroup', 'Label' , "UserMacros");
4339
        foreach my $key ( sort keys %macros)
4340
        {
4341
            $writer->dataElement($key, $macros{$key});
4342
        }
4343
        $writer->endTag('PropertyGroup');
4344
        $macros{'GBE_TYPE'}     = 1;
4345
 
4346
        #
4347
        #   Extend the search paths for includes and libaraies
4348
        #   
4349
        #$writer->emptyTag('ItemDefinitionGroup');
4350
        $writer->startTag('ItemDefinitionGroup');
4351
 
4352
        $writer->startTag('ClCompile');
4353
        $writer->dataElement('AdditionalIncludeDirectories', $AdditionalIncludeDirectories . ';%(AdditionalIncludeDirectories)');
4354
        $writer->dataElement('PreprocessorDefinitions', $PreprocessorDefinitions . ';%(PreprocessorDefinitions)');
4355
        $writer->endTag('ClCompile');
4356
 
4357
        $writer->startTag('Link');
4358
        $writer->dataElement('AdditionalLibraryDirectories', $AdditionalLibraryDirectories . ';%(AdditionalLibraryDirectories)');
4359
        $writer->endTag('Link');
4360
        $writer->endTag('ItemDefinitionGroup');
4361
 
4362
        #
4363
        #   Specify all macro names
4364
        #
4365
        $writer->startTag('ItemGroup');
4366
        foreach my $key ( sort keys %macros)
4367
        {
4368
            $writer->startTag('BuildMacro', 'Include' , $key);
4369
            $writer->dataElement('Value', '$(' . $key . ')');
4370
            $writer->endTag('BuildMacro');
4371
        }
4372
 
4373
        #
4374
        #   Close tags and write the XML file
4375
        #
4376
        $writer->endTag('ItemGroup');
4377
        $writer->endTag('Project');
4378
        $writer->end();
4379
    }
4380
}
4381
 
4382
 
4383
#-------------------------------------------------------------------------------
227 dpurdie 4384
# Function        : Usage
4385
#
4386
# Description     : Display program usage information
4387
#
4388
# Inputs          : args            - Text message to display
4389
#
4390
#                   $opt_help       - Level of verbose ness
4391
#
4392
# Returns         : Does not return
4393
#                   This function will exit
4394
#
4395
sub Usage
4396
{
4397
    my( $msg ) = @_;
4398
    my %usage_args;
4399
 
4400
    #
4401
    #   Create a hash of arguments for the pod2usage function
4402
    #
4403
    $usage_args{'-input'} = __FILE__;
4404
    $usage_args{'-exitval'} = 42;
4405
    $usage_args{'-message'} = "\nbuildlib $msg\n" if $msg;
4406
    $usage_args{'-verbose'} = $opt_help < 3 ? $opt_help - 1 : 3 if ( $opt_help );
4407
 
4408
    #
4409
    #   Generate nice help
4410
    #
4411
    pod2usage(\%usage_args);
4412
}
4413
 
4414
#-------------------------------------------------------------------------------
4415
#   Documentation
4416
#
4417
 
4418
=pod
4419
 
361 dpurdie 4420
=for htmltoc    JATS::build
4421
 
227 dpurdie 4422
=head1 NAME
4423
 
361 dpurdie 4424
build - Build Environment and Makefiles
227 dpurdie 4425
 
4426
=head1 SYNOPSIS
4427
 
4428
jats build [options] [command]
4429
 
4430
     [perl buildlib.pl [options] PWD [command]]
4431
 
4432
 Options:
331 dpurdie 4433
    -help          - Display terse usage
361 dpurdie 4434
    -help -help    - Display verbose usage
331 dpurdie 4435
    -man           - Display internal manual
4436
    -verbose[=n]   - Set level of progress verbosity
4437
    -debug[=n]     - Set the debug level
4438
    -nolog         - Do not generate/update Changelog
4439
    -cache         - Cache packages in the local dpkg_package cache
361 dpurdie 4440
    -cache -cache  - Forced refresh dependent packages in the local cache
331 dpurdie 4441
    -package       - Ignore packages that are not available and continue
2078 dpurdie 4442
    -nopackages    - Ignore package processing directives
331 dpurdie 4443
    -forcebuildpkg - Treat LinkPkgArchive directives as BuildPkgArchive
361 dpurdie 4444
                     Also suppress the use of symlinks so that the physical
4445
                     file will be copied locally.
331 dpurdie 4446
    -[no]force     - Force build even if build.pl is not newer
363 dpurdie 4447
                     Default: -force
4778 dpurdie 4448
    -[no]generic   - Build system sanity test
4449
                     Default: Do not test
227 dpurdie 4450
 
4451
 Sticky settings:
331 dpurdie 4452
    -all           - Build for all platforms ignoring GBE_BUILDFILTER
4453
    -expert[=n]    - Relaxing dependency checks on the user makefiles
227 dpurdie 4454
 
4455
 Commands:
361 dpurdie 4456
    changelog      - Only update ChangeLog.
2078 dpurdie 4457
    clobber        - Remove generated build system (eg Makefiles).
361 dpurdie 4458
    interface      - Only (re)build the interface tree, including ChangeLog.
4459
    rootonly       - Only (re)build the root directory.
227 dpurdie 4460
 
4461
=head1 OPTIONS
4462
 
4463
=over 8
4464
 
331 dpurdie 4465
=item B<-help>
227 dpurdie 4466
 
4467
Print a brief help message and exits.
4468
 
4469
=item B<-help -help>
4470
 
4471
Print a detailed help message with an explanation for each option.
4472
 
4473
=item B<-man>
4474
 
4475
Prints the manual page and exits.
4476
 
331 dpurdie 4477
=item B<-verbose[=n]>
227 dpurdie 4478
 
261 dpurdie 4479
Increases program output.
227 dpurdie 4480
 
261 dpurdie 4481
If an argument is provided, then it will be used to set the level, otherwise the
4482
existing level will be incremented. This option may be specified multiple times.
227 dpurdie 4483
 
261 dpurdie 4484
=item B<-debug>
4485
 
227 dpurdie 4486
Increases program output. Enable internal debugging messages to generate detailed
4487
progress information.
4488
 
261 dpurdie 4489
If an argument is provided, then it will be used to set the level, otherwise the
4490
existing level will be incremented. This option may be specified multiple times.
4491
 
331 dpurdie 4492
=item B<-nolog>
227 dpurdie 4493
 
4494
Do not generate or update the ChangeLog maintained when a CVS directory is detected
4495
in the build directory.
4496
 
331 dpurdie 4497
=item B<-cache>
227 dpurdie 4498
 
4499
This option will cause dependent packages to be cached in the local
4500
dpkg_archive cache.
4501
 
4502
If the option is used twice then the packages will be forcibly refreshed.
4503
 
331 dpurdie 4504
=item B<-package>
227 dpurdie 4505
 
4506
This option will cause the build process to ignore packages that cannot be
4507
located. The package build may fail at a later stage.
4508
 
4509
This option is used by the Auto Build Tool to handle packages that may not be
4510
needed in all builds.
4511
 
2078 dpurdie 4512
=item B<-nopackage>
4513
 
4514
This options will cause all the directives that process external packages to be
4515
ignored.
4516
 
4517
This directive has limited use. It can be used in conjunction with the
4518
'interface' build command in order to create Version Information files in a
4519
sandbox where the required packages do not yet exist.
4520
 
331 dpurdie 4521
=item B<-forcebuildpkg>
227 dpurdie 4522
 
4523
This option will force LinkPkgArchive directives to be treated as
4524
BuildPkgArchive directives. The result is that the 'interface' directory will be
4525
populated with the contents of all dependent packages. Moreover, on a Unix
4526
machine, the files will be copied and not referenced with a soft link.
4527
 
4528
This may be useful for:
4529
 
4530
=over 8
4531
 
361 dpurdie 4532
=item *
227 dpurdie 4533
 
361 dpurdie 4534
Remote Development
227 dpurdie 4535
 
361 dpurdie 4536
=item *
227 dpurdie 4537
 
361 dpurdie 4538
Collecting header files for scanning
4539
 
4540
=item *
4541
 
4542
Local modification of files for test/debug/development
4543
 
227 dpurdie 4544
=back
4545
 
331 dpurdie 4546
=item B<-[no]force>
227 dpurdie 4547
 
331 dpurdie 4548
The '-noforce' option will only perform a build, if the build.pl file
363 dpurdie 4549
has been modified, or the buildfilter has changed, since the last build.
331 dpurdie 4550
 
363 dpurdie 4551
The default operation will always force a build.
331 dpurdie 4552
 
4778 dpurdie 4553
=item B<-[no]generic>
4554
 
4555
If used, this option will perform a sanity test on the build type. If set to 
4556
Generic then the build must be a GENERIC build. If set to noGeneric then the build
4557
must not be a GENERIC build.
4558
 
4559
The default is to not perform the test.
4560
 
4561
This option is intended to be used by the automated build system.
4562
 
331 dpurdie 4563
=item B<-all>
4564
 
227 dpurdie 4565
This option will cause the build process to generate makefiles for all
4566
possible build targets ignoring the use of GBE_BUILDFILTER.
4567
 
4568
This option is sticky. Once used in a build it will be retained when makefiles
4569
are rebuilt.
4570
 
331 dpurdie 4571
=item B<-expert[=n]>
227 dpurdie 4572
 
4573
This option causes the generation of makefiles with relaxed dependancy checks.
4574
 
261 dpurdie 4575
If an argument is provided, then it will be used to set the level, otherwise a
4576
level of '1' will be set.
4577
 
227 dpurdie 4578
The makefiles will have no dependancy between the makefiles and the JATS build
4579
files or the users makefile. If the user's makefile.pl is changed then JATS
4580
will not detect the change and will not rebuild the makefiles. The user manually
4581
force the rebuild with the command 'jats rebuild'.
4582
 
4583
This option should be used with care and with full knowledge of its impact.
4584
 
4585
This option is sticky. Once used in a build it will be retained when makefiles
363 dpurdie 4586
are rebuilt. It will only be lost when the next 'jats build' is performed.
227 dpurdie 4587
 
261 dpurdie 4588
The effect of the option can be changed when the makefiles are processed. This
4589
option simply sets the default' mode of operation.
4590
 
227 dpurdie 4591
=item B<changelog>
4592
 
4593
This command will only update the CVS change log.
4594
 
4595
=item B<interface>
4596
 
4597
This command will only build, or rebuild, the 'interface' directory and the
4598
changelog ( if required ).
4599
 
261 dpurdie 4600
This command will not build, or rebuild, the root directory. The build
227 dpurdie 4601
process will not recurse through the subdirectories creating makefiles.
4602
 
261 dpurdie 4603
=item B<rootonly>
4604
 
4605
This command will only build, or rebuild, the 'interface' directory, the
4606
changelog (if required) and the root-level makefiles.
4607
 
4608
The build process will not recurse through the subdirectories creating
4609
makefiles. These can be made on-demand by jats if a 'make' command is issued.
4610
 
227 dpurdie 4611
=item B<clobber>
4612
 
4613
This command will remove generated build system files and directories.
4614
 
4615
=back
4616
 
4617
=head1 DESCRIPTION
4618
 
4619
The default build process will parse the user's build.pl file and create the
4620
'interface' directory before creating makefiles for each target platform.
4621
 
4622
The 'build' process simply generates the build sandbox. It does not invoke the
4623
generated makefiles. This must be done by the user in a different phase.
4624
 
4625
The 'build' process need only be invoked if the build.pl file has changed. The
4626
generated makefiles will detected changes to the makefile.pl's and cause them to
4627
be generated as required. The 'build' step sets up the sandboxes external
4628
environment.
4629
 
4630
=head1 INVOCATION
4631
 
4632
This perl library (buildlib.pl) is not designed to be invoked directly by the
4633
user. It should be invoked through a 'build.pl' file. Moreover, for historical
4634
reasons, the build.pl is not easily invoked. It is best to only invoke the
4635
'build' process via the JATS wrapper scripts : jats.bat or jats.sh.
4636
 
331 dpurdie 4637
The build.pl file must be invoked with one fixed arguments, followed by user
227 dpurdie 4638
options and subcommands
4639
 
4640
=over 8
4641
 
361 dpurdie 4642
=item   1
227 dpurdie 4643
 
361 dpurdie 4644
The current working directory
4645
 
227 dpurdie 4646
This could have been derived directly by the program, rather than having it
4647
passed in.
4648
 
361 dpurdie 4649
=item   2
227 dpurdie 4650
 
361 dpurdie 4651
Options and commands may follow the first two mandatory arguments.
4652
 
227 dpurdie 4653
=back
4654
 
4655
The build.pl file must 'require' the buildlib.pl and makelib.pl. The preferred
4656
code is:
4657
 
4658
=over 8
4659
 
4660
    build.pl: First statements
4661
    $MAKELIB_PL     = "$ENV{ GBE_TOOLS }/makelib.pl";
4662
    $BUILDLIB_PL    = "$ENV{ GBE_TOOLS }/buildlib.pl";
4663
 
4664
    require         "$BUILDLIB_PL";
4665
    require         "$MAKELIB_PL";
4666
 
4667
=back
4668
 
4669
=cut
4670
 
4671
1;