Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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