Subversion Repositories DevTools

Rev

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

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