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' ,'' );
131
 
132
    EnvImportOptional ( 'GBE_PLATFORM' );           # optional PLATFORM filter
133
    EnvImportOptional ( 'GBE_BUILDFILTER' );        # optional BUILD filter       
134
    EnvImportOptional ( 'GBE_ABT' );                # optional ABT flags          
135
 
136
#.. Common stuff
137
#
138
    require "$::GBE_TOOLS/common.pl";
139
    CommonInit( "buildlib" );
140
    Debug( "Version:   $BuildVersion" );
279 dpurdie 141
    Require( "$::GBE_CONFIG/PLATFORM", "PLATFORM_CFG.PM"  );
227 dpurdie 142
 
143
#.. Parse command line
144
#
145
    $ScmBuildSrc = $0;                          # Name of the build file
146
    ($Cwd, $Makelib) = @ARGV;
147
    $Cwd =~ tr~\\/~/~s;;                        # Need / in path, Remove doubles
148
 
149
    Debug( "Host:      $ScmHost" );
150
    Debug( "Cwd:       $Cwd" );
151
    Debug( "Makelib:   $Makelib" );
152
    Debug( "BuildFile: $ScmBuildSrc" );
153
 
261 dpurdie 154
    Verbose ("Command Line: @ARGV");
155
    my $result = GetOptions (
263 dpurdie 156
                "help|h:+"      => \$opt_help,
157
                "man:3"         => \$opt_help,
261 dpurdie 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
                );
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),
1611
                       split( $::ScmPathSep, $::GBE_DPKG_STORE) )
1612
    {
1613
 
1614
        #
1615
        #   Detect various tags that have been placed in the search list
1616
        #   to flag the end of the sandbox search and the end of the local
1617
        #   archive search
1618
        #
1619
        if ( $dpkg eq '--NotSandbox' )
1620
        {
1621
            $sandbox = 0;
1622
            next;
1623
        }
1624
        if ( $dpkg eq '--NotLocal' )
1625
        {
1626
            $local = 0;
1627
            $isa_cache = 1;
1628
            next;
1629
        }
1630
        if ( $dpkg eq '--NotCache' )
1631
        {
1632
            $isa_cache = 0;
1633
            next;
1634
        }
1635
 
1636
 
1637
        #
1638
        #   If we are playing in a sandbox, then the version number is
1639
        #   not used. The Package suffix is still used so that we can
1640
        #   differentiate sysbasetypes.xxxxx.mas and sysbasetypes.xxxxx.syd
1641
        #
1642
        if ( $sandbox )
1643
        {
1644
            $version = 'sandbox';
1645
            $version .= '.' . $ps if ( $ps );
1646
        }
1647
        else
1648
        {
1649
            $version = $uversion;
1650
        }
1651
 
1652
        #
1653
        #   Alias support
1654
        #   If the 'version' is '!current' then use a version of:
1655
        #       current
1656
        #       current_<USER_NAME>
1657
        #   This is an old mechanism whose use should not be encouraged
1658
        #
1659
        #..
1660
        if ( $version eq "!current" )
1661
        {                                       # 'current' user
1662
            EnvImport( "USER" );
1663
 
1664
            $pkg = "$dpkg/$name/current";       # default
1665
 
1666
            $pkg = "$dpkg/$name/current.lnk"
1667
                if ( -e "$dpkg/$name/current.lnk" );
1668
 
1669
                                                # USER specific
1670
            $pkg = "$dpkg/$name/current_$::USER"
1671
                if ( -e "$dpkg/$name/current_$::USER" );
1672
 
1673
            $pkg = "$dpkg/$name/current_$::USER.lnk"
1674
                if ( -e "$dpkg/$name/current_$::USER.lnk" );
1675
        }
1676
        else
1677
        {                                       # standard
1678
            $pkg = "$dpkg/$name/$version";
1679
 
1680
            $pkg = "$dpkg/$name/$version.lnk"
1681
                if ( -e "$dpkg/$name/$version.lnk" );
1682
        }
1683
 
1684
        #
1685
        #   Using a soft link
1686
        #   Emulate a link in software. The link file contains one line
1687
        #   which is the real pathname of the package
1688
        #
1689
        if ( $pkg =~ m~(.*)\.lnk$~  )
1690
        {
1691
            #
1692
            #   Warn the user if both a link and a real directory
1693
            #   are both present - the link may well be incorrect
1694
            #
1695
            my $non_link = $1;
1696
            Warning ("Suspect package link: $pkg",
1697
                     "Both a link and a package where found - using the link" )
1698
                                                            if ( -d $non_link );
1699
 
1700
            Debug( "           link found -> $pkg" );
1701
            my $link_src = $pkg;
283 dpurdie 1702
            open( LNKFILE, '<', "$pkg" ) || Error( "cannot open '$pkg'" );
227 dpurdie 1703
            $pkg = <LNKFILE>;                   # real path
1704
            close( LNKFILE );
1705
            $pkg = '' unless ( $pkg );
1706
            chomp $pkg;
1707
 
1708
            Error ("Broken link: $pkg",
1709
                   "Source link: $link_src",
1710
                   "Try deleting the .lnk file" ) unless ( -d $pkg );
1711
        }
1712
 
1713
        Debug( "           searching $pkg" );
1714
 
1715
        #   Does the package directory exist?
1716
        #   Terminate the directory name with a "/" to detect hidden spaces
1717
        #..
1718
        $pkg =~ s~//~/~g;
1719
        next unless ( -d "$pkg/" );             # exists ?
1720
 
1721
        #
1722
        #   If the package exists within the dpkg_archive cache then mark the
1723
        #   version as having been used. Used by cache cleanup algorithms
1724
        #
1725
        if ( $isa_cache  )
1726
        {
1727
            TouchFile ( "$pkg/used.cache", "Marks the cache copy as being used");
1728
        }
1729
 
1730
        #
1731
        #   Use the first suitable package found
1732
        #..
1733
 
1734
        Debug( "           importing $pkg" );
1735
        return $pkg, $local;
1736
    }
1737
 
1738
    #
1739
    #   Package not found
1740
    #   This is an error, although it can be bypassed
1741
    #
261 dpurdie 1742
    Error ("Required package not found: '$name/$version'" ) unless ( $NoPackageError );
227 dpurdie 1743
 
261 dpurdie 1744
    Log( "WARNING .... Package not available: '$name/$version'" );
283 dpurdie 1745
    return;
227 dpurdie 1746
}
1747
 
1748
 
1749
#-------------------------------------------------------------------------------
1750
# Function        : LinkEntry
1751
#
1752
# Description     : Scan a package an locate platform specific directories
1753
#                   Create data structures to capture the information
1754
#                   This function is used by LinkPkgArchive and LinkSandbox
1755
#                   to perfom the bulk of package inclusion work.
1756
#
1757
# Inputs          : platform being processed
1758
#                   path to the package
1759
#                   name of the package
1760
#                   version of the package
1761
#                   sandbox support (non-zero)
1762
#
1763
sub LinkEntry
1764
{
1765
    my( $platform, $pkg, $name, $version, $sandbox ) = @_;
1766
    my( $entry );
1767
 
1768
    #   Create entry record
1769
    #
1770
    #..
1771
    $entry = PackageEntry::New( $pkg, $name, $version, $sandbox, 'link' );
1772
 
1773
    #   Populate includes:
1774
    #
1775
    #   - include/$platform                 (eg include/solaris)
1776
    #   - inc/$platform                     (eg inc/solaris)
1777
    #   - include.$platform                 (eg include.solaris)
1778
    #   - inc.$platform                     (eg inc.solaris)
1779
    #   - include                           (eg include)
1780
    #   - inc                               (eg inc)
1781
    #
1782
    #   plus, product specialisation directores
1783
    #
1784
    #   eg. BuildProduct( 'IDFC', 'WIN32' );
1785
    #
1786
    #   - inc/IDFC_WIN32                    <- derived platform
1787
    #   - inc/IDFC                          <- product
1788
    #   - inc/WIN32                         <- target
1789
    #..
1790
    my $parts = $BUILDINFO{$platform}{PARTS};
1791
 
1792
    foreach my $part ( @$parts )
1793
    {
1794
        $entry->RuleInc( "/include." . $part ) if ( !$sandbox );
1795
        $entry->RuleInc( "/inc." . $part )     if ( !$sandbox );
1796
        $entry->RuleInc( "/include/" . $part ) if ( !$sandbox );
1797
        $entry->RuleInc( "/inc/" . $part );
1798
    }
1799
 
1800
    #
1801
    #   Also search the root include directory - last
1802
    #
1803
    $entry->RuleInc( "/include" )               if ( !$sandbox );
1804
    $entry->RuleInc( "/inc" );
1805
 
1806
    #   Populate libraries:
1807
    #
1808
    #   - lib/lib.$platform[D|P]            (eg lib/lib.sparcD)
1809
    #   - lib/$platform[D|P]                (eg lib/lib.sparc)
1810
    #   - lib.$platform[D|P]                (eg lib.sparcD)
1811
    #
1812
    #   plus, product specialisation directores
1813
    #
1814
    #   eg. BuildProduct( 'IDFC', 'WIN32' );
1815
    #
1816
    #   - lib/IDFC_WIN32                    <- derived platform
1817
    #   - lib/IDFC                          <- product
1818
    #   - lib/WIN32                         <- target
1819
    #..
1820
    $parts = $BUILDINFO{$platform}{PARTS};
1821
 
1822
    foreach my $part ( @$parts )
1823
    {
1824
        $entry->RuleLib("/lib" . ".$part" )     if ( !$sandbox );
1825
        $entry->RuleLib("/lib" . "/lib.$part" ) if ( !$sandbox );
1826
        $entry->RuleLib("/lib" . "/$part" );
1827
    }
1828
 
1829
    #
1830
    #   Some extra places to search
1831
    #   None. This is good as it indicates that all locations are described in PARTS
1832
    #
1833
    #   Do NOT search in /lib. There are no libraries that work on all platforms
1834
    #   Libraries are binaries!
1835
    #
1836
    #    $entry->RuleLib( "/lib" );
1837
 
1838
    #   Tools:
1839
    #
1840
    #   Tools provide an extensible search path for tools and
1841
    #   utilities used to build programs. These are tools that
1842
    #   are executable on the current host machine and are
1843
    #   independent of the toolset.
1844
    #
1845
    #..
1846
    $entry->ExamineToolPath();
1847
    $entry->ExamineThxPath($platform);
1848
    IncludePkg ( $name, $pkg );
1849
    $entry->Cleanup();                          # cleanup tables
1850
 
1851
    #
1852
    #   Add the package entry to the array of such entries for
1853
    #   the current platform. Maintain the discovery order
1854
    #
1855
    #..
1856
    push ( @{$PKGRULES{$platform}}, $entry );
1857
}
1858
 
1859
 
