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