Subversion Repositories DevTools

Rev

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

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