1860
#-------------------------------------------------------------------------------
1861
# Function        : BuildPkgArchive
1862
#
1863
# Description     : Include an external package into the build sandbox
1864
#                   by copying the packages files into the interface directory
1865
#
1866
# Inputs          : package name
1867
#                   package version
1868
#
1869
sub BuildPkgArchive
1870
{
1871
    my( $name, $version ) = @_;
1872
 
1873
    return if ( $Clobber );                     # clobber mode ?
1874
 
1875
    Debug( "BuildPkgArchive:" );
1876
    Debug( "Name:      $name" );
1877
    Debug( "Version:   $version" );
1878
 
1879
    DataDirective("BuildPkgArchive");           # This directive allowed here
1880
 
1881
    #
1882
    #   Ensure that we have do not have multiple definitions
1883
    #
1884
    if ( PackageEntry::Exists( $name, $version ) )
1885
    {
261 dpurdie 1886
        Log( "Duplicate Package: $name, $version. Duplicate entry ignored" );
227 dpurdie 1887
        return;
1888
    }
1889
 
1890
    if ( $Cache && $::GBE_DPKG_CACHE )
1891
    {
1892
        my $mode = ($Cache > 1) ? "-refresh" : "";
261 dpurdie 1893
        Log( "BuildPkgArchive . $name ($version) Update Cache" );
227 dpurdie 1894
        System('--NoExit', "$::GBE_PERL $::GBE_TOOLS/cache_dpkg.pl $mode -quiet $name/$version" );
1895
    }
1896
 
1897
    #
1898
    #   Locate the package
1899
    #   Use the first instance of the package that it found
1900
    #
261 dpurdie 1901
    Log( "BuildPkgArchive . $name ($version)" );
227 dpurdie 1902
    my ( $pkg, $local ) = PackageLocate( $name, $version );
1903
    if ( $pkg )
1904
    {
1905
        #
1906
        #   Create a Package Entry
1907
        #
1908
        my $entry = PackageEntry::New( $pkg, $name, $version, 0, 'build' );
1909
 
1910
        #
1911
        #   Determine if the package needs to be installed:
1912
        #       If the package is a 'local' package then force transfer
1913
        #       If the user has specified --cache then force transfer
1914
        #       If package is newer that copy, then force transfer
1915
        #       If copy does not exist, then force a transfer
1916
        #
1917
        my $tag_dir = "$Cwd/$BUILDINTERFACE/BuildTags";
1918
        my $tag_file = "$tag_dir/${name}_${version}.tag";
1919
 
1920
        my $package_installed;
1921
        $package_installed = 1
1922
            if ( !$local &&
1923
                 !$Cache &&
1924
                 !FileIsNewer( $entry->GetBaseDir('descpkg'), $tag_file ) );
1925
 
1926
        #
1927
        #   Determine the package format and use the appropriate installer
1928
        #   Supported formats
1929
        #       1) Package has a descpkg file (new style)
1930
        #       2) Package has a InstallPkg.sh file (old style)
1931
        #       3) Package has a Install.sh file (old style is it used ??)
1932
        #
1933
        if ( $package_installed ) {
1934
            Verbose ("Package already installed: $name, $version");
1935
 
1936
        } else {
261 dpurdie 1937
            Log( "                . installing '$pkg'" );
1938
            Log( "                . -> " . readlink($pkg) ) if ( -l $pkg );
227 dpurdie 1939
 
1940
            if ( -e "$pkg/descpkg" )
1941
            {
1942
 
1943
                #
1944
                #   If forcing a BuildPkg, then don't use symlinks
1945
                #   to files in dpkg_archive
1946
                #
1947
                my $opts = "";
1948
                $opts = "--NoSymlinks" if ( $ForceBuildPkg );
1949
 
1950
                #
1951
                #   Determine all the Platforms, Products and Targets
1952
                #   that need to be installed
1953
                #
1954
                my $arglist = GenerateInstallArgumentList();
1955
                System( "cd $pkg; $::GBE_PERL $::GBE_TOOLS/installpkg.pl $Cwd/$BUILDINTERFACE $Cwd $opts $arglist");
1956
                Error( "Package installation error" ) if ( $? != 0 );
1957
            }
1958
            elsif ( -e "$pkg/InstallPkg.sh" )
1959
            {
1960
                System( "(cd $pkg; ./InstallPkg.sh $Cwd/$BUILDINTERFACE $Cwd)" );
1961
            }
1962
            elsif ( -e "$pkg/Install.sh" )
1963
            {
1964
                System( "(cd $pkg; ./Install.sh $Cwd/$BUILDINTERFACE $Cwd)" );
1965
            }
1966
            else
1967
            {
1968
                Error ("Unknown package format for package $name/$version found in $pkg");
1969
            }
1970
 
1971
            #
1972
            #   Tag the package as installed - after it has been transferred
1973
            #
1974
            mkdir ( $tag_dir );
1975
            TouchFile( $tag_file );
1976
        }
1977
 
1978
        #
1979
        #   Process package
1980
        #
1981
        IncludePkg ( $name, $pkg );
1982
 
1983
        #
1984
        #   Complete the creation of the package entry
1985
        #   Add the information for all platforms
1986
        #
1987
        $entry->Cleanup();
1988
        for my $platform (@BUILD_ACTIVEPLATFORMS)
1989
        {
1990
            $entry->ExamineToolPath();
1991
            $entry->ExamineThxPath($platform);
1992
            push ( @{$PKGRULES{$platform}}, $entry );
1993
        }
1994
    }
1995
}
1996
 
1997
#-------------------------------------------------------------------------------
311 dpurdie 1998
# Function        : CreateInterfacePackage
1999
#
2000
# Description     : Create a dummy package entry to describe the Interface
2001
#                   This is done AFTER all the BuildPkgArchive directives have
2002
#                   been processed so that the interface directory is fully
2003
#                   processed
2004
#
2005
# Inputs          : None
2006
#
2007
# Returns         : 
2008
#
2009
sub CreateInterfacePackage
2010
{
2011
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
2012
    {
2013
        my $entry = PackageEntry::Interface( "$::Cwd/$BUILDINTERFACE" );
2014
 
2015
        #
2016
        #   Locate include and lib bits within the interface
2017
        #   This is much simpler than for a LinkPkgArchive as the form
2018
        #   has been sanitized
2019
        #
2020
        my $parts = $BUILDINFO{$platform}{PARTS};
2021
 
2022
        foreach my $part ( @$parts )
2023
        {
2024
            $entry->RuleInc( "/include/" . $part );
2025
        }
2026
        $entry->RuleInc( "/include" );
2027
 
2028
        foreach my $part ( @$parts )
2029
        {
2030
            $entry->RuleLib("/lib/" . $part );
2031
        }
2032
 
2033
        $entry->ExamineToolPath();
2034
        $entry->ExamineThxPath($platform);
2035
        $entry->Cleanup();
2036
 
2037
        #
2038
        #   Add the package entry to the array of such entries for
2039
        #   the current platform. Force it to be the first one as
2040
        #   the interface directory will be scanned first
2041
        #
2042
        unshift ( @{$PKGRULES{$platform}}, $entry );
2043
    }
2044
}
2045
 
2046
#-------------------------------------------------------------------------------
227 dpurdie 2047
# Function        : GenerateInstallArgumentList
2048
#
2049
# Description     : Generate an argument list for the installpkg.pl script
2050
#                   The argument list is of the form
2051
#                       --Platform:xx[:xx[:xx]] --Platform:yy[:yy[:yy]] ...
2052
#                   Where xx is:
2053
#                       * a 'part' of the target platform
2054
#                         Order is: platform, product, ...  target( in that order )
2055
#                       * --Option[=yyy]
2056
#                        An option to be passed to the script. These are bound only
2057
#                        to the enclosed platform.
2058
# Inputs          :
2059
#
2060
# Returns         : See above
2061
#
2062
sub GenerateInstallArgumentList
2063
{
2064
    my @arglist;
2065
 
2066
    #
2067
    #   Generate the argument list as an array
2068
    #
2069
    for (@BUILD_ACTIVEPLATFORMS)
2070
    {
2071
        my @args = '--Platform';
2072
        push @args, @{$BUILDINFO{$_}{PARTS}};
2073
        push @arglist, join (":" , @args );
2074
    }
2075
 
2076
    return "@arglist";
2077
}
2078
 
2079
#-------------------------------------------------------------------------------
2080
# Function        : GeneratePlatformList
2081
#
2082
# Description     : Return a list of platforms that should particiate in this
2083
#                   build. This is a function of
2084
#                       1) Platforms defined in the build.pl file
2085
#                       2) User filter defined in GBE_BUILDFILTER
2086
#
2087
#                   The primary use of this function is to limit the creation
2088
#                   of makefiles to those that have supported compilers on
2089
#                   the underlying machine.
2090
#
2091
#                   GBE_BUILDFILTER is a space seperated string of words
2092
#                   Each word may be one of
2093
#                       OPTION=TAG or OPTION=!TAG
2094
#                       TAG or !TAG. This is the same as --TARGET=TAG
2095
#
2096
#                   Bare tags are taken to be TARGETS.
2097
#
2098
#                   Where OPTION may be one of
2099
#                       --PLATFORM
2100
#                       --PRODUCT
2101
#                       --TARGET
2102
#
2103
#                   Special cases
2104
#                   1) If GBE_BUILDFILTER is empty, then all available platforms are used
2105
#                      The global $All is set, then all available platforms are used
2106
#                   2) If the first word of GBE_BUILDFILTER is a negative filter,
2107
#                      ie is used the !xxxx or yyy=!xxxx construct, then it is assumed
2108
#                      that the filter will start with all available platforms
2109
#                   3) The special word --ALL forces selection of ALL platforms
2110
#                      and may reset any existing scanning
2111
#                   4) GBE_BUILDFILTER is parsed left to right. It is possible to add and
2112
#                      subtract items from the list.
2113
#                   5) OPTIONS are case insensitive
2114
#                      TAGS are case sensitive
2115
#
2116
#
2117
# Inputs          : GBE_BUILDFILTER from the environment
2118
#
2119
# Returns         : An array of platforms to include in the build
2120
#                   Maintains @BUILD_ACTIVEPLATFORMS  - the last calculated result
2121
#                   Ensures that @DEFBUILDPLATFORMS is a subset of @BUILD_ACTIVEPLATFORMS
2122
#
2123
sub GeneratePlatformList
2124
{
2125
    #
2126
    #   Return the cached result for speed
2127
    #   The value need only be calculated once
2128
    #
2129
    unless ( defined @BUILD_ACTIVEPLATFORMS )
2130
    {
2131
        my ($platform_filter);
2132
        my %result;
2133
        my %part_to_platform;
2134
 
2135
        #
2136
        #   Create a data structure to assist in the production of the platform list
2137
        #   The structure will be a hash of hashes of arrays
2138
        #
2139
        #   The first level hash will be keyed by the word TARGET, PRODUCT or PLATFORM
2140
        #   The second level of the hash will keyed by available targets, products or platforms
2141
        #   The value of the field will be an array of platforms that match the keyword
2142
        #
2143
        for my $platform (keys (%::BUILDINFO))
2144
        {
2145
            my $pParts = $::BUILDINFO{$platform};
2146
 
2147
            #
2148
            #   Skip platforms that are known to be unavailable on this build
2149
            #   machine. Self configure
2150
            #
2151
            next if ( $pParts->{NOT_AVAILABLE} );
2152
 
2153
            my $target  = $pParts->{TARGET};
2154
            my $product = $pParts->{PRODUCT};
2155
 
2156
            push @{$part_to_platform{'PLATFORM'}{$platform}}, $platform;
2157
            push @{$part_to_platform{'TARGET'}  {$target}}  , $platform;
2158
            push @{$part_to_platform{'PRODUCT'} {$product}} , $platform;
2159
        }
2160
        #
2161
        #   Determine the source of the filter
2162
        #   If the user provides one, then use it.
2163
        #   Otherwise its taken from the environment.
2164
        #
2165
        #   Global build all platforms - Kill any user filter
2166
        #
2167
        if ( $All )
2168
        {
2169
            $platform_filter = "";
2170
        }
2171
        else
2172
        {
2173
            $platform_filter = "";
2174
            $platform_filter = $::GBE_BUILDFILTER
2175
                if ( defined($::GBE_BUILDFILTER) );
2176
        }
2177
        Debug( "GeneratePlatformList: Filter:$platform_filter" );
2178
 
2179
        #
2180
        #   Detect the special cases
2181
        #       1) No user definition - assume all platforms
2182
        #       2) First word contains a subtractive element
2183
        #
2184
        my (@filter) = split( ' ', $platform_filter );
2185
 
2186
        if ( !scalar @filter || $filter[0] =~ m/^$/ || $filter[0] =~ m/!/ )
2187
        {
2188
            %result = %{$part_to_platform{'PLATFORM'}}
2189
                if exists $part_to_platform{'PLATFORM'} ;
2190
        }
2191
#DebugDumpData( "PartToPlatform", \%part_to_platform );
2192
 
2193
        #
2194
        #   Process each element in the user filter list
2195
        #   Expand platforms into known aliases
2196
        #
2197
        for my $word (@filter)
2198
        {
2199
            my $platform;
2200
 
2201
            if ( $word =~ m/^--ALL/i )
2202
            {
2203
                %result = %{$part_to_platform{'PLATFORM'}};
2204
            }
2205
            elsif ( $word =~ m/^--(TARGET)=(!?)(.*)/i ||
2206
                    $word =~ m/^--(PRODUCT)=(!?)(.*)/i ||
2207
                    $word =~ m/^--(PLATFORM)=(!?)(.*)/i ||
2208
                    ( $word !~ m/^-/ && $word =~ m/()(!?)(.*)/ )
2209
                )
2210
            {
2211
                my $table = uc($1);
2212
                $table = "TARGET"
2213
                    unless ( $1 );
2214
 
2215
                #
2216
                #   Expand PLATFORMs into known aliases
2217
                #   Alias will expand to PLATFORMs so it won't work unless we are
2218
                #   processing PALTFORMs.
2219
                #
2220
                my @taglist = ( $table eq "PLATFORM" ) ? ExpandPlatforms($3) : $3;
2221
 
2222
                #
2223
                #   Add / Remove items from the result
2224
                #
2225
                for my $item ( @taglist )
2226
                {
2227
                    my $plist = $part_to_platform{$table}{$item};
2228
                    for ( @{$plist})
2229
                    {
2230
                        if ( $2 )
2231
                        {
2232
                            delete $result{$_};
2233
                        }
2234
                        else
2235
                        {
2236
                            $result{$_} = 1;
2237
                        }
2238
                    }
2239
                }
2240
            }
2241
            else
2242
            {
2243
                print "GBE_BUILDFILTER filter term not understood: $word\n";
2244
            }
2245
        }
2246
 
2247
        #
2248
        #   Return an array of platforms to process
2249
        #
2250
        @BUILD_ACTIVEPLATFORMS = sort keys %result;
2251
 
2252
        #
2253
        #   Ensure that DEFBUILDPLATFORMS is a subset of build active platforms
2254
        #
2255
        my @NEW_DEFBUILDPLATFORMS;
2256
        foreach ( @DEFBUILDPLATFORMS )
2257
        {
2258
            push @NEW_DEFBUILDPLATFORMS, $_
2259
                if ( exists $result{$_} );
2260
        }
2261
        @DEFBUILDPLATFORMS = @NEW_DEFBUILDPLATFORMS;
2262
    }
2263
 
2264
    Debug("GeneratePlatformList: Result:@BUILD_ACTIVEPLATFORMS");
2265
    return @BUILD_ACTIVEPLATFORMS;
2266
}
2267
 
