Subversion Repositories DevTools

Rev

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