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