2268
#-------------------------------------------------------------------------------
2269
# Function        : PrintPlatforms
2270
#
2271
# Description     : Petty print the specified platform list, breaking line
2272
#                   on either a primary key change or length width >78.
2273
#
2274
# Returns         : Formated string
2275
#
2276
# Example Output :
2277
#
2278
#           DDU_LMOS_WIN32 DDU_LMOS_linux_armv4 DDU_LMOS_linux_i386
2279
#           IDFC_LMOS_WIN32 IDFC_LMOS_linux_armv4 IDFC_LMOS_linux_i386
2280
#           LMOS_WCEPSPC_ARM LMOS_WCEPSPC_EMU LMOS_WIN32 LMOS_linux_armv4
2281
#           LMOS_linux_i386
2282
#..
2283
sub PrintPlatforms
2284
{
2285
    my ($platforms, $nl) = @_;
2286
    my ($string) = "";                          # result
2287
 
2288
    if ( defined(@$platforms) )
2289
    {
2290
        my ($key_run) = 0;
2291
        my ($pkey);                             # previous key
2292
 
2293
        #   Perform a simple formatting and determine if there is key 
2294
        #   change greater then 1 or whether the total length exceeds 78.
2295
        #
2296
        #   If the line exceeds 78, the printer shall then reformat 
2297
        #   breaking based on line length and possiblity keys.
2298
        #
2299
        $pkey = "";
2300
        for my $k (sort @$platforms) 
2301
        {
2302
            my ($d);                            # delimitor
2303
 
2304
            if (($d = index( $k, '_' )) != index( $pkey, '_' ) ||
2305
                    substr( $k, 0, $d ) ne substr( $pkey, 0, $d )) {
2306
                $key_run = 1
2307
                    if ($key_run <= 1);         # change, reset run if <= 1
2308
            } else {
2309
                $key_run++;                     # same primary key
2310
            }
2311
 
2312
            $string .= " " if ($pkey);
2313
            $string .= $k;
2314
            $pkey = $k;
2315
        }
2316
 
2317
        #   Reprint if required.
2318
        #
2319
        if (length($nl)+length($string) > 78)
2320
        {
2321
            my ($llen);                         # line length
2322
 
2323
            $llen = length($nl);
2324
 
2325
            $pkey = "";
2326
            $string = "";
2327
 
2328
            for my $k (sort @$platforms)
2329
            {
2330
                my ($klen, $d);                 # key length, delimitor
2331
 
2332
                $klen = length($k);
2333
                if ($pkey ne "")
2334
                {
2335
                    if ($llen + $klen > 78 ||
2336
                        ($key_run > 1 && (
2337
                            ($d = index( $k, '_' )) != index( $pkey, '_' ) ||
2338
                            substr( $k, 0, $d ) ne substr( $pkey, 0, $d ) )) )
2339
                    {                           # line >70 or key change
2340
                        $string .= $nl;
2341
                        $llen = length($nl);
2342
                    }
2343
                    else
2344
                    {
2345
                        $string .= " ";
2346
                        $llen++;
2347
                    }
2348
                }
2349
                $string .= $k;
2350
                $pkey = $k;
2351
                $llen += $klen;
2352
            }
2353
        }    
2354
    }
2355
    return $string;
2356
}
241 dpurdie 2357
#-------------------------------------------------------------------------------
2358
# Function        : PrintList
2359
#
2360
# Description     : Pretty format an array to fit within 80 char line
2361
#                   Perform wrapping as required
2362
#
2363
# Inputs          : $list           - Reference to an array
2364
#                   $nl             - New line stuff.
2365
#                                     Use to prefix new lines
2366
#
2367
# Returns         : string
2368
#
2369
sub PrintList
2370
{
2371
    my ($list, $nl) = @_;
2372
    my ($string) = '';                          # result
2373
    my $sep;
227 dpurdie 2374
 
241 dpurdie 2375
    if ( @$list )
2376
    {
2377
        my ($llen) = length($nl);
227 dpurdie 2378
 
241 dpurdie 2379
        for my $k (@$list)
2380
        {
2381
            my $klen = length($k);
2382
            if ($llen + $klen > 78 )
2383
            {
2384
                $string .= $nl;
2385
                $llen = length($nl);
2386
            }
2387
            else
2388
            {
2389
                if ( $sep )
2390
                {
2391
                    $string .= $sep;
2392
                    $llen++;
2393
                }
2394
                else
2395
                {
2396
                    $sep = ' ';
2397
                }
2398
            }
2399
            $string .= $k;
2400
            $llen += $klen;
2401
        }
2402
    }
2403
    return $string;
2404
}
2405
 
305 dpurdie 2406
#-------------------------------------------------------------------------------
2407
# Function        : BuildReleaseFile
2408
#
2409
# Description     : Legacy function
2410
#                   Don't know what it was meant to do
2411
#                   Unfortunately it is present in a lot of build.pl files
2412
#
2413
#                   Not well supported on all machine types
2414
#
2415
# Inputs          : $BuildFilename          - Root of output filename
2416
#                   $BuildDir               - Path of subdir to tar
2417
#
2418
#                   Also uses the undocumented: GBE_SNAPSHOT_DIR
2419
#
2420
# Returns         : Does not return
2421
#                   Once invoked this function will exit the build
2422
#
227 dpurdie 2423
sub BuildReleaseFile
2424
{
2425
    my ( $BuildFilename, $BuildDir ) = @_;
2426
    my ( $SnapDir );
2427
 
2428
    # Check if archive requested...
2429
    #
2430
    return unless ( $CmdSwitch eq "archive" );
2431
 
2432
    # Build the release archive file...
2433
    #
2434
    $SnapDir = "$ENV{ \"GBE_SNAPSHOT_DIR\" }/";
2435
    $SnapDir = "" unless ($SnapDir ne "/");
2436
 
261 dpurdie 2437
    Log( "Creating release archive: $SnapDir$BuildFilename.tgz of $Cwd/$BuildDir/" );
227 dpurdie 2438
 
2439
    # GNU tar and zip the build directory NOT following links...
2440
    #
2441
    System( "$::GBE_BIN/tar czf $SnapDir$BuildFilename.tgz $BuildDir" );
2442
 
2443
    Error( "To extract use: $::GBE_BIN/tar xvzf $BuildFilename.tgz" );
2444
}
2445
 
305 dpurdie 2446
#-------------------------------------------------------------------------------
2447
# Function        : BuildSnapshot
2448
#
2449
# Description     : Legacy function
2450
#                   Don't know what it was meant to do
2451
#                   Unfortunately it is present in a lot of build.pl files
2452
#
2453
# Inputs          : None that are used
2454
#
2455
# Returns         : Undefined
2456
#
227 dpurdie 2457
sub BuildSnapshot
2458
{
2459
}
2460
 
305 dpurdie 2461
#-------------------------------------------------------------------------------
2462
# Function        : BuildSrcArchive
2463
#
2464
# Description     : Create a source snapshot of the build source
2465
#                   Designed to provide a source image for packaging
2466
#                   examples
2467
#
2468
#                   Should be platform independent
2469
#
2470
#                   Creates an archive file and places it into the
2471
#                   interface directory. The archive will be packaged
2472
#                   automatically by the build process
2473
#
2474
#                   Use the 'pax' utility
2475
#                       1) Can massage the file path such that the stored
2476
#                          directory image contains the package name and version
2477
#
2478
#                   Directive can be used at any time before the BuildMake
2479
#
2480
#                   Will handle the existence of an auto.pl file by inserting
2481
#                   it as build.pl.
2482
#
2483
# Inputs          : Options
2484
#
2485
#
2486
# Returns         : 
2487
#
2488
sub BuildSrcArchive
2489
{
2490
    #
2491
    #   If we are clobbering, then there is nothing to do
2492
    #   The generated file is placed within the interface
2493
    #   directory and that directory will be deleted during the clobber
2494
    #
2495
    return if ( $Clobber );
2496
    DataDirective("BuildSrcArchive");
227 dpurdie 2497
 
305 dpurdie 2498
    #
2499
    #   Currently this operation is only supported of some platforms
2500
    #   Only supported on Unix platforms
2501
    #   Uses the 'pax' utility
2502
    #
2503
    unless ( LocateProgInPath ( 'pax', '--All' ) && ( $ScmHost eq "Unix" ) )
2504
    {
2505
        Log( "SrcPackage . Not supported" );
2506
        return;
2507
    }
2508
 
2509
    #
2510
    #   Only allow one instance of the directive
2511
    #
2512
    Error ("Multiple BuildSrcArchive directives not supported")
2513
        if ( $build_source_pkg );
2514
 
2515
    #
2516
    #   Create the name of the archive
2517
    #       Based on the package name and version
2518
    #       Has no spaces
2519
    #
2520
    my $build_name = $BUILDNAME;
2521
    $build_name =~ s~\s+~_~g;
2522
 
2523
    #
2524
    #   Create the archive in the interface directory
2525
    #   Don't need to clobber it as the entire interface directory
2526
    #   will be clobbered
2527
    #
2528
    $build_source_pkg = $build_name;
2529
}
2530
 
