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