Subversion Repositories DevTools

Rev

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