2531
#-------------------------------------------------------------------------------
2532
# Function        : BuildSrcArchiveBody
227 dpurdie 2533
#
305 dpurdie 2534
# Description     : Function to implement the body of the BuildSrcArchive
2535
#                   operation. Will be invoked during BuildMake
2536
#
2537
# Inputs          : None
2538
#
2539
# Returns         : 
2540
#
2541
sub BuildSrcArchiveBody
2542
{
2543
    return unless ( $build_source_pkg );
2544
 
2545
    my $archive_dir = "pkg/$BUILDNAME_PACKAGE/src";
2546
    my $archive_file = "$build_source_pkg" . '.tar';
2547
 
2548
    Log( "SrcPackage . $archive_file.gz" );
2549
    unlink "$archive_dir/$archive_file";
2550
    unlink "$archive_dir/$archive_file.gz";
2551
    mkpath($archive_dir, 0, 0775);
2552
 
2553
    #
2554
    #   Create a list of files and top-level dirs to add to source archive
2555
    #   Many files are ignored
2556
    #   Should only be executed on the first 'build' thus many internal
2557
    #   directories will not be present
2558
    #
2559
    my @flist;
2560
    my $auto_pl;
2561
    opendir (my $tp, '.' ) or Error ("Cannot read current directory");
2562
    while ( $_ = readdir($tp) )
2563
    {
2564
        next if ( m/^\.$/ );
2565
        next if ( m'^\.\.$' );
2566
        next if ( m'^build\.log$' );
2567
        next if ( m'\.gbe$' );
2568
        next if ( m'^local$' );
2569
        next if ( m'^pkg$' );
2570
        next if ( m/^$BUILDINTERFACE$/ );
2571
        $auto_pl = 1, next  if ( m'^auto\.pl$' );
2572
        next if (  m'^build\.pl$' );
2573
        next if ( m/^$build_source_pkg$/ );
2574
        push @flist, $_;
2575
    }
2576
    closedir $tp;
2577
 
2578
    #
2579
    #   If we don't have an auto.pl, then we add the build.pl file
2580
    #   If we do have a auto.pl - it gets tricky. Its don't after the
2581
    #   initial pax command
2582
    #
2583
    unless ( $auto_pl )
2584
    {
2585
        push @flist, 'build.pl';
2586
    }
2587
 
2588
    #
2589
    #   Create the command to be executed
2590
    #   Prefix archive paths with build_name
2591
    #
2592
    my @command = ( 'pax', '-w', '-f', "$archive_dir/$archive_file" );
2593
    System( '--NoShell' , @command, '-s', "~^~$build_source_pkg/~", @flist );
2594
 
2595
    #
2596
    #   If we have an auto.pl file, then we need to add it to the archive
2597
    #   but it needs to be called build.pl
2598
    #
2599
    if ( $auto_pl )
2600
    {
2601
        System( '--NoShell' , @command, '-a', '-s', "~^auto.pl~$build_source_pkg/build.pl~" , 'auto.pl' );
2602
    }
2603
 
2604
    #
2605
    #   Must now zip the file
2606
    #   Can't zip and append at the same time
2607
    #
2608
    System( '--NoShell' , 'gzip', "$archive_dir/$archive_file" );
2609
 
2610
    #
2611
    #   Display the results
2612
    #
2613
    System ('--NoShell', 'pax', '-z', "-f$archive_dir/$archive_file.gz")
2614
        if (IsVerbose (1));
2615
}
2616
 
2617
#-------------------------------------------------------------------------------
2618
# Function        : BuildAccessPerms
2619
#
2620
# Description     : Check if access/permissions setting requested...
2621
#                   Legacy
2622
#
2623
# Inputs          : None
2624
#
2625
# Returns         : 
2626
#
227 dpurdie 2627
sub BuildAccessPerms
2628
{
2629
    my( $PermsFilename );
2630
 
2631
    return unless ( $CmdSwitch eq "perms" );
2632
 
2633
    # Set the build access permissions from the shell script...
2634
    $PermsFilename = $CmdParm;
2635
    if ( -e $PermsFilename )
2636
    {
261 dpurdie 2637
        Log( "Setting build access permissions from $PermsFilename..." );
227 dpurdie 2638
        System( "su root -c \"sh $PermsFilename\"" );
2639
    }
2640
    else
2641
    {
261 dpurdie 2642
        Log( "ERROR: Could not find file to set the access permissions: $PermsFilename" );
227 dpurdie 2643
    }
2644
    die "\n";
2645
}
2646
 
2647
 
2648
sub BuildSetenv
2649
{
2650
    push( @BUILDSETENV, @_ );
2651
}
2652
 
2653
#-------------------------------------------------------------------------------
2654
# Function        : DataDirective
2655
#
2656
# Description     : Called by data collection directives to ensure that we are
2657
#                   still collecting data and that we have collected other data
2658
#
2659
# Inputs          : $dname              - Directive Name
2660
#
2661
# Returns         : Will error if we are not
2662
#
2663
sub DataDirective
2664
{
2665
    my ($dname) = @_;
2666
 
2667
    Error( "$dname() must appear after BuildName()...")
2668
        if ( $BUILDNAME eq "" );
2669
 
2670
    Error( "$dname() must appear after BuildInterface()...")
2671
        unless( $BUILDINTERFACE );
2672
 
2673
    Error( "$dname() not allowed after BuildDescpkg, BuildIncpkg, BuildVersion or BuildMake")
2674
        if( $BUILDPHASE);
2675
}
2676
 
2677
#-------------------------------------------------------------------------------
2678
# Function        : StartBuildPhase
2679
#
2680
# Description     : Called by directives that deal with the building phases
2681
#                   to perform common initialisation and to ensure that
2682
#                   directives that collect data are no longer called
2683
#
305 dpurdie 2684
# Inputs          : last                - True: Last directive expected
227 dpurdie 2685
#
2686
# Returns         : May generate an error
2687
#
2688
sub StartBuildPhase
2689
{
305 dpurdie 2690
    my ($last) = @_;
2691
 
227 dpurdie 2692
    #
305 dpurdie 2693
    #   Ensure directive is allowed
2694
    #       $BUILDPHASE >  1     - No more directives allowed
2695
    #       $BUILDPHASE == 1     - Allowed directive
2696
    #
2697
    if ( $BUILDPHASE > 1 )
2698
    {
2699
        my $function = (caller(1))[3];
2700
        $function =~ s~.*::~~;
2701
        Error ("Directive not allowed: $function","'BuildMake' must be the last directive in the build file");
2702
    }
2703
 
2704
    #
227 dpurdie 2705
    #   Only do it once
2706
    #
305 dpurdie 2707
    return if ( $BUILDPHASE  );
2708
    $BUILDPHASE = 1;
227 dpurdie 2709
 
2710
    #
2711
    #   Calcuate the aliases that are being extracted from targets
2712
    #
2713
    Process_TargetAlias();
2714
 
2715
    #
311 dpurdie 2716
    #   Create dummy package to describe the Interface directory
2717
    #
2718
    CreateInterfacePackage();
2719
 
2720
    #
227 dpurdie 2721
    #   Sanity test the users packages
2722
    #
2723
    PackageEntry::SanityTest() unless $Clobber;
2724
 
2725
    #
2726
    #   Validate the $Srcdir before its first real use
2727
    #   This is calculated from the user directives
2728
    #
2729
 
2730
    #.. Determine default "source" root
2731
    #
2732
    if ( $Srcdir eq "" )
2733
    {
2734
        Warning( "Both the directories 'src' and 'SRC' exist ....." )
2735
            if ( $ScmHost eq "Unix" && -e "src" && -e "SRC" );
2736
 
2737
        if ( -e "src" ) {
2738
            $Srcdir = "src";
2739
        } else {
2740
            ( -e "SRC" ) ||
2741
                Error( "Neither the directory 'src' nor 'SRC' exist ....." );
2742
            $Srcdir = "SRC";
2743
        }
2744
    }
2745
 
2746
    #
2747
    #   Must have a valid Srcdir
2748
    #
2749
    Error ("Source directory not found: $Srcdir")
2750
        unless ( $Srcdir && -d $Srcdir );
2751
 
305 dpurdie 2752
    #
2753
    #   Create source package
2754
    #
2755
    BuildSrcArchiveBody();
2756
 
227 dpurdie 2757
    return $Srcdir;
2758
}
2759
 
2760
#-------------------------------------------------------------------------------
305 dpurdie 2761
# Function        : LastBuildDirective
2762
#
2763
# Description     : No more build directives allowed
2764
#
2765
# Inputs          : 
2766
#
2767
# Returns         : 
2768
#
2769
sub LastBuildDirective
2770
{
2771
    $BUILDPHASE = 2;
2772
}
2773
 
2774
#-------------------------------------------------------------------------------
227 dpurdie 2775
# Function        : BuildPackageLink
2776
#
2777
# Description     : Create a soft link from sandbox_dpkg_archive to the package
2778
#                   being created by this build
2779
#
2780
#                   For backward compatability.
2781
#                   If GBE_DPKG_SBOX is not defined, then use GBE_DPKG_LOCAL
2782
#
2783
#                   This will allow multiple components to work together
2784
#
2785
#                   Note: When called in Clobber-mode the link will be deleted
2786
#
2787
# Inputs          : $BUILDNAME              - The package name
2788
#                   $BUILDNAME_PROJECT      - Project extension
2789
#                   $::GBE_DPKG_SBOX        - Path of sandbox_dpkg_archive
2790
#                   $::GBE_DPKG_LOCAL       - Path of local_dpkg_archive
2791
#                   $::GBE_DPKG             - Main repository
2792
#
2793
# Returns         : Nothing
2794
#
2795
sub BuildPackageLink
2796
{
2797
    my $target_archive;
2798
    my $target_archive_name;
2799
    my $link_file;
2800
    my $tag;
2801
 
2802
    #
2803
    #   Determine the path (and name) of the target archive
2804
    #   Use sandbox_dpkg_archive if it exists
2805
    #   Use local_dpkg_acrhive for backward compatability (should be removed after JATS 2.64.2+)
2806
    #
2807
    if ( $target_archive = $::GBE_DPKG_SBOX )
2808
    {
2809
        $target_archive_name = "sandbox_dpkg_archive";
2810
        $tag = "Sandbox";
2811
 
2812
        $link_file  = 'sandbox';
2813
        $link_file .= '.' . $BUILDNAME_PROJECT if ( $BUILDNAME_PROJECT );
2814
        $link_file .= '.lnk';
2815
    }
2816
    elsif ( $target_archive = $::GBE_DPKG_LOCAL )
2817
    {
2818
        $target_archive_name = "local_dpkg_archive";
2819
        $link_file = "$BUILDVERSION.lnk";
2820
        $tag = "Local";
2821
    }
2822
    else
2823
    {
2824
        Verbose("Cannot locate local or sandbox archive")
2825
            unless $Clobber;
2826
        return;
2827
    }
2828
 
2829
    #
2830
    #   Santity test
2831
    #   Target must be a directory
2832
    #
2833
    unless ( -d $target_archive )
2834
    {
241 dpurdie 2835
        Warning("$target_archive_name is not a directory: $target_archive")
227 dpurdie 2836
            unless $Clobber;
2837
        return;
2838
    }
2839
 
2840
    my $link_dir = "$target_archive/$BUILDNAME_PACKAGE";
2841
    my $link_path = "$link_dir/$link_file";
2842
 
2843
    if ( $Clobber )
2844
    {
2845
        unlink $link_path;          # Delete the link
2846
        rmdir $link_dir;            # Delete only if empty
2847
    }
2848
    else
2849
    {
261 dpurdie 2850
        Log( "Local Link . $BUILDNAME_PACKAGE/$link_file ($tag)");
2851
        mkdir $link_dir unless -d $link_dir;
2852
        FileCreate ( $link_path, "$Cwd/pkg/$BUILDNAME_PACKAGE");
227 dpurdie 2853
    }
2854
}
2855
 
