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