Subversion Repositories DevTools

Rev

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