2856
#-------------------------------------------------------------------------------
2857
# Function        : BuildSandboxData
2858
#
2859
# Description     : Create data structures to allow this package to be built
2860
#                   within a multi-package sandbox.
2861
#
2862
#                   This will allow multiple components to work together
2863
#
2864
#                   Note: When called in Clobber-mode the link will be deleted
2865
#
2866
# Inputs          : $BUILDNAME              - The package name
2867
#                   $BUILDNAME_PROJECT      - Project extension
2868
#                   $::GBE_DPKG_SBOX        - Path of sandbox_dpkg_archive
2869
#                   $::GBE_DPKG             - Main repository
2870
#
2871
# Returns         : Nothing
2872
#
2873
sub BuildSandboxData
2874
{
2875
    my $sandbox_dpkg_archive = $::GBE_DPKG_SBOX;
2876
    return unless ( $sandbox_dpkg_archive );
2877
 
2878
    unless ( -d $sandbox_dpkg_archive )
2879
    {
241 dpurdie 2880
        Error("sandbox_dpkg_archive is not a directory: $sandbox_dpkg_archive")
227 dpurdie 2881
            unless $Clobber;
2882
        return;
2883
    }
2884
 
2885
    #
2886
    #   Create a name for this package in the sandbox
2887
    #   Must use the package name and extension. Don't use the version
2888
    #   information as this will not be correct
2889
    #
2890
    #   PACKAGE/sandbox.PRJ.cfg
2891
    #
2892
    my $link_dir = "$sandbox_dpkg_archive/$BUILDNAME_PACKAGE";
2893
    my $link_file = 'sandbox';
2894
       $link_file .= '.' . $BUILDNAME_PROJECT if ( $BUILDNAME_PROJECT );
2895
       $link_file .= '.cfg';
2896
    my $link_path = "$link_dir/$link_file";
2897
 
2898
    if ( $Clobber )
2899
    {
2900
        unlink $link_path;          # Delete the link
2901
        rmdir $link_dir;            # Delete only if empty
2902
    }
2903
    else
2904
    {
261 dpurdie 2905
        Log( "Sandbox cfg. $link_file");
227 dpurdie 2906
        unlink $link_path;
2907
        mkdir $link_dir;
2908
 
2909
        #
2910
        #   Create the sandbox config data structure
2911
        #
2912
        my %sandbox_info = (
2913
            BUILDDIR     => $Cwd,
2914
            INTERFACEDIR => $BUILDINTERFACE,
2915
            );
2916
 
2917
        #
2918
        #   Write out the Parsed Config File with new information
2919
        #
2920
        my $fh = ConfigurationFile::New( $link_path );
2921
        $fh->Header( "buildlib (version $::BuildVersion)",
2922
                                  "Sandbox configuration" );
2923
 
2924
        #
2925
        #   Dump out the configuration information
2926
        #
2927
        $fh->Dump( [\%sandbox_info], [qw(*sandbox_info)] );
2928
        $fh->Close();
2929
    }
2930
}
2931
 
2932
 
2933
#-------------------------------------------------------------------------------
2934
# Function        : BuildMake
2935
#
2936
# Description     : Generate the makefiles
2937
#                   This directive MUST be the last directive in the build.pl
2938
#                   file. The directive triggers the processing of all the
2939
#                   information that has been collected
2940
#
2941
#
2942
# Inputs          : None
2943
#
2944
# Returns         : Nothing
2945
#
2946
 
2947
sub BuildMake
2948
{
2949
    my( $argc, $platform );
2950
 
2951
    #
2952
    #   Must have a valid $BUILDINTERFACE
2953
    #   Normally this is held in the interface directory, but this is not
2954
    #   always created. If there is no $BUILDINTERFACE, then use the
2955
    #   build directory
2956
    #
2957
    $BUILDINTERFACE = "." unless ( $BUILDINTERFACE );
2958
 
2959
    #.. Starting the build phase. No more data collection
2960
    #
305 dpurdie 2961
    StartBuildPhase();
2962
    LastBuildDirective();
227 dpurdie 2963
 
2964
    sub DeleteCfg
2965
    {
2966
        #
2967
        #   Delete files that will be re-created
2968
        #   Some of these files are read and written.
2969
        #   Errors in the files are solved by deleting the files now.
2970
        #
2971
        unlink "$BUILDINTERFACE/build.cfg";
2972
        unlink "$BUILDINTERFACE/Makefile.cfg";
2973
        unlink glob ("$BUILDINTERFACE/Makefile*.cfg");
2974
        unlink "$BUILDINTERFACE/Buildfile.cfg";
2975
        unlink "$BUILDINTERFACE/Dpackage.cfg";
2976
    }
2977
 
2978
    if ( $Clobber )                             # clobber mode ?
2979
    {
2980
        if ( -e "Makefile.gbe" )
2981
        {
263 dpurdie 2982
            JatsTool ( 'jmake.pl', 'unmakefiles');
227 dpurdie 2983
            unlink "Makefile.gbe";
2984
        }
2985
 
2986
        DeleteCfg();
2987
 
2988
        #
2989
        #   JATS creates a 'pkg' directory for the target package
2990
        #
2991
        push @CLOBBERDIRS, "pkg";
2992
 
2993
        #
2994
        #   Deployment creates a 'build/deploy' directory
2995
        #
2996
        push @CLOBBERDIRS, "build/deploy";
2997
 
2998
        #
2999
        #   Delete interface directories and other directories that have been
3000
        #   marked to be clobberd
3001
        #
3002
        foreach my $dir ( @CLOBBERDIRS )
3003
        {
3004
            next if ( $dir eq '.' );
3005
            next if ( $dir eq '..' );
3006
            if ( -d $dir )
3007
            {
3008
                System( "$::GBE_BIN/chmod -fR +w $dir" );
3009
                System( "$::GBE_BIN/rm -rf $dir" );
3010
            }
3011
        }
3012
 
3013
        foreach my $file ( @CLOBBERFILES )
3014
        {
3015
            if ( -f $file )
3016
            {
3017
                System( "$::GBE_BIN/chmod -fR +w $file" );
3018
                System( "$::GBE_BIN/rm -f $file" );
3019
            }
3020
        }
3021
 
3022
        #
3023
        #   DPACKAGE may be a user file, Only delete it if we created it
3024
        #
299 dpurdie 3025
        unlink "$Srcdir/DPACKAGE.$::GBE_MACHTYPE" if $DeleteDPACKAGE;
227 dpurdie 3026
 
3027
        BuildPackageLink();
3028
        BuildSandboxData();
3029
        return;
3030
    }
3031
 
3032
    #.. Build support files
3033
    #
3034
    DeleteCfg();
3035
    BuildConfig();
3036
    BuildRuleFiles();
3037
    BuildSharedLibFiles();
3038
    LinkClean();                                # clean previous images
3039
    WriteParsedBuildConfig();
3040
    BuildPackageLink();
3041
    BuildSandboxData();
3042
 
3043
    #
3044
    #  ONLY (re)building interface dir
3045
    #
3046
    return
3047
        if ( $Interface );
3048
 
3049
    #---------------------------------------------------------------------------
3050
    #
3051
    #.. Make bootstrap "makefile",
3052
    #   Simulate a top level makefile
3053
    #       Pass argumenst to makelib
3054
    #       Sumulate SubDir() operations
3055
    #       Sumulate a Platform(*);
3056
    #
3057
    #       Due to the normal way that makelib.pl is executed,
3058
    #       the following substitutions are done.
3059
    #
3060
    @ARGV = ();
3061
    $0 = "makefile.pl ";
3062
    push @ARGV, "$Cwd";                         # current working directory
3063
    push @ARGV, "$::MAKELIB_PL";                # makelib.pl image
3064
    push @ARGV, "--interface=$BUILDINTERFACE"
261 dpurdie 3065
        if ($BUILDINTERFACE);
227 dpurdie 3066
 
3067
    Debug( "ARGV:      @ARGV" );
3068
 
3069
    #.. (re)Build root makefile
3070
    #
3071
    $ScmBuildlib = 0;                           # clear Buildlib flag for 'makelib.pl'
3072
    RootMakefile();                             # inform 'makelib.pl'
3073
    MakeLibInit();                              # run initialisation
3074
 
3075
 
3076
    #.. Register subdir(s)
3077
    #
3078
    UniquePush (\@BUILDSUBDIRS, $Srcdir );
3079
    SubDir( @BUILDSUBDIRS );
3080
    Platform( @BUILD_ACTIVEPLATFORMS );
3081
 
3082
    #.. (re)build src makefiles and associated information
3083
    #
263 dpurdie 3084
    my @cmds = ('jmake.pl', 'rebuild');
227 dpurdie 3085
    push @cmds, 'NORECURSE=1' if ( $RootOnly );
3086
 
263 dpurdie 3087
    JatsTool ( @cmds);
305 dpurdie 3088
 
3089
    #
3090
    #   Generate some warnings that will be seen at the end of the build
3091
    #
3092
    Warning ("BuildSrcArchive Directive Present","Read JATS Manual for correct usage")
3093
        if ($build_source_pkg);
227 dpurdie 3094
}
3095
 
3096
 
3097
#-------------------------------------------------------------------------------
3098
# Function        : BuildVersion
3099
#
3100
# Description     : Generate version.c and version.h files
3101
#
3102
# Inputs          : Options
3103
#                       --Prefix=prefix         Text prepended to variables created
3104
#                                               as a part of the "C" versions
3105
#                       --Type=type             Type of "C" style data
3106
#                                               Allowed types are: array
3107
#                       --Defs=name             Generate a "C" definitions file.
3108
#                                               This file simply contains definitions
3109
#                       --Defs                  Same as --Defs=defs
3110
#                       --Style=style           Output file style
3111
#                                               Supported styles:
3112
#                                                   "C" - Default
3113
#                                                   "CSharp"
3114
#                                                   "WinRC"
289 dpurdie 3115
#                                                   "Delphi"
227 dpurdie 3116
#                       --File=name             Specifies the output file name
3117
#                                               Default is determined by the style
3118
#
3119
#                   Also allows for an 'old' style format in which
3120
#                   the first three arguments are prefix,type and defs
3121
# Returns         :
3122
#
3123
 
3124
sub BuildVersion
3125
{
3126
    my ( $Prefix, $Type, $Mode ) = @_;
3127
    my $ModePrefix;
3128
    my $Style = "C";
3129
    my $FileName;
3130
    my $VersionFiles;
267 dpurdie 3131
    my @opts;
3132
    my $supports_opts;
227 dpurdie 3133
 
3134
    StartBuildPhase();                          # Starting the build phase. No more data collection
3135
 
279 dpurdie 3136
    if ( defined($Prefix) && $Prefix =~ /^-/ )
227 dpurdie 3137
    {
3138
        $Prefix = undef;
3139
        $Type = undef;
3140
        $Mode = undef;
3141
        foreach  ( @_ )
3142
        {
3143
            if (      /^--Prefix=(.*)/ ) {
3144
                $Prefix = $1;
3145
                $VersionFiles = 1;
3146
 
3147
            } elsif ( /^--Type=(.*)/ ) {
3148
                $Type = $1;
3149
                $VersionFiles = 1;
3150
 
3151
            } elsif ( /^--Defs=(.*)/ ) {
3152
                $Mode = $1;
3153
                $ModePrefix = "_$1";
3154
 
3155
            } elsif ( /^--Defs$/ ) {
3156
                $Mode = 'defs';
3157
                $ModePrefix = "";
3158
 
3159
            } elsif ( /^--Style=(.*)/ ) {
3160
                $Style = $1;
279 dpurdie 3161
                $VersionFiles = 1;
267 dpurdie 3162
                $supports_opts = 1 if ( $Style =~ /^WinRC/i );
227 dpurdie 3163
 
3164
            } elsif ( /^--File=(.*)/ ) {
3165
                $FileName = $1;
3166
 
267 dpurdie 3167
            } elsif ($supports_opts ) {
3168
                push @opts, $_;
235 dpurdie 3169
 
227 dpurdie 3170
            } else {
3171
                Error ("BuildVersion: Unknown option: $_");
3172
 
3173
            }
3174
        }
3175
    }
3176
    else
3177
    {
3178
        #
3179
        #   Old style positional arguments.
3180
        #
3181
        $VersionFiles = 1;
3182
        if ( defined( $Mode ) )
3183
        {
3184
            if ( $Mode =~ m/^defs(=(.*))?$/i )
3185
            {
3186
                $Mode       = $2 ? $2    : 'defs';
3187
                $ModePrefix = $2 ? "_$2" : "";
3188
            }
3189
            else
3190
            {
3191
                Error ("BuildVersion: Bad Mode argument. Need 'defs' or 'defs=name'");
3192
            }
3193
        }
3194
    }
3195
 
3196
    #
3197
    #   Determine the style of version file to create
3198
    #
3199
    if ( $Style =~ /^CSharp/i ) {
3200
        BuildVersionCSharp( $FileName );
3201
 
229 dpurdie 3202
    } elsif ( $Style =~ /^Properties/i ) {
3203
        BuildVersionProperties( $FileName, $Prefix );
3204
 
227 dpurdie 3205
    } elsif ( $Style =~ /^WinRC/i ) {
267 dpurdie 3206
        BuildVersionWinRC( $FileName, @opts );
227 dpurdie 3207
 
289 dpurdie 3208
    } elsif ( $Style =~ /^Delphi/i ) {
3209
        BuildVersionDelphi( $FileName, $Prefix );
3210
 
227 dpurdie 3211
    } elsif ( $Style eq "C" ) {
289 dpurdie 3212
        BuildVersionC    ( $FileName, $Prefix, $Type )     if ( $VersionFiles );
3213
        BuildVersionCdefs( $FileName, $Mode, $ModePrefix ) if ( $Mode );
227 dpurdie 3214
 
3215
    } else {
3216
        Error("BuildVersion: Unknown style: $Style");
3217
    }
3218
}
3219
 
