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