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