Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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