Subversion Repositories DevTools

Rev

Rev 391 | Rev 2449 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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