3220
#-------------------------------------------------------------------------------
3221
# Function        : BuildDescpkg
3222
#
3223
# Description     : Create a package description file
3224
#                   The format of this file matches that generated by JANTS
3225
#                   Take care when extending the format
3226
#
3227
#                   NOTE: It turns out that JANTS is not a standard and the
3228
#                         implementors (of JANTS) kept on changing it.
3229
#
3230
# Inputs          :
3231
#
3232
# Returns         :
3233
#
3234
sub BuildDescpkg
3235
{
3236
    StartBuildPhase();                          # Starting the build phase. No more data collection
3237
 
247 dpurdie 3238
    #
3239
    #   Store the files location for use at runtime
3240
    #   It will be a file that is 'known' to JATS
3241
    #
3242
    my $pkgfile = BuildAddKnownFile ( $Srcdir, 'descpkg' );
3243
    return if ( $Clobber );                 # clobber mode ?
227 dpurdie 3244
 
261 dpurdie 3245
    my @desc;
279 dpurdie 3246
    push @desc, "Package Name:  $BUILDNAME_PACKAGE";
3247
    push @desc, "Version:       $BUILDVERSION";
3248
    push @desc, "Released By:   $::USER";
3249
    push @desc, "Released On:   $::CurrentTime";
3250
    push @desc, "Build Machine: $::GBE_HOSTNAME";
3251
    push @desc, "Path:          $Cwd";
3252
    push @desc, "Jats Version:  $::GBE_VERSION";
3253
    push @desc, "Jats Path:     $::GBE_CORE";
261 dpurdie 3254
    push @desc, "";
3255
    push @desc, "Build Dependencies:";
3256
    push @desc, "";
227 dpurdie 3257
 
3258
    foreach my $tag ( PackageEntry::GetPackageList )
3259
    {
3260
        my ($name, $version, $type) = PackageEntry::GetPackageData($tag);
3261
 
3262
        my @attributes;
3263
 
3264
        push @attributes, "name=\"$name\"";
3265
        push @attributes, "version=\"$version\"";
3266
        push @attributes, "build=\"true\"" if $type =~ /Build/i;
3267
 
261 dpurdie 3268
        push @desc, "<sandbox @attributes/>";
227 dpurdie 3269
    }
247 dpurdie 3270
 
261 dpurdie 3271
    FileCreate ($pkgfile, \@desc );
227 dpurdie 3272
}
3273
 
3274
#-------------------------------------------------------------------------------
3275
# Function        : BuildIncpkg
3276
#
3277
# Description     : Create a package inclusion file
3278
#
3279
# Inputs          :
3280
#
3281
# Returns         :
3282
#
3283
sub BuildIncpkg
3284
{
3285
    StartBuildPhase();                          # Starting the build phase. No more data collection
3286
    if ( $Clobber )                             # clobber mode ?
3287
    {
3288
        System( "$::GBE_BIN/rm -f $Srcdir/incpkg" );
3289
        return;
3290
    }
3291
 
3292
    my $fh = ConfigurationFile::New( "$Srcdir/incpkg" );
3293
    $fh->Header( "buildlib (Version $BuildVersion)",
3294
                              "Package inclusion list" );
3295
 
3296
    foreach my $tag ( PackageEntry::GetPackageList )
3297
    {
3298
        my ($name, $version, $type) = PackageEntry::GetPackageData($tag);
3299
        $type = ($type =~ /build/i) ? "Build" : "Link";
3300
 
3301
        $fh->Write( "${type}PkgArchive( '$name', '$version' );\n" );
3302
    }
3303
 
3304
    $fh->Close();
3305
}
3306
 
