Subversion Repositories DevTools

Rev

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