3307
#-------------------------------------------------------------------------------
3308
# Function        : BuildConfig
3309
#
3310
# Description     : Create the file interface/build.cfg
3311
#                   This file contains information gathered by the build process
3312
#                   that is to be used when makefiles are created and re-created
3313
#
3314
# Inputs          : None
3315
#
3316
# Returns         : Nothing
3317
#
283 dpurdie 3318
sub BuildConfig
227 dpurdie 3319
{
3320
    Error( "No BuildInterface directive encountered\n" )
3321
        unless ($BUILDINTERFACE);
3322
 
3323
    my $fh = ConfigurationFile::New( "$BUILDINTERFACE/build.cfg");
3324
    $fh->Header( "buildlib (Version $BuildVersion)",
3325
                              "Makelib configuration file", "
3326
\$ScmBuildMachType              = \"$::GBE_MACHTYPE\";
3327
\$ScmInterfaceVersion           = \"$::InterfaceVersion\";
3328
\$ScmBuildName                  = \"$BUILDNAME\";
3329
\$ScmBuildPackage               = \"$BUILDNAME_PACKAGE\";
3330
\$ScmBuildVersion               = \"$BUILDNAME_VERSION\";
3331
\$ScmBuildProject               = \"$BUILDNAME_PROJECT\";
3332
\$ScmBuildVersionFull           = \"$BUILDVERSION\";
3333
\$ScmBuildPreviousVersion       = \"$BUILDPREVIOUSVERSION\";
3334
\$ScmLocal                      = \"$BUILDLOCAL\";
3335
\$ScmDeploymentPatch            = \"$DEPLOY_PATCH\";
3336
\$ScmSrcDir                     = \"$Srcdir\";
3337
\$ScmBuildSrc                   = \"$ScmBuildSrc\";
3338
\$ScmExpert                     = \"$Expert\";
261 dpurdie 3339
\$ScmAll                        = \"$All\";
227 dpurdie 3340
");
3341
 
3342
#.. Alias
3343
#
3344
    $fh->DumpData(
3345
        "\n# Aliases.\n#\n",
3346
        "ScmBuildAliases", \%BUILDALIAS );
3347
 
3348
#.. Products
3349
#
3350
    $fh->DumpData(
3351
        "# Product mapping.\n#\n",
3352
        "ScmBuildProducts", \%BUILDPRODUCT_PARTS );
3353
 
3354
#.. Create ScmBuildPlatforms
3355
#
3356
    my( @platforms_merged, %platform_args ) = ();
3357
 
3358
    UniquePush ( \@platforms_merged, @BUILDPLATFORMS );
3359
 
3360
    foreach my $key ( keys %BUILDPRODUCT ) {
3361
        my( @list ) = split( ' ', $BUILDALIAS{ $key } || '' );
3362
        my( $platform );
3363
 
3364
        foreach my $elem ( @list ) {
3365
            if ( $elem =~ /^--/ ) {             # argument
3366
                HashJoin( \%platform_args, $;, $platform, $elem )
3367
                    if ( defined($platform) );
3368
                next;
3369
            }
3370
            $platform = $elem;                  # platform
3371
            UniquePush( \@platforms_merged, $elem );
3372
        }
3373
    }
3374
 
3375
#.. Create ScmBuildPlatforms
3376
#   Contains per platform options extracted from alias and platform args
3377
#
3378
    my %ScmBuildPlatforms;
3379
    foreach my $key ( @platforms_merged ) {
3380
 
3381
        my( @arguments ) = ();
3382
        UniquePush( \@arguments, split( /$;/, $BUILDPLATFORMARGS{ $key } ))
3383
            if ( exists $BUILDPLATFORMARGS{ $key } );
3384
 
3385
        UniquePush( \@arguments, split( /$;/, $platform_args{ $key } ))
3386
            if ( exists $platform_args{ $key } );
3387
 
3388
        $ScmBuildPlatforms{$key} = join "$;", @arguments;
3389
    }
3390
 
3391
    $fh->DumpData(
3392
        "# Platform and global argument list.\n#\n",
3393
        "ScmBuildPlatforms", \%ScmBuildPlatforms );
3394
 
3395
 
3396
# .. Create BuildPkgRules
3397
#
3398
#    This most of the information contained within %PKGRULES, which
3399
#    requires additional processing within makelib.
3400
#
3401
    my %ScmBuildPkgRules;
3402
    foreach my $platform ( keys %PKGRULES )
3403
    {
3404
        foreach my $package ( @{$PKGRULES{$platform}} )
3405
        {
3406
            my %entry;
3407
 
3408
            $entry{ROOT}     = $package->{'base'};
3409
            $entry{NAME}     = $package->{'name'};
3410
            $entry{VERSION}  = $package->{'version'};
3411
            $entry{DNAME}    = $package->{'dname'};
3412
            $entry{DVERSION} = $package->{'dversion'};
3413
            $entry{DPROJ}    = $package->{'dproj'};
3414
            $entry{TYPE}     = $package->{'type'};
3415
            $entry{CFGDIR}   = $package->{'cfgdir'} if ( defined( $package->{'cfgdir'} ) );
3416
 
3417
 
3418
            foreach my $dir (qw (PINCDIRS PLIBDIRS TOOLDIRS THXDIRS) )
3419
            {
3420
                $entry{$dir} = $package->{$dir} ;
3421
            }
3422
 
3423
            push @{$ScmBuildPkgRules{$platform}}, \%entry;
3424
        }
3425
    }
3426
 
3427
    $fh->DumpData(
3428
        "# Imported packages.\n#\n",
3429
        "ScmBuildPkgRules", \%ScmBuildPkgRules );
3430
 
3431
#
3432
#   BUILDPLATFORMS,
3433
#       The value that is saved only contains the active platforms
3434
#
3435
#   DEFBUILDPLATFORMS,
3436
#       The value that is matchs the wildcard specification for Platform 
3437
#       directives.
3438
#
3439
    $fh->DumpData(
3440
        "# A list of platforms active within the view.\n#\n",
3441
        "BUILDPLATFORMS", \@BUILD_ACTIVEPLATFORMS );
3442
 
3443
    $fh->DumpData(
3444
        "# A list of default platforms within the view.\n#\n",
3445
        "DEFBUILDPLATFORMS", \@DEFBUILDPLATFORMS );
3446
 
3447
#
3448
#   BUILDTOOLS
3449
#       A list of toolset extension paths
3450
#
3451
    $fh->DumpData(
3452
        "# A list of paths with toolset extension programs.\n#\n",
3453
        "BUILDTOOLSPATH", \@BUILDTOOLS );
3454
 
3455
#
3456
#   BUILDPLATFORM_PARTS
3457
#       A subset of BUILDINFO exported as BUILDPLATFORM_PARTS
3458
#       This exists only for backward compatability with existing code
3459
#       in external packages ( deployfiles).
3460
#
3461
#   Only save those parts that are part of the current build
3462
#   This will prevent users attempting to build for platforms that have not
3463
#   been correctly constructed.
3464
#
3465
    my %active =  map { ${_} => 1 } @BUILD_ACTIVEPLATFORMS;
3466
    my %active_buildplatform_parts;
3467
    my %active_build_info;
3468
    foreach ( keys %BUILDINFO )
3469
    {
3470
        next unless ( $active{$_} );
3471
        $active_buildplatform_parts{$_} = $BUILDINFO{$_}{PARTS};
3472
        $active_build_info{$_}          = $BUILDINFO{$_};
3473
    }
3474
 
3475
    $fh->DumpData(
3476
        "# Parts of all platforms.\n#\n",
3477
        "BUILDPLATFORM_PARTS", \%active_buildplatform_parts );
3478
#
3479
#   BUILDINFO
3480
#       Complete TARGET Information
3481
#
3482
    $fh->DumpData(
3483
        "# Extended build information.\n#\n",
3484
        "BUILDINFO", \%active_build_info );
3485
 
3486
#
247 dpurdie 3487
#   BUILD_KNOWNFILES
3488
#       All paths are relative to the project root directory
3489
#       ie: The directory that conatins the build.pl file
3490
#
3491
    $fh->DumpData(
3492
        "# Generated Files that may be known when used as Src files.\n#\n",
3493
        "BUILD_KNOWNFILES", \%BUILD_KNOWNFILES );
3494
 
3495
#
227 dpurdie 3496
#   Close out the file
3497
#
3498
    $fh->Close();
3499
}
3500
 
3501
#-------------------------------------------------------------------------------
3502
# Function        : WriteParsedBuildConfig
3503
#
3504
# Description     : Write all the parsed build.pl data to a single file
3505
#                   Its all in there for use
3506
#
3507
# Inputs          : 
3508
#
3509
# Returns         : 
3510
#
3511
sub WriteParsedBuildConfig
3512
{
3513
    my $cfg_file = "$::BUILDINTERFACE/Buildfile.cfg";
3514
    my %cf_build_info = ();
3515
 
3516
    #
3517
    #   Examine the symbol table and capture most of the entries
3518
    #
3519
    foreach my $symname (keys %main::)
3520
    {
3521
        next if ( $symname =~ m/::/  );                 # No Typeglobs
3522
        next if ( $symname =~ m/^cf_build_info/  );     # Not myself
3523
        next unless ( $symname =~ m/^[A-Za-z]/  );      # No system type names
3524
        next if ( $symname =~ m/^SIG$/  );              # Useless
3525
        next if ( $symname =~ m/^ENV$/  );              # Don't keep the user ENV
3526
        next if ( $symname =~ m/^INC$/  );              # Don't keep the INC paths
3527
        next if ( $symname =~ m/^DEFINES/  );           # Don't keep
3528
        next if ( $symname =~ m/^TOOLSETRULES/  );      # Don't keep
3529
 
3530
        local *sym = $main::{$symname};
3531
 
3532
        $cf_build_info{"\$$symname"} =  $::sym if defined $::sym;
3533
        $cf_build_info{"\@$symname"} = \@::sym if defined @::sym;
3534
        $cf_build_info{"\%$symname"} = \%::sym if defined %::sym;
3535
    }
3536
 
3537
    #
3538
    #   Dump out the configuration information
3539
    #
3540
    my $fh = ConfigurationFile::New( "$cfg_file" );
3541
    $fh->Header( "buildlib (version $::BuildVersion)",
3542
                              "Buildfile configuration" );
3543
    $fh->Dump( [\%cf_build_info], [qw(*cf_build_info)] );
3544
    $fh->Close();
3545
}
3546
 
3547
 
3548
#-------------------------------------------------------------------------------
3549
# Function        : BuildRuleFiles
3550
#
3551
# Description     : Create a set of rule files in the interface directory
3552
#                   These will be included directly into makefiles to
3553
#                   extend library and header search paths to the Linked
3554
#                   archives
3555
#
3556
#                   One file is created for each platform to simplify the
3557
#                   inclusion rules
3558
#
3559
#
3560
#                   The PKGRULES data structure is of the form:
3561
#
3562
#                   A hash, by platform, of an array of package information
3563
#                   Each block of package information is a hash containing
3564
#                       'name'      -  short name of the package
3565
#                       'version'   -  short name of the package
3566
#                       'base'      - path of the package root
3567
#                       'PINCDIRS'  - Array of included directories
3568
#                       'PLIBDIRS'  - Array of library directories
3569
#
3570
#                   Arrays are used to preserve the user specified search
3571
#                   order, both of packages and directories within each
3572
#                   package
3573
#
3574
# Inputs          :
3575
#
3576
# Returns         :
3577
#
3578
sub BuildRuleFiles
3579
{
3580
    #
3581
    #   A file is generated for each platform
3582
    #   Within this lines are generated for each package
3583
    #
3584
    foreach my $platform ( keys %PKGRULES )
3585
    {
3586
        my $pPlatform = $PKGRULES{$platform};
3587
 
3588
        my $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/$platform.rul", '--NoEof', '--Type=mak' );
3589
        $fh->Header( "Buildlib ($BuildVersion)","Package import specification" );
3590
 
3591
        $fh->Write ( "PINCDIRS\t=\t\t" . "# includes\n" );
3592
        $fh->Write ( "PLIBDIRS\t=\t\t" . "# libraries\n" );
3593
        $fh->Write ( "\n" );
3594
 
3595
        #
3596
        #   For each Available package accessable to this platform
3597
        #
3598
        foreach my $package ( @{$pPlatform} )
3599
        {
311 dpurdie 3600
            #
3601
            #   Skip the pseudo package that encapsulates the interface
3602
            #   directory. Currently the makefiles do this in a different
3603
            #   manner - to be resolved
3604
            #
3605
            #   Just comment out the lines so that the data is visible
3606
            #   Its a hint to make use of the data
3607
            #
3608
            my $prefix = '';
3609
            $prefix = '# ' if ( $package->{'type'} eq 'interface' );
3610
 
3611
 
227 dpurdie 3612
            my $name = $package->{'name'} . '/' . $package->{'version'};
3613
            my $base = $package->{'base'};
3614
 
3615
            $fh->Write ( "##########################################################\n");
3616
            $fh->Write ( "# Source:  $name\n" );
3617
            $fh->Write ( "#\n" );
3618
 
3619
            #
3620
            #   List include and library directories
257 dpurdie 3621
            #   Need the True Path for windows.
3622
            #       Some makefile functions (wildcard) only work as expected
3623
            #       if the case of the pathname is correct. Really only a problem
3624
            #       with badly formed legecy packages where the Windows user
3625
            #       guessed at the package format.
227 dpurdie 3626
            #
257 dpurdie 3627
            #
227 dpurdie 3628
            for my $type (qw (PINCDIRS PLIBDIRS) )
3629
            {
3630
                for my $path ( @{$package->{$type}} )
3631
                {
311 dpurdie 3632
                    $fh->Write ( "$prefix$type\t+= " . TruePath($base . $path) . "\n" );
227 dpurdie 3633
                }
3634
            }
3635
            $fh->Write ( "\n" );
3636
        }
3637
        $fh->Close();
3638
    }
3639
}
3640
 
3641
#-------------------------------------------------------------------------------
3642
# Function        : BuildSharedLibFiles
3643
#
3644
# Description     : Create a file in the interface directory that will specify
3645
#                   the locations of shared libraries.
3646
#
3647
#                   Note: Always create a file as makefile targets depend on it.
3648
#
3649
#                   This is a bit ugly.
3650
#
3651
#                   There needs be an association between the build machine and
3652
#                   the target platform. Need to know if the current target is
3653
#                   native to the current build machine. If it is then we can
3654
#                   run tests on the machine and we then need to extend the
3655
#                   search path for the target.
3656
#
3657
#                   The BUILDINFO{EXT_SHARED} is used to control the creation of
3658
#                   the files by specifying the extension of the file.
3659
#
3660
# Inputs          : None
3661
#
3662
# Returns         :
3663
#
3664
sub BuildSharedLibFiles
3665
{
3666
    if ( $ScmHost eq "DOS" || $ScmHost eq "WIN" ) {
3667
        BuildSharedLibFiles_WIN(@_);
3668
 
3669
    } elsif ( $ScmHost eq "Unix" ) {
3670
        BuildSharedLibFiles_Unix(@_);
3671
 
3672
    } else {
3673
        Error("Cannot build. Unknown machine type: $ScmHost",
3674
              "Need WIN, DOS or Unix" );
3675
    }
3676
}
3677
 
3678
#-------------------------------------------------------------------------------
3679
# Function        : BuildSharedLibFiles_WIN
3680
#
3681
# Description     : Implementation of BuildSharedLibFiles for Windows
3682
#
3683
# Inputs          : None
3684
#
3685
sub BuildSharedLibFiles_WIN
3686
{
3687
 
3688
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
3689
    {
3690
        next unless ( exists $BUILDINFO{$platform}{EXT_SHARED} );
3691
        my @dos_paths = BuildSharedLibFiles_list( $platform, $BUILDINFO{$platform}{EXT_SHARED} );
3692
 
3693
        #
3694
        #   Create a .bat file for WIN32
3695
        #   This may be consumed by user wrapper programs
3696
        #
229 dpurdie 3697
        #   Features: No Echo
3698
        #             Use of SETLOCAL to prevent pollution of environment
3699
        #
227 dpurdie 3700
        my $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/set_$platform.bat", '--NoEof', '--Type=bat' );
229 dpurdie 3701
        $fh->Write ( "\@echo off\n");
227 dpurdie 3702
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
229 dpurdie 3703
        $fh->Write ( "\nSETLOCAL\n");
227 dpurdie 3704
        foreach ( reverse @dos_paths )
3705
        {
3706
            $_ =~ s~/~\\~g;
3707
            $fh->Write ( "PATH=$_;\%PATH\%\n" );
3708
        }
3709
        $fh->Write ( "\n%*\n" );
229 dpurdie 3710
        $fh->Write ( "\nENDLOCAL\n");
231 dpurdie 3711
        $fh->Write ( "EXIT /B %ERRORLEVEL%\n");
227 dpurdie 3712
        $fh->Close();
3713
 
3714
        #
3715
        #   Create a .sh file for WIN32
3716
        #   This may be consumed by a shell - as used within JATS
3717
        #
3718
        $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/set_$platform.sh", '--NoEof', '--Type=sh' );
3719
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
3720
        foreach ( reverse @dos_paths )
3721
        {
3722
            tr~\\/~/~s;
3723
            $fh->Write ( "PATH=$_\\;\$PATH\n" );
3724
        }
287 dpurdie 3725
        $fh->Write ( "\n" . '[ -n "$*" ] && "$@"'  ."\n" );
227 dpurdie 3726
        $fh->Close();
3727
    }
3728
}
3729
 
3730
#-------------------------------------------------------------------------------
3731
# Function        : BuildSharedLibFiles_Unix
3732
#
3733
# Description     : Implementation of BuildSharedLibFiles for Unix
3734
#                   Extend the Shared Library search path via LD_LIBRARY_PATH
3735
#
3736
# Inputs          : None
3737
#
3738
sub BuildSharedLibFiles_Unix
3739
{
3740
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
3741
    {
3742
        next unless ( exists $BUILDINFO{$platform}{EXT_SHARED} );
3743
        my @unix_paths = BuildSharedLibFiles_list( $platform, $BUILDINFO{$platform}{EXT_SHARED} );
3744
 
3745
        #
3746
        #   Create a .sh file for Unix
3747
        #
229 dpurdie 3748
        my $file = "$BUILDINTERFACE/set_$platform.sh";
3749
        my $fh = ::ConfigurationFile::New( $file , '--NoEof', '--Type=sh' );
227 dpurdie 3750
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
3751
        foreach ( reverse @unix_paths )
3752
        {
3753
            $fh->Write ( "export LD_LIBRARY_PATH=$_:\$LD_LIBRARY_PATH\n" );
3754
        }
275 dpurdie 3755
        $fh->Write ( "\n\"\$\@\"\n" );
227 dpurdie 3756
        $fh->Close();
229 dpurdie 3757
 
3758
        #
3759
        #   Make the file executable under unix
3760
        #
3761
        chmod 0755, $file;
227 dpurdie 3762
    }
3763
}
3764
 
3765
#-------------------------------------------------------------------------------
3766
# Function        : BuildSharedLibFiles_list
3767
#
3768
# Description     : Determine a list of Shared Library paths that can be used
3769
#                   by the current target
3770
#
3771
# Inputs          : $platform       - Current platform
3772
#                   $so             - Shared object extensions
3773
#
3774
# Returns         : List of search paths
3775
#
3776
sub BuildSharedLibFiles_list
3777
{
3778
    my ($platform, $so ) = @_;
3779
    my @paths;
3780
    my @parts = @{$BUILDINFO{$platform}{PARTS}};
3781
 
3782
    #
3783
    #   Paths from the current build
3784
    #       Local directory         - for installed components
3785
    #       Interface directory     - for BuildPkgArchives
3786
    #
3787
    if ( $BUILDLOCAL )
3788
    {
3789
        foreach ( @parts )
3790
        {
3791
            push @paths, AbsPath("$BUILDLOCAL/lib/$_");
3792
        }
3793
    }
3794
 
3795
    foreach ( @parts )
3796
    {
3797
            push @paths, AbsPath("$BUILDINTERFACE/lib/$_");
3798
    }
3799
 
3800
    #
289 dpurdie 3801
    #   $so may be a scalar of an array
311 dpurdie 3802
    #   Convert scalar to an array
289 dpurdie 3803
    #
3804
    my @solist = (ref($so) eq 'ARRAY') ? @$so : $so;
3805
 
3806
    #
227 dpurdie 3807
    #   For each LinkPkgArchive
3808
    #
3809
    foreach my $package ( @{$PKGRULES{$platform}} )
3810
    {
3811
        next unless ( $package->{'type'} eq 'link' );
3812
 
3813
        my $base = $package->{'base'};
3814
        for my $path ( @{$package->{'PLIBDIRS'}} )
3815
        {
289 dpurdie 3816
            my @so_libs;
3817
            push @so_libs, glob ( "$base$path/*$_") foreach ( @solist );
227 dpurdie 3818
            next unless scalar @so_libs;
3819
            push @paths, $base . $path;;
3820
        }
3821
    }
3822
 
3823
    #
3824
    #   Returns paths found
3825
    #
3826
    return @paths;
3827
}
3828
 
3829
#-------------------------------------------------------------------------------
247 dpurdie 3830
# Function        : BuildAddKnownFile
3831
#
3832
# Description     : Save the file as a file that will be known  to the JATS
3833
#                   makefiles. It will be available SRCS, but will not be a
3834
#                   part of any object list.
3835
#
3836
#                   Known Files will be deleted on clobber
3837
#
3838
# Inputs          : $path
3839
#                   $file
289 dpurdie 3840
#                   $noadd                    - Don't add to known
247 dpurdie 3841
#
3842
# Returns         : Path and filename
3843
#
3844
 
3845
sub BuildAddKnownFile
3846
{
289 dpurdie 3847
    my ($path, $file, $noadd) = @_;
247 dpurdie 3848
    $path .= '/'. $file;
289 dpurdie 3849
    $BUILD_KNOWNFILES {$file} = $path
3850
        unless ( defined($noadd) && $noadd);
247 dpurdie 3851
    push @CLOBBERFILES, $path;
3852
 
3853
    return $path;
3854
}
3855
 
3856
#-------------------------------------------------------------------------------
227 dpurdie 3857
# Function        : Usage
3858
#
3859
# Description     : Display program usage information
3860
#
3861
# Inputs          : args            - Text message to display
3862
#
3863
#                   $opt_help       - Level of verbose ness
3864
#
3865
# Returns         : Does not return
3866
#                   This function will exit
3867
#
3868
sub Usage
3869
{
3870
    my( $msg ) = @_;
3871
    my %usage_args;
3872
 
3873
    #
3874
    #   Create a hash of arguments for the pod2usage function
3875
    #
3876
    $usage_args{'-input'} = __FILE__;
3877
    $usage_args{'-exitval'} = 42;
3878
    $usage_args{'-message'} = "\nbuildlib $msg\n" if $msg;
3879
    $usage_args{'-verbose'} = $opt_help < 3 ? $opt_help - 1 : 3 if ( $opt_help );
3880
 
3881
    #
3882
    #   Generate nice help
3883
    #
3884
    pod2usage(\%usage_args);
3885
}
3886
 
3887
#-------------------------------------------------------------------------------
3888
#   Documentation
3889
#
3890
 
3891
=pod
3892
 
3893
=head1 NAME
3894
 
3895
jats sandbox bootstrap
3896
 
3897
=head1 SYNOPSIS
3898
 
3899
jats build [options] [command]
3900
 
3901
     [perl buildlib.pl [options] PWD [command]]
3902
 
3903
 
3904
 Options:
3905
    --help          - Display terse usage
3906
    --help --help   - Display verbose usage
3907
    --man           - Display internal manual
261 dpurdie 3908
    --verbose[=n]   - Set level of progress verbosity
3909
    --debug[=n]     - Set the debug level
227 dpurdie 3910
    --nolog         - Do not generate/update Changelog
3911
    --cache         - Cache packages in the local dpkg_package cache
3912
    --cache --cache - Forced refresh dependent packages in the local cache
3913
    --project       - Generate support files for external tools
3914
    --package       - Ignore packages that are not available and continue
3915
    --forcebuildpkg - Treat LinkPkgArchive directives as BuildPkgArchive
3916
                      Also suppress the use of symlinks so that the phsical
3917
                      file will be copied locally.
3918
 
3919
 Sticky settings:
3920
    --all           - Build for all platforms ignoring GBE_BUILDFILTER
261 dpurdie 3921
    --expert[=n]    - Relaxing dependency checks on the user makefiles
227 dpurdie 3922
 
3923
 Commands:
3924
    changelog       - Only update ChangeLog.
3925
    interface       - Only (re)build the interface tree, including ChangeLog.
3926
    rootonly        - Only (re)build the root directory.
3927
    clobber         - Remove generated build system (eg Makefiles).
3928
 
3929
 
3930
=head1 OPTIONS
3931
 
3932
=over 8
3933
 
3934
=item B<--help>
3935
 
3936
Print a brief help message and exits.
3937
 
3938
=item B<-help -help>
3939
 
3940
Print a detailed help message with an explanation for each option.
3941
 
3942
=item B<-man>
3943
 
3944
Prints the manual page and exits.
3945
 
261 dpurdie 3946
=item B<--verbose[=n]>
227 dpurdie 3947
 
261 dpurdie 3948
Increases program output.
227 dpurdie 3949
 
261 dpurdie 3950
If an argument is provided, then it will be used to set the level, otherwise the
3951
existing level will be incremented. This option may be specified multiple times.
227 dpurdie 3952
 
261 dpurdie 3953
=item B<-debug>
3954
 
227 dpurdie 3955
Increases program output. Enable internal debugging messages to generate detailed
3956
progress information.
3957
 
261 dpurdie 3958
If an argument is provided, then it will be used to set the level, otherwise the
3959
existing level will be incremented. This option may be specified multiple times.
3960
 
227 dpurdie 3961
=item B<--nolog>
3962
 
3963
Do not generate or update the ChangeLog maintained when a CVS directory is detected
3964
in the build directory.
3965
 
3966
=item B<--cache>
3967
 
3968
This option will cause dependent packages to be cached in the local
3969
dpkg_archive cache.
3970
 
3971
If the option is used twice then the packages will be forcibly refreshed.
3972
 
3973
=item B<--project>
3974
 
3975
This option is used to indicate that the build.pl is being processed by a full
3976
JATS environment and not by any pre-existing mechanism.
3977
 
3978
This option will prevent the generation of configuration batch files that are
3979
not required by the full environment.
3980
 
3981
=item B<--package>
3982
 
3983
This option will cause the build process to ignore packages that cannot be
3984
located. The package build may fail at a later stage.
3985
 
3986
This option is used by the Auto Build Tool to handle packages that may not be
3987
needed in all builds.
3988
 
3989
=item B<--forcebuildpkg>
3990
 
3991
This option will force LinkPkgArchive directives to be treated as
3992
BuildPkgArchive directives. The result is that the 'interface' directory will be
3993
populated with the contents of all dependent packages. Moreover, on a Unix
3994
machine, the files will be copied and not referenced with a soft link.
3995
 
3996
This may be useful for:
3997
 
3998
=over 8
3999
 
4000
=item * Remote Development
4001
 
4002
=item * Collecting header files for scanning
4003
 
4004
=item * Local modification of files for test/debug/development
4005
 
4006
=back
4007
 
4008
=item B<--all>
4009
 
4010
This option will cause the build process to generate makefiles for all
4011
possible build targets ignoring the use of GBE_BUILDFILTER.
4012
 
4013
This option is sticky. Once used in a build it will be retained when makefiles
4014
are rebuilt.
4015
 
261 dpurdie 4016
=item B<--expert[=n]>
227 dpurdie 4017
 
4018
This option causes the generation of makefiles with relaxed dependancy checks.
4019
 
261 dpurdie 4020
If an argument is provided, then it will be used to set the level, otherwise a
4021
level of '1' will be set.
4022
 
227 dpurdie 4023
The makefiles will have no dependancy between the makefiles and the JATS build
4024
files or the users makefile. If the user's makefile.pl is changed then JATS
4025
will not detect the change and will not rebuild the makefiles. The user manually
4026
force the rebuild with the command 'jats rebuild'.
4027
 
4028
This option should be used with care and with full knowledge of its impact.
4029
 
4030
This option is sticky. Once used in a build it will be retained when makefiles
261 dpurdie 4031
are rebuilt. It will only be lost when the next 'jats build' is perfromed.
227 dpurdie 4032
 
261 dpurdie 4033
The effect of the option can be changed when the makefiles are processed. This
4034
option simply sets the default' mode of operation.
4035
 
227 dpurdie 4036
=item B<changelog>
4037
 
4038
This command will only update the CVS change log.
4039
 
4040
=item B<interface>
4041
 
4042
This command will only build, or rebuild, the 'interface' directory and the
4043
changelog ( if required ).
4044
 
261 dpurdie 4045
This command will not build, or rebuild, the root directory. The build
227 dpurdie 4046
process will not recurse through the subdirectories creating makefiles.
4047
 
261 dpurdie 4048
=item B<rootonly>
4049
 
4050
This command will only build, or rebuild, the 'interface' directory, the
4051
changelog (if required) and the root-level makefiles.
4052
 
4053
The build process will not recurse through the subdirectories creating
4054
makefiles. These can be made on-demand by jats if a 'make' command is issued.
4055
 
227 dpurdie 4056
=item B<clobber>
4057
 
4058
This command will remove generated build system files and directories.
4059
 
4060
=back
4061
 
4062
=head1 DESCRIPTION
4063
 
4064
The default build process will parse the user's build.pl file and create the
4065
'interface' directory before creating makefiles for each target platform.
4066
 
4067
The 'build' process simply generates the build sandbox. It does not invoke the
4068
generated makefiles. This must be done by the user in a different phase.
4069
 
4070
The 'build' process need only be invoked if the build.pl file has changed. The
4071
generated makefiles will detected changes to the makefile.pl's and cause them to
4072
be generated as required. The 'build' step sets up the sandboxes external
4073
environment.
4074
 
4075
=head1 INVOCATION
4076
 
4077
This perl library (buildlib.pl) is not designed to be invoked directly by the
4078
user. It should be invoked through a 'build.pl' file. Moreover, for historical
4079
reasons, the build.pl is not easily invoked. It is best to only invoke the
4080
'build' process via the JATS wrapper scripts : jats.bat or jats.sh.
4081
 
4082
The build.pl file must be invoked with two fixed arguments, followed by user
4083
options and subcommands
4084
 
4085
=over 8
4086
 
4087
=item   1 The current working directory
4088
 
4089
This could have been derived directly by the program, rather than having it
4090
passed in.
4091
 
4092
=item   2 The absolute path to buildlib.pl (this library)
4093
 
4094
In practice this value is not used, but is provided for historical reasons.
4095
 
4096
=item   3 Options and commands may follow the first two mandatory arguments.
4097
 
4098
=back
4099
 
4100
The build.pl file must 'require' the buildlib.pl and makelib.pl. The preferred
4101
code is:
4102
 
4103
=over 8
4104
 
4105
    build.pl: First statements
4106
    $MAKELIB_PL     = "$ENV{ GBE_TOOLS }/makelib.pl";
4107
    $BUILDLIB_PL    = "$ENV{ GBE_TOOLS }/buildlib.pl";
4108
 
4109
    require         "$BUILDLIB_PL";
4110
    require         "$MAKELIB_PL";
4111
 
4112
=back
4113
 
4114
=cut
4115
 
4116
1;