Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
363 dpurdie 1
########################################################################
7300 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). 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;
6133 dpurdie 26
use ToolsetFiles;
227 dpurdie 27
use Pod::Usage;
261 dpurdie 28
use Getopt::Long;
305 dpurdie 29
use File::Path;
5969 dpurdie 30
use XML::Writer;
5986 dpurdie 31
use ArrayHashUtils;
7301 dpurdie 32
use File::Find;
7310 dpurdie 33
use Storable qw(dclone);
34
#use Digest::SHA qw(sha1);
35
use Digest::SHA::PurePerl qw(sha1);
7301 dpurdie 36
use IPC::Open3;
227 dpurdie 37
 
38
our $BuildVersion           = "2.1.0";
39
 
40
#.. Switchs
41
#
42
our $ScmBuildlib            = 0;
43
our $ScmBuildSrc            = "";
44
 
45
our $CmdSwitch              = "";
46
our $Clobber                = 0;
47
our $Archive                = 0;
48
our $Interface              = 0;
49
our $RootOnly               = 0;
50
our $Perms                  = 0;
51
our $Expert                 = 0;
52
our $All                    = 0;
5109 dpurdie 53
our $Cache                  = $ENV{GBE_DPKG_CACHE_CTL} || 0;
261 dpurdie 54
our $NoPackageError         = 0;
227 dpurdie 55
our $ForceBuildPkg          = 0;
56
our $Srcdir                 = "";               # default source root
331 dpurdie 57
our $ForceBuild             = 1;
2078 dpurdie 58
our $IgnorePkgs             = 0;
4778 dpurdie 59
our $GenericBuild           = undef;            # Build System Generic Build Test
227 dpurdie 60
 
61
#.. Public symbols, referenced by many build.pl implementations
62
#
63
our $BUILDPREVIOUSVERSION   = "0.0.0";          # BuildPreviousVersion()
64
our @BUILDPLATFORMS         = ();               # BuildPlatforms()
65
our %BUILDINFO              = ();               # BuildInfo
66
our @DEFBUILDPLATFORMS      = ();
67
our %BUILDPLATFORMARGS      = ();
68
our @BUILD_ACTIVEPLATFORMS  = ();
69
our @BUILDSUBDIRS           = ();               # BuildSubDir()
70
our @BUILDSETENV            = ();               # BuildSetenv()
71
our $BUILDINTERFACE         = "";               # BuildInterface()
72
our $BUILDLOCAL             = "";               # BuildInterface()
73
our $BUILDDIRTREE           = "";               # BuildDirTree()
241 dpurdie 74
our @BUILD_BADNAME          = ();               # Unknown platforms
7309 dpurdie 75
our @GENERIC_TARGETS        = ();               # Generic targets - only one allowed
227 dpurdie 76
 
77
our $BUILDNAME              = "";               # BuildName()
78
our $BUILDVERSION           = "";               # BuildName()
79
our $BUILDNAME_PACKAGE;                         # Name
80
our $BUILDNAME_VERSION;                         # Version
81
our $BUILDNAME_PROJECT;                         # Project(optional)
359 dpurdie 82
our $BUILDNAME_SUFFIX;                          # Project (available)
227 dpurdie 83
our $DEPLOY_PATCH           = 0;                # Deplyment patch number
7301 dpurdie 84
our $BUILDSIGNATURE;                            # Source signature
227 dpurdie 85
 
86
our %BUILDALIAS_DELAY       = ();               # Delayed aliases
87
our %BUILDALIAS_TARGETS     = ();               # BuildAlias from --Targets
88
our %BUILDALIAS             = ();               # BuildAlias
89
our %BUILDPRODUCT           = ();               # BuildProduct
90
our %BUILDPRODUCT_PARTS     = ();               # BuildProduct parts
91
our %PKGRULES               = ();               # Package include and link rules
92
our @BUILDTOOLS             = ();               # Extended tool path
93
our $BUILDPHASE             = 0;                # In Build Phase
94
our @CLOBBERDIRS            = ();               # Directories to clobber
375 dpurdie 95
our @REMOVEDIRS             = ();               # Directories to remove - if empty
247 dpurdie 96
our %BUILD_KNOWNFILES       = ();               # Files that will be known
5679 dpurdie 97
our @BUILDEXCLUDE           = ();               # Platforms to be excluded
227 dpurdie 98
 
333 dpurdie 99
our $Makelib                = "";
263 dpurdie 100
our $GBE_CORE;                                  # Root of JATS
101
our $InterfaceVersion;                          # Interface directory format version
3967 dpurdie 102
our $ScmRoot;                                   # Package Root
263 dpurdie 103
our $ScmInterface;                              # Interface directory
363 dpurdie 104
our $ScmBuildFilter;                            # Build Filter when build was created
4003 dpurdie 105
our $NoBuild                = 0;                # Dummy Build under ABT only
7300 dpurdie 106
our $BUILD_UUID             = time() . substr(rand(),2); # Build Unique Identifier
227 dpurdie 107
 
108
my  $DeleteDPACKAGE         = 0;                # Must clobber DPACKAGE
305 dpurdie 109
my  $build_source_pkg       = 0;                # Flag to build source package
227 dpurdie 110
my  $opt_help               = 0;
6133 dpurdie 111
my  $pkgFromSandbox         = 0;                # Flags that we have imported a package from a sandbox
227 dpurdie 112
 
6133 dpurdie 113
my  $genToolsetPlatform     = 0;                # BuildToolset directive has been seen
114
my  $genToolsetActive       = 0;                # TOOLSET platform required:1, Error:2
115
my  $toolsetPlatform        = 'NONE';           # TOOLSET Display Value
116
my  @genToolsetArgs;                            # Args for a generated TOOLSET
117
 
227 dpurdie 118
BuildLibInit();
119
 
120
sub BuildLibInit
121
{
122
 
123
#.. Set environment
124
#
331 dpurdie 125
    EnvImport( 'GBE_VERSION' );
126
    EnvImport( 'GBE_BIN' );
127
    EnvImport( 'GBE_CORE' );
128
    EnvImport( 'GBE_PERL' );
129
    EnvImport( 'GBE_TOOLS' );
130
    EnvImport( 'GBE_CONFIG' );
131
    EnvImport( 'GBE_DPKG' );
132
    EnvImport( 'GBE_MACHTYPE' );
133
    EnvImport( 'USER' );
134
    EnvImport( 'GBE_HOSTNAME');
135
    EnvImport( 'GBE_DRV' )
136
        if ( $ScmHost ne 'Unix' );            # DOS or WIN special
227 dpurdie 137
 
4688 dpurdie 138
    EnvImportOptional ( 'GBE_DPKG_REPLICA','' );
227 dpurdie 139
    EnvImportOptional ( 'GBE_DPKG_STORE','' );
140
    EnvImportOptional ( 'GBE_DPKG_CACHE','' );
141
    EnvImportOptional ( 'GBE_DPKG_LOCAL','' );
142
    EnvImportOptional ( 'GBE_DPKG_SBOX' ,'' );
313 dpurdie 143
    EnvImportOptional ( 'GBE_DPLY'      ,'' );
341 dpurdie 144
    EnvImportOptional ( 'GBE_SANDBOX'   ,'' );
227 dpurdie 145
 
146
    EnvImportOptional ( 'GBE_PLATFORM' );           # optional PLATFORM filter
147
    EnvImportOptional ( 'GBE_BUILDFILTER' );        # optional BUILD filter       
148
    EnvImportOptional ( 'GBE_ABT' );                # optional ABT flags          
149
 
150
#.. Common stuff
151
#
152
    require "$::GBE_TOOLS/common.pl";
331 dpurdie 153
    CommonInit( 'buildlib' );
227 dpurdie 154
    Debug( "Version:   $BuildVersion" );
279 dpurdie 155
    Require( "$::GBE_CONFIG/PLATFORM", "PLATFORM_CFG.PM"  );
227 dpurdie 156
 
157
#.. Parse command line
158
#
159
    $ScmBuildSrc = $0;                          # Name of the build file
331 dpurdie 160
    $Cwd = shift @ARGV;
227 dpurdie 161
    $Cwd =~ tr~\\/~/~s;;                        # Need / in path, Remove doubles
3967 dpurdie 162
    $::ScmRoot = StripDrive($Cwd);
333 dpurdie 163
    $Makelib = shift @ARGV;                     # Only for legacy build.pl files
227 dpurdie 164
 
261 dpurdie 165
    Verbose ("Command Line: @ARGV");
313 dpurdie 166
    my $result = GetOptions( "help|h:+"      => \$opt_help,
167
                             "man:3"         => \$opt_help,
168
                             "debug:+"       => \$::ScmDebug,
169
                             "verbose:+"     => \$::ScmVerbose,
170
                             "expert:1"      => \$Expert,
171
                             "all"           => \$All,
331 dpurdie 172
                             "cache:+"       => \$Cache,
313 dpurdie 173
                             "package"       => \$NoPackageError,
2078 dpurdie 174
                             "nopackages"    => \$IgnorePkgs,
313 dpurdie 175
                             "forcebuildpkg" => \$ForceBuildPkg,
331 dpurdie 176
                             "force!"        => \$ForceBuild,
4778 dpurdie 177
                             "generic!"      => \$GenericBuild,
313 dpurdie 178
                             );
261 dpurdie 179
    Usage() if ( $opt_help || !$result );
227 dpurdie 180
 
331 dpurdie 181
    Debug( "Host:          ", $ScmHost );
182
    Debug( "Cwd:           ", $Cwd );
333 dpurdie 183
    Debug( "Makelib:       ", $Makelib );
331 dpurdie 184
    Debug( "BuildFile:     ", $ScmBuildSrc );
185
    Debug( "Debug:         ", $::ScmDebug );
186
    Debug( "Verbose:       ", $::ScmVerbose );
187
    Debug( "Expert:        ", $Expert );
188
    Debug( "All:           ", $All );
189
    Debug( "Cache:         ", $Cache );
190
    Debug( "package:       ", $NoPackageError );
191
    Debug( "ForcePkg  :    ", $ForceBuildPkg );
192
    Debug( "ForceBuild :   ", $ForceBuild );
4778 dpurdie 193
    Debug( "IgnorePkgs :   ", $IgnorePkgs );
194
    Debug( "GenericTest :  ", $GenericBuild );
227 dpurdie 195
 
196
#.. Command
197
#
3967 dpurdie 198
 
199
    $CmdSwitch = (lc shift @ARGV) if @ARGV;
331 dpurdie 200
    Debug( "CmdSwitch:     ", $CmdSwitch );
227 dpurdie 201
 
331 dpurdie 202
    if ( $CmdSwitch )
203
    {
204
        if ( $CmdSwitch eq "interface" ) {
205
            $Interface      = 1;
227 dpurdie 206
 
331 dpurdie 207
        } elsif ( $CmdSwitch eq "rootonly" ) {
208
            $RootOnly       = 1;
227 dpurdie 209
 
331 dpurdie 210
        } elsif ( $CmdSwitch eq "clobber" ) {
211
            $Clobber        = 1;
227 dpurdie 212
 
331 dpurdie 213
        } elsif ( $CmdSwitch eq "help" || $CmdSwitch eq "usage" ) {
214
            $opt_help = 1;
215
            Usage();
227 dpurdie 216
 
331 dpurdie 217
        } else {
218
            Usage( "(E) build. Unknown command \"$CmdSwitch\"" );
219
        }
220
    }
227 dpurdie 221
 
331 dpurdie 222
    #
341 dpurdie 223
    #   If we are not performing a ForceBuild, then we don't need to continue
224
    #   We have updated the interface directory with BuildPkgArchive
225
    #   information.
331 dpurdie 226
    #
341 dpurdie 227
    unless ( $::GBE_SANDBOX )
331 dpurdie 228
    {
341 dpurdie 229
        TestForForcedBuild();
227 dpurdie 230
    }
231
 
232
    #
233
    #   Must inform makelib that its running under buildlib
234
    #
235
    $ScmBuildlib = 1;
236
 
237
    #
238
    #   In clobber mode System commands will not force termination
239
    #   otherwise, within build.pl, a failed system command will die.
240
    #
241
    SystemConfig ('UseShell' => 1,
283 dpurdie 242
                  'ExitOnError' => ($Clobber == 0) );
5109 dpurdie 243
 
244
    #
245
    #   Capture messages while processing directives
246
    # 
247
    StartCapture(1) 
248
        unless ($Clobber);
227 dpurdie 249
}
250
 
251
 
252
#-------------------------------------------------------------------------------
253
# Function        : Log
254
#
255
# Description     : Internal function to generate a log file of the build process
341 dpurdie 256
#                   The function will print its arguments to the screen and a log file
227 dpurdie 257
#
258
# Inputs          : Arguments will be printed
259
#
260
# Returns         : Nothing
261
#
262
sub Log
263
{
264
    if ( ! $Clobber )
265
    {
261 dpurdie 266
        print "@_\n";
267
        FileAppend ('build.log', \@_ );
227 dpurdie 268
    }
269
}
270
 
271
#-------------------------------------------------------------------------------
272
# Function        : BuildSubDir
273
#
274
# Description     : Specify one or more directories in which makefile.pl's can be
275
#                   found to be processed.
276
#
277
#                   This function will flag the build 'src' dir.
278
#                   This will be the first directory specified UNLESS there
279
#                   is a 'src' directory in the list
280
#
281
#                   The function may be called multiple times.
282
#
283
# Inputs          : NewDirs             - An array of directories
284
#
285
# Returns         : Nothing
286
#
287
 
288
sub BuildSubDir
289
{
290
    my( @NewDirs );
291
 
292
    @NewDirs = map { split /\s+/ } @_;
293
    @NewDirs = grep { defined $_ } @NewDirs;
294
 
295
    Debug( "BuildSubDir(@NewDirs)" );
296
 
297
    foreach my $ThisDir ( @NewDirs )
298
    {
299
        unless ( $Clobber )
300
        {
2450 dpurdie 301
            $ThisDir =~ s~/+$~~;
227 dpurdie 302
            if ( $ThisDir eq "." )
303
            {
304
                Error( "BuildSubDir() cannot specify the current directory (.)",
305
                       "The makefile.pl in the root directory is included in all makefile.pl's" );
306
            }
307
 
308
            if ( $ThisDir =~ m~\\~)
309
            {
310
                Warning ("BuildSubDir contains a '\\' character: $ThisDir" );
311
            }
312
            if ( grep /^$ThisDir$/, @BUILDSUBDIRS )
313
            {
314
                Warning( "BuildSubDir() duplicate subdirectory ignored '$ThisDir'." );
315
                next;
316
            }
317
            if ( ! ( -e $ThisDir and -d $ThisDir ) )
318
            {
319
                Error( "BuildSubDir() non-existent subdirectory: '$ThisDir'." );
320
            }
321
            if ( ! -f $ThisDir . '/makefile.pl' )
322
            {
323
                Error( "BuildSubDir() makefile.pl not found in subdirectory: '$ThisDir'." );
324
            }
325
 
326
            push( @BUILDSUBDIRS, $ThisDir );
327
        }
328
 
329
        #
330
        #   Capture the first source directory mentioned
331
        #   This will be used as the root of the build
332
        #
333
        #   If there is a Src directory then use this
334
        #
335
        $Srcdir = $ThisDir
336
            if ( $ThisDir =~ m/^src$/i );
337
        $Srcdir = $ThisDir
338
            unless ( $Srcdir );
339
    }
340
}
341
 
342
#-------------------------------------------------------------------------------
6133 dpurdie 343
# Function        : isKeyword 
344
#
345
# Description     : Test for an attempt to use reserved platform name 
346
#
347
# Inputs          : $test   - Name to test
348
#
349
# Returns         : Reserved word or none
350
#
351
sub isKeyword
352
{
353
    my ($test) = @_;
7307 dpurdie 354
    foreach my $keyword ( @PlatformConfig::BuildKeywords )
6133 dpurdie 355
    {
356
        return $keyword if (uc($test) eq $keyword);
357
    }
358
 
359
    return undef;
360
}
361
 
362
 
363
#-------------------------------------------------------------------------------
227 dpurdie 364
# Function        : BuildAlias
365
#
366
# Description     : Create an alias for multiple targets
367
#                   The default operations will:
368
#                       Add the alias as a default platform (* in the makefile.pl)
369
#                       Perform an implicit BuildPlatform for the alias targets
370
#
371
#                   In hindsight this was not good. Options modify the behaviour
372
#                   Options:
373
#                       --NotDefault    The alias will not be a part of the default
374
#                                       platform for the makefile.pls
375
#                       --Define        Simply define text substitution
376
#                                       Do not implicitly create platforms
377
#                       --Target        Accumulate platforms with specified targets
378
#                                       Complete alias determination is delayed
379
#                                       The named targets are specified as an alias
380
#                                       until the calculation is done
381
#
382
# Inputs          : alias[,--options]   comma seperated options
383
#                   arguments           alias arguments; platforms or targets
384
#
385
# Returns         : Nothing
386
#
387
sub BuildAlias
388
{
389
    my( $alias, @arguments ) = @_;
390
    my $notdefault;
391
    my $define;
392
    my $target_mode;
393
 
394
    Debug( "BuildAlias($alias, @arguments)" );
395
    Error ("BuildAlias: No platforms specified") unless ( @arguments );
396
    Error( "BuildAlias() must appear before BuildName()..." ) if ( $BUILDNAME );
397
 
398
    #   Parse attributes
399
    #
400
    my ( @attrs ) = split( ',', $alias );
401
 
402
    $alias = "";
403
    foreach ( @attrs ) {
404
        if ( /^--/ ) {
405
            if ( /^--NotDefault$/ ) {
406
                $notdefault = 1;
407
 
408
            } elsif ( /^--Define$/ ) {
409
                $define = 1;
410
 
411
            } elsif ( /^--Target$/ ) {
412
                $target_mode = 1;
413
 
414
            } else {
415
                Warning( "BuildAlias() unknown attribute: $_ -- ignored" );
416
            }
417
 
418
        } else {
5262 dpurdie 419
            Error( "BuildAlias() multiple alias specifications", "First: $alias and now $_" )
227 dpurdie 420
                if ( $alias ne "" );
421
            $alias = $_;
422
        }
423
    }
424
    Error( "BuildAlias() missing alias specifications" )
425
        if ( $alias eq "" );
426
 
7307 dpurdie 427
    if ( isKeyword($alias) ) {
428
        Error   ("BuildAlias() attempt to alias a keyword: $alias") unless defined($::GBE_ABT);
429
        Warning ("BuildAlias() attempt to alias a keyword: $alias -- builtin ignored");
430
    }
227 dpurdie 431
 
432
    #
433
    #   If we need to recalculate the alias based on targets, then tag the alias
434
    #   to be processed
435
    #
436
    $BUILDALIAS_TARGETS{ $alias } = ''
437
        if ( $target_mode );
438
 
439
    #   Define alias
440
    #
6133 dpurdie 441
    if ( PlatformConfig::targetHasTag($alias, 'GENERIC') )
227 dpurdie 442
    {
4551 dpurdie 443
        Error( "BuildAlias() cannot create an alias named $alias", "That name is reserved for generic targets" );
227 dpurdie 444
    }
445
    elsif ( $alias ne quotemeta( $alias ) )
446
    {
6133 dpurdie 447
        Error   ("BuildAlias() alias '$alias' contains invalid characters") unless defined($::GBE_ABT);
227 dpurdie 448
        Warning( "BuildAlias() alias '$alias' contains invalid characters -- ignored" );
449
    }
450
    elsif ( $BUILDALIAS{ $alias } )
451
    {
6133 dpurdie 452
        Error   ("BuildAlias() duplicate alias '$alias'") unless defined($::GBE_ABT);
227 dpurdie 453
        Warning( "BuildAlias() duplicate alias '$alias' -- alias ignored" );
454
    }
455
    else
456
    {
457
        #
458
        #   Expand alias UNLESS using --Target.
459
        #   The --Target is a real target and not a subject to alias expansion
460
        #   This solves order dependancy problems.
461
        #
462
        @arguments = ExpandPlatforms( @arguments )
463
            unless $target_mode;
464
 
6133 dpurdie 465
        my $platform = '';                   # current platform
227 dpurdie 466
        my @pargs = ();                      # current args
467
 
468
        #
469
        #   Process the expanded arguments
470
        #   Collect arguments and process when a new platform is discovered
471
        #
472
        foreach my $arg ( @arguments, '++' )
473
        {
474
            if ( $arg =~ /^--/ )
475
            {
476
                push @pargs, $arg;
477
                next;
478
            }
479
            else
480
            {
481
                #
482
                #   Start of a platform
483
                #   Process previous data, once a platform has been seen
484
                #
485
                if ( $platform )
486
                {
487
                    #   Add arguments to BUILDALIAS as we see them
488
                    #
489
                    HashJoin( \%BUILDALIAS, ' ', $alias, $platform );
490
                    HashJoin( \%BUILDALIAS, ' ', $alias, grep(!/^--Uses=/, @pargs) );
491
 
492
                    #
493
                    #   The BuildAlias can also define a platform.
494
                    #   (Sounded like a good idea at the time!)
495
                    #
496
                    unless ( $define || $target_mode )
497
                    {
498
                        push @pargs, '--NotDefault' if ( $notdefault );
499
                        push @pargs, '--FunctionName=BuildAlias';
500
                        BuildPlatforms( $platform, @pargs );
501
                    }
502
                }
503
 
504
                #
505
                #   Start collecting args for the next platform
506
                #
507
                @pargs = ();
508
                $platform = $arg;
509
            }
510
        }
511
    }
512
}
513
 
6133 dpurdie 514
#-------------------------------------------------------------------------------
515
# Function        : BuildAliasDef  
516
#
517
# Description     : Shorthand for BuildAlias (xxx,-Define, ... )
518
#                   The way is should have been done  :(
519
#
520
# Inputs          : $alias          Name of alias to define
521
#                   arguments       Alias arguments; platforms or targets
522
#
523
sub BuildAliasDef()
524
{
525
    my( $alias, @arguments ) = @_;
526
    BuildAlias($alias . ',--Define', @arguments);
527
}
227 dpurdie 528
 
529
#-------------------------------------------------------------------------------
530
# Function        : Process_TargetAlias
531
#
532
# Description     : Post Process the --Target option for the build alias
533
#                   Filter all platforms and extract those with a matching targets
534
#
535
# Inputs          : None
536
#
537
# Returns         : Nothing
538
#
539
sub Process_TargetAlias
540
{
541
    #
542
    #   Merge any delayed aliases with the complete set of alias
543
    #   Delayed alias are not used in expansions during the processing
5410 dpurdie 544
    #   of platforms and targets, but can be used to pick up errors
227 dpurdie 545
    #
546
    while ( my($key,$value) = each(%BUILDALIAS_DELAY) )
547
    {
548
        if ( exists($BUILDALIAS{$key}) )
549
        {
5867 dpurdie 550
            abtWarning(0,"BuildAlias() duplicates internal alias '$key'");
227 dpurdie 551
            next;
552
        }
553
        $BUILDALIAS{$key} = $value;
554
    }
5410 dpurdie 555
    ErrorDoExit();
227 dpurdie 556
 
7310 dpurdie 557
    #
558
    #   Empty so that its not seen in Buildfile.
559
    #
560
    %BUILDALIAS_DELAY =();
561
 
227 dpurdie 562
    foreach my $alias ( keys %BUILDALIAS_TARGETS )
563
    {
564
        Debug( "BuildTargetAlias($alias)" );
565
 
566
        #
567
        #   Replace the existing alias - it has done its JOB
568
        #
569
        my $arguments = delete $BUILDALIAS{ $alias } ;
570
 
571
        foreach my $arg ( split / /, $arguments )
572
        {
573
            if ( $arg =~ /^--/ )                # argument
574
            {
575
                #   Add arguments to BUILDALIAS as we see them
576
                #
577
                HashJoin( \%BUILDALIAS, ' ', $alias, $arg );
578
                next;
579
            }
580
 
581
            foreach my $platform ( keys %BUILDINFO )
582
            {
583
                foreach my $element ( qw (TARGET BASE ) )
584
                {
585
                    my $target = $BUILDINFO{$platform}{$element};
586
                    if ( $target && $target eq $arg )
587
                    {
588
                        HashUniqueJoin( \%BUILDALIAS, ' ', $alias, $platform );
589
                        Debug( "BuildTargetAlias: $alias, $target -> $platform" );
590
                    }
591
                }
592
            }
593
        }
594
    }
595
}
596
 
597
#-------------------------------------------------------------------------------
6133 dpurdie 598
# Function        : CleanUp_Aliases 
599
#
600
# Description     : Will fully expand aliases to simplify display and processing 
601
#                       Remove arguments that  start with a '-'
602
#                       Remove bits that start with a !
603
#
604
# Inputs          : 
605
#
606
# Returns         : 
607
#
608
sub CleanUp_Aliases
609
{
610
    #
611
    #   Clean up Aliases
612
    #
613
#DebugDumpData("BEFORE CleanUp_Aliases", \%BUILDALIAS);
7310 dpurdie 614
 
6133 dpurdie 615
    foreach my $alias ( keys %BUILDALIAS )
616
    {
7310 dpurdie 617
        #
618
        #   Build hash of bits to be added and bits to be removed
619
        #   Remove all options - only need platforms
620
        #
6133 dpurdie 621
        my @aliasList = split(/ /, $BUILDALIAS{$alias});
622
        my @expanded =  ExpandPlatforms(@aliasList);
623
 
624
        my %add;
625
        my %remove;
626
 
627
        foreach ( @expanded)
628
        {
629
            if (m/^-/) {
630
            } elsif (m/^!(.*)/) {
631
                $remove{$1} = 1;
632
            } else {
633
                $add{$_} = 1;
634
            }
635
        }
636
 
637
        #
638
        #   If there are NO additive expressions in the alias, then
639
        #   assume all the active targets
640
        #
641
        unless (keys %add) {
7310 dpurdie 642
            my %add = map { $_ => 1 } @BUILD_ACTIVEPLATFORMS;
6133 dpurdie 643
        }
644
 
645
        foreach ( keys %remove) {
646
            delete $add { $_};
647
        }
648
 
7310 dpurdie 649
        #
650
        #   Delete ALIAS if it has no expansion
651
        #       May cause issues with the Platforms directive
652
        #
653
        if (keys %add) {
654
            $BUILDALIAS{$alias} = join(' ',keys %add);
655
        } else {
656
            delete $BUILDALIAS{$alias};
657
        }
6133 dpurdie 658
    }
659
#DebugDumpData("AFTER CleanUp_Aliases", \%BUILDALIAS);
660
}
661
 
7310 dpurdie 662
#-------------------------------------------------------------------------------
663
# Function        : ProcessBuildExclude  
664
#
665
# Description     : Process BuildExclude directive info
666
#                   A list of targets to be excluded
667
#                   INSTRUMENT is a key word
668
#  
669
#
670
# Inputs          : None
671
#
672
# Returns         : Modifies BUILDINFO
673
#
674
sub ProcessBuildExclude
675
{
676
    for my $word (@BUILDEXCLUDE)
677
    {
678
        Debug("ProcessBuildExclude: $word");
679
        Error('BuildExclude: Unknown option: ' . $word) if ($word =~ m~^-~);
680
        Error('BuildExclude: Invalid format: ' . $word) if ($word =~ m~^!~);
6133 dpurdie 681
 
7310 dpurdie 682
        #
683
        #   INSTRUMENT is a key word
684
        #       Remove all instrumented builds
685
        #
686
        if ($word eq 'INSTRUMENT')
687
        {
688
            foreach my $platform ( keys %BUILDINFO )
689
            {
690
                if ( PlatformConfig::targetHasTag( $platform, 'INSTRUMENT') ) {
691
                    $BUILDINFO{$platform}{NOT_AVAILABLE} = 2;
692
                    Debug("ProcessBuildExclude. Remove $platform ");
693
                }
694
            }
695
        }
696
        elsif (exists $BUILDINFO{$word} )
697
        {
698
            $BUILDINFO{$word}{NOT_AVAILABLE} = 2;
699
            Debug("ProcessBuildExclude. Remove $word ");
700
 
701
        } else {
702
            Warning('BuildExclude: Unknown target:' . $word ) 
703
        }
704
    }
705
}
706
 
6133 dpurdie 707
#-------------------------------------------------------------------------------
227 dpurdie 708
# Function        : BuildProduct
709
#
710
# Description     : Create a family of Platforms with a common product line
711
#                   ie: Create two flavors of the TP5, one based on the MOSF and
712
#                   the othe based on the MOS68 toolset.
713
#
714
# Inputs          : $product[,opts]+    The name of the product
715
#                                       This will be the base name for the family
716
#                                       Allowed options are:
7304 dpurdie 717
#                                           --NotDefault       : This is not a default build platform
718
#                                           --Uses=x1,x2:x3    : All use another platform
719
#                                           --Alias=y1,y2:x3   : All alias to this name
227 dpurdie 720
#
721
#                   platforms           One or more root platforms, with options
722
#                                       The platform is macro expanded.
723
#                                       Options may be a part of the platform or
724
#                                       distinct.
725
#
726
# Returns         :
727
#
728
 
729
sub BuildProduct
730
{
731
    my( $product, @arguments ) = @_;
732
    my $notdefault = 0;
7304 dpurdie 733
    my @commonArgs = ();
227 dpurdie 734
 
735
    Debug( "BuildProduct($product, @arguments)" );
736
    Error( "BuildProduct must appear before BuildName()..." )
737
        if ( $BUILDNAME ne "" );
738
 
739
    #   Parse attributes
740
    #
741
    my( @attrs ) = split( ',', $product );
742
 
743
    $product = "";
744
    foreach ( @attrs ) {
745
        if ( /^--/ ) {
746
            if ( /^--NotDefault$/ ) {
747
                $notdefault++;
748
 
7304 dpurdie 749
            } elsif ( /^(--Uses=.*)/ ) {
750
                UniquePush (\@commonArgs, $1 );
227 dpurdie 751
 
5115 dpurdie 752
            } elsif ( /^(--Alias=.*)/ ) {
7304 dpurdie 753
                UniquePush (\@commonArgs, $1 );
5115 dpurdie 754
 
227 dpurdie 755
            } else {
756
                Warning( "BuildProduct() unknown attribute: $_ -- ignored" );
757
            }
758
 
759
        } else {
760
            Error( "BuildProduct() multiple product specifications not allowed" )
761
                if ( $product ne "" );
762
            $product = $_;
763
        }
764
    }
765
 
766
    #
767
    #   Sanity test
768
    #
769
    Error( "BuildProduct() missing product specifications" )
770
        if ( $product eq "" );
771
 
772
    Error( "BuildProduct() product '$product' contains invalid characters" )
773
        if ( $product ne quotemeta( $product ) );
774
 
775
    Error( "BuildProduct() duplicate product '$product'" )
776
        if ( $BUILDPRODUCT{ $product } );
777
 
778
    Error( "BuildProduct() duplicate alias '$product'" )
779
        if ( $BUILDALIAS{ $product } );
780
 
781
    #
782
    #   Expand the user specified targets to allow the use of BuildAlias
783
    #   The (bad) side effect of this is that target options get reorganised
784
    #       PLATFORM,--Uses=ANOTHER  ==> PLATFORM --Uses=ANOTHER
785
    #
7304 dpurdie 786
    #   Insert markers(++) into @arguments to mark when to process collected data
227 dpurdie 787
    #   Insert before each PLATFORM and at the end of the list
788
    #   platform specifier or the end of the list. Scan the arguments
789
    #
790
    @arguments = ExpandPlatforms( @arguments );
791
    my @new_args;
792
    foreach  ( @arguments )
793
    {
794
        push (@new_args, '++') unless ( m/^--/ );
795
        push (@new_args, $_ );
796
    }
797
    push (@new_args, '++');
798
    shift @new_args if $new_args[0] eq '++';
799
 
7304 dpurdie 800
    my @targs = @commonArgs;
227 dpurdie 801
    my $target;
802
    foreach my $arg ( @new_args )
803
    {
804
        #
805
        #   Collect per-platform arguments
806
        #
7304 dpurdie 807
        if ( $arg =~ /^--/ ) {
227 dpurdie 808
            push @targs, $arg;
809
            next;
810
        }
811
 
812
        #
813
        #   Collect target(platform) name
814
        #
815
        unless ( $arg eq '++' )
816
        {
817
            $target = $arg;
818
            Error( "BuildProduct() cannot create a product based on a GENERIC platform" )
6133 dpurdie 819
                if ( PlatformConfig::targetHasTag($target,'GENERIC') );
227 dpurdie 820
            next;
821
        }
822
 
823
        #
824
        #   Infer a BuildPlatform
825
        #   Do not provide a platform name. This will be created later when the
826
        #   full name is known - or can be calculated.
827
        #
7304 dpurdie 828
        CreateBuildPlatformEntry('BuildProduct', $notdefault, $product, $target, \@targs );
227 dpurdie 829
 
7304 dpurdie 830
        @targs = @commonArgs;
227 dpurdie 831
        $target = undef;
832
    }
833
}
834
 
835
#-------------------------------------------------------------------------------
836
# Function        : CreateBuildPlatformEntry
837
#
838
# Description     : Internal routine to create the Build Entry
839
#                   Single point to create a platform, whatever one of those is
840
#
841
# Inputs          : $fname                  - Name of invoking directive
842
#                   $notdefault             - True if the platform is not to be added to the
843
#                                             list of default platforms
844
#                   $product                - Optional product name
845
#                   $target                 - Target platform name
846
#                   $pArgs                  - Ref to an array of platform arguments
7304 dpurdie 847
#                                             Known: --Uses=aaa,bbb and --Alias=xxx,yyy
227 dpurdie 848
#
849
# Returns         :
850
#
851
 
852
sub CreateBuildPlatformEntry
853
{
7304 dpurdie 854
    my ($fname, $notdefault, $product, $target, $pArgs ) = @_;
227 dpurdie 855
    my %buildentry;
856
    my $platform;
857
 
858
    #
859
    #   Create a basic BUILDINFO entry
860
    #
861
    $buildentry{FNAME} = $fname;
7310 dpurdie 862
    $buildentry{NOT_DEFAULT} = $notdefault if $notdefault;
227 dpurdie 863
    $buildentry{PRODUCT} = $product;
864
    $buildentry{TARGET} = $target;
865
    $buildentry{BASE} = $target;
363 dpurdie 866
    foreach ( @$pArgs )
867
    {
868
        if ( m~^--Alias=(.+)~ ) {
7304 dpurdie 869
            foreach my $alias (split('[:,]',$1))
6133 dpurdie 870
            {
871
                Error ("$fname() attempt to alias a keyword: $alias")
872
                    if ( isKeyword($alias) );
873
                push @{$buildentry{USERALIAS}},$alias;
874
            }
7304 dpurdie 875
        } elsif ( m~^--Uses=(.+)~ ) {
876
            push @{$buildentry{USES}},split('[:,]',$1);
877
 
6133 dpurdie 878
        } else {
363 dpurdie 879
            push @{$buildentry{ARGS}}, $_;
880
        }
881
    }
227 dpurdie 882
 
4728 dpurdie 883
    #   Detect reserved words being misused as a platform name
6133 dpurdie 884
    #   At the moment, the value of NATIVE and TOOLSET are calculate towards the end of the
885
    #   build process so that it can be limited to platforms that are present.
886
    foreach my $reserved ( qw (NATIVE TOOLSET INSTRUMENT))
887
    {
888
        Error("Invalid use of the platform alias $reserved","The $reserved alias cannot be used to define build platforms")
889
            if (uc($target) eq uc($reserved));
890
    }
4728 dpurdie 891
 
227 dpurdie 892
    #
7310 dpurdie 893
    #   Expand families of platforms into multiple platforms
894
    #       ie: DEVLINUX -> COBRA, VIPER, ....
227 dpurdie 895
    #
7310 dpurdie 896
    foreach my $name (@PlatformConfig::BuildFamilies)
227 dpurdie 897
    {
297 dpurdie 898
        #
7310 dpurdie 899
        #   Is this target a buildFamily alias
303 dpurdie 900
        #
7310 dpurdie 901
        if (uc($target) eq uc($name))
902
        {
903
            #
904
            #   Get the list of targets that have been tagged with the family name
905
            #   Must exist - else its an internal error
906
            #   
907
            my @targets = PlatformConfig::getTargetsByTag($name);
908
            Error ("Internal: No platforms are tagged as members of $name") unless @targets;
303 dpurdie 909
 
7310 dpurdie 910
            #   Instantiate all targets
911
            #       Give them an ALIAS for the Family name
912
            #       Register new enrty with the build system
913
            #
914
            foreach my $target ( @targets )
915
            {
916
                my $pInfo = dclone(\%buildentry);
917
                $pInfo->{ALIAS} = $pInfo->{TARGET};
918
                $pInfo->{TARGET} = $target;
919
                AddBuildPlatformEntry( $pInfo );
920
            }
921
            #   Mark the original entry as a TEMPLATE so that it won't be added
922
            $buildentry{TEMPLATE} = 1;
923
            last;
227 dpurdie 924
        }
925
    }
7310 dpurdie 926
 
227 dpurdie 927
    #
7310 dpurdie 928
    #   Add the basic entry into the build system, unless its been flagged as a TEMPLATE
227 dpurdie 929
    #
930
    AddBuildPlatformEntry (\%buildentry )
931
        unless ( $buildentry{TEMPLATE} );
932
}
933
 
934
#-------------------------------------------------------------------------------
935
# Function        : AddBuildPlatformEntry
936
#
937
# Description     : Internal routine to add a Build Entry into the build system
938
#                   This function MAY be called from the build extensions
939
#
940
#                   NOTES:
941
#                   No processing of the info structure is performed. This MUST
942
#                   have been done before now.
943
#
944
#                   Additional information may be added to the structure.
945
#
946
#
947
# Inputs          : $pInfo              - Reference to a BuildInfo structure
948
#
949
# Returns         : Nothing
950
#
951
sub AddBuildPlatformEntry
952
{
953
    my ($pInfo) = @_;
954
    my $fname = $pInfo->{FNAME};
955
 
956
    #
7310 dpurdie 957
    #   Ensure that it exsists and is numeric
958
    #
959
    $pInfo->{NOT_AVAILABLE} = 0;
960
 
961
    #
227 dpurdie 962
    #   Locate the optional PLATFORM configuration file
963
    #   If it does exist then it can extend build-time information
964
    #
965
    my $target = $pInfo->{TARGET};
241 dpurdie 966
 
279 dpurdie 967
    #
4551 dpurdie 968
    #   Detect GENERIC targets
969
    #       The Build file is only allowed to have one that can be built on any one machine
970
    #
7309 dpurdie 971
    my $buildAvailability = PlatformConfig::targetHasTag( $target, 'MACHTYPE' );
972
    if (PlatformConfig::targetHasTag( $target, 'GENERIC' ) )
4551 dpurdie 973
    {
974
        UniquePush (\@GENERIC_TARGETS, $target );
6133 dpurdie 975
    }
976
 
977
    #
978
    #   Detect GENERIC_<machType> targets
979
    #
7309 dpurdie 980
    if (PlatformConfig::targetHasTag( $target, 'GENERIC_MACHTYPE' ) )
6133 dpurdie 981
    {
4551 dpurdie 982
        $pInfo->{IS_GENERIC} = 1;
6133 dpurdie 983
        $pInfo->{ALIAS} = 'GENERIC';
984
        $pInfo->{NOT_AVAILABLE} = 1 unless needToolset();
4551 dpurdie 985
    }
986
 
987
    #
279 dpurdie 988
    #   Ensure target is known to JATS
7310 dpurdie 989
    #   Remove unknown targets from the build. 
990
    #   Create a list of unknown targets and report them later.
279 dpurdie 991
    #
7310 dpurdie 992
    unless ( $pInfo->{NOT_AVAILABLE} || exists $BUILDINFO{$target} || $pInfo->{IS_GENERIC}  )
227 dpurdie 993
    {
7309 dpurdie 994
        my $base_target = PlatformConfig::targetHasTag( $target, 'BASE_TARGET' ) || $target;
279 dpurdie 995
        unless ( Exists( "$::GBE_CONFIG/PLATFORM", $base_target  ) )
996
        {
6133 dpurdie 997
            UniquePush (\@BUILD_BADNAME, $target ); 
7310 dpurdie 998
            $pInfo->{NOT_AVAILABLE} = 3;
999
            $pInfo->{BADNAME} = 1;
279 dpurdie 1000
        }
1001
    }
1002
 
7310 dpurdie 1003
    #
1004
    #   Mark as NOT_AVAILABLE platforms that are not available on this machine
1005
    #
7309 dpurdie 1006
    if ($buildAvailability)
1007
    {
7310 dpurdie 1008
         $pInfo->{MACHTYPE} = $buildAvailability;
7309 dpurdie 1009
         $pInfo->{NOT_AVAILABLE} = 1 unless ($buildAvailability eq $::GBE_MACHTYPE)
1010
    }
1011
 
279 dpurdie 1012
    #
7310 dpurdie 1013
    #   Extend the build information
279 dpurdie 1014
    #
1015
    unless ($pInfo->{NOT_AVAILABLE} )
1016
    {
7310 dpurdie 1017
        if ( my $build_cfg = Require( "$::GBE_CONFIG/PLATFORM", "${target}.cfg"  ) )
227 dpurdie 1018
        {
1019
            Verbose ("Processing(add) Platform Configuration file: $build_cfg");
7310 dpurdie 1020
            my $package_name = "${target}_Build";
227 dpurdie 1021
 
1022
            if ( $package_name->can('add_platform') )
1023
            {
1024
                Verbose ("Processing(add) Platform Configuration: $package_name");
1025
                $package_name->add_platform( $pInfo );
1026
            }
1027
            else
1028
            {
1029
                Debug ("Processing(add) Platform Configuration: $package_name. 'add_platform' function not found");
1030
            }
1031
        }
1032
    }
1033
 
1034
    #
1035
    #   If a product name has been provided then the platform is a product
1036
    #   and will need additional processing
1037
    #
1038
    if ( $pInfo->{PRODUCT} )
1039
    {
1040
        #
1041
        #   Create the platform name. Derived from the product and the target
1042
        #
1043
        $pInfo->{PLATFORM} = $pInfo->{PRODUCT} . '_' . $pInfo->{TARGET};
1044
 
1045
        #
1046
        #   Remember the product name
1047
        #
1048
        $BUILDPRODUCT{ $pInfo->{PRODUCT} } = 1;
1049
 
1050
        #
1051
        #   Add platform name to the alias explansion being created
1052
        #   Allows the user to reference the entire FAMILY of platforms
1053
        #
1054
        HashJoin( \%BUILDALIAS, ' ', $pInfo->{PRODUCT}, $pInfo->{PLATFORM} );
1055
 
1056
        #
1057
        #   Create an element to assist in creating %ScmBuildProducts
1058
        #
1059
        $pInfo->{ISPRODUCT} = 1;
1060
        $BUILDPRODUCT_PARTS{$pInfo->{PLATFORM}} = "$pInfo->{PRODUCT},$pInfo->{TARGET}";
1061
    }
1062
    else
1063
    {
1064
        $pInfo->{PRODUCT} = $pInfo->{TARGET};
1065
        $pInfo->{PLATFORM} = $pInfo->{TARGET};
1066
    }
1067
 
1068
    #---------------------------------------------------------------------------
1069
    #   All the hard work has been done
1070
    #   We now know the platforms full name
1071
    #
1072
    #   Ensure that the target platform has not been been specified
1073
    #   Perhaps this should be an error
1074
    #
1075
    my $platform = $pInfo->{PLATFORM};
1076
 
5109 dpurdie 1077
    if ( defined ( $BUILDINFO{$platform}) && ! $Clobber)
227 dpurdie 1078
    {
5867 dpurdie 1079
        abtWarning(1,"$fname() duplicate platform '$platform'");
5429 dpurdie 1080
        return;
227 dpurdie 1081
    }
1082
 
1083
    #
1084
    #   Add platform (tag) to various lists
1085
    #
7311 dpurdie 1086
    UniquePush( \@BUILDPLATFORMS, $platform )    unless exists ($pInfo->{BADNAME});
227 dpurdie 1087
    UniquePush( \@DEFBUILDPLATFORMS, $platform ) unless ( $pInfo->{NOT_DEFAULT} );
1088
 
1089
    #
1090
    #   Create a simple alias if requested
1091
    #   Used if a platform creates multiple entires
1092
    #
1093
    if ( $pInfo->{ALIAS} )
1094
    {
317 dpurdie 1095
        HashJoin( \%BUILDALIAS_DELAY, ' ', $_, $platform )
1096
            foreach ( ArrayList($pInfo->{ALIAS}) );
227 dpurdie 1097
    }
1098
 
363 dpurdie 1099
    if ( $pInfo->{USERALIAS} )
1100
    {
1101
        HashJoin( \%BUILDALIAS_DELAY, ' ', $_, $platform )
1102
            foreach ( ArrayList($pInfo->{USERALIAS}) );
1103
    }
1104
 
227 dpurdie 1105
    #
1106
    #   Create the 'parts' of the platform. This is a list of unique
1107
    #   bits to search. It will consist of:
1108
    #       [0]     - platform
1109
    #       [1]     - product
1110
    #       ...     - Uses bits ...
1111
    #       [last]  - target
1112
    #
1113
    my @parts;
1114
 
379 dpurdie 1115
    if ( $pInfo->{USES_FIRST} )
1116
    {
1117
        UniquePush (\@parts, @{$pInfo->{USES_FIRST}} );
1118
    }
1119
 
1120
    UniquePush (\@parts, $platform);
1121
 
227 dpurdie 1122
    #
1123
    #   Include all the product extensions
1124
    #
1125
    if ( $pInfo->{ISPRODUCT}  )
1126
    {
1127
        UniquePush (\@parts, map {+ "$pInfo->{PRODUCT}_${_}" } @{$pInfo->{USES}});
1128
        UniquePush (\@parts, map {+ "$pInfo->{PRODUCT}_${_}" } @{$pInfo->{ALSO_USES}});
1129
        UniquePush (\@parts, $pInfo->{PRODUCT} );
1130
    }
1131
 
1132
    #
1133
    #   Add in non-product expanded parts
1134
    #
1135
    UniquePush (\@parts, @{$pInfo->{EXTRA_USES}});
1136
 
1137
    #
1138
    #   Create a structure to assist in search path resolution
1139
    #   The order is important. It sets the include search order for include
1140
    #   files and libraries
1141
    #   If A uses B then search in A_B, A, B
1142
    #       ie: GAK uses MOS68K Search stuff in GAK_MOS68K, GAK, MOS68K
1143
    #
1144
    #       Usage:  OBFTP uses TP5 on MOSCF(target)       (BuildProduct)
1145
    #       Expansion: OBFTP, TP5_MOSCF, TP5
1146
    #
1147
    #       Usage: VS2003(target) also uses WIN32(uses)     (BuildPlatform)
1148
    #       Expansion: VS2003, VS2003_WIN32, WIN32
1149
    #
1150
    if ( $pInfo->{ISPRODUCT}  )
1151
    {
1152
        UniquePush (\@parts, map {+ "${_}_$pInfo->{TARGET}", $_, $pInfo->{TARGET}} @{$pInfo->{USES}});
1153
        UniquePush (\@parts, map {+ "${_}_$pInfo->{TARGET}", $_, $pInfo->{TARGET}} @{$pInfo->{ALSO_USES}});
1154
    }
1155
    else
1156
    {
1157
        UniquePush (\@parts, map {+ "$pInfo->{TARGET}_${_}", $pInfo->{TARGET}, $_} @{$pInfo->{USES}});
1158
        UniquePush (\@parts, map {+ "$pInfo->{TARGET}_${_}", $pInfo->{TARGET}, $_} @{$pInfo->{ALSO_USES}});
1159
    }
1160
 
1161
    #
1162
    #   Finally - the target
1163
    #
1164
    UniquePush (\@parts, $pInfo->{TARGET} );
1165
 
1166
    #
1167
    #   Save the PARTS
1168
    #   Also saved as BUILDPLATFORM_PARTS for interface with older versions
1169
    #   of the deployments scripts.
1170
    #
1171
    $pInfo->{PARTS} = \@parts;
1172
 
1173
    #
1174
    #   Add any arguments to the platforms argument list
1175
    #
1176
    PlatformArgument( $platform, @{$pInfo->{ARGS}} ) if ( $pInfo->{ARGS} );
1177
 
1178
    #
1179
    #   Clean up and save
1180
    #
1181
    delete $pInfo->{TEMPLATE};
1182
    delete $pInfo->{FNAME};
1183
    $BUILDINFO{$platform} = $pInfo;
1184
#    DebugDumpData("BUILDINFO", \%BUILDINFO );
1185
}
1186
 
1187
 
1188
sub BuildArgument
1189
{
1190
    my( $platform, @arguments ) = @_;
1191
    my( @platforms );
1192
 
1193
    Debug( "BuildArgument($platform, @arguments)" );
1194
 
1195
    Error( "BuildArgument must appear before BuildName()..." )
1196
        if ( $BUILDNAME ne "" );
1197
 
1198
    #
1199
    #   Allow a wildcard to apply a single argument to all platforms
1200
    #   Should only be used AFTER all the platforms have been specified
1201
    #
1202
    if ( $platform eq '*' )
1203
    {
1204
        @platforms = @BUILDPLATFORMS;          # Simple Wildcard
1205
    }
1206
    else
1207
    {
1208
        @platforms = ExpandPlatforms( $platform );  # aliasing
1209
    }
1210
 
283 dpurdie 1211
    foreach my $platform ( @platforms )
227 dpurdie 1212
    {
1213
        next if ( $platform =~ /^--/ );         # argument, ignore
1214
 
1215
        PlatformArgument( $platform, @arguments );
1216
    }
1217
}
1218
 
1219
 
1220
sub BuildPlatforms
1221
{
1222
    my( @arguments ) = @_;
1223
    my $fname = "BuildPlatforms";
1224
 
1225
    Debug( "BuildPlatforms(@arguments)" );
1226
 
1227
    Error( "BuildPlatforms must appear before BuildName()..." )
1228
        if ( $BUILDNAME ne "" );
1229
 
1230
    #
1231
    #   Expand the user specified platforms to allow the use of BuildAlias
1232
    #   The (bad) side effect of this is that platform options get reorganised
1233
    #       PLATFORM,--Uses=ANOTHER  ==> PLATFORM --Uses=ANOTHER
1234
    #
1235
    #   Insert markers(++) into @aruments to mark when to process collected data
1236
    #   Insert before each PLATFORM and at the end of the list
1237
    #   platform specifier or the end of the list. Scan the arguments
1238
    #
1239
    @arguments = ExpandPlatforms( @arguments );
1240
    my @new_args;
1241
    foreach  ( @arguments )
1242
    {
1243
        push (@new_args, '++') unless ( m/^--/ );
1244
        push (@new_args, $_ );
1245
    }
1246
    push (@new_args, '++');
1247
    shift @new_args if $new_args[0] eq '++';
1248
 
1249
 
1250
    my $platform  = "";                         # current platform
1251
    my $notdefault  = 0;
1252
    my @pargs = ();
1253
 
1254
    foreach my $arg ( @new_args )
1255
    {
1256
        #
1257
        #   Extract known options
1258
        #   Unknown options bind to the current platform
1259
        #
1260
        if ( $arg =~ /^--/ ) {
1261
            if ( $arg =~ /^--NotDefault$/ ) {
1262
                $notdefault = 1;
1263
 
1264
            } elsif ( $arg =~/^--FunctionName=(.*)/ ) {
1265
                $fname = $1;
1266
 
1267
            } else {
1268
                push @pargs, $arg;
1269
            }
1270
            next;
1271
        }
1272
 
1273
        #
1274
        #   New platform. Save name for later. Collect arguments first
1275
        #
1276
        unless ( $arg eq '++' )
1277
        {
1278
            $platform = $arg;
1279
 
1280
            Error( "$fname() missing platform specification" )
1281
                unless ( $platform );
1282
 
1283
            Error( "$fname() product '$platform' contains invalid characters" )
1284
                unless ( $platform eq quotemeta( $platform ) );
1285
 
1286
            next;
1287
        }
1288
 
1289
        #
1290
        #   Create new platform
1291
        #   Have collected name and arguments
1292
        #
7304 dpurdie 1293
        CreateBuildPlatformEntry($fname, $notdefault, undef, $platform, \@pargs  );
227 dpurdie 1294
 
1295
        #
1296
        #   Reset collection variables for next platform
1297
        #
1298
        $platform = "";
1299
        $notdefault  = 0;
1300
        @pargs = ();
1301
    }
1302
}
1303
 
1304
 
1305
#   PlatformArgument ---
1306
#       Append an argument list to the specified platform argument list.
1307
#       Internal use only
1308
#..
1309
 
1310
sub PlatformArgument
1311
{
1312
    my( $platform, @arguments ) = @_;
1313
 
1314
    Debug( "  PlatformArguments($platform, @arguments)" );
1315
 
1316
    HashJoin( \%BUILDPLATFORMARGS, $;, $platform, @arguments )
1317
        if ( $platform );
1318
}
1319
 
279 dpurdie 1320
#-------------------------------------------------------------------------------
5679 dpurdie 1321
# Function        : BuildExclude 
1322
#
1323
# Description     : Allow specific platforms to be excluded from the Build
1324
#                   Intended use:
1325
#                       Allow the use if a platform alias, but not all elements of it
1326
#                       ie: Use DEVLINUX, but not ARM9TDMI as we no longer support it 
1327
#                           in this version.
1328
#                   Multiple BuildExclude directives are allowed
1329
#                   Order or location is not important        
1330
#
1331
# Inputs          : Platforms names and options
7310 dpurdie 1332
#                       zzzz                Build Platform Name
1333
#                       INSTRUMENT          (Keyword - no instrumented builds)
5679 dpurdie 1334
#                       
1335
#
1336
# Returns         : Nothing 
1337
#
1338
sub BuildExclude
1339
{
1340
    my( @arguments ) = @_;
1341
    Debug( "BuildExclude(@arguments)" );
1342
 
1343
    Error( "BuildExclude must appear before BuildName()..." )
1344
        if ( $BUILDNAME ne "" );
1345
 
1346
    #
1347
    #   Simply save the arguments for later
1348
    #   Allow multiple specs in the one definition
1349
    #
1350
    foreach ( @arguments)
1351
    {
7310 dpurdie 1352
        Error ("Invalid format: $_") if m/[\s]/;
5679 dpurdie 1353
        UniquePush (\@BUILDEXCLUDE, split(/\s*,\s*/,$_));
1354
    }
1355
}
1356
 
1357
#-------------------------------------------------------------------------------
6133 dpurdie 1358
# Function        : BuildToolset 
1359
#
1360
# Description     : Indicate that this package will build binary parts of a JATS
1361
#                   toolset.
1362
#                   
1363
#                   Should be used to indicate that it building non-binary parts
1364
#                   too.
1365
#                   
1366
#                   Used as a sanity test.
1367
#
1368
# Inputs          : Options to limit the Machine Types affected 
1369
#
1370
# Returns         : 
1371
#
1372
sub BuildToolset
1373
{
1374
    my( @arguments ) = @_;
1375
    my ($exclude, $include, $including);
1376
 
1377
    $genToolsetPlatform = 1;
1378
    Debug( "BuildToolset(@arguments)" );
1379
    Error( "BuildToolset must appear before BuildName()..." )
1380
        if ( $BUILDNAME ne "" );
1381
 
1382
    #
1383
    #   Process TOOLSET specific options
1384
    #       --ExcludeMachType=xxxx,yyy
1385
    #       --MachType=xxxx,yyy
1386
    #
1387
    foreach ( @arguments )
1388
    {
1389
        if ( m~^--ExcludeMachType=(.+)~i ) {
1390
            foreach my $arch (split(',',$1))
1391
            {
1392
                if (uc($arch) eq uc($::GBE_MACHTYPE))
1393
                {
1394
                    Verbose("Exclude TOOLSET on this machine");
1395
                    $exclude = 1;
1396
                    last;
1397
                }
1398
            }
1399
        } elsif ( m~^--MachType=(.+)~i ) {
1400
            $including = 1;
1401
            foreach my $arch (split(',',$1))
1402
            {
1403
                if (uc($arch) eq uc($::GBE_MACHTYPE))
1404
                {
1405
                    Verbose("Include TOOLSET on this machine");
1406
                    $include = 1;
1407
                    last;
1408
                }
1409
            }
1410
 
1411
        } else {
1412
            Error ("BuildToolset: Unknown option: $_");
1413
        }
1414
    }
1415
 
1416
    #
1417
    #   Show we build for this architecture
1418
    #
1419
    $genToolsetActive = 0;
1420
    if ($exclude) {
1421
        $toolsetPlatform = 'Excluded';
1422
        return;
1423
    }
1424
 
1425
    if ($including) {
1426
        if ($include) {
1427
            $genToolsetActive = 1;
1428
        } else {
1429
            $toolsetPlatform = 'Not included';
1430
        }
1431
        return;
1432
    }
1433
 
1434
    $genToolsetActive = 1;
1435
    return;
1436
}
1437
 
1438
 
1439
#-------------------------------------------------------------------------------
279 dpurdie 1440
# Function        : BuildName
1441
#
1442
# Description     : Defines the package name and version
1443
#
1444
# Inputs          : build arguments
1445
#                   Various formats are allowed for backward compatability
1446
#                   Must support a number of different formats
1447
#                       "name nn.nn.nn prj"
1448
#                       "name nn.nn.nn.prj"
1449
#
1450
#                       "name nn.nn.nn prj", "nn.nn.nn"
1451
#                       "name nn.nn.nn.prj", "nn.nn.nn"
1452
#
1453
#                       "name", "nn.nn.nn.prj"
1454
#
1455
#                       "name", "nn.nn.nn", "prj", --RelaxedVersion
1456
#
1457
# Returns         : Nothing
1458
#
227 dpurdie 1459
sub BuildName
1460
{
1461
    my( @arguments ) = @_;
1462
    my $relaxed_version_name = 0;
1463
    my @args;
1464
 
1465
    Debug( "BuildName(@arguments)" );
315 dpurdie 1466
    Error( "Platform(s) not defined.",
227 dpurdie 1467
            "BuildAlias, BuildProduct and BuildPlatform directives must be defined prior to BuildName()." )
1468
        unless( scalar @BUILDPLATFORMS );
1469
 
1470
#.. Parse arguments
1471
#.
1472
    my $build_info = parseBuildName( @arguments );
1473
 
1474
    $BUILDNAME_PACKAGE = $build_info->{BUILDNAME_PACKAGE};
1475
    $BUILDNAME_VERSION = $build_info->{BUILDNAME_VERSION};
1476
    $BUILDNAME_PROJECT = $build_info->{BUILDNAME_PROJECT};
359 dpurdie 1477
    $BUILDNAME_SUFFIX  = $BUILDNAME_PROJECT ? '.' . $BUILDNAME_PROJECT : '';
227 dpurdie 1478
 
1479
    $BUILDNAME         = $build_info->{BUILDNAME};
1480
    $BUILDVERSION      = $build_info->{BUILDVERSION};
1481
 
1482
    $DEPLOY_PATCH      = $build_info->{DEPLOY_PATCH} || 0;
1483
 
1484
    #
1485
    #   Clobber processing done after values have been accumulated
1486
    #   as they may be used later
1487
    #
1488
    return if ( $Clobber );
6133 dpurdie 1489
    ToolsetFiles::AddFile('build.log');
4003 dpurdie 1490
 
227 dpurdie 1491
#.. Create build.log summary information
1492
#
261 dpurdie 1493
    my ($sep) = "\n".(" " x 11) . ". ";
227 dpurdie 1494
 
261 dpurdie 1495
    Log( "\nBuild configuration (version $::GBE_VERSION)" );
1496
    Log( "Name ....... $BUILDNAME ($ScmHost)" );
1497
    Log( "Version .... $BUILDNAME_VERSION" );
1498
    Log( "DeployPatch. $DEPLOY_PATCH" ) if ($DEPLOY_PATCH);
1499
    Log( "Project .... $BUILDNAME_PROJECT" )if ($BUILDNAME_PROJECT);
1500
    Log( "Project .... ****** Specifically supressed ******" )unless ($BUILDNAME_PROJECT);
1501
    Log( "DateTime ... $::CurrentTime" );
1502
    Log( "AutoBuild... Enabled:$::GBE_ABT" ) if defined($::GBE_ABT) ;
359 dpurdie 1503
    Log( "Build dir... $Cwd" ) if defined($::GBE_ABT) || $::GBE_DPKG_SBOX;
4161 dpurdie 1504
    Log( "Build Mach.. $::GBE_HOSTNAME" ) if defined($::GBE_ABT);
227 dpurdie 1505
 
359 dpurdie 1506
    Log( "PERL ....... $::GBE_PERL" );
261 dpurdie 1507
    Log( "BIN  ....... $::GBE_BIN" );
1508
    Log( "TOOLS ...... $::GBE_TOOLS" );
1509
    Log( "CONFIG ..... $::GBE_CONFIG" );
1510
    Log( "MACHTYPE ... $::GBE_MACHTYPE" );
227 dpurdie 1511
 
261 dpurdie 1512
    Log( "PLATFORM ... " . PrintList([split(' ', $::GBE_PLATFORM)], $sep) )    if defined ($::GBE_PLATFORM);
5708 dpurdie 1513
    Log( "EXCLUDE .... " . PrintList([@BUILDEXCLUDE], $sep) )    if (@BUILDEXCLUDE);
261 dpurdie 1514
    Log( "BUILDFILTER. " . PrintList([split(' ', $::GBE_BUILDFILTER)], $sep) ) if defined ($::GBE_BUILDFILTER);
227 dpurdie 1515
 
261 dpurdie 1516
    Log( "DPKG_STORE.. $::GBE_DPKG_STORE" );
1517
    Log( "DPKG ....... $::GBE_DPKG" );
4688 dpurdie 1518
    Log( "DPKG_REPLI . $::GBE_DPKG_REPLICA" );
261 dpurdie 1519
    Log( "DPKG_CACHE . $::GBE_DPKG_CACHE" );
1520
    Log( "DPKG_LOCAL . $::GBE_DPKG_LOCAL" );
1521
    Log( "DPKG_SBOX .. $::GBE_DPKG_SBOX" );
7301 dpurdie 1522
    Log( "Sandbox .... Development" );
7307 dpurdie 1523
    Log( "LocalFilter. $::GBE_DPKG_SBOX/buildfilter") if ( $::GBE_DPKG_SBOX && -f $::GBE_DPKG_SBOX . '/buildfilter' );
227 dpurdie 1524
 
1525
    #
1526
    #   Generate a list of active platforms
1527
    #   Ensure that there are some active platforms
1528
    #
7310 dpurdie 1529
    ProcessBuildExclude();
227 dpurdie 1530
    GeneratePlatformList();
6133 dpurdie 1531
    Log( "Platforms .. " . PrintPlatforms(\@BUILDPLATFORMS, $sep) );
4551 dpurdie 1532
 
1533
    #
1534
    #   Detect a mix of Generic and non Generic targets
1535
    #       Cannot mix generic and non-generic targets
1536
    #
1537
    if ($#GENERIC_TARGETS >= 0 && $#BUILD_ACTIVEPLATFORMS >= 0)
1538
    {
1539
        if ($#BUILD_ACTIVEPLATFORMS != $#GENERIC_TARGETS )
1540
        {
1541
            Verbose("Active:", @BUILD_ACTIVEPLATFORMS);
1542
            Verbose("Generic:", @GENERIC_TARGETS);
1543
            Error("Cannot mix GENERIC and non-GENERIC targets in the one build");
1544
        }
1545
    }
1546
 
4778 dpurdie 1547
    #
6133 dpurdie 1548
    #   Build System Generic Sanity Test
4778 dpurdie 1549
    #       If Generic   then MUST be a GENERIC build
1550
    #       If NoGeneric then MUST not be a GENERIC build
1551
    #
1552
    if (defined $GenericBuild)
1553
    {
1554
        if ( scalar(@GENERIC_TARGETS) ne $GenericBuild)
1555
        {
1556
            Error("Generic build inconsistency",
1557
                  "Release Manager entry indicates: $GenericBuild",
1558
                  "Build File indicates: " . scalar(@GENERIC_TARGETS)
1559
                  );
1560
        }
1561
    }
1562
 
4003 dpurdie 1563
    unless( @BUILD_ACTIVEPLATFORMS )
1564
    {
5109 dpurdie 1565
        my $msg = 'GBE_BUILDFILTER prevents any targets being built';
7301 dpurdie 1566
        if (defined($::GBE_ABT) || 1) {
227 dpurdie 1567
 
4003 dpurdie 1568
            # Build filter on this machine prevents the package building
1569
            # On a Build System this is not an error
1570
            #   Create a dummy platform called NOBUILD
1571
            #   Do not populate the interface directory with package data
1572
            #   Flag for jmake to do very little
1573
            #
1574
            CreateBuildPlatformEntry('Internal', 0, undef, 'NOBUILD');
1575
            $IgnorePkgs = 1;
1576
            $NoBuild = 1;
5109 dpurdie 1577
            Log( "Build for .. ". PrintPlatforms(['NOBUILD - ' . $msg], $sep));
4003 dpurdie 1578
 
1579
        } else {
5109 dpurdie 1580
            Error( $msg );
4003 dpurdie 1581
        }
1582
    }
1583
    else
1584
    {
1585
        Log( "Build for .. ". PrintPlatforms(\@BUILD_ACTIVEPLATFORMS, $sep));
1586
    }
1587
 
6133 dpurdie 1588
    ProcessToolSetPlatform() if $genToolsetActive;
1589
    Log( "Toolset .... " . $toolsetPlatform ) if $genToolsetPlatform;
1590
    Error ("No suitable TOOLSET platform found") if (($genToolsetActive > 1) && $::GBE_ABT);
1591
 
227 dpurdie 1592
    #
1593
    #   Generate an error if nothing can be done because the GBE_PLATFORM
1594
    #   masks any useful operation.
1595
    #
1596
    if ( $::GBE_PLATFORM )
1597
    {
1598
        my @MAKE_PLATFORMS;
1599
        my %active_platforms;
1600
 
239 dpurdie 1601
        #
1602
        #   Create a hash of active platforms based on the array of
1603
        #   active platforms to simplify testing
1604
        #
1605
        $active_platforms{$_} = 1 foreach ( @BUILD_ACTIVEPLATFORMS  );
227 dpurdie 1606
 
4551 dpurdie 1607
        unless ( $#GENERIC_TARGETS >= 0 )
227 dpurdie 1608
        {
239 dpurdie 1609
            foreach  ( split( ' ', $::GBE_PLATFORM) )
1610
            {
1611
                push @MAKE_PLATFORMS, $_
1612
                    if ( $active_platforms{$_} );
1613
            }
227 dpurdie 1614
 
239 dpurdie 1615
            Error ("The GBE_PLATFORM filter prevents any targets being made",
1616
                   "GBE_PLATFORM: $::GBE_PLATFORM" ) unless ( @MAKE_PLATFORMS );
227 dpurdie 1617
 
261 dpurdie 1618
            Log( "Make for ... ". PrintPlatforms(\@MAKE_PLATFORMS, $sep));
239 dpurdie 1619
        }
227 dpurdie 1620
 
1621
    }
1622
 
7310 dpurdie 1623
    #
1624
    #   NoBuilds do not generate warnings
1625
    #
1626
    return if $NoBuild;
1627
 
1628
    #
1629
    #   Generate a list of platforms that are completely unknown to JATS
1630
    #   May be the result of a user typo or a guess
1631
    #
1632
    if ( @BUILD_BADNAME )
1633
    {
1634
        Log( "Unknown Pl . " . PrintPlatforms(\@BUILD_BADNAME, $sep) );
1635
        Error ("The following platform names are not known to JATS", "@BUILD_BADNAME");
1636
    }
1637
 
1638
    #
1639
    #   Detect multiple GENERIC targets
1640
    #       Only one such target can be processed on any one machine
1641
    #
1642
    if ($#GENERIC_TARGETS > 0)
1643
    {
1644
        Error ("Multiple GENERIC targets detected", PrintPlatforms(\@GENERIC_TARGETS, $sep));
1645
    }
1646
 
227 dpurdie 1647
    return 1;
1648
}
1649
 
6133 dpurdie 1650
#-------------------------------------------------------------------------------
1651
# Function        : needToolset 
1652
#
1653
# Description     : Internal. Determine if this machine needs to build for
1654
#                   a TOOLSET or a GENERIC_<MachType>
1655
#                   
1656
#                   In Build System
1657
#                       BUILDFILTER must identify the machine performing TOOLSET builds
1658
#                       
1659
#                       The build filter MUST contain the psuedo platform TOOLSET in order for 
1660
#                       the alias to be created. This requires that the build daemons be configured to 
1661
#                       specify a TOOLSET. 
1662
#                       
1663
#                       Care MUST be taken to not configure multiple TOOLSET candiates 
1664
#                       on similar machine types.
1665
#                       
1666
#                   Non Build Sytem (User Development)
1667
#                       True    
1668
#
1669
# Inputs          : 
1670
#
1671
# Returns         : 
1672
#
1673
sub needToolset
1674
{
1675
    my $toolsetNeeded;
227 dpurdie 1676
 
6133 dpurdie 1677
    $toolsetNeeded = 1 if (!defined($::GBE_ABT));
1678
    if (!$toolsetNeeded && defined($::GBE_BUILDFILTER) ) {
1679
        $toolsetNeeded = grep( /^TOOLSET$/, split( ' ', $::GBE_BUILDFILTER ) );
1680
    }
1681
 
1682
    return $toolsetNeeded;
1683
}
1684
 
1685
#-------------------------------------------------------------------------------
1686
# Function        : ProcessToolSetPlatform 
1687
#
1688
# Description     : Locate the TOOLSET platform if required
1689
#                   In Build System
1690
#                       BUILDFILTER must identify the machine performing TOOLSET builds
1691
#                       The first suitable target will be chosen
1692
#                       
1693
#                       The build filter MUST contain the psuedo platform TOOLSET in order for 
1694
#                       the alias to be created. This requires that the build daemons be configured to 
1695
#                       specify a TOOLSET. 
1696
#                       
1697
#                       Care MUST be taken to not configure multiple TOOLSET candiates 
1698
#                       on similar machine types.
1699
#                       
1700
#                   Non Build Sytem (User Development)
1701
#                       The first suitable target will be chosen    
1702
#
1703
# Inputs          : 
1704
#
1705
# Returns         : 
1706
#
1707
sub ProcessToolSetPlatform
1708
{
1709
    my $toolsetNeeded;
1710
    my $toolset;
1711
 
1712
    #
1713
    #   User is not allowed to create a TOOLSET alias
1714
    #       This should be captured before here, but ...
1715
    #
1716
    if (exists $BUILDALIAS{TOOLSET})
1717
    {
1718
        Error('Internal: User has manually specified a TOOLSET alias' );
1719
    }
1720
 
1721
    #
1722
    #   Determine if we need to do any work
1723
    #
1724
    return unless needToolset();
1725
 
1726
    #
1727
    #   Need to ensure that we have a TOOLSET platform in the build set
1728
    #
1729
    my %activePlatformMap = map {$_ => 1} @BUILD_ACTIVEPLATFORMS;
1730
    my @toolsetTargets = PlatformConfig::getTargetsByTag('TOOLSET'); 
1731
    foreach my $item (@toolsetTargets)
1732
    {
1733
        if (exists($activePlatformMap{$item}))
1734
        {
1735
            #
1736
            #   Add TOOLSET arguments into the existing target
1737
            #   Really only expecting --OnlyProd
1738
            #
1739
            if ( @genToolsetArgs) {
1740
                PlatformArgument($item, @genToolsetArgs);
1741
            }
1742
 
1743
            # Update the displayed Toolset platform
1744
            $toolset = $item;
1745
            $toolsetPlatform = $toolset;
1746
            last;
1747
        }
1748
    }
1749
 
1750
    #
1751
    #   No toolset platform found in the current build set
1752
    #   
1753
    unless ($toolset) {
1754
        $toolsetPlatform = "None found in current build set"; 
1755
        $genToolsetActive = 2;
1756
        return;
1757
    }
1758
 
1759
    #
1760
    #   Insert alias information
1761
    #
1762
    $BUILDALIAS{TOOLSET} = $toolset;
1763
    push @{$BUILDINFO{$toolset}{USERALIAS}}, 'TOOLSET';
1764
}
1765
 
1766
#-------------------------------------------------------------------------------
1767
# Function        : BuildPreviousVersion 
1768
#
1769
# Description     : Deprecated. Do not use 
1770
#
1771
# Inputs          : 
1772
#
1773
# Returns         : 
1774
#
227 dpurdie 1775
sub BuildPreviousVersion
1776
{
1777
    my( $version ) = shift;
1778
 
1779
    $BUILDPREVIOUSVERSION = $version;
261 dpurdie 1780
    Log( "Previous Version ... $BUILDPREVIOUSVERSION" );
227 dpurdie 1781
 
1782
    return 1;
1783
}
1784
 
1785
 
1786
sub BuildInterface
1787
{
1788
    my( $ifdirname ) = @_;
1789
 
1790
    #
1791
    #   Clobber the directory - at the end.
1792
    #
1793
    if ( $Clobber )
1794
    {
1795
        #
1796
        #   If this Interface directory contains the Dpackage.cfg file
1797
        #   then JATS has created DPACKAGE and it needs to be clobbered
1798
        #   Flag that it needs to be done later - when we know where it is
1799
        #
1800
        $DeleteDPACKAGE = 1 if ( -f "$ifdirname/Dpackage.cfg" );
1801
    }
1802
 
1803
    #
6133 dpurdie 1804
    #   Generate the required directory
227 dpurdie 1805
    #
6133 dpurdie 1806
    BuildInterfaceInternal($ifdirname);
1807
    Log( "Interface .. $ifdirname" );
1808
    return 1;
1809
}
227 dpurdie 1810
 
6133 dpurdie 1811
#-------------------------------------------------------------------------------
1812
# Function        : BuildInterfaceInternal  
1813
#
1814
# Description     : Internal Use Only
1815
#                   Guts of the BuildInterface processing 
1816
#
1817
# Inputs          : $ifdirname  - Name of an interface directory
1818
#
1819
# Returns         : 
1820
#
1821
 
1822
sub BuildInterfaceInternal
1823
{
1824
    my( $ifdirname ) = @_;
1825
    my @createDirs;
1826
 
1827
    push @CLOBBERDIRS, $ifdirname;
1828
 
227 dpurdie 1829
    if ( $ifdirname eq "local" ) {
6133 dpurdie 1830
        push @createDirs, "$ifdirname/inc";
227 dpurdie 1831
        $BUILDLOCAL = "local";
1832
 
1833
    } else {
6133 dpurdie 1834
        push @createDirs, "$ifdirname/include";
227 dpurdie 1835
        $BUILDINTERFACE = $ifdirname;
1836
        $::ScmInterface = $ifdirname;
1837
    }
1838
 
6133 dpurdie 1839
    unless ($Clobber) {
1840
        push @createDirs, "$ifdirname/bin";
1841
        push @createDirs, "$ifdirname/lib";
1842
 
1843
        foreach my $dir ( @createDirs)
1844
        {
1845
            mkpath($dir);
1846
        }
1847
        ToolsetFiles::AddDir($ifdirname, 'Internal');
1848
    }
227 dpurdie 1849
}
1850
 
1851
 
6133 dpurdie 1852
 
227 dpurdie 1853
sub BuildDirTree
1854
{
1855
    my( $dirfile, $dirhead ) = @_;
1856
    my( $dirname, $c );
1857
 
1858
    $dirhead = '.'
1859
        unless defined( $dirhead );
1860
 
1861
    if ( $Clobber )                             # clobber mode ?
1862
    {
1863
        push @CLOBBERDIRS, $dirhead unless $dirhead eq '.';
1864
        return;
1865
    }
1866
 
1867
    #
1868
    #   Allow for an empty "dirfile". This will allow a directory to be created
1869
    #   without the overhead of the file
1870
    #
1871
    if ( ! $dirfile )
1872
    {
261 dpurdie 1873
        Log( "DirTree .... $dirhead" );
341 dpurdie 1874
        mkpath ( $dirhead );
227 dpurdie 1875
    }
1876
    else
1877
    {
261 dpurdie 1878
        Log( "DirTree .... $dirfile within $dirhead" );
341 dpurdie 1879
        mkpath ( $dirhead );
1880
 
283 dpurdie 1881
        open( DIRFILE, '<' ,$dirfile ) ||
227 dpurdie 1882
            Error( "cannot open '$dirfile'" );
1883
 
1884
        while( $dirname = <DIRFILE> )
1885
        {
1886
            chop $dirname;
1887
            $dirname =~ s/#.*//;
1888
            $c = $dirname =~ s/\s*(\S+).*/$1/g;
1889
 
1890
            next unless ( $c == 1 );
1891
 
1892
            if ( ! -d "$dirhead/$dirname" )
1893
            {
261 dpurdie 1894
                Log( "Dir ........ $dirhead/$dirname" );
341 dpurdie 1895
                mkpath ( "$dirhead/$dirname" );
227 dpurdie 1896
            }
1897
        }
1898
 
1899
        close( DIRFILE );
1900
    }
1901
    $BUILDDIRTREE = $dirhead;
1902
}
1903
 
1904
#-------------------------------------------------------------------------------
1905
# Function        : IncludePkg
1906
#
1907
# Description     : Examine a fully specified package directory for a file
1908
#                   that will specify packages to be included. This allows
1909
#                   a package to be simply a package of other packages
1910
#
1911
#                   Internal function. Not to be used by users
1912
#
1913
# Inputs          : Name of the package
1914
#                   Full directory path of the package to examine
1915
#
1916
# Returns         : Nothing
1917
#
1918
sub IncludePkg
1919
{
1920
    my ($name, $pkg) = @_;
1921
    my $file = "$pkg/incpkg";
1922
 
363 dpurdie 1923
    Debug ("IncludePkg: $name, $pkg" );
227 dpurdie 1924
 
1925
    #
1926
    #   Using a require will ensure that the package is only processed once
1927
    #   even though the function user may be called multiple times.
1928
    #   Also prevents recursion within included packages.
1929
    #
1930
    if ( -f $file  )
1931
    {
261 dpurdie 1932
        Log( "PackageIncludes. $name" ) unless ( $INC{$file} );
227 dpurdie 1933
        require $file;
1934
    }
1935
}
1936
 
1937
#-------------------------------------------------------------------------------
1938
# Function        : LinkPkgArchive
1939
#
1940
# Description     : Include an external package into the build sandbox
1941
#                   by extending the compiler and linker search paths to
1942
#                   include suitable directories found in the package
1943
#
1944
# Inputs          : package name
1945
#                   package version
1946
#
1947
sub LinkPkgArchive
1948
{
1949
    my( $name, $version ) = @_;
1950
 
1951
    return BuildPkgArchive( @_ )
1952
        if ( $ForceBuildPkg );                  # Forcing interface directory
1953
    return if ( $Clobber );                     # clobber mode ?
1954
 
1955
    Debug( "LinkPkgArchive:" );
1956
    Debug( "Name:      $name" );
1957
    Debug( "Version:   $version" );
1958
 
1959
    DataDirective("LinkPkgArchive");            # This directive allowed here
1960
 
7312 dpurdie 1961
#   if ( $IgnorePkgs )
1962
#   {
1963
#       Log( "LinkPkgArchive .. $name ($version) - Ignored" );
1964
#       return;
1965
#   }
2078 dpurdie 1966
 
227 dpurdie 1967
    #
1968
    #   Ensure that we have do not have multiple definitions
1969
    #
1970
    if ( PackageEntry::Exists( $name, $version ) )
1971
    {
261 dpurdie 1972
        Log( "Duplicate Package: $name, $version. Duplicate entry ignored" );
227 dpurdie 1973
        return;
1974
    }
1975
 
1976
    if ( $Cache && $::GBE_DPKG_CACHE )
1977
    {
1978
        my $mode = ($Cache > 1) ? "-refresh" : "";
331 dpurdie 1979
        Log( "LinkPkgArchive .. $name ($version) Update Cache" );
5744 dpurdie 1980
        System('--NoExit', "$::GBE_PERL $::GBE_TOOLS/cache_dpkg.pl $mode -wait -quiet $name/$version" );
227 dpurdie 1981
    }
1982
 
1983
    #
1984
    #   Locate the package ONCE
1985
    #
331 dpurdie 1986
    Log( "LinkPkgArchive .. $name ($version)" );
7301 dpurdie 1987
    my ($pkg, $local, $pkgSig ) = PackageLocate( $name, $version );
227 dpurdie 1988
    if ( $pkg )
1989
    {
1990
        #
1991
        #   Generate package rules for each active platform
1992
        #
363 dpurdie 1993
        IncludePkg ( $name, $pkg );
7310 dpurdie 1994
        foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
227 dpurdie 1995
        {
7301 dpurdie 1996
            LinkEntry( $platform, $pkg, $name, $version, 0, $local, $pkgSig );
227 dpurdie 1997
        }
1998
    }
1999
}
2000
 
2001
#-------------------------------------------------------------------------------
2002
# Function        : PackageLocate
2003
#
2004
# Description     : Locate a package
2005
#                   Once located a package will be processed for each
2006
#                   platform, but it need only be located ONCE
2007
#
2008
# Inputs          : package name
2009
#                   package version
2010
#
2011
# Returns         : path to the package
2012
#                   local       1 - From local package repository
7301 dpurdie 2013
#                   Package Signature
227 dpurdie 2014
#
2015
sub PackageLocate
2016
{
2017
    my ($name, $uversion ) = @_;
283 dpurdie 2018
    my $pkg;
227 dpurdie 2019
    my $local = 1;
7301 dpurdie 2020
    my $sandbox = 1;
227 dpurdie 2021
    my $isa_cache = 0;
2022
    my $version;
7302 dpurdie 2023
    my $pkgSig = 'Unknown';
227 dpurdie 2024
 
2025
    Debug( "PackageLocate: ($name/$uversion)" );
2026
 
2027
    #
7301 dpurdie 2028
    #   If we are in a SandBox, then we use package signatures to locate pre-built
2029
    #   packages.
2030
    #
2031
    if ($::GBE_SANDBOX)
2032
    {
2033
        my @ret = PackageLocateBySignature(@_);
2034
        if ($ret[0])
2035
        {
2036
            return @ret;
2037
        }
7303 dpurdie 2038
        Log ("                  Not found by signature - revert to package version");
7301 dpurdie 2039
    }
2040
 
2041
    #
227 dpurdie 2042
    #   Look in each package archive directory
2043
    #
2044
    foreach my $dpkg ( split( $::ScmPathSep, $::GBE_DPKG_SBOX),
2045
                       '--NotSandbox',
2046
                       split( $::ScmPathSep, $::GBE_DPKG_LOCAL),
2047
                       '--NotLocal',
2048
                       split( $::ScmPathSep, $::GBE_DPKG_CACHE),
2049
                       '--NotCache',
4688 dpurdie 2050
                       split( $::ScmPathSep, $::GBE_DPKG_REPLICA),
227 dpurdie 2051
                       split( $::ScmPathSep, $::GBE_DPKG),
313 dpurdie 2052
                       split( $::ScmPathSep, $::GBE_DPLY),
227 dpurdie 2053
                       split( $::ScmPathSep, $::GBE_DPKG_STORE) )
2054
    {
2055
 
2056
        #
2057
        #   Detect various tags that have been placed in the search list
2058
        #   to flag the end of the sandbox search and the end of the local
2059
        #   archive search
2060
        #
2061
        if ( $dpkg eq '--NotSandbox' )
2062
        {
2063
            $sandbox = 0;
2064
            next;
2065
        }
2066
        if ( $dpkg eq '--NotLocal' )
2067
        {
2068
            $local = 0;
2069
            $isa_cache = 1;
2070
            next;
2071
        }
2072
        if ( $dpkg eq '--NotCache' )
2073
        {
2074
            $isa_cache = 0;
2075
            next;
2076
        }
2077
 
2078
        #
2079
        #   If we are playing in a sandbox, then the version number is
2080
        #   not used. The Package suffix is still used so that we can
2081
        #   differentiate sysbasetypes.xxxxx.mas and sysbasetypes.xxxxx.syd
2082
        #
2083
        if ( $sandbox )
2084
        {
359 dpurdie 2085
            my ($pn, $pv, $ps ) = SplitPackage ($name, $uversion );
227 dpurdie 2086
            $version = 'sandbox';
2087
            $version .= '.' . $ps if ( $ps );
2088
        }
2089
        else
2090
        {
2091
            $version = $uversion;
2092
        }
2093
 
6133 dpurdie 2094
        $pkg = "$dpkg/$name/$version";
2095
        $pkg = "$dpkg/$name/$version.lnk"
2096
            if ( -e "$dpkg/$name/$version.lnk" );
2097
 
227 dpurdie 2098
        #
2099
        #   Using a soft link
2100
        #   Emulate a link in software. The link file contains one line
2101
        #   which is the real pathname of the package
2102
        #
2103
        if ( $pkg =~ m~(.*)\.lnk$~  )
2104
        {
2105
            #
2106
            #   Warn the user if both a link and a real directory
2107
            #   are both present - the link may well be incorrect
2108
            #
2109
            my $non_link = $1;
2110
            Warning ("Suspect package link: $pkg",
2111
                     "Both a link and a package where found - using the link" )
2112
                                                            if ( -d $non_link );
2113
 
2114
            Debug( "           link found -> $pkg" );
2115
            my $link_src = $pkg;
6133 dpurdie 2116
            $pkg = TagFileRead($pkg);
2117
            $pkg =~ s~\\~/~g;
5819 dpurdie 2118
            if ($pkg =~ s~^GBE_SANDBOX/~$::GBE_SANDBOX/~)
2119
            {
7307 dpurdie 2120
                    $pkgFromSandbox++;
2121
 
5819 dpurdie 2122
                    # If the target sandbox is in the 'deploymode' then the package
2123
                    # will not be in the expected location. It will be in a 'build/deploy'
2124
                    # subdir. Remove the pkg/name dir to get to the root of the package
2125
                    my @dirs = File::Spec->splitdir( $pkg );
2126
                    splice(@dirs, -2);
2127
                    my $deployBox = catdir(@dirs, 'build', 'deploy');
2128
                    $pkg = $deployBox if ( -d $deployBox);
2129
            }
227 dpurdie 2130
 
2078 dpurdie 2131
            unless ( -d $pkg )
2132
            {
2133
                Error ("Broken link: $pkg",
2134
                       "Source link: $link_src",
2135
                       "Try deleting the .lnk file" ) unless ( $NoPackageError );
2136
 
2137
                Warning ("Package not available. Broken link: $pkg");
2138
            }
227 dpurdie 2139
        }
2140
 
2141
        Debug( "           searching $pkg" );
2142
 
2143
        #   Does the package directory exist?
2144
        #   Terminate the directory name with a "/" to detect hidden spaces
2145
        #..
2146
        $pkg =~ s~//~/~g;
2147
        next unless ( -d "$pkg/" );             # exists ?
2148
 
2149
        #
2150
        #   If the package exists within the dpkg_archive cache then mark the
2151
        #   version as having been used. Used by cache cleanup algorithms
2152
        #
2153
        if ( $isa_cache  )
2154
        {
2155
            TouchFile ( "$pkg/used.cache", "Marks the cache copy as being used");
2156
        }
2157
 
2158
        #
2159
        #   Use the first suitable package found
2160
        #..
2161
 
2162
        Debug( "           importing $pkg" );
7301 dpurdie 2163
        return $pkg, $local, $pkgSig;
227 dpurdie 2164
    }
2165
 
2166
    #
2167
    #   Package not found
2168
    #   This is an error, although it can be bypassed
2169
    #
261 dpurdie 2170
    Error ("Required package not found: '$name/$version'" ) unless ( $NoPackageError );
227 dpurdie 2171
 
261 dpurdie 2172
    Log( "WARNING .... Package not available: '$name/$version'" );
283 dpurdie 2173
    return;
227 dpurdie 2174
}
2175
 
7301 dpurdie 2176
#-------------------------------------------------------------------------------
2177
# Function        : PackageLocateBySignature
2178
#
2179
# Description     : Locate a package via its signature
2180
#                   In a monoRepo sandbox pre-build package artifacts are located
2181
#                   via the signature of the source package. This must be generated
2182
#                   before it can be used.
2183
#                   
2184
#                   At the moment we simply generate an error if the signature cannot be
2185
#                   found. We could be clever and invoke jats to generate the required 
2186
#                   signature.
2187
#                   
2188
#
2189
# Inputs          : package name
2190
#                   package version
2191
#
2192
# Returns         : path to the package
2193
#                   local       1 - From local package repository
2194
#                   Package Signature
2195
#
2196
sub PackageLocateBySignature
2197
{
2198
    my ($name, $uversion ) = @_;
2199
    my $prj = '';
2200
    my $pkg;
2201
    my $local = 1;
2202
    my $in_sandbox = 1;
2203
    my $isa_cache = 0;
2204
    my $version;
7302 dpurdie 2205
    my $pkgSig = 'Unknown';
227 dpurdie 2206
 
7301 dpurdie 2207
    Debug( "PackageLocateBySignature: ($name/$uversion)" );
2208
 
2209
    # 
2210
    #   We are in a sandbox and expect to find a interface/Package.sig file
2211
    #   This will allow us to locate the package in the package store
2212
    #   
2213
    #   If there is no interface/Package.sig, then the user must build (not make)
2214
    #   the package in the sandbox.
2215
    #   
2216
    #   ie: the interface/Package.sig file allows us to use the package from package cache
2217
    #       or indicates that the user has not yet built the package
2218
    #       
2219
    #
2220
    #   First locate the packages interface directory
2221
    #   We have a nice link from the sandbox to assist in this
2222
    #
2223
    my ($pn, $pv, $ps ) = SplitPackage ($name, $uversion );
2224
    $version = 'sandbox';
2225
    $prj = '.' . $ps if ( $ps ); 
2226
    $version .= $prj;
2227
 
2228
    my $ifaceDir = catdir($::GBE_SANDBOX, 'sandbox_dpkg_archive', $name, $version . '.int');
2229
    $ifaceDir = TagFileRead($ifaceDir);
2230
    $ifaceDir =~ s~\\~/~g;
2231
    $ifaceDir =~ s~GBE_SANDBOX/~$::GBE_SANDBOX/~;
2232
    my $pkgSigFile = catfile( $ifaceDir, 'Package.sig');
2233
 
7312 dpurdie 2234
    # Temp: Remove when we no longer have package-versions
7301 dpurdie 2235
    return unless -f $pkgSigFile; 
2236
 
2237
    Error("Package signature not found for $name/$version", "You must 'build' the package before using it")
2238
        unless ( -f $pkgSigFile);
2239
    $pkgSig = TagFileRead($pkgSigFile);
2240
    Error("Package signature invalid for $name/$version", "Signature: $pkgSig") 
7302 dpurdie 2241
        if((length($pkgSig) != 40) && $pkgSig !~ m~^MSG:~) ;
7301 dpurdie 2242
 
2243
    #
2244
    #   Look in each package archive directory
2245
    #
2246
    foreach my $dpkg ( split( $::ScmPathSep, $::GBE_DPKG_SBOX),
2247
                       '--NotSandbox',
2248
                       split( $::ScmPathSep, $::GBE_DPKG_LOCAL),
2249
                       '--NotLocal',
2250
                       split( $::ScmPathSep, $::GBE_DPKG_CACHE),
2251
                       '--NotCache',
2252
                       split( $::ScmPathSep, $::GBE_DPKG_REPLICA),
2253
                       split( $::ScmPathSep, $::GBE_DPKG),
2254
                       split( $::ScmPathSep, $::GBE_DPLY),
2255
                       split( $::ScmPathSep, $::GBE_DPKG_STORE) )
2256
    {
2257
 
2258
        #
2259
        #   Detect various tags that have been placed in the search list
2260
        #   to flag the end of the sandbox search and the end of the local
2261
        #   archive search
2262
        #
2263
        if ( $dpkg eq '--NotSandbox' )
2264
        {
2265
            $in_sandbox = 0;
2266
            next;
2267
        }
2268
        if ( $dpkg eq '--NotLocal' )
2269
        {
2270
            $local = 0;
2271
            $isa_cache = 1;
2272
            next;
2273
        }
2274
        if ( $dpkg eq '--NotCache' )
2275
        {
2276
            $isa_cache = 0;
2277
            next;
2278
        }
2279
 
2280
        $pkg = "$dpkg/$name$prj/$pkgSig";
2281
        $pkg = "$dpkg/$name/$version.lnk"
2282
            if ( -e "$dpkg/$name/$version.lnk" );
2283
 
2284
        #
2285
        #   If we are scanning the sandbox archive itself, then we can will override the signature
2286
        #   if the package has been built within the sandbox. This is indicated by the presence of a
2287
        #   valid .lnk file.
2288
        #   
2289
        #       Note: The .lnk file may be present, but it won't point to anything valid until
2290
        #             the package has been built.
2291
        #
2292
        if ($in_sandbox)
2293
        {
2294
            my $pkgLinkFile = $pkg;
2295
            $pkgLinkFile =~ s~pkgsig$~lnk~;
2296
 
2297
            if ( -f $pkgLinkFile )
2298
            {
2299
                Debug( "           link found -> $pkg" );
2300
                my $pkgLink = TagFileRead($pkgLinkFile);
2301
                $pkgLink =~ s~\\~/~g;
2302
                if ($pkgLink =~ s~^GBE_SANDBOX/~$::GBE_SANDBOX/~)
2303
                {
2304
                        # If the target sandbox is in the 'deploymode' then the package
2305
                        # will not be in the expected location. It will be in a 'build/deploy'
2306
                        # subdir. Remove the pkg/name dir to get to the root of the package
2307
                        my @dirs = File::Spec->splitdir( $pkgLink );
2308
                        splice(@dirs, -2);
2309
                        my $deployBox = catdir(@dirs, 'build', 'deploy');
2310
                        $pkgLink = $deployBox if ( -d $deployBox);
2311
                }
2312
 
2313
                # 
2314
                #   Handle badly formed packages - test for descpkg file
2315
                #   Or those have the body of the code in the pkg directory
2316
                #   
2317
                my $pkgDescpkg = catfile( $pkgLink, 'descpkg');
2318
                if (-d $pkgLink && -f $pkgDescpkg)
2319
                {
2320
                    $pkg = $pkgLink;
2321
Debug0("============== From Sandbox: $pkgSig");
2322
#                    $pkgFromSandbox++;
2323
                }
2324
            }
2325
        }
2326
 
2327
        Debug( "           searching $pkg" );
2328
 
2329
        #   Does the package directory exist?
2330
        #   Terminate the directory name with a "/" to detect hidden spaces
2331
        #..
2332
        $pkg =~ s~//~/~g;
2333
        next unless ( -d "$pkg/" );             # exists ?
2334
 
2335
        #
2336
        #   If the package exists within the dpkg_archive cache then mark the
2337
        #   version as having been used. Used by cache cleanup algorithms
2338
        #
2339
        if ( $isa_cache  )
2340
        {
2341
            TouchFile ( "$pkg/used.cache", "Marks the cache copy as being used");
2342
        }
2343
 
2344
        #
2345
        #   Use the first suitable package found
2346
        #..
2347
 
2348
        Debug( "           importing $pkg" );
2349
        return $pkg, $local, $pkgSig;
2350
    }
2351
 
2352
    #
2353
    #   Package not found
2354
    #   This is an error, although it can be bypassed
2355
    #
7312 dpurdie 2356
    Error ("Required package not found by signature: '$name/$version'" ) unless ( $NoPackageError );
2357
 
2358
    Log( "WARNING .... Package not available: '$name/$version'" );
7301 dpurdie 2359
    return;
2360
}
2361
 
227 dpurdie 2362
#-------------------------------------------------------------------------------
2363
# Function        : LinkEntry
2364
#
2365
# Description     : Scan a package an locate platform specific directories
2366
#                   Create data structures to capture the information
7310 dpurdie 2367
#                   This function is used by LinkPkgArchive
227 dpurdie 2368
#                   to perfom the bulk of package inclusion work.
2369
#
2370
# Inputs          : platform being processed
2371
#                   path to the package
2372
#                   name of the package
2373
#                   version of the package
2374
#                   sandbox support (non-zero)
331 dpurdie 2375
#                   local package
7301 dpurdie 2376
#                   package Signature
227 dpurdie 2377
#
2378
sub LinkEntry
2379
{
7301 dpurdie 2380
    my( $platform, $pkg, $name, $version, $sandbox, $local, $pkgSig ) = @_;
227 dpurdie 2381
    my( $entry );
2382
 
2383
    #   Create entry record
2384
    #
2385
    #..
7301 dpurdie 2386
    $entry = PackageEntry::New( $pkg, $name, $version, $sandbox, 'link', $local, $pkgSig );
227 dpurdie 2387
 
2388
    #   Populate includes:
2389
    #
2390
    #   - include/$platform                 (eg include/solaris)
2391
    #   - inc/$platform                     (eg inc/solaris)
2392
    #   - include.$platform                 (eg include.solaris)
2393
    #   - inc.$platform                     (eg inc.solaris)
2394
    #   - include                           (eg include)
2395
    #   - inc                               (eg inc)
2396
    #
2397
    #   plus, product specialisation directores
2398
    #
2399
    #   eg. BuildProduct( 'IDFC', 'WIN32' );
2400
    #
2401
    #   - inc/IDFC_WIN32                    <- derived platform
2402
    #   - inc/IDFC                          <- product
2403
    #   - inc/WIN32                         <- target
2404
    #..
2405
    my $parts = $BUILDINFO{$platform}{PARTS};
2406
 
2407
    foreach my $part ( @$parts )
2408
    {
2409
        $entry->RuleInc( "/include." . $part ) if ( !$sandbox );
2410
        $entry->RuleInc( "/inc." . $part )     if ( !$sandbox );
2411
        $entry->RuleInc( "/include/" . $part ) if ( !$sandbox );
2412
        $entry->RuleInc( "/inc/" . $part );
2413
    }
2414
 
2415
    #
2416
    #   Also search the root include directory - last
2417
    #
2418
    $entry->RuleInc( "/include" )               if ( !$sandbox );
2419
    $entry->RuleInc( "/inc" );
2420
 
2421
    #   Populate libraries:
2422
    #
2423
    #   - lib/lib.$platform[D|P]            (eg lib/lib.sparcD)
2424
    #   - lib/$platform[D|P]                (eg lib/lib.sparc)
2425
    #   - lib.$platform[D|P]                (eg lib.sparcD)
2426
    #
2427
    #   plus, product specialisation directores
2428
    #
2429
    #   eg. BuildProduct( 'IDFC', 'WIN32' );
2430
    #
2431
    #   - lib/IDFC_WIN32                    <- derived platform
2432
    #   - lib/IDFC                          <- product
2433
    #   - lib/WIN32                         <- target
2434
    #..
2435
    $parts = $BUILDINFO{$platform}{PARTS};
2436
 
2437
    foreach my $part ( @$parts )
2438
    {
2439
        $entry->RuleLib("/lib" . ".$part" )     if ( !$sandbox );
2440
        $entry->RuleLib("/lib" . "/lib.$part" ) if ( !$sandbox );
2441
        $entry->RuleLib("/lib" . "/$part" );
2442
    }
2443
 
2444
    #
2445
    #   Some extra places to search
2446
    #   None. This is good as it indicates that all locations are described in PARTS
2447
    #
2448
    #   Do NOT search in /lib. There are no libraries that work on all platforms
2449
    #   Libraries are binaries!
2450
    #
2451
    #    $entry->RuleLib( "/lib" );
2452
 
2453
    #   Tools:
2454
    #
2455
    #   Tools provide an extensible search path for tools and
2456
    #   utilities used to build programs. These are tools that
2457
    #   are executable on the current host machine and are
2458
    #   independent of the toolset.
2459
    #
2460
    #..
2461
    $entry->ExamineToolPath();
2462
    $entry->ExamineThxPath($platform);
2463
    $entry->Cleanup();                          # cleanup tables
2464
 
2465
    #
2466
    #   Add the package entry to the array of such entries for
2467
    #   the current platform. Maintain the discovery order
2468
    #
2469
    #..
2470
    push ( @{$PKGRULES{$platform}}, $entry );
2471
}
2472
 
2473
 
2474
#-------------------------------------------------------------------------------
2475
# Function        : BuildPkgArchive
2476
#
2477
# Description     : Include an external package into the build sandbox
2478
#                   by copying the packages files into the interface directory
2479
#
2480
# Inputs          : package name
2481
#                   package version
2482
#
2483
sub BuildPkgArchive
2484
{
2485
    my( $name, $version ) = @_;
2486
 
2487
    return if ( $Clobber );                     # clobber mode ?
2488
 
2489
    Debug( "BuildPkgArchive:" );
2490
    Debug( "Name:      $name" );
2491
    Debug( "Version:   $version" );
2492
 
2493
    DataDirective("BuildPkgArchive");           # This directive allowed here
2494
 
7312 dpurdie 2495
#   if ( $IgnorePkgs )
2496
#   {
2497
#       Log( "BuildPkgArchive . $name ($version) - Ignored" );
2498
#       return;
2499
#   }
2078 dpurdie 2500
 
227 dpurdie 2501
    #
2502
    #   Ensure that we have do not have multiple definitions
2503
    #
2504
    if ( PackageEntry::Exists( $name, $version ) )
2505
    {
261 dpurdie 2506
        Log( "Duplicate Package: $name, $version. Duplicate entry ignored" );
227 dpurdie 2507
        return;
2508
    }
2509
 
2510
    if ( $Cache && $::GBE_DPKG_CACHE )
2511
    {
2512
        my $mode = ($Cache > 1) ? "-refresh" : "";
261 dpurdie 2513
        Log( "BuildPkgArchive . $name ($version) Update Cache" );
5744 dpurdie 2514
        System('--NoExit', "$::GBE_PERL $::GBE_TOOLS/cache_dpkg.pl $mode -wait -quiet $name/$version" );
227 dpurdie 2515
    }
2516
 
2517
    #
2518
    #   Locate the package
6133 dpurdie 2519
    #   Use the first instance of the package that is found
227 dpurdie 2520
    #
261 dpurdie 2521
    Log( "BuildPkgArchive . $name ($version)" );
7301 dpurdie 2522
    my ( $pkg, $local, $pkgSig ) = PackageLocate( $name, $version );
227 dpurdie 2523
    if ( $pkg )
2524
    {
2525
        #
2526
        #   Create a Package Entry
2527
        #
7301 dpurdie 2528
        my $entry = PackageEntry::New( $pkg, $name, $version, 0, 'build', $local, $pkgSig );
227 dpurdie 2529
 
2530
        #
2531
        #   Determine if the package needs to be installed:
2532
        #       If the package is a 'local' package then force transfer
2533
        #       If the user has specified --cache then force transfer
2534
        #       If package is newer that copy, then force transfer
2535
        #       If copy does not exist, then force a transfer
2536
        #
2537
        my $tag_dir = "$Cwd/$BUILDINTERFACE/BuildTags";
2538
        my $tag_file = "$tag_dir/${name}_${version}.tag";
6073 dpurdie 2539
        my $arglist = GenerateInstallArgumentList();
227 dpurdie 2540
 
2541
        my $package_installed;
2542
        $package_installed = 1
2543
            if ( !$local &&
2544
                 !$Cache &&
6073 dpurdie 2545
                 !FileIsNewer( $entry->GetBaseDir('descpkg'), $tag_file ) &&
2546
                 TagFileMatch( $tag_file, $arglist)
2547
                  );
227 dpurdie 2548
 
2549
        #
2550
        #   Determine the package format and use the appropriate installer
2551
        #   Supported formats
6133 dpurdie 2552
        #       1) Package has a descpkg file (only style currently supported)
227 dpurdie 2553
        #
2554
        if ( $package_installed ) {
2555
            Verbose ("Package already installed: $name, $version");
2556
 
2557
        } else {
261 dpurdie 2558
            Log( "                . installing '$pkg'" );
2559
            Log( "                . -> " . readlink($pkg) ) if ( -l $pkg );
227 dpurdie 2560
 
2561
            if ( -e "$pkg/descpkg" )
2562
            {
2563
 
2564
                #
2565
                #   If forcing a BuildPkg, then don't use symlinks
2566
                #   to files in dpkg_archive
2567
                #
331 dpurdie 2568
                my @opts;
2569
                push @opts, "--NoSymlinks" if ( $ForceBuildPkg );
2570
                push @opts, "--AllowOverWrite" if ( $local );
227 dpurdie 2571
 
2572
                #
2573
                #   Determine all the Platforms, Products and Targets
2574
                #   that need to be installed
2575
                #
6073 dpurdie 2576
 
331 dpurdie 2577
                System( "cd $pkg; $::GBE_PERL $::GBE_TOOLS/installpkg.pl $Cwd/$BUILDINTERFACE $Cwd @opts $arglist");
227 dpurdie 2578
                Error( "Package installation error" ) if ( $? != 0 );
2579
            }
2580
            else
2581
            {
2582
                Error ("Unknown package format for package $name/$version found in $pkg");
2583
            }
2584
 
2585
            #
2586
            #   Tag the package as installed - after it has been transferred
2587
            #
2588
            mkdir ( $tag_dir );
6073 dpurdie 2589
            FileCreate( $tag_file, $arglist );
227 dpurdie 2590
        }
2591
 
2592
        #
2593
        #   Process package
2594
        #
2595
        IncludePkg ( $name, $pkg );
2596
 
2597
        #
2598
        #   Complete the creation of the package entry
2599
        #   Add the information for all platforms
2600
        #
2601
        $entry->Cleanup();
2602
        for my $platform (@BUILD_ACTIVEPLATFORMS)
2603
        {
2604
            $entry->ExamineToolPath();
2605
            $entry->ExamineThxPath($platform);
2606
            push ( @{$PKGRULES{$platform}}, $entry );
2607
        }
2608
    }
2609
}
2610
 
2611
#-------------------------------------------------------------------------------
311 dpurdie 2612
# Function        : CreateInterfacePackage
2613
#
2614
# Description     : Create a dummy package entry to describe the Interface
2615
#                   This is done AFTER all the BuildPkgArchive directives have
2616
#                   been processed so that the interface directory is fully
2617
#                   processed
2618
#
2619
# Inputs          : None
2620
#
2621
# Returns         : 
2622
#
2623
sub CreateInterfacePackage
2624
{
2625
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
2626
    {
2627
        my $entry = PackageEntry::Interface( "$::Cwd/$BUILDINTERFACE" );
2628
 
2629
        #
2630
        #   Locate include and lib bits within the interface
2631
        #   This is much simpler than for a LinkPkgArchive as the form
2632
        #   has been sanitized
2633
        #
2634
        my $parts = $BUILDINFO{$platform}{PARTS};
2635
 
2636
        foreach my $part ( @$parts )
2637
        {
2638
            $entry->RuleInc( "/include/" . $part );
2639
        }
2640
        $entry->RuleInc( "/include" );
2641
 
2642
        foreach my $part ( @$parts )
2643
        {
2644
            $entry->RuleLib("/lib/" . $part );
2645
        }
2646
 
2647
        $entry->ExamineToolPath();
2648
        $entry->ExamineThxPath($platform);
2649
        $entry->Cleanup();
2650
 
2651
        #
2652
        #   Add the package entry to the array of such entries for
2653
        #   the current platform. Force it to be the first one as
2654
        #   the interface directory will be scanned first
2655
        #
2656
        unshift ( @{$PKGRULES{$platform}}, $entry );
2657
    }
2658
}
2659
 
2660
#-------------------------------------------------------------------------------
227 dpurdie 2661
# Function        : GenerateInstallArgumentList
2662
#
2663
# Description     : Generate an argument list for the installpkg.pl script
2664
#                   The argument list is of the form
2665
#                       --Platform:xx[:xx[:xx]] --Platform:yy[:yy[:yy]] ...
2666
#                   Where xx is:
2667
#                       * a 'part' of the target platform
2668
#                         Order is: platform, product, ...  target( in that order )
2669
#                       * --Option[=yyy]
2670
#                        An option to be passed to the script. These are bound only
2671
#                        to the enclosed platform.
2672
# Inputs          :
2673
#
2674
# Returns         : See above
2675
#
2676
sub GenerateInstallArgumentList
2677
{
2678
    my @arglist;
2679
 
2680
    #
2681
    #   Generate the argument list as an array
2682
    #
2683
    for (@BUILD_ACTIVEPLATFORMS)
2684
    {
2685
        my @args = '--Platform';
2686
        push @args, @{$BUILDINFO{$_}{PARTS}};
2687
        push @arglist, join (":" , @args );
2688
    }
2689
 
2690
    return "@arglist";
2691
}
2692
 
2693
#-------------------------------------------------------------------------------
2694
# Function        : GeneratePlatformList
2695
#
2696
# Description     : Return a list of platforms that should particiate in this
2697
#                   build. This is a function of
2698
#                       1) Platforms defined in the build.pl file
5679 dpurdie 2699
#                       2) Platforms excluded in the build.pl file
2700
#                       3) User filter defined in GBE_BUILDFILTER
227 dpurdie 2701
#
2702
#                   The primary use of this function is to limit the creation
2703
#                   of makefiles to those that have supported compilers on
2704
#                   the underlying machine.
2705
#
2706
#                   GBE_BUILDFILTER is a space seperated string of words
2707
#                   Each word may be one of
2708
#                       OPTION=TAG or OPTION=!TAG
2709
#                       TAG or !TAG. This is the same as --TARGET=TAG
2710
#
2711
#                   Bare tags are taken to be TARGETS.
2712
#
2713
#                   Where OPTION may be one of
2714
#                       --PLATFORM
2715
#                       --PRODUCT
2716
#                       --TARGET
5679 dpurdie 2717
#                   For a BuildProduct( AA,BB,CC)
2718
#                       Product     - AA
2719
#                       Targets     - BB, CC
2720
#                       Platforms   - AA_BB, AA_CC
227 dpurdie 2721
#
2722
#                   Special cases
2723
#                   1) If GBE_BUILDFILTER is empty, then all available platforms are used
2724
#                      The global $All is set, then all available platforms are used
2725
#                   2) If the first word of GBE_BUILDFILTER is a negative filter,
2726
#                      ie is used the !xxxx or yyy=!xxxx construct, then it is assumed
2727
#                      that the filter will start with all available platforms
2728
#                   3) The special word --ALL forces selection of ALL platforms
2729
#                      and may reset any existing scanning
2730
#                   4) GBE_BUILDFILTER is parsed left to right. It is possible to add and
2731
#                      subtract items from the list.
2732
#                   5) OPTIONS are case insensitive
2733
#                      TAGS are case sensitive
2734
#
2735
#
2736
# Inputs          : GBE_BUILDFILTER from the environment
2737
#
2738
# Returns         : An array of platforms to include in the build
2739
#                   Maintains @BUILD_ACTIVEPLATFORMS  - the last calculated result
2740
#                   Ensures that @DEFBUILDPLATFORMS is a subset of @BUILD_ACTIVEPLATFORMS
7310 dpurdie 2741
#                   Rebuilds BUILDPLATFORMS to ensure that excluded platforms are not present
227 dpurdie 2742
#
2743
sub GeneratePlatformList
2744
{
2745
    #
2746
    #   Return the cached result for speed
2747
    #   The value need only be calculated once
2748
    #
2931 dpurdie 2749
    unless ( @BUILD_ACTIVEPLATFORMS )
227 dpurdie 2750
    {
2751
        my ($platform_filter);
2752
        my %result;
2753
        my %part_to_platform;
7310 dpurdie 2754
        my @New_BUILDPLATFORMS = ();
227 dpurdie 2755
 
2756
        #
2757
        #   Create a data structure to assist in the production of the platform list
2758
        #   The structure will be a hash of hashes of arrays
2759
        #
2760
        #   The first level hash will be keyed by the word TARGET, PRODUCT or PLATFORM
2761
        #   The second level of the hash will keyed by available targets, products or platforms
2762
        #   The value of the field will be an array of platforms that match the keyword
2763
        #
2764
        for my $platform (keys (%::BUILDINFO))
2765
        {
2766
            my $pParts = $::BUILDINFO{$platform};
2767
 
2768
            #
7310 dpurdie 2769
            #   Include into New_BUILDPLATFORMS 
2770
            #
2771
            if ($pParts->{NOT_AVAILABLE} <= 1) {
2772
                push @New_BUILDPLATFORMS, $platform;
2773
            }
2774
 
2775
            #
227 dpurdie 2776
            #   Skip platforms that are known to be unavailable on this build
2777
            #   machine. Self configure
2778
            #
2779
            next if ( $pParts->{NOT_AVAILABLE} );
2780
 
2781
            my $target  = $pParts->{TARGET};
2782
            my $product = $pParts->{PRODUCT};
2783
 
2784
            push @{$part_to_platform{'PLATFORM'}{$platform}}, $platform;
2785
            push @{$part_to_platform{'TARGET'}  {$target}}  , $platform;
2786
            push @{$part_to_platform{'PRODUCT'} {$product}} , $platform;
2787
        }
2788
        #
2789
        #   Determine the source of the filter
2790
        #   If the user provides one, then use it.
2791
        #   Otherwise its taken from the environment.
2792
        #
2793
        #   Global build all platforms - Kill any user filter
2794
        #
2795
        if ( $All )
2796
        {
2797
            $platform_filter = "";
2798
        }
2799
        else
2800
        {
2801
            $platform_filter = "";
2802
            $platform_filter = $::GBE_BUILDFILTER
2803
                if ( defined($::GBE_BUILDFILTER) );
2804
        }
2805
        Debug( "GeneratePlatformList: Filter:$platform_filter" );
2806
 
2807
        #
2808
        #   Detect the special cases
5679 dpurdie 2809
        #       1) No user definition
227 dpurdie 2810
        #       2) First word contains a subtractive element
5679 dpurdie 2811
        #   And assume all platforms    
227 dpurdie 2812
        #
2813
        my (@filter) = split( ' ', $platform_filter );
2814
 
2815
        if ( !scalar @filter || $filter[0] =~ m/^$/ || $filter[0] =~ m/!/ )
2816
        {
2817
            %result = %{$part_to_platform{'PLATFORM'}}
2818
                if exists $part_to_platform{'PLATFORM'} ;
2819
        }
5679 dpurdie 2820
 
7310 dpurdie 2821
        #
2822
        # Add GENERIC platforms to the platform filter, if available
2823
        #
2824
        if (exists $part_to_platform{'PLATFORM'})
2825
        {
2826
            foreach my $platform( 'GENERIC', 'GENERIC_' . uc($::GBE_MACHTYPE) )
2827
            {
2828
                $result{$platform} = 1 if (exists $part_to_platform{'PLATFORM'}{$platform}) 
2829
            }
2830
        }
2831
 
227 dpurdie 2832
#DebugDumpData( "PartToPlatform", \%part_to_platform );
7310 dpurdie 2833
#DebugDumpData("Result", \%result);
227 dpurdie 2834
 
2835
        #
2836
        #   Process each element in the user filter list
2837
        #   Expand platforms into known aliases
2838
        #
2839
        for my $word (@filter)
2840
        {
2841
            my $platform;
2842
 
2843
            if ( $word =~ m/^--ALL/i )
2844
            {
2845
                %result = %{$part_to_platform{'PLATFORM'}};
2846
            }
2847
            elsif ( $word =~ m/^--(TARGET)=(!?)(.*)/i ||
2848
                    $word =~ m/^--(PRODUCT)=(!?)(.*)/i ||
2849
                    $word =~ m/^--(PLATFORM)=(!?)(.*)/i ||
2850
                    ( $word !~ m/^-/ && $word =~ m/()(!?)(.*)/ )
2851
                )
2852
            {
2853
                my $table = uc($1);
2854
                $table = "TARGET"
2855
                    unless ( $1 );
2856
 
2857
                #
2858
                #   Expand PLATFORMs into known aliases
2859
                #   Alias will expand to PLATFORMs so it won't work unless we are
6133 dpurdie 2860
                #   processing PLATFORMs.
227 dpurdie 2861
                #
2862
                my @taglist = ( $table eq "PLATFORM" ) ? ExpandPlatforms($3) : $3;
2863
 
2864
                #
2865
                #   Add / Remove items from the result
2866
                #
2867
                for my $item ( @taglist )
2868
                {
2869
                    my $plist = $part_to_platform{$table}{$item};
2870
                    for ( @{$plist})
2871
                    {
6133 dpurdie 2872
                        if ( $2 ) {
227 dpurdie 2873
                            delete $result{$_};
6133 dpurdie 2874
                        } else {
227 dpurdie 2875
                            $result{$_} = 1;
2876
                        }
2877
                    }
2878
                }
2879
            }
2880
            else
2881
            {
2882
                print "GBE_BUILDFILTER filter term not understood: $word\n";
2883
            }
2884
        }
2885
 
2886
        #
2887
        #   Return an array of platforms to process
2888
        #
2889
        @BUILD_ACTIVEPLATFORMS = sort keys %result;
2890
 
2891
        #
2892
        #   Ensure that DEFBUILDPLATFORMS is a subset of build active platforms
2893
        #
2894
        my @NEW_DEFBUILDPLATFORMS;
2895
        foreach ( @DEFBUILDPLATFORMS )
2896
        {
2897
            push @NEW_DEFBUILDPLATFORMS, $_
2898
                if ( exists $result{$_} );
2899
        }
2900
        @DEFBUILDPLATFORMS = @NEW_DEFBUILDPLATFORMS;
7310 dpurdie 2901
 
2902
        #
2903
        #   Update BUILDPLATFORMS
2904
        #
2905
        @BUILDPLATFORMS = @New_BUILDPLATFORMS;
227 dpurdie 2906
    }
2907
 
2908
    Debug("GeneratePlatformList: Result:@BUILD_ACTIVEPLATFORMS");
2909
    return @BUILD_ACTIVEPLATFORMS;
2910
}
2911
 
2912
#-------------------------------------------------------------------------------
2913
# Function        : PrintPlatforms
2914
#
2915
# Description     : Petty print the specified platform list, breaking line
7310 dpurdie 2916
#                   on either a primary key change or length width >100.
227 dpurdie 2917
#
7310 dpurdie 2918
# Inputs          : $list           - Reference to an array
2919
#                   $nl             - New line stuff.
2920
#                                     Use to prefix new lines
227 dpurdie 2921
#
7310 dpurdie 2922
# Returns         : Formatted string
2923
#
227 dpurdie 2924
# Example Output :
2925
#
2926
#           DDU_LMOS_WIN32 DDU_LMOS_linux_armv4 DDU_LMOS_linux_i386
2927
#           IDFC_LMOS_WIN32 IDFC_LMOS_linux_armv4 IDFC_LMOS_linux_i386
2928
#           LMOS_WCEPSPC_ARM LMOS_WCEPSPC_EMU LMOS_WIN32 LMOS_linux_armv4
2929
#           LMOS_linux_i386
2930
#..
2931
sub PrintPlatforms
2932
{
2933
    my ($platforms, $nl) = @_;
7310 dpurdie 2934
    my ($string) = "";
2935
    my $maxLen = 100 - length($nl);
227 dpurdie 2936
 
2931 dpurdie 2937
    if ( @$platforms )
227 dpurdie 2938
    {
7310 dpurdie 2939
        my $line = "";
2940
        my $pel = "";
2941
        my $first = 1;
2942
        my $prefix = '';
2943
        foreach my $k ( sort @$platforms)
227 dpurdie 2944
        {
7310 dpurdie 2945
            my $k2 = substr($k, 0 , 2);
2946
            if (( $k2 ne $pel  || (length($line) + length ($k) > $maxLen) ) && (!$first)) {
2947
                $string .= $line;
2948
                $line = $nl;
2949
                $prefix = '';
227 dpurdie 2950
            }
7310 dpurdie 2951
            $line .= $prefix . $k;
2952
            $pel = $k2;
2953
            $first = 0;
2954
            $prefix = ' ';
227 dpurdie 2955
        }
7310 dpurdie 2956
        $string .= $line;
227 dpurdie 2957
    }
2958
    return $string;
2959
}
241 dpurdie 2960
#-------------------------------------------------------------------------------
2961
# Function        : PrintList
2962
#
2963
# Description     : Pretty format an array to fit within 80 char line
2964
#                   Perform wrapping as required
2965
#
2966
# Inputs          : $list           - Reference to an array
2967
#                   $nl             - New line stuff.
2968
#                                     Use to prefix new lines
2969
#
2970
# Returns         : string
2971
#
2972
sub PrintList
2973
{
7310 dpurdie 2974
    my ($platforms, $nl) = @_;
2975
    my ($string) = "";
2976
    my $maxLen = 100 - length($nl);
227 dpurdie 2977
 
7310 dpurdie 2978
    if ( @$platforms )
241 dpurdie 2979
    {
7310 dpurdie 2980
        my $line = "";
2981
        my $first = 1;
2982
        my $prefix = '';
2983
        foreach my $k ( sort @$platforms)
241 dpurdie 2984
        {
7310 dpurdie 2985
            if ((length($line) + length ($k) > $maxLen) && (!$first)) {
2986
                $string .= $line;
2987
                $line = $nl;
2988
                $prefix = '';
241 dpurdie 2989
            }
7310 dpurdie 2990
            $line .= $prefix . $k;
2991
            $first = 0;
2992
            $prefix = ' ';
241 dpurdie 2993
        }
7310 dpurdie 2994
        $string .= $line;
241 dpurdie 2995
    }
2996
    return $string;
2997
}
2998
 
305 dpurdie 2999
#-------------------------------------------------------------------------------
3000
# Function        : BuildReleaseFile
3001
#
3002
# Description     : Legacy function
3003
#                   Don't know what it was meant to do
3004
#                   Unfortunately it is present in a lot of build.pl files
3005
#
3006
#                   Not well supported on all machine types
3007
#
331 dpurdie 3008
# Inputs          : None that are used
305 dpurdie 3009
#
331 dpurdie 3010
# Returns         : Undefined
305 dpurdie 3011
#
227 dpurdie 3012
sub BuildReleaseFile
3013
{
3014
}
3015
 
305 dpurdie 3016
#-------------------------------------------------------------------------------
3017
# Function        : BuildSnapshot
3018
#
3019
# Description     : Legacy function
3020
#                   Don't know what it was meant to do
3021
#                   Unfortunately it is present in a lot of build.pl files
3022
#
3023
# Inputs          : None that are used
3024
#
3025
# Returns         : Undefined
3026
#
227 dpurdie 3027
sub BuildSnapshot
3028
{
3029
}
3030
 
305 dpurdie 3031
#-------------------------------------------------------------------------------
3032
# Function        : BuildSrcArchive
3033
#
3034
# Description     : Create a source snapshot of the build source
3035
#                   Designed to provide a source image for packaging
3036
#                   examples
3037
#
3038
#                   Should be platform independent
3039
#
3040
#                   Creates an archive file and places it into the
3041
#                   interface directory. The archive will be packaged
3042
#                   automatically by the build process
3043
#
3044
#                   Use the 'pax' utility
3045
#                       1) Can massage the file path such that the stored
3046
#                          directory image contains the package name and version
3047
#
3048
#                   Directive can be used at any time before the BuildMake
3049
#
3050
#                   Will handle the existence of an auto.pl file by inserting
3051
#                   it as build.pl.
3052
#
6133 dpurdie 3053
# Inputs          : $platform   - In ABT mode. Process under this platform name
305 dpurdie 3054
#
3055
#
3056
# Returns         : 
3057
#
3058
sub BuildSrcArchive
3059
{
6133 dpurdie 3060
    my ($platform) = @_;
3061
    Error ("BuildSrcArchive requires one platform specifier") unless (defined $platform);
3062
 
3063
 
305 dpurdie 3064
    #
3065
    #   If we are clobbering, then there is nothing to do
3066
    #   The generated file is placed within the interface
3067
    #   directory and that directory will be deleted during the clobber
3068
    #
3069
    return if ( $Clobber );
3070
    DataDirective("BuildSrcArchive");
227 dpurdie 3071
 
305 dpurdie 3072
    #
6133 dpurdie 3073
    #   If not in ABT mode, then build archive on developers machine
3074
    #   In ABT mode only build the archive on a machine whose platform name is in the build filter
3075
    #
3076
    my $doBuild;
3077
    if (defined($::GBE_ABT))
3078
    {
3079
        if (defined ($::GBE_BUILDFILTER))
3080
        {
3081
            $doBuild  = grep( /^$platform/, split( ' ', $::GBE_BUILDFILTER ) );
3082
        }
3083
        unless ( $doBuild )
3084
        {
3085
            Log( "SrcPackage . Not on this machine" );
3086
            return; 
3087
        }
3088
    }
3089
 
3090
 
3091
    #
305 dpurdie 3092
    #   Currently this operation is only supported of some platforms
3093
    #   Only supported on Unix platforms
3094
    #   Uses the 'pax' utility
3095
    #
3096
    unless ( LocateProgInPath ( 'pax', '--All' ) && ( $ScmHost eq "Unix" ) )
3097
    {
3098
        Log( "SrcPackage . Not supported" );
3099
        return;
3100
    }
3101
 
3102
    #
3103
    #   Only allow one instance of the directive
3104
    #
3105
    Error ("Multiple BuildSrcArchive directives not supported")
3106
        if ( $build_source_pkg );
3107
 
3108
    #
3109
    #   Create the name of the archive
3110
    #       Based on the package name and version
3111
    #       Has no spaces
3112
    #
3113
    my $build_name = $BUILDNAME;
3114
    $build_name =~ s~\s+~_~g;
3115
 
3116
    #
3117
    #   Create the archive in the interface directory
3118
    #   Don't need to clobber it as the entire interface directory
3119
    #   will be clobbered
3120
    #
3121
    $build_source_pkg = $build_name;
3122
}
3123
 
3124
#-------------------------------------------------------------------------------
3125
# Function        : BuildSrcArchiveBody
227 dpurdie 3126
#
305 dpurdie 3127
# Description     : Function to implement the body of the BuildSrcArchive
3128
#                   operation. Will be invoked during BuildMake
3129
#
3130
# Inputs          : None
3131
#
3132
# Returns         : 
3133
#
3134
sub BuildSrcArchiveBody
3135
{
3136
    return unless ( $build_source_pkg );
3137
 
3138
    my $archive_dir = "pkg/$BUILDNAME_PACKAGE/src";
3139
    my $archive_file = "$build_source_pkg" . '.tar';
3140
 
3141
    Log( "SrcPackage . $archive_file.gz" );
3142
    unlink "$archive_dir/$archive_file";
3143
    unlink "$archive_dir/$archive_file.gz";
3144
    mkpath($archive_dir, 0, 0775);
3145
 
3146
    #
3147
    #   Create a list of files and top-level dirs to add to source archive
3148
    #   Many files are ignored
3149
    #   Should only be executed on the first 'build' thus many internal
3150
    #   directories will not be present
3151
    #
3152
    my @flist;
3153
    my $auto_pl;
3154
    opendir (my $tp, '.' ) or Error ("Cannot read current directory");
3155
    while ( $_ = readdir($tp) )
3156
    {
3157
        next if ( m/^\.$/ );
3158
        next if ( m'^\.\.$' );
3159
        next if ( m'^build\.log$' );
3160
        next if ( m'\.gbe$' );
6133 dpurdie 3161
        next if ( m'\.svn$' );
3162
        next if ( m'\.git$' );
3163
        next if ( m'\.cvs$' );
3164
        next if ( m'local_dpkg_archive$' );
3165
        next if ( m'\.jats.packageroot$' );
305 dpurdie 3166
        next if ( m'^local$' );
3167
        next if ( m'^pkg$' );
3168
        next if ( m/^$BUILDINTERFACE$/ );
3169
        $auto_pl = 1, next  if ( m'^auto\.pl$' );
3170
        next if (  m'^build\.pl$' );
3171
        next if ( m/^$build_source_pkg$/ );
3172
        push @flist, $_;
3173
    }
3174
    closedir $tp;
3175
 
3176
    #
3177
    #   If we don't have an auto.pl, then we add the build.pl file
3178
    #   If we do have a auto.pl - it gets tricky. Its don't after the
3179
    #   initial pax command
3180
    #
3181
    unless ( $auto_pl )
3182
    {
3183
        push @flist, 'build.pl';
3184
    }
3185
 
3186
    #
3187
    #   Create the command to be executed
3188
    #   Prefix archive paths with build_name
3189
    #
3190
    my @command = ( 'pax', '-w', '-f', "$archive_dir/$archive_file" );
3191
    System( '--NoShell' , @command, '-s', "~^~$build_source_pkg/~", @flist );
3192
 
3193
    #
3194
    #   If we have an auto.pl file, then we need to add it to the archive
3195
    #   but it needs to be called build.pl
3196
    #
3197
    if ( $auto_pl )
3198
    {
3199
        System( '--NoShell' , @command, '-a', '-s', "~^auto.pl~$build_source_pkg/build.pl~" , 'auto.pl' );
3200
    }
3201
 
3202
    #
3203
    #   Must now zip the file
3204
    #   Can't zip and append at the same time
3205
    #
3206
    System( '--NoShell' , 'gzip', "$archive_dir/$archive_file" );
3207
 
3208
    #
3209
    #   Display the results
3210
    #
3211
    System ('--NoShell', 'pax', '-z', "-f$archive_dir/$archive_file.gz")
3212
        if (IsVerbose (1));
3213
}
3214
 
3215
#-------------------------------------------------------------------------------
3216
# Function        : BuildAccessPerms
3217
#
3218
# Description     : Check if access/permissions setting requested...
3219
#                   Legacy
3220
#
331 dpurdie 3221
#                   Don't know what it was meant to do
3222
#                   Unfortunately it is present in a lot of build.pl files
305 dpurdie 3223
#
331 dpurdie 3224
# Inputs          : None that are used
305 dpurdie 3225
#
331 dpurdie 3226
# Returns         : Undefined
3227
#
227 dpurdie 3228
sub BuildAccessPerms
3229
{
3230
}
3231
 
3232
 
3233
sub BuildSetenv
3234
{
3235
    push( @BUILDSETENV, @_ );
3236
}
3237
 
3238
#-------------------------------------------------------------------------------
3239
# Function        : DataDirective
3240
#
3241
# Description     : Called by data collection directives to ensure that we are
3242
#                   still collecting data and that we have collected other data
3243
#
3244
# Inputs          : $dname              - Directive Name
3245
#
3246
# Returns         : Will error if we are not
3247
#
3248
sub DataDirective
3249
{
3250
    my ($dname) = @_;
3251
 
3252
    Error( "$dname() must appear after BuildName()...")
3253
        if ( $BUILDNAME eq "" );
3254
 
3255
    Error( "$dname() must appear after BuildInterface()...")
3256
        unless( $BUILDINTERFACE );
3257
 
3258
    Error( "$dname() not allowed after BuildDescpkg, BuildIncpkg, BuildVersion or BuildMake")
3259
        if( $BUILDPHASE);
3260
}
3261
 
3262
#-------------------------------------------------------------------------------
3263
# Function        : StartBuildPhase
3264
#
3265
# Description     : Called by directives that deal with the building phases
3266
#                   to perform common initialisation and to ensure that
3267
#                   directives that collect data are no longer called
3268
#
305 dpurdie 3269
# Inputs          : last                - True: Last directive expected
227 dpurdie 3270
#
3271
# Returns         : May generate an error
3272
#
3273
sub StartBuildPhase
3274
{
305 dpurdie 3275
    my ($last) = @_;
3276
 
227 dpurdie 3277
    #
305 dpurdie 3278
    #   Ensure directive is allowed
3279
    #       $BUILDPHASE >  1     - No more directives allowed
3280
    #       $BUILDPHASE == 1     - Allowed directive
3281
    #
3282
    if ( $BUILDPHASE > 1 )
3283
    {
3284
        my $function = (caller(1))[3];
3285
        $function =~ s~.*::~~;
3286
        Error ("Directive not allowed: $function","'BuildMake' must be the last directive in the build file");
3287
    }
3288
 
3289
    #
227 dpurdie 3290
    #   Only do it once
3291
    #
305 dpurdie 3292
    return if ( $BUILDPHASE  );
3293
    $BUILDPHASE = 1;
227 dpurdie 3294
 
3295
    #
341 dpurdie 3296
    #   If we are not performing a ForceBuild, then we don't need to continue
3297
    #   We have updated the interface directory with BuildPkgArchive
3298
    #   information.
3299
    #
3300
    TestForForcedBuild();
3301
 
3302
    #
6133 dpurdie 3303
    #   Calculate the aliases that are being extracted from targets
227 dpurdie 3304
    #
3305
    Process_TargetAlias();
3306
 
3307
    #
7307 dpurdie 3308
    #   Calculate defined aliases
6133 dpurdie 3309
    #       Limit the Aliases to active platforms
7307 dpurdie 3310
    #       ie: NATIVE INSTRUMENT PKG_WIN PKG_RPM PKG_DEB SK
4728 dpurdie 3311
    #
7310 dpurdie 3312
    my %activePlatformMap;
3313
    foreach my $item ( keys %BUILDINFO) {
3314
           my $pInfo = $BUILDINFO{$item};
3315
           next if $pInfo->{NOT_AVAILABLE} > 1; 
3316
           push @{$activePlatformMap{$pInfo->{TARGET}}}, $item;
3317
    }
3318
 
7307 dpurdie 3319
    foreach my $alias ( @PlatformConfig::BuildAliases )
4728 dpurdie 3320
    {
7310 dpurdie 3321
        if (exists $BUILDALIAS{$alias})  
4728 dpurdie 3322
        {
7307 dpurdie 3323
            # Will occur if GBE_ABT has been set, for backward compatibility
6133 dpurdie 3324
            Warning("User has manually specified a $alias alias",'Default alias will not be set.');
7310 dpurdie 3325
            #DebugDumpData("BUILDALIAS", \%BUILDALIAS);
4728 dpurdie 3326
        }
6133 dpurdie 3327
        else
3328
        {
3329
            my @activeAliases;
7309 dpurdie 3330
            foreach my $item (PlatformConfig::getTargetsByTag($alias)) {
7310 dpurdie 3331
                if (exists($activePlatformMap{$item})) {
3332
                    push (@activeAliases, @{$activePlatformMap{$item}});
3333
                }
6133 dpurdie 3334
            }
7310 dpurdie 3335
 
6133 dpurdie 3336
            $BUILDALIAS{$alias} = join(' ', @activeAliases) if (@activeAliases);
3337
 
3338
            #
3339
            #   Add to the build entry too
3340
            #
7310 dpurdie 3341
            foreach my $aliasTarget (@activeAliases) {
6133 dpurdie 3342
                push @{$BUILDINFO{$aliasTarget}{USERALIAS}}, $alias;
3343
            }
3344
        }
4728 dpurdie 3345
    }
6133 dpurdie 3346
    CleanUp_Aliases();
4728 dpurdie 3347
 
3348
    #
311 dpurdie 3349
    #   Create dummy package to describe the Interface directory
3350
    #
3351
    CreateInterfacePackage();
3352
 
3353
    #
227 dpurdie 3354
    #   Sanity test the users packages
6133 dpurdie 3355
    #       In a sandbox all bet are off
227 dpurdie 3356
    #
6133 dpurdie 3357
    PackageEntry::SanityTest() unless ($Clobber || $::GBE_SANDBOX);
227 dpurdie 3358
 
3359
    #
3360
    #   Validate the $Srcdir before its first real use
3361
    #   This is calculated from the user directives
3362
    #
3363
 
3364
    #.. Determine default "source" root
3365
    #
3366
    if ( $Srcdir eq "" )
3367
    {
3368
        Warning( "Both the directories 'src' and 'SRC' exist ....." )
3369
            if ( $ScmHost eq "Unix" && -e "src" && -e "SRC" );
3370
 
3371
        if ( -e "src" ) {
3372
            $Srcdir = "src";
3373
        } else {
3374
            ( -e "SRC" ) ||
3375
                Error( "Neither the directory 'src' nor 'SRC' exist ....." );
3376
            $Srcdir = "SRC";
3377
        }
3378
    }
3379
 
3380
    #
3381
    #   Must have a valid Srcdir
3382
    #
3383
    Error ("Source directory not found: $Srcdir")
3384
        unless ( $Srcdir && -d $Srcdir );
3385
 
305 dpurdie 3386
    #
3387
    #   Create source package
3388
    #
3389
    BuildSrcArchiveBody();
3390
 
227 dpurdie 3391
    return $Srcdir;
3392
}
3393
 
3394
#-------------------------------------------------------------------------------
341 dpurdie 3395
# Function        : TestForForcedBuild
3396
#
3397
# Description     : If a non-forced build has been requested, then see
3398
#                   if a build is required ( ie: build.pl modified )
6133 dpurdie 3399
#                   
3400
#                   Check:
3401
#                       Time stamp of build.pl
3402
#                       Time stamp of Makefile.gbe
3403
#                       BuildFilter has not changed
3404
#                       Signature of dependencies has not changed
3405
#                       No packages consumed from within the sandbox
341 dpurdie 3406
#
3407
# Inputs          : None
3408
#
3409
# Returns         : May not return
6133 dpurdie 3410
#                   Will return if we need to perform a build
341 dpurdie 3411
#
3412
sub TestForForcedBuild
3413
{
3414
    #
3415
    #   Always return if in clobber mode
3416
    #
3417
    return if ( $Clobber );
3418
 
3419
    if ( ! $ForceBuild  )
3420
    {
3421
        my @build_warn;
3422
        my $bstamp = -M "$Cwd/$ScmBuildSrc";
3423
        my $tstamp = -M "$Cwd/Makefile.gbe";
3424
 
3425
        push @build_warn, "Missing: Makefile.gbe" unless ( defined $tstamp );
3426
        push @build_warn, "Modified build file ($ScmBuildSrc)" if ( $tstamp && $bstamp < $tstamp );
3427
 
363 dpurdie 3428
        #
3429
        #   Ensure that the build filter has not changed
3430
        #   If the user has changed the buildfilter, then we need to
3431
        #   force a build.
3432
        #
6133 dpurdie 3433
        #   The root Makefile.gbe will have a $ScmBuildFilter entry
363 dpurdie 3434
        #
3435
        unless ( @build_warn )
3436
        {
3437
            use JatsMakeInfo;
3438
            ReadMakeInfo();
5726 dpurdie 3439
            my $line = $::ScmBuildFilter || '';
3440
            $line =~ s~\s+~ ~g;
363 dpurdie 3441
 
5726 dpurdie 3442
            my $filter = $::GBE_BUILDFILTER || '';
3443
            $filter =~ s~\s+~ ~g;
3444
            if ( $line ne $filter )
3445
            {
3446
                push @build_warn, "Build filter has changed";
3447
                Verbose2 ("Buildfilter Test: Was:$line, Is:$::GBE_BUILDFILTER");
3448
            }
363 dpurdie 3449
        }
3450
 
6133 dpurdie 3451
        #
7301 dpurdie 3452
        #   See if the dependencies have changed
3453
        #   
7310 dpurdie 3454
        my $BuildpkgSig = Digest::SHA::PurePerl->new;
7301 dpurdie 3455
        $BuildpkgSig->add("PKGNAME: $BUILDNAME_PACKAGE $BUILDNAME_VERSION $BUILDNAME_SUFFIX");
3456
 
3457
        #
3458
        #   Include the signature of ALL dependent packages
3459
        #   Ie: The build fingerprint is a function of the source and its dependents
3460
        #
3461
        my $depTagFile = catfile($ScmInterface, 'build.bfp');
3462
        unless (-f $depTagFile) {
3463
            push @build_warn, "Missing: $depTagFile";
3464
        }
3465
        else
3466
        {
3467
            foreach my $tag ( PackageEntry::GetPackageList() )
3468
            {
3469
                my $pkgSig = PackageEntry::GetPackageSignature($tag);
3470
                $BuildpkgSig->add("PKGSIGNATURE: $pkgSig");
3471
            }
3472
            my $depSha1 =  $BuildpkgSig->hexdigest;
3473
            Debug2("DepSha1: $depSha1");
3474
            unless (TagFileMatch ($depTagFile, $depSha1))
3475
            {
3476
                push @build_warn, "Dependency signatures have changed";
3477
            }
3478
        }
3479
 
3480
        #
6133 dpurdie 3481
        #   If any of the imported packages are from a sandbox, then we must force a build
3482
        #   and a make.
3483
        #
3484
        if ($pkgFromSandbox)
3485
        {
3486
            push @build_warn, "Consuming packages from within the sandbox";
3487
        }
3488
 
341 dpurdie 3489
        if ( @build_warn )
3490
        {
363 dpurdie 3491
            Verbose ("Forcing Build.", @build_warn );
341 dpurdie 3492
        }
3493
        else
3494
        {
3495
            Verbose ("No build performed. Build files up to date");
3496
            Log ("Build files up to date") if $::GBE_SANDBOX;
3497
            exit 0;
3498
        }
3499
    }
3500
}
3501
 
3502
#-------------------------------------------------------------------------------
305 dpurdie 3503
# Function        : LastBuildDirective
3504
#
3505
# Description     : No more build directives allowed
3506
#
3507
# Inputs          : 
3508
#
3509
# Returns         : 
3510
#
3511
sub LastBuildDirective
3512
{
3513
    $BUILDPHASE = 2;
3514
}
3515
 
3516
#-------------------------------------------------------------------------------
227 dpurdie 3517
# Function        : BuildPackageLink
3518
#
3519
# Description     : Create a soft link from sandbox_dpkg_archive to the package
3520
#                   being created by this build
3521
#
3522
#                   For backward compatability.
3523
#                   If GBE_DPKG_SBOX is not defined, then use GBE_DPKG_LOCAL
3524
#
3525
#                   This will allow multiple components to work together
3526
#
3527
#                   Note: When called in Clobber-mode the link will be deleted
3528
#
3529
# Inputs          : $BUILDNAME              - The package name
3530
#                   $BUILDNAME_PROJECT      - Project extension
3531
#                   $::GBE_DPKG_SBOX        - Path of sandbox_dpkg_archive
3532
#                   $::GBE_DPKG_LOCAL       - Path of local_dpkg_archive
3533
#                   $::GBE_DPKG             - Main repository
3534
#
3535
# Returns         : Nothing
3536
#
3537
sub BuildPackageLink
3538
{
3539
    my $target_archive;
3540
    my $target_archive_name;
3541
    my $link_file;
3542
    my $tag;
371 dpurdie 3543
    my $root_path;
227 dpurdie 3544
 
3545
    #
3546
    #   Determine the path (and name) of the target archive
3547
    #   Use sandbox_dpkg_archive if it exists
3548
    #   Use local_dpkg_acrhive for backward compatability (should be removed after JATS 2.64.2+)
3549
    #
3550
    if ( $target_archive = $::GBE_DPKG_SBOX )
3551
    {
3552
        $target_archive_name = "sandbox_dpkg_archive";
3553
        $tag = "Sandbox";
7301 dpurdie 3554
        $link_file  = 'sandbox' . ${BUILDNAME_SUFFIX} . '.lnk';
371 dpurdie 3555
        $root_path = 'GBE_SANDBOX' . substr($Cwd, length($::GBE_SANDBOX));
3556
        Verbose2("Root Path: $::GBE_SANDBOX, $root_path");
227 dpurdie 3557
    }
3558
    elsif ( $target_archive = $::GBE_DPKG_LOCAL )
3559
    {
3560
        $target_archive_name = "local_dpkg_archive";
3561
        $link_file = "$BUILDVERSION.lnk";
3562
        $tag = "Local";
371 dpurdie 3563
        $root_path = $Cwd;
227 dpurdie 3564
    }
3565
    else
3566
    {
3567
        Verbose("Cannot locate local or sandbox archive")
3568
            unless $Clobber;
3569
        return;
3570
    }
3571
 
3572
    #
3573
    #   Santity test
3574
    #   Target must be a directory
3575
    #
3576
    unless ( -d $target_archive )
3577
    {
241 dpurdie 3578
        Warning("$target_archive_name is not a directory: $target_archive")
227 dpurdie 3579
            unless $Clobber;
3580
        return;
3581
    }
3582
 
3583
    my $link_dir = "$target_archive/$BUILDNAME_PACKAGE";
3584
    my $link_path = "$link_dir/$link_file";
3585
 
6133 dpurdie 3586
    if ( $Clobber || $NoBuild )
227 dpurdie 3587
    {
3588
        unlink $link_path;          # Delete the link
3589
        rmdir $link_dir;            # Delete only if empty
3590
    }
3591
    else
3592
    {
261 dpurdie 3593
        Log( "Local Link . $BUILDNAME_PACKAGE/$link_file ($tag)");
3594
        mkdir $link_dir unless -d $link_dir;
371 dpurdie 3595
        FileCreate ( $link_path, "$root_path/pkg/$BUILDNAME_PACKAGE");
227 dpurdie 3596
    }
3597
}
3598
 
3599
#-------------------------------------------------------------------------------
3600
# Function        : BuildSandboxData
3601
#
3602
# Description     : Create data structures to allow this package to be built
3603
#                   within a multi-package sandbox.
3604
#
3605
#                   This will allow multiple components to work together
6133 dpurdie 3606
#                   Creates:
3607
#                       sandbox.int     - Rel path to the packages interface
3608
#                       sandbox.ffp     - Fast FingerPrint over the package body
3609
#                       sandbox.nob     - No Build marker
227 dpurdie 3610
#
3611
#                   Note: When called in Clobber-mode the link will be deleted
3612
#
3613
# Inputs          : $BUILDNAME              - The package name
3614
#                   $BUILDNAME_PROJECT      - Project extension
3615
#                   $::GBE_DPKG_SBOX        - Path of sandbox_dpkg_archive
3616
#                   $::GBE_DPKG             - Main repository
3617
#
3618
# Returns         : Nothing
3619
#
3620
sub BuildSandboxData
3621
{
3622
    my $sandbox_dpkg_archive = $::GBE_DPKG_SBOX;
3623
    return unless ( $sandbox_dpkg_archive );
3624
 
3625
    unless ( -d $sandbox_dpkg_archive )
3626
    {
241 dpurdie 3627
        Error("sandbox_dpkg_archive is not a directory: $sandbox_dpkg_archive")
227 dpurdie 3628
            unless $Clobber;
3629
        return;
3630
    }
3631
 
3632
    #
3633
    #   Create a name for this package in the sandbox
3634
    #   Must use the package name and extension. Don't use the version
3635
    #   information as this will not be correct
3636
    #
3637
    #   PACKAGE/sandbox.PRJ.cfg
3638
    #
3639
    my $link_dir = "$sandbox_dpkg_archive/$BUILDNAME_PACKAGE";
6133 dpurdie 3640
    my $base = 'sandbox' . ${BUILDNAME_SUFFIX}; 
359 dpurdie 3641
 
6133 dpurdie 3642
    my $nob_path  = $base . ".nob";
3643
    my $ffp_path  = $base . ".ffp";
3644
    my $int_path  = $base . ".int";
227 dpurdie 3645
 
6133 dpurdie 3646
    $nob_path = "$link_dir/$nob_path";
3647
    $ffp_path = "$link_dir/$ffp_path";
3648
    $int_path = "$link_dir/$int_path";
3649
 
227 dpurdie 3650
    if ( $Clobber )
3651
    {
3652
        rmdir $link_dir;            # Delete only if empty
3653
    }
3654
    else
3655
    {
6133 dpurdie 3656
        ToolsetFiles::AddFile($nob_path);
3657
        ToolsetFiles::AddFile($ffp_path);
3658
        ToolsetFiles::AddFile($int_path);
3659
 
3660
        #Log( "Sandbox Data. $base");
3661
        unlink $int_path;
227 dpurdie 3662
        mkdir $link_dir;
3663
 
3664
        #
6133 dpurdie 3665
        #   File with path to the interface directory
3666
        #   Relative to the base of the sandbox
227 dpurdie 3667
        #
6133 dpurdie 3668
        FileCreate($int_path, catdir('GBE_SANDBOX',RelPath($Cwd,$::GBE_SANDBOX),$BUILDINTERFACE ));
227 dpurdie 3669
 
3670
        #
6133 dpurdie 3671
        #   Indicate packages not build on this machine
227 dpurdie 3672
        #
6133 dpurdie 3673
        unlink $nob_path;           # Delete the NoBuild marker
3674
        if ($NoBuild) {
3675
            TouchFile($nob_path);
3676
        }
227 dpurdie 3677
    }
3678
}
3679
 
3680
 
3681
#-------------------------------------------------------------------------------
3682
# Function        : BuildMake
3683
#
3684
# Description     : Generate the makefiles
3685
#                   This directive MUST be the last directive in the build.pl
3686
#                   file. The directive triggers the processing of all the
3687
#                   information that has been collected
3688
#
3689
#
3690
# Inputs          : None
3691
#
3692
# Returns         : Nothing
3693
#
3694
 
3695
sub BuildMake
3696
{
3697
    my( $argc, $platform );
3698
 
3699
    #
3700
    #   Must have a valid $BUILDINTERFACE
3701
    #   Normally this is held in the interface directory, but this is not
3702
    #   always created. If there is no $BUILDINTERFACE, then use the
3703
    #   build directory
3704
    #
6133 dpurdie 3705
    BuildInterfaceInternal($::ScmInterface) unless ( $BUILDINTERFACE );
227 dpurdie 3706
 
6133 dpurdie 3707
 
227 dpurdie 3708
    #.. Starting the build phase. No more data collection
3709
    #
305 dpurdie 3710
    StartBuildPhase();
3711
    LastBuildDirective();
227 dpurdie 3712
 
5109 dpurdie 3713
    #
3714
    #   Now that the bulk of the information has been displayed
3715
    #   we can display captured messages. These warnings will be 
3716
    #   at the end of the log so that users can see them.
3717
    DumpCapture();
3718
 
227 dpurdie 3719
    sub DeleteCfg
3720
    {
3721
        #
3722
        #   Delete files that will be re-created
3723
        #   Some of these files are read and written.
3724
        #   Errors in the files are solved by deleting the files now.
3725
        #
3726
        unlink "$BUILDINTERFACE/build.cfg";
3727
        unlink "$BUILDINTERFACE/Makefile.cfg";
3728
        unlink glob ("$BUILDINTERFACE/Makefile*.cfg");
3729
        unlink "$BUILDINTERFACE/Buildfile.cfg";
3730
        unlink "$BUILDINTERFACE/Dpackage.cfg";
3731
    }
3732
 
3733
    if ( $Clobber )                             # clobber mode ?
3734
    {
4003 dpurdie 3735
        #
3736
        #   Unmake all the makefiles
3737
        #   No longer needed as we track the file that are created
3738
        #
3739
        #if ( -e "Makefile.gbe" )
3740
        #{
3741
        #    JatsTool ( 'jmake.pl', 'unmakefiles');
3742
        #}
3743
 
3744
        #
3745
        #   Delete my own configuration files
3746
        #
227 dpurdie 3747
        DeleteCfg();
3748
 
3749
        #
3750
        #   JATS creates a 'pkg' directory for the target package
3751
        #
3752
        push @CLOBBERDIRS, "pkg";
3753
 
3754
        #
3755
        #   Deployment creates a 'build/deploy' directory
375 dpurdie 3756
        #   The 'build' directory may contain user files - only remove if empty
227 dpurdie 3757
        #
3758
        push @CLOBBERDIRS, "build/deploy";
375 dpurdie 3759
        push @REMOVEDIRS, "build";
227 dpurdie 3760
 
3761
        #
6133 dpurdie 3762
        #   List of files maintained by the build system
3763
        #
3764
        my @toolsetFiles = ToolsetFiles::GetFiles();
3765
 
3766
        #
227 dpurdie 3767
        #   Delete interface directories and other directories that have been
375 dpurdie 3768
        #   marked to be clobbered
227 dpurdie 3769
        #
3770
        foreach my $dir ( @CLOBBERDIRS )
3771
        {
3772
            next if ( $dir eq '.' );
3773
            next if ( $dir eq '..' );
3774
            if ( -d $dir )
3775
            {
361 dpurdie 3776
                RmDirTree ( $dir );
227 dpurdie 3777
            }
3778
        }
3779
 
375 dpurdie 3780
        foreach my $dir ( @REMOVEDIRS )
3781
        {
3782
            next if ( $dir eq '.' );
3783
            next if ( $dir eq '..' );
3784
            if ( -d $dir )
3785
            {
3786
                rmdir ( $dir ); # Only if empty
3787
            }
3788
        }
3789
 
6133 dpurdie 3790
        foreach my $file (@toolsetFiles)
227 dpurdie 3791
        {
6133 dpurdie 3792
            RmDirTree ( $file ) if ( -f $file );
227 dpurdie 3793
        }
3794
 
3795
        #
3796
        #   DPACKAGE may be a user file, Only delete it if we created it
3797
        #
299 dpurdie 3798
        unlink "$Srcdir/DPACKAGE.$::GBE_MACHTYPE" if $DeleteDPACKAGE;
227 dpurdie 3799
 
3800
        BuildPackageLink();
3801
        BuildSandboxData();
3802
        return;
3803
    }
3804
 
3805
    #.. Build support files
3806
    #
3807
    DeleteCfg();
3808
    BuildConfig();
3809
    BuildSharedLibFiles();
3810
    WriteParsedBuildConfig();
3811
    BuildPackageLink();
3812
    BuildSandboxData();
4003 dpurdie 3813
    NoBuildMarker();
227 dpurdie 3814
 
3815
    #
3816
    #  ONLY (re)building interface dir
3817
    #
3818
    return
3819
        if ( $Interface );
3820
 
3821
    #---------------------------------------------------------------------------
3822
    #
3823
    #.. Make bootstrap "makefile",
3824
    #   Simulate a top level makefile
3825
    #       Pass argumenst to makelib
3826
    #       Sumulate SubDir() operations
3827
    #       Sumulate a Platform(*);
3828
    #
3829
    #       Due to the normal way that makelib.pl is executed,
3830
    #       the following substitutions are done.
3831
    #
3832
    @ARGV = ();
3833
    $0 = "makefile.pl ";
3834
    push @ARGV, "$Cwd";                         # current working directory
331 dpurdie 3835
    push @ARGV, "$::GBE_TOOLS/makelib.pl";     # makelib.pl image
227 dpurdie 3836
    push @ARGV, "--interface=$BUILDINTERFACE"
261 dpurdie 3837
        if ($BUILDINTERFACE);
227 dpurdie 3838
 
3839
    Debug( "ARGV:      @ARGV" );
3840
 
3841
    #.. (re)Build root makefile
3842
    #
3843
    $ScmBuildlib = 0;                           # clear Buildlib flag for 'makelib.pl'
3844
    RootMakefile();                             # inform 'makelib.pl'
3845
    MakeLibInit();                              # run initialisation
3846
 
3847
    #.. Register subdir(s)
3848
    #
3849
    UniquePush (\@BUILDSUBDIRS, $Srcdir );
3850
    SubDir( @BUILDSUBDIRS );
3851
    Platform( @BUILD_ACTIVEPLATFORMS );
3852
 
3853
    #.. (re)build src makefiles and associated information
367 dpurdie 3854
    #   JatsTool will not return on error
227 dpurdie 3855
    #
263 dpurdie 3856
    my @cmds = ('jmake.pl', 'rebuild');
227 dpurdie 3857
    push @cmds, 'NORECURSE=1' if ( $RootOnly );
263 dpurdie 3858
    JatsTool ( @cmds);
305 dpurdie 3859
 
3860
    #
7301 dpurdie 3861
    #   Generate package signature
3862
    #
6133 dpurdie 3863
    ErrorConfig( 'name' => 'buildlib')   ;
7301 dpurdie 3864
    BuildSignature();
3865
 
3866
    #
305 dpurdie 3867
    #   Generate some warnings that will be seen at the end of the build
3868
    #
3869
    Warning ("BuildSrcArchive Directive Present","Read JATS Manual for correct usage")
3870
        if ($build_source_pkg);
227 dpurdie 3871
}
3872
 
7301 dpurdie 3873
#-------------------------------------------------------------------------------
3874
# Function        : BuildSignature 
3875
#
3876
# Description     : Generate a package 'signature' for this package
3877
#               
3878
#                   The signature is used to bypass the entire Make processing in a sandbox
3879
#                   If we can find a matching package in the package store then we don't 
3880
#                   need to 'make' this package.
3881
#
3882
#                   There are two scenarios:
3883
#                       In a GIT enabled sandbox
3884
#                       Without GIT
3885
#                       
3886
#                   In a GIT enabled sandbox the signature allows the use of a pre-built 
3887
#                   package - even if the package has been built on a different branch.
3888
#                   
3889
#                       The signature includes:
3890
#                           The name of this package
3891
#                           The GIT sha1 of the directory trees that contain this package
3892
#                           The package signatures of all dependent packages
3893
#                           
3894
#                   In a Non-GIT enabled sandbox the package signature will be set such that
3895
#                   the package will never be found in the package store and the package MUST
3896
#                   be built within the sandbox.
3897
#                   
7302 dpurdie 3898
#                   The hard part is determing the directory trees that contains this package
7301 dpurdie 3899
#                   Ideally this is a single dir-tree, but this cannot be enforced.
3900
#                   
3901
#                   Source directories have been gathered during makefile generation
3902
#                   
3903
#                   This suits most cases, but there are a few where the user needs
3904
#                   to give JATS a hint. Use the AsdSrcDir directive to extend
3905
#                   the signature paths to directories not under the build.pl
3906
#                   or any makefile included by the build.pl
3907
#                       
3908
# Inputs          : 
3909
#
3910
# Returns         : 
3911
#
3912
sub BuildSignature
3913
{
3914
    my %sigExcludeDirs;
3915
    my %sigExcludeFiles;
3916
    my $BuildSignatureSha1;
3917
    my $signatureFile = catfile($Cwd, $BUILDINTERFACE, 'Package.sig');
3918
    my $sigDebugFile  = catfile($Cwd, $BUILDINTERFACE, 'Package.dsig');
3919
    my @sigList;
227 dpurdie 3920
 
7301 dpurdie 3921
    #
3922
    #   Only create the Signature file ONCE
3923
    #   Done on first build (after a clobber)
3924
    #
3925
#   if (-f $signatureFile)
3926
#   {
3927
#       Message("Generate Package Signature - Already generated");
3928
#       return;
3929
#   }
3930
 
3931
    Message("Generate Package Signature");
3932
 
3933
    #
3934
    #   Determine if this is a GIT enabled sandbox build
3935
    #   Need a .git directory or file in the root of the sandbox
3936
    #
3937
    my $gitEnabled;
3938
    if ($::GBE_SANDBOX && -e catfile ($::GBE_SANDBOX, '.git') )
3939
    {
3940
        $gitEnabled = 1;
3941
    }
3942
 
3943
    #
3944
    #   Start generating the signature
3945
    #       Include the package Name,Version and Project
3946
    #
7310 dpurdie 3947
    $BuildSignatureSha1 = Digest::SHA::PurePerl->new;
7301 dpurdie 3948
    $BuildSignatureSha1->add("PKGNAME: $BUILDNAME_PACKAGE $BUILDNAME_VERSION $BUILDNAME_SUFFIX");
3949
    push @sigList, "PKGNAME: $BUILDNAME_PACKAGE $BUILDNAME_VERSION $BUILDNAME_SUFFIX: " . $BuildSignatureSha1->clone->hexdigest;
3950
 
3951
    #
3952
    #   Include the signature of ALL dependent packages
3953
    #   Ie: The package signature is a function of the source and its dependents
3954
    #
3955
    foreach my $tag ( PackageEntry::GetPackageList() )
3956
    {
3957
        my $pkgSig = PackageEntry::GetPackageSignature($tag);
3958
        $BuildSignatureSha1->add("PKGSIGNATURE: $pkgSig");
7302 dpurdie 3959
        push @sigList, sprintf("PKGSIGNATURE: [%s] %s: %s", PackageEntry::GetNameVersion($tag), $pkgSig , $BuildSignatureSha1->clone->hexdigest);
7301 dpurdie 3960
    }
3961
 
3962
    #
3963
    #   Save the signature of the package header and the dependencies
3964
    #   This will be used for a simple test to see in we need to rebuild the build file 
3965
    #
3966
    my $depSha1 =  $BuildSignatureSha1->clone->hexdigest;
3967
    Debug2("DepSha1: $depSha1");
3968
    FileCreate( catfile($ScmInterface, 'build.bfp'), $depSha1 );
3969
 
3970
    if ($gitEnabled)
3971
    {
3972
        #
3973
        #   Include the sha1 of all 'git' tree items that form the complete source image
7312 dpurdie 3974
        #   Warn user if not all components are version controlled
7301 dpurdie 3975
        #
3976
        my @relDirList = map { my $relName = $_; $relName =~ s~^$::GBE_SANDBOX/~~; $relName  } ToolsetFiles::GetSubTrees(); 
3977
        my @cmdList = map { 'HEAD:' . $_  } @relDirList;
7312 dpurdie 3978
        Debug3(" GIT CMD: " . "git rev-parse", @cmdList );
3979
 
3980
        #
3981
        #   Callback function to process the output of the Git parse
3982
        #   Expect one line for each HEAD: item
3983
        #
7301 dpurdie 3984
        my $index = 0;
7312 dpurdie 3985
        my @notControlled;
7301 dpurdie 3986
        my $callback = sub {
3987
            my ($cdata, $line) = @_;
3988
            $line =~ s~\s+$~~;
7312 dpurdie 3989
            Debug3(" GIT OUT: " . $line  );
3990
            if ($line =~ m~^HEAD:(.*)~) {
3991
                push @notControlled, $1;
3992
            }
7301 dpurdie 3993
            $BuildSignatureSha1->add($line);
3994
            push @sigList, "PKGSRC: $relDirList[$index++]: $line: " . $BuildSignatureSha1->clone->hexdigest;
3995
            return 0;
3996
        };
3997
 
7312 dpurdie 3998
        my $rv = GitCmd('rev-parse', @cmdList, { process => $callback } );
3999
        Debug2("GitCmd Result: $rv");
7301 dpurdie 4000
        $BUILDSIGNATURE =  $BuildSignatureSha1->hexdigest;
7312 dpurdie 4001
 
4002
        if (@notControlled) {
4003
            Warning('The folling paths are not version controlled:', @notControlled);
4004
        }
7301 dpurdie 4005
    }
4006
    else
4007
    {
7302 dpurdie 4008
        $BUILDSIGNATURE = 'MSG: Sandbox is not git enabled';
7301 dpurdie 4009
    }
4010
 
4011
    Message("Signature: $BUILDSIGNATURE");
4012
    push @sigList, "Signature: $BUILDSIGNATURE";
4013
    FileCreate( $signatureFile, $BUILDSIGNATURE );
4014
    FileCreate( $sigDebugFile, @sigList );
4015
Debug0("sigDebugFile: $sigDebugFile");
4016
 
4017
    #
7312 dpurdie 4018
    #   See if the package exists in one of the package stores
4019
    #   Look in each package archive directory
4020
    #   
4021
    foreach my $dpkg ( $::GBE_DPKG_SBOX,
4022
                       $::GBE_DPKG_LOCAL,
4023
                       $::GBE_DPKG_CACHE,
4024
                       $::GBE_DPKG_REPLICA,
4025
                       $::GBE_DPKG,
4026
                       $::GBE_DPLY,
4027
                       $::GBE_DPKG_STORE )
4028
    {
4029
        my $pkgDir = catdir( $dpkg, $BUILDNAME_PACKAGE . $BUILDNAME_SUFFIX, $BUILDSIGNATURE);
4030
        if (-d $pkgDir ) {
4031
            Message("PreBuild: $pkgDir");
4032
            last;
4033
        }
4034
    }
4035
 
4036
    #
7301 dpurdie 4037
    #   Create the descpkg file - to include the signature
4038
    #
4039
    BuildDescpkg('Internal');
4040
}
4041
 
227 dpurdie 4042
#-------------------------------------------------------------------------------
7301 dpurdie 4043
# Function        : GitCmd
4044
#
4045
# Description     : Run a Git Command and capture/process the output
4046
#
7312 dpurdie 4047
#                   Based on JatsSvnCore:SvnCmd
7301 dpurdie 4048
#
4049
# Inputs          : Command
4050
#                   Command arguments
4051
#                   Last argument may be a hash of options.
4052
#                       nosavedata  - Don't save the data
4053
#                       process     - Callback function
4054
#                       printdata   - Print data
4055
#                       error       - Error Message
4056
#                                     Used as first line of an Error call
4057
#
4058
# Returns         : non-zero on errors detected
4059
#
4060
sub GitCmd
4061
{
4062
    my $self;           # Local storage
4063
    Debug ("GitCmd");
4064
 
4065
    #
4066
    #   Locate essential tools
4067
    #
4068
    our $GBE_SVN_PATH;
4069
    EnvImportOptional('GBE_GIT_PATH', '');
4070
    Debug ("GBE_GIT_PATH", $::GBE_GIT_PATH);
4071
 
4072
    my $stdmux = LocateProgInPath ( 'stdmux');
4073
    my $git    = LocateProgInPath ( 'git', '--All', '--Path=' . $::GBE_GIT_PATH );
4074
 
4075
    #
4076
    #   Extract arguments and options
4077
    #   If last argument is a hash, then its a hash of options
4078
    #
4079
    my $opt;
4080
    $opt = pop @_
4081
        if (@_ > 0 and UNIVERSAL::isa($_[-1],'HASH'));
4082
 
4083
    $self->{PRINTDATA} = $opt->{'printdata'} if ( exists $opt->{'printdata'} );
4084
 
4085
    Verbose2 "GitCmd $git @_";
4086
 
4087
    #
4088
    # Useful debugging
4089
    #
4090
    # $self->{LAST_CMD} = [$svn, @_];
4091
 
4092
    #
4093
    #   Reset command output data
4094
    #
4095
    $self->{ERROR_LIST} = [];
4096
    $self->{RESULT_LIST} = [];
4097
#    $self->{LAST_CMD} = \@_;
4098
 
4099
    #
4100
    #   Make use of a wrapper program to mux the STDERR and STDOUT into
4101
    #   one stream (STDOUT). #   This solves a lot of problems
4102
    #
4103
    #   Do not use IO redirection of STDERR because as this will cause a
4104
    #   shell (sh or cmd.exe) to be invoked and this makes it much
4105
    #   harder to kill on all platforms.
4106
    #
4107
    #   Use open3 as it allows the arguments to be passed
4108
    #   directly without escaping and without any shell in the way
4109
    #
4110
    local (*CHLD_OUT, *CHLD_IN);
4111
    my $pid = open3( \*CHLD_IN, \*CHLD_OUT, '>&STDERR', $stdmux, $git, @_);
4112
 
4113
    #
4114
    #   Looks as though we always get a PID - even if the process dies
4115
    #   straight away or can't be found. I suspect that open3 doesn't set
4116
    #   $! anyway. I know it doesn't set $?
4117
    #
4118
    Debug ("Pid: $pid");
4119
    Error ("Can't run command: $!") unless $pid;
4120
 
4121
    #
4122
    #   Close the input handle
4123
    #   We don't have anything to send to this program
4124
    #
4125
    close(CHLD_IN);
4126
 
4127
    #
4128
    #   Monitor the output from the utility
4129
    #   Have used stdmux to multiplex stdout and stderr
4130
    #
4131
    #   Note: IO::Select doesn't work on Windows :(
4132
    #   Note: Open3 will cause blocking unless both streams are read
7312 dpurdie 4133
    #         Can't read both streams because IO::Select doesn't work
7301 dpurdie 4134
    #
4135
    #   Observation:
4136
    #       svn puts errors to STDERR
4137
    #       svn puts status to STDOUT
4138
    #
4139
    while (<CHLD_OUT>)
4140
    {
4141
        s~\s+$~~;
4142
        tr~\\/~/~;
4143
 
4144
 
4145
        Verbose3 ( "GitCmd:" . $_);
4146
        m~^STD(...):(.+)~;
4147
        my $data = $1 ? $2 : $_;
4148
        next unless ( $data );
4149
 
4150
        if ( $1 && $1 eq 'ERR' )
4151
        {
4152
            #
4153
            #   Process STDERR output
4154
            #
4155
            push @{$self->{ERROR_LIST}}, $data;
4156
        }
4157
        else
4158
        {
4159
            #
4160
            #   Process STDOUT data
4161
            #
4162
            push @{$self->{RESULT_LIST}}, $data unless ($opt->{'nosavedata'});
4163
 
4164
            #
4165
            #   If the user has specified a processing function then pass each
4166
            #   line to the specified function.  A non-zero return will
4167
            #   be taken as a signal to kill the command.
4168
            #
4169
            if ( exists ($opt->{'process'}) && $opt->{'process'}($self, $data) )
4170
            {
4171
                kill 9, $pid;
4172
                sleep(1);
4173
                last;
4174
            }
4175
        }
4176
    }
4177
 
4178
    close(CHLD_OUT);
4179
 
4180
    #
4181
    #   MUST wait for the process
4182
    #   Under Windows if this is not done then we eventually fill up some
4183
    #   perl-internal structure and can't spawn anymore processes.
4184
    #
4185
    my $rv = waitpid ( $pid, 0);
4186
 
4187
    #
4188
    #   If an error condition was detected and the user has provided
4189
    #   an error message, then display the error
4190
    #
4191
    #   This simplifies the user error processing
4192
    #
4193
    if ( @{$self->{ERROR_LIST}} && $opt->{'error'}  )
4194
    {
4195
        Error ( $opt->{'error'}, @{$self->{ERROR_LIST}} );
4196
    }
4197
 
4198
    #
4199
    #   Exit status has no meaning since open3 has been used
4200
    #   This is because perl does not treat the opened process as a child
4201
    #   Not too sure it makes any difference anyway
4202
    #
4203
    #
4204
    Debug ("Useless Exit Status: $rv");
4205
    my $result = @{$self->{ERROR_LIST}} ? 1 : 0;
4206
    Verbose3 ("Exit Code: $result");
4207
 
4208
    return $result;
4209
}
4210
 
4211
 
4212
#-------------------------------------------------------------------------------
227 dpurdie 4213
# Function        : BuildVersion
4214
#
4215
# Description     : Generate version.c and version.h files
4216
#
4217
# Inputs          : Options
4218
#                       --Prefix=prefix         Text prepended to variables created
4219
#                                               as a part of the "C" versions
4220
#                       --Type=type             Type of "C" style data
4221
#                                               Allowed types are: array
4222
#                       --Defs=name             Generate a "C" definitions file.
4223
#                                               This file simply contains definitions
4224
#                       --Defs                  Same as --Defs=defs
4225
#                       --Style=style           Output file style
4226
#                                               Supported styles:
4227
#                                                   "C" - Default
4228
#                                                   "CSharp"
4229
#                                                   "WinRC"
289 dpurdie 4230
#                                                   "Delphi"
315 dpurdie 4231
#                                                   "VB"
227 dpurdie 4232
#                       --File=name             Specifies the output file name
4233
#                                               Default is determined by the style
4234
#
4235
#                   Also allows for an 'old' style format in which
4236
#                   the first three arguments are prefix,type and defs
4237
# Returns         :
4238
#
4239
 
4240
sub BuildVersion
4241
{
4242
    my ( $Prefix, $Type, $Mode ) = @_;
4243
    my $ModePrefix;
4244
    my $Style = "C";
4245
    my $FileName;
4246
    my $VersionFiles;
267 dpurdie 4247
    my @opts;
4248
    my $supports_opts;
227 dpurdie 4249
 
4250
    StartBuildPhase();                          # Starting the build phase. No more data collection
4251
 
279 dpurdie 4252
    if ( defined($Prefix) && $Prefix =~ /^-/ )
227 dpurdie 4253
    {
4254
        $Prefix = undef;
4255
        $Type = undef;
4256
        $Mode = undef;
4257
        foreach  ( @_ )
4258
        {
4259
            if (      /^--Prefix=(.*)/ ) {
4260
                $Prefix = $1;
4261
                $VersionFiles = 1;
4262
 
4263
            } elsif ( /^--Type=(.*)/ ) {
4264
                $Type = $1;
4265
                $VersionFiles = 1;
4266
 
4267
            } elsif ( /^--Defs=(.*)/ ) {
4268
                $Mode = $1;
4269
                $ModePrefix = "_$1";
4270
 
4271
            } elsif ( /^--Defs$/ ) {
4272
                $Mode = 'defs';
4273
                $ModePrefix = "";
4274
 
4275
            } elsif ( /^--Style=(.*)/ ) {
4276
                $Style = $1;
279 dpurdie 4277
                $VersionFiles = 1;
267 dpurdie 4278
                $supports_opts = 1 if ( $Style =~ /^WinRC/i );
227 dpurdie 4279
 
4280
            } elsif ( /^--File=(.*)/ ) {
4281
                $FileName = $1;
4282
 
267 dpurdie 4283
            } elsif ($supports_opts ) {
4284
                push @opts, $_;
235 dpurdie 4285
 
227 dpurdie 4286
            } else {
4287
                Error ("BuildVersion: Unknown option: $_");
4288
 
4289
            }
4290
        }
4291
    }
4292
    else
4293
    {
4294
        #
4295
        #   Old style positional arguments.
4296
        #
4297
        $VersionFiles = 1;
4298
        if ( defined( $Mode ) )
4299
        {
4300
            if ( $Mode =~ m/^defs(=(.*))?$/i )
4301
            {
4302
                $Mode       = $2 ? $2    : 'defs';
4303
                $ModePrefix = $2 ? "_$2" : "";
4304
            }
4305
            else
4306
            {
4307
                Error ("BuildVersion: Bad Mode argument. Need 'defs' or 'defs=name'");
4308
            }
4309
        }
4310
    }
4311
 
4312
    #
4313
    #   Determine the style of version file to create
4314
    #
4315
    if ( $Style =~ /^CSharp/i ) {
4316
        BuildVersionCSharp( $FileName );
4317
 
229 dpurdie 4318
    } elsif ( $Style =~ /^Properties/i ) {
4319
        BuildVersionProperties( $FileName, $Prefix );
4320
 
227 dpurdie 4321
    } elsif ( $Style =~ /^WinRC/i ) {
267 dpurdie 4322
        BuildVersionWinRC( $FileName, @opts );
227 dpurdie 4323
 
289 dpurdie 4324
    } elsif ( $Style =~ /^Delphi/i ) {
4325
        BuildVersionDelphi( $FileName, $Prefix );
315 dpurdie 4326
 
4327
    } elsif ( $Style =~ /^VB/i ) {
4328
        BuildVersionVB( $FileName, $Prefix );
289 dpurdie 4329
 
227 dpurdie 4330
    } elsif ( $Style eq "C" ) {
289 dpurdie 4331
        BuildVersionC    ( $FileName, $Prefix, $Type )     if ( $VersionFiles );
4332
        BuildVersionCdefs( $FileName, $Mode, $ModePrefix ) if ( $Mode );
227 dpurdie 4333
 
4334
    } else {
4335
        Error("BuildVersion: Unknown style: $Style");
4336
    }
4337
}
4338
 
4339
#-------------------------------------------------------------------------------
4340
# Function        : BuildDescpkg
4341
#
4342
# Description     : Create a package description file
4343
#                   The format of this file matches that generated by JANTS
4344
#                   Take care when extending the format
4345
#
4346
#                   NOTE: It turns out that JANTS is not a standard and the
4347
#                         implementors (of JANTS) kept on changing it.
4348
#
7301 dpurdie 4349
# Inputs          : $mode - 'Internal' - Skip sanity test
227 dpurdie 4350
#
4351
# Returns         :
4352
#
4353
sub BuildDescpkg
4354
{
7301 dpurdie 4355
    my ($mode) = @_;
4356
    unless ($mode && $mode eq 'Internal')
4357
    {
4358
        StartBuildPhase();                  # Starting the build phase. No more data collection
4359
    }
4003 dpurdie 4360
    return if ( $Clobber );                 # clobber mode ?
227 dpurdie 4361
 
247 dpurdie 4362
    #
4363
    #   Store the files location for use at runtime
4364
    #   It will be a file that is 'known' to JATS
4365
    #
4003 dpurdie 4366
    my $pkgfile = BuildAddKnownFile ( $NoBuild ? $Cwd : $Srcdir, 'descpkg' );
227 dpurdie 4367
 
261 dpurdie 4368
    my @desc;
279 dpurdie 4369
    push @desc, "Package Name:  $BUILDNAME_PACKAGE";
4370
    push @desc, "Version:       $BUILDVERSION";
7301 dpurdie 4371
    push @desc, "Signature:     $BUILDSIGNATURE" if defined $BUILDSIGNATURE;
279 dpurdie 4372
    push @desc, "Released By:   $::USER";
4373
    push @desc, "Released On:   $::CurrentTime";
4374
    push @desc, "Build Machine: $::GBE_HOSTNAME";
4375
    push @desc, "Path:          $Cwd";
4376
    push @desc, "Jats Version:  $::GBE_VERSION";
4377
    push @desc, "Jats Path:     $::GBE_CORE";
261 dpurdie 4378
    push @desc, "";
4379
    push @desc, "Build Dependencies:";
4380
    push @desc, "";
227 dpurdie 4381
 
4382
    foreach my $tag ( PackageEntry::GetPackageList )
4383
    {
4384
        my ($name, $version, $type) = PackageEntry::GetPackageData($tag);
4385
 
4386
        my @attributes;
4387
 
4388
        push @attributes, "name=\"$name\"";
4389
        push @attributes, "version=\"$version\"";
4390
        push @attributes, "build=\"true\"" if $type =~ /Build/i;
4391
 
261 dpurdie 4392
        push @desc, "<sandbox @attributes/>";
227 dpurdie 4393
    }
247 dpurdie 4394
 
261 dpurdie 4395
    FileCreate ($pkgfile, \@desc );
227 dpurdie 4396
}
4397
 
4398
#-------------------------------------------------------------------------------
4003 dpurdie 4399
# Function        : NoBuildMarker
4400
#
4401
# Description     : Maintain the nobuild marker
4402
#                   This is file placed in the interface directory simply
4403
#                   to indicate to the 'create_dpkg' utility that this build
4404
#                   does not do anything useful.
4405
#
6133 dpurdie 4406
#                   It will only be used on a build machine by the build daemon
4003 dpurdie 4407
#
4408
#                   Its not placed in the interface directory as it would be
4409
#                   harder for create_dpkg to find it.
4410
#
4411
# Inputs          : None
4412
# Globals         : $NoBuild, $Clobber
4413
#
4414
# Returns         : Nothing
4415
#
4416
sub NoBuildMarker
4417
{
4418
    return if ( $Clobber );
4419
 
4420
    # Always delete the file - in case we toggle build forms
4421
    #
5986 dpurdie 4422
    my $markerFile = BuildAddKnownFile( $::ScmRoot, 'noBuild.gbe');
4003 dpurdie 4423
    unlink($markerFile);
4424
 
4425
    TouchFile($markerFile)
4426
        if ($NoBuild);
4427
}
4428
 
4429
#-------------------------------------------------------------------------------
227 dpurdie 4430
# Function        : BuildIncpkg
4431
#
4432
# Description     : Create a package inclusion file
4433
#
4434
# Inputs          :
4435
#
4436
# Returns         :
4437
#
4438
sub BuildIncpkg
4439
{
4440
    StartBuildPhase();                          # Starting the build phase. No more data collection
4441
    if ( $Clobber )                             # clobber mode ?
4442
    {
361 dpurdie 4443
        RmDirTree( "$Srcdir/incpkg" );
227 dpurdie 4444
        return;
4445
    }
4446
 
4447
    my $fh = ConfigurationFile::New( "$Srcdir/incpkg" );
4448
    $fh->Header( "buildlib (Version $BuildVersion)",
4449
                              "Package inclusion list" );
4450
 
4451
    foreach my $tag ( PackageEntry::GetPackageList )
4452
    {
4453
        my ($name, $version, $type) = PackageEntry::GetPackageData($tag);
4454
        $type = ($type =~ /build/i) ? "Build" : "Link";
4455
 
4456
        $fh->Write( "${type}PkgArchive( '$name', '$version' );\n" );
4457
    }
4458
 
4459
    $fh->Close();
4460
}
4461
 
4462
#-------------------------------------------------------------------------------
4463
# Function        : BuildConfig
4464
#
4465
# Description     : Create the file interface/build.cfg
4466
#                   This file contains information gathered by the build process
4467
#                   that is to be used when makefiles are created and re-created
4468
#
4469
# Inputs          : None
4470
#
4471
# Returns         : Nothing
4472
#
283 dpurdie 4473
sub BuildConfig
227 dpurdie 4474
{
4475
    Error( "No BuildInterface directive encountered\n" )
4476
        unless ($BUILDINTERFACE);
4477
 
4478
    my $fh = ConfigurationFile::New( "$BUILDINTERFACE/build.cfg");
4479
    $fh->Header( "buildlib (Version $BuildVersion)",
4480
                              "Makelib configuration file", "
4481
\$ScmBuildMachType              = \"$::GBE_MACHTYPE\";
4482
\$ScmInterfaceVersion           = \"$::InterfaceVersion\";
4483
\$ScmBuildName                  = \"$BUILDNAME\";
4484
\$ScmBuildPackage               = \"$BUILDNAME_PACKAGE\";
4485
\$ScmBuildVersion               = \"$BUILDNAME_VERSION\";
4486
\$ScmBuildProject               = \"$BUILDNAME_PROJECT\";
4487
\$ScmBuildVersionFull           = \"$BUILDVERSION\";
4488
\$ScmBuildPreviousVersion       = \"$BUILDPREVIOUSVERSION\";
4489
\$ScmLocal                      = \"$BUILDLOCAL\";
4490
\$ScmDeploymentPatch            = \"$DEPLOY_PATCH\";
4491
\$ScmSrcDir                     = \"$Srcdir\";
4492
\$ScmBuildSrc                   = \"$ScmBuildSrc\";
4493
\$ScmExpert                     = \"$Expert\";
261 dpurdie 4494
\$ScmAll                        = \"$All\";
4003 dpurdie 4495
\$ScmNoBuild                    = \"$NoBuild\";
7300 dpurdie 4496
\$ScmBuildUuid                  = \"$BUILD_UUID\";
227 dpurdie 4497
");
4498
 
4499
#.. Alias
4500
#
4501
    $fh->DumpData(
4502
        "\n# Aliases.\n#\n",
4503
        "ScmBuildAliases", \%BUILDALIAS );
4504
 
4505
#.. Products
4506
#
4507
    $fh->DumpData(
4508
        "# Product mapping.\n#\n",
4509
        "ScmBuildProducts", \%BUILDPRODUCT_PARTS );
4510
 
4511
#.. Create ScmBuildPlatforms
4512
#
4513
    my( @platforms_merged, %platform_args ) = ();
4514
 
4515
    UniquePush ( \@platforms_merged, @BUILDPLATFORMS );
4516
 
4517
    foreach my $key ( keys %BUILDPRODUCT ) {
4518
        my( @list ) = split( ' ', $BUILDALIAS{ $key } || '' );
4519
        my( $platform );
4520
 
4521
        foreach my $elem ( @list ) {
4522
            if ( $elem =~ /^--/ ) {             # argument
4523
                HashJoin( \%platform_args, $;, $platform, $elem )
4524
                    if ( defined($platform) );
4525
                next;
4526
            }
4527
            $platform = $elem;                  # platform
4528
            UniquePush( \@platforms_merged, $elem );
4529
        }
4530
    }
4531
 
4532
#.. Create ScmBuildPlatforms
4533
#   Contains per platform options extracted from alias and platform args
4534
#
4535
    my %ScmBuildPlatforms;
4536
    foreach my $key ( @platforms_merged ) {
4537
 
7310 dpurdie 4538
        my $pInfo = $BUILDINFO{$key};
4539
        next if ($pInfo->{NOT_AVAILABLE});
4540
 
227 dpurdie 4541
        my( @arguments ) = ();
4542
        UniquePush( \@arguments, split( /$;/, $BUILDPLATFORMARGS{ $key } ))
4543
            if ( exists $BUILDPLATFORMARGS{ $key } );
4544
 
4545
        UniquePush( \@arguments, split( /$;/, $platform_args{ $key } ))
4546
            if ( exists $platform_args{ $key } );
4547
 
4548
        $ScmBuildPlatforms{$key} = join "$;", @arguments;
4549
    }
4550
 
4551
    $fh->DumpData(
4552
        "# Platform and global argument list.\n#\n",
4553
        "ScmBuildPlatforms", \%ScmBuildPlatforms );
4554
 
7310 dpurdie 4555
#.. Create ScmBuildMatrix
4556
#   Contains information on all the platforms that the package builds for and target machines
4557
#   
4558
    my %ScmBuildMatrix;
4559
    foreach my $key ( keys %BUILDINFO ) {
4560
        my $pInfo = $BUILDINFO{$key};
4561
        next if exists ($pInfo->{BADNAME});
4562
        next if ($pInfo->{NOT_AVAILABLE} > 1);
4563
        Error ("Internal: No MACHTYPE provided for $key") unless exists $pInfo->{MACHTYPE};
4564
        $ScmBuildMatrix{$key} = $pInfo->{MACHTYPE};
4565
    }
227 dpurdie 4566
 
7310 dpurdie 4567
    $fh->DumpData(
4568
        "# Build Matrix.\n#\n",
4569
        "ScmBuildMatrix", \%ScmBuildMatrix );
4570
 
227 dpurdie 4571
# .. Create BuildPkgRules
4572
#
367 dpurdie 4573
#    This is most of the information contained within %PKGRULES, which
227 dpurdie 4574
#    requires additional processing within makelib.
4575
#
367 dpurdie 4576
#   Need the True Path for windows.
4577
#       Some makefile functions (wildcard) only work as expected
4578
#       if the case of the pathname is correct. Really only a problem
4579
#       with badly formed legecy packages where the Windows user
4580
#       guessed at the package format.
4581
#
227 dpurdie 4582
    my %ScmBuildPkgRules;
4583
    foreach my $platform ( keys %PKGRULES )
4584
    {
4585
        foreach my $package ( @{$PKGRULES{$platform}} )
4586
        {
4587
            my %entry;
4588
 
367 dpurdie 4589
            $entry{ROOT}     = TruePath( $package->{'base'} );
227 dpurdie 4590
            $entry{NAME}     = $package->{'name'};
4591
            $entry{VERSION}  = $package->{'version'};
4592
            $entry{DNAME}    = $package->{'dname'};
4593
            $entry{DVERSION} = $package->{'dversion'};
4594
            $entry{DPROJ}    = $package->{'dproj'};
4595
            $entry{TYPE}     = $package->{'type'};
4596
            $entry{CFGDIR}   = $package->{'cfgdir'} if ( defined( $package->{'cfgdir'} ) );
4597
 
367 dpurdie 4598
            foreach my $dir (qw (TOOLDIRS) )
227 dpurdie 4599
            {
4600
                $entry{$dir} = $package->{$dir} ;
4601
            }
4602
 
367 dpurdie 4603
            my $baselen = length($package->{'base'});
4604
            foreach my $dir (qw (PINCDIRS PLIBDIRS THXDIRS) )
4605
            {
4606
                $entry{$dir} = [];
4607
                foreach my $file ( @{$package->{$dir}} )
4608
                {
4609
                    push @{$entry{$dir}}, substr TruePath($package->{'base'} . $file ), $baselen;
4610
                }
4611
            }
4612
 
227 dpurdie 4613
            push @{$ScmBuildPkgRules{$platform}}, \%entry;
4614
        }
4615
    }
4616
 
4617
    $fh->DumpData(
4618
        "# Imported packages.\n#\n",
4619
        "ScmBuildPkgRules", \%ScmBuildPkgRules );
4620
 
4621
#
4622
#   BUILDPLATFORMS,
4623
#       The value that is saved only contains the active platforms
4624
#
4625
#   DEFBUILDPLATFORMS,
4626
#       The value that is matchs the wildcard specification for Platform 
4627
#       directives.
4628
#
4629
    $fh->DumpData(
4630
        "# A list of platforms active within the view.\n#\n",
4631
        "BUILDPLATFORMS", \@BUILD_ACTIVEPLATFORMS );
4632
 
4633
    $fh->DumpData(
4634
        "# A list of default platforms within the view.\n#\n",
4635
        "DEFBUILDPLATFORMS", \@DEFBUILDPLATFORMS );
4636
 
4637
#
4638
#   BUILDTOOLS
4639
#       A list of toolset extension paths
4640
#
4641
    $fh->DumpData(
4642
        "# A list of paths with toolset extension programs.\n#\n",
4643
        "BUILDTOOLSPATH", \@BUILDTOOLS );
4644
 
4645
#
4646
#   BUILDPLATFORM_PARTS
4647
#       A subset of BUILDINFO exported as BUILDPLATFORM_PARTS
4648
#       This exists only for backward compatability with existing code
4649
#       in external packages ( deployfiles).
4650
#
4651
#   Only save those parts that are part of the current build
4652
#   This will prevent users attempting to build for platforms that have not
4653
#   been correctly constructed.
4654
#
4655
    my %active =  map { ${_} => 1 } @BUILD_ACTIVEPLATFORMS;
4656
    my %active_buildplatform_parts;
4657
    my %active_build_info;
4658
    foreach ( keys %BUILDINFO )
4659
    {
4660
        next unless ( $active{$_} );
4661
        $active_buildplatform_parts{$_} = $BUILDINFO{$_}{PARTS};
4662
        $active_build_info{$_}          = $BUILDINFO{$_};
4663
    }
4664
 
4665
    $fh->DumpData(
4666
        "# Parts of all platforms.\n#\n",
4667
        "BUILDPLATFORM_PARTS", \%active_buildplatform_parts );
4668
#
4669
#   BUILDINFO
4670
#       Complete TARGET Information
4671
#
4672
    $fh->DumpData(
4673
        "# Extended build information.\n#\n",
4674
        "BUILDINFO", \%active_build_info );
4675
 
4676
#
247 dpurdie 4677
#   BUILD_KNOWNFILES
4678
#       All paths are relative to the project root directory
4679
#       ie: The directory that conatins the build.pl file
4680
#
4681
    $fh->DumpData(
4682
        "# Generated Files that may be known when used as Src files.\n#\n",
4683
        "BUILD_KNOWNFILES", \%BUILD_KNOWNFILES );
4684
 
4685
#
227 dpurdie 4686
#   Close out the file
4687
#
4688
    $fh->Close();
363 dpurdie 4689
 
227 dpurdie 4690
}
4691
 
4692
#-------------------------------------------------------------------------------
4693
# Function        : WriteParsedBuildConfig
4694
#
4695
# Description     : Write all the parsed build.pl data to a single file
4696
#                   Its all in there for use
4697
#
4698
# Inputs          : 
4699
#
4700
# Returns         : 
4701
#
4702
sub WriteParsedBuildConfig
4703
{
4704
    my $cfg_file = "$::BUILDINTERFACE/Buildfile.cfg";
4705
    my %cf_build_info = ();
4706
 
4707
    #
4708
    #   Examine the symbol table and capture most of the entries
4709
    #
4710
    foreach my $symname (keys %main::)
4711
    {
4712
        next if ( $symname =~ m/::/  );                 # No Typeglobs
4713
        next if ( $symname =~ m/^cf_build_info/  );     # Not myself
4714
        next unless ( $symname =~ m/^[A-Za-z]/  );      # No system type names
4715
        next if ( $symname =~ m/^SIG$/  );              # Useless
4716
        next if ( $symname =~ m/^ENV$/  );              # Don't keep the user ENV
4717
        next if ( $symname =~ m/^INC$/  );              # Don't keep the INC paths
4718
        next if ( $symname =~ m/^DEFINES/  );           # Don't keep
4719
        next if ( $symname =~ m/^TOOLSETRULES/  );      # Don't keep
4720
 
331 dpurdie 4721
        no strict 'vars';
227 dpurdie 4722
        local *sym = $main::{$symname};
4723
 
331 dpurdie 4724
        $cf_build_info{"\$$symname"} =  $sym if defined $sym;
369 dpurdie 4725
        $cf_build_info{"\@$symname"} = \@sym if @sym;
4726
        $cf_build_info{"\%$symname"} = \%sym if %sym;
331 dpurdie 4727
        use strict 'vars';
227 dpurdie 4728
    }
4729
 
4730
    #
4731
    #   Dump out the configuration information
4732
    #
4733
    my $fh = ConfigurationFile::New( "$cfg_file" );
4734
    $fh->Header( "buildlib (version $::BuildVersion)",
4735
                              "Buildfile configuration" );
4736
    $fh->Dump( [\%cf_build_info], [qw(*cf_build_info)] );
4737
    $fh->Close();
4738
}
4739
 
4740
 
4741
#-------------------------------------------------------------------------------
4742
# Function        : BuildSharedLibFiles
4743
#
4744
# Description     : Create a file in the interface directory that will specify
4745
#                   the locations of shared libraries.
4746
#
4747
#                   Note: Always create a file as makefile targets depend on it.
4748
#
4749
#                   This is a bit ugly.
4750
#
4751
#                   There needs be an association between the build machine and
4752
#                   the target platform. Need to know if the current target is
4753
#                   native to the current build machine. If it is then we can
4754
#                   run tests on the machine and we then need to extend the
4755
#                   search path for the target.
4756
#
4757
#                   The BUILDINFO{EXT_SHARED} is used to control the creation of
4758
#                   the files by specifying the extension of the file.
4759
#
4760
# Inputs          : None
4761
#
4762
# Returns         :
4763
#
4764
sub BuildSharedLibFiles
4765
{
4766
    if ( $ScmHost eq "DOS" || $ScmHost eq "WIN" ) {
4767
        BuildSharedLibFiles_WIN(@_);
4768
 
4769
    } elsif ( $ScmHost eq "Unix" ) {
4770
        BuildSharedLibFiles_Unix(@_);
4771
 
4772
    } else {
4773
        Error("Cannot build. Unknown machine type: $ScmHost",
4774
              "Need WIN, DOS or Unix" );
4775
    }
4776
}
4777
 
4778
#-------------------------------------------------------------------------------
4779
# Function        : BuildSharedLibFiles_WIN
4780
#
4781
# Description     : Implementation of BuildSharedLibFiles for Windows
4782
#
4783
# Inputs          : None
4784
#
4785
sub BuildSharedLibFiles_WIN
4786
{
4787
 
4788
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
4789
    {
4790
        next unless ( exists $BUILDINFO{$platform}{EXT_SHARED} );
4791
        my @dos_paths = BuildSharedLibFiles_list( $platform, $BUILDINFO{$platform}{EXT_SHARED} );
4792
 
4793
        #
4794
        #   Create a .bat file for WIN32
4795
        #   This may be consumed by user wrapper programs
4796
        #
229 dpurdie 4797
        #   Features: No Echo
4798
        #             Use of SETLOCAL to prevent pollution of environment
4799
        #
227 dpurdie 4800
        my $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/set_$platform.bat", '--NoEof', '--Type=bat' );
229 dpurdie 4801
        $fh->Write ( "\@echo off\n");
227 dpurdie 4802
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
229 dpurdie 4803
        $fh->Write ( "\nSETLOCAL\n");
227 dpurdie 4804
        foreach ( reverse @dos_paths )
4805
        {
4806
            $_ =~ s~/~\\~g;
4807
            $fh->Write ( "PATH=$_;\%PATH\%\n" );
4808
        }
4809
        $fh->Write ( "\n%*\n" );
229 dpurdie 4810
        $fh->Write ( "\nENDLOCAL\n");
231 dpurdie 4811
        $fh->Write ( "EXIT /B %ERRORLEVEL%\n");
227 dpurdie 4812
        $fh->Close();
4813
 
4814
        #
4815
        #   Create a .sh file for WIN32
4816
        #   This may be consumed by a shell - as used within JATS
4817
        #
4818
        $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/set_$platform.sh", '--NoEof', '--Type=sh' );
4819
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
4820
        foreach ( reverse @dos_paths )
4821
        {
4822
            tr~\\/~/~s;
4823
            $fh->Write ( "PATH=$_\\;\$PATH\n" );
4824
        }
287 dpurdie 4825
        $fh->Write ( "\n" . '[ -n "$*" ] && "$@"'  ."\n" );
227 dpurdie 4826
        $fh->Close();
4827
    }
4828
}
4829
 
4830
#-------------------------------------------------------------------------------
4831
# Function        : BuildSharedLibFiles_Unix
4832
#
4833
# Description     : Implementation of BuildSharedLibFiles for Unix
4834
#                   Extend the Shared Library search path via LD_LIBRARY_PATH
5877 dpurdie 4835
#                   
4836
#                   Create sonames for all external shared libraries
227 dpurdie 4837
#
4838
# Inputs          : None
4839
#
4840
sub BuildSharedLibFiles_Unix
4841
{
4842
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
4843
    {
4844
        next unless ( exists $BUILDINFO{$platform}{EXT_SHARED} );
4845
        my @unix_paths = BuildSharedLibFiles_list( $platform, $BUILDINFO{$platform}{EXT_SHARED} );
4846
 
4847
        #
5877 dpurdie 4848
        #   Create sonames for all shared libraries
4849
        #   Append to the begging of the search list - so that it will rendered last
4850
        #   
4851
        my $sodir = BuildSoNameLinks_Unix($platform, @unix_paths);
4852
        unshift( @unix_paths, $sodir ) if defined $sodir;
4853
 
4854
        #
227 dpurdie 4855
        #   Create a .sh file for Unix
4856
        #
229 dpurdie 4857
        my $file = "$BUILDINTERFACE/set_$platform.sh";
4858
        my $fh = ::ConfigurationFile::New( $file , '--NoEof', '--Type=sh' );
227 dpurdie 4859
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
4860
        foreach ( reverse @unix_paths )
4861
        {
4862
            $fh->Write ( "export LD_LIBRARY_PATH=$_:\$LD_LIBRARY_PATH\n" );
4863
        }
275 dpurdie 4864
        $fh->Write ( "\n\"\$\@\"\n" );
227 dpurdie 4865
        $fh->Close();
229 dpurdie 4866
 
4867
        #
4868
        #   Make the file executable under unix
4869
        #
4870
        chmod 0755, $file;
227 dpurdie 4871
    }
4872
}
4873
 
4874
#-------------------------------------------------------------------------------
5877 dpurdie 4875
# Function        : BuildSoNameLinks_Unix 
4876
#
4877
# Description     : Generate soname links for all shared libraries from external
4878
#                   packages.
4879
#                   
4880
#                   There is a bit of a cheat. We don't examine the library to determine
4881
#                   the soname. We simple create all possible sonames to the library
4882
#
4883
# Inputs          : $platform       - Target platform
4884
#                   @paths          - Array of paths to scan for libraries 
4885
#
4886
# Returns         : soLinkDir       - Absolute path to the directory of gernerated
4887
#                                     symlinks
4888
#
4889
sub BuildSoNameLinks_Unix
4890
{
4891
    my ($platform, @paths) = @_;
4892
    my $soLinkDir = catdir($BUILDINTERFACE, 'soLinks', $platform );
4893
 
4894
    Verbose("Create Unix SoName links - $soLinkDir");
4895
    RmDirTree( $soLinkDir );
4896
 
4897
    #
4898
    #   Search provided library paths for shared libaries
4899
    #       These are names of the form *.so.* ie : libz.so.1.2.5
4900
    #
4901
    foreach my $path (@paths)
4902
    {
4903
        foreach my $file (glob(catdir($path, '*.so.*')))
4904
        {
4905
            #
4906
            #   Skip the debug symbol files
4907
            #
4908
            next if $file =~ m~\.debug$~;
4909
            next if $file =~ m~\.dbg$~;
4910
 
4911
            #
4912
            #   Generate all possible sonames by removing .nnnn from the 
4913
            #   end of the file name
4914
            #   
4915
            my $sofile = $file;
4916
            while ($sofile =~ m~(.*)\.\d+$~)
4917
            {
4918
                $sofile = $1;
4919
                unless (-f $sofile) {
4920
                    Verbose2("Need Soname: $sofile");
4921
 
4922
                    #
4923
                    #   Create link from soname to full name
4924
                    #   
4925
                    mkpath ( $soLinkDir ) unless -d $soLinkDir;
4926
                    my $sofilename = $sofile;
4927
                    $sofilename =~ s~.*/~~;
4928
                    $sofilename = catdir($soLinkDir, $sofilename);
4929
                    unless (-f $sofilename) {
4930
                        symlink ($file, $sofilename) || Error ("Cannot create symlink to $sofilename. $!"); 
4931
                    }
4932
                }
4933
            }
4934
        }
4935
    }
4936
 
4937
    #
4938
    #   Return the path the generated soLink dir
4939
    #
4940
    return AbsPath($soLinkDir) if (-d $soLinkDir);
4941
    return undef;
4942
}
4943
 
4944
#-------------------------------------------------------------------------------
227 dpurdie 4945
# Function        : BuildSharedLibFiles_list
4946
#
4947
# Description     : Determine a list of Shared Library paths that can be used
4948
#                   by the current target
4949
#
4950
# Inputs          : $platform       - Current platform
4951
#                   $so             - Shared object extensions
4952
#
4953
# Returns         : List of search paths
4954
#
4955
sub BuildSharedLibFiles_list
4956
{
4957
    my ($platform, $so ) = @_;
4958
    my @paths;
4959
    my @parts = @{$BUILDINFO{$platform}{PARTS}};
4960
 
4961
    #
4962
    #   Paths from the current build
4963
    #       Local directory         - for installed components
4964
    #       Interface directory     - for BuildPkgArchives
4965
    #
4966
    if ( $BUILDLOCAL )
4967
    {
5986 dpurdie 4968
        my @localParts;
4969
        UniquePush \@localParts, $BUILDINFO{$platform}{PLATFORM} , $BUILDINFO{$platform}{PRODUCT}, $BUILDINFO{$platform}{TARGET};
4970
        foreach ( @localParts )
227 dpurdie 4971
        {
4972
            push @paths, AbsPath("$BUILDLOCAL/lib/$_");
4973
        }
4974
    }
4975
 
4976
    foreach ( @parts )
4977
    {
4978
            push @paths, AbsPath("$BUILDINTERFACE/lib/$_");
4979
    }
4980
 
4981
    #
4982
    #   For each LinkPkgArchive
4983
    #
4984
    foreach my $package ( @{$PKGRULES{$platform}} )
4985
    {
4986
        next unless ( $package->{'type'} eq 'link' );
4987
 
4988
        my $base = $package->{'base'};
4989
        for my $path ( @{$package->{'PLIBDIRS'}} )
4990
        {
289 dpurdie 4991
            my @so_libs;
317 dpurdie 4992
            push @so_libs, glob ( "$base$path/*$_") foreach ( ArrayList($so) );
227 dpurdie 4993
            next unless scalar @so_libs;
4994
            push @paths, $base . $path;;
4995
        }
4996
    }
4997
 
4998
    #
4999
    #   Returns paths found
5000
    #
5001
    return @paths;
5002
}
5003
 
5004
#-------------------------------------------------------------------------------
247 dpurdie 5005
# Function        : BuildAddKnownFile
5006
#
5007
# Description     : Save the file as a file that will be known  to the JATS
5008
#                   makefiles. It will be available SRCS, but will not be a
5009
#                   part of any object list.
5010
#
5011
#                   Known Files will be deleted on clobber
5012
#
5013
# Inputs          : $path
5014
#                   $file
289 dpurdie 5015
#                   $noadd                    - Don't add to known
247 dpurdie 5016
#
5017
# Returns         : Path and filename
5018
#
5019
 
5020
sub BuildAddKnownFile
5021
{
289 dpurdie 5022
    my ($path, $file, $noadd) = @_;
247 dpurdie 5023
    $path .= '/'. $file;
2450 dpurdie 5024
    $path =~ tr~/~/~s;
289 dpurdie 5025
    $BUILD_KNOWNFILES {$file} = $path
5026
        unless ( defined($noadd) && $noadd);
4003 dpurdie 5027
 
6133 dpurdie 5028
    ToolsetFiles::AddFile( $path )
3967 dpurdie 5029
        unless ($Clobber);
5030
 
247 dpurdie 5031
    return $path;
5032
}
5033
 
5034
#-------------------------------------------------------------------------------
5969 dpurdie 5035
# Function        : WinPath 
5036
#
5037
# Description     : Covert path to a windows formatted path
5038
#
5039
# Inputs          : One path element
5040
#
5041
# Returns         : One ugly path element
5042
#
5043
 
5044
sub WinFullPath
5045
{
5046
    my ($path) = @_;
5047
    $path = FullPath($path);
5048
    $path =~ tr~\\/~\\~s;
5049
    return $path;
5050
}
5051
 
5052
#-------------------------------------------------------------------------------
5053
# Function        : BuildPropertyPages 
5054
#
5055
# Description     : Create a props file suitable for use by VS2010, VS2012 (possibly others)
5056
#                   Only supported for C/C++ projects
5057
#                   Provide info for:
5058
#                       Include Search paths
5059
#                       Library search paths
5060
#                       Nice Macros 
5061
#
5062
# Inputs          : 
5063
#
5064
# Returns         : 
5065
#
5066
sub BuildPropertyPages
5067
{
5068
    StartBuildPhase();                      # Starting the build phase. No more data collection
5986 dpurdie 5069
    return if $Clobber;
5969 dpurdie 5070
    foreach my $platform ( keys %BUILDINFO )
5071
    {
5072
        next unless $BUILDINFO{$platform}{MSBUILDPROPS};
5986 dpurdie 5073
        my $propsFile = BuildAddKnownFile ($Srcdir, 'jats_'. $BUILDINFO{$platform}{TARGET} . '.props');
5074
 
5969 dpurdie 5075
        Message("BuildPropertyPages: $propsFile");
5076
 
5077
        my %macros;
5078
        my @libpaths;
5079
        my @incpaths;
5080
        my @parts = @{$BUILDINFO{$platform}{PARTS}};
5081
 
5082
        #
5083
        #   Basic definitions
5084
        #   
5085
        $macros{'GBE_ROOT'}     = WinFullPath(".");
5086
        $macros{'GBE_PLATFORM'} = $BUILDINFO{$platform}{PLATFORM};
5087
        $macros{'GBE_PRODUCT'}  = $BUILDINFO{$platform}{PRODUCT};
5088
        $macros{'GBE_TARGET'}   = $BUILDINFO{$platform}{TARGET};
5089
        $macros{'GBE_MACHTYPE'} = $::GBE_MACHTYPE;
5090
        $macros{'GBE_PKGDIR'}   = WinFullPath('./pkg/' . $BUILDNAME_PACKAGE);
5091
        $macros{'GBE_BUILDNAME'}= $BUILDNAME_PACKAGE;
5092
 
5093
        #
5094
        #   Paths from the current build
5095
        #       Local directory         - for installed components
5096
        #       Interface directory     - for BuildPkgArchives
5097
        #
5098
        if ( $BUILDLOCAL )
5099
        {
5100
            my $macroName = 'GBE_LOCALDIR';
5101
            $macros{$macroName} = WinFullPath("$BUILDLOCAL") ;
5102
            $macroName = '$(' . $macroName . ')';
5986 dpurdie 5103
            my @localParts;
5104
            UniquePush \@localParts, $BUILDINFO{$platform}{PLATFORM} , $BUILDINFO{$platform}{PRODUCT}, $BUILDINFO{$platform}{TARGET};
5105
            foreach ( @localParts )
5969 dpurdie 5106
            {
5107
                push @libpaths, catdir($macroName, 'lib', $_);
5108
                push @incpaths, catdir($macroName ,'include' ,$_);
5109
            }
5110
            push @incpaths, catdir($macroName ,'include');
5111
        }
5112
 
5113
        my $macroName = 'GBE_INTERFACEDIR';
5114
        $macros{$macroName} = WinFullPath("$BUILDINTERFACE") ;
5115
        $macroName = '$(' . $macroName . ')';
5116
 
5117
        foreach ( @parts )
5118
        {
5119
                push @libpaths, catdir($macroName, 'lib' , $_);
5120
                push @incpaths, catdir($macroName ,'include' ,$_);
5121
        }
5122
        push @incpaths, catdir($macroName ,'include');
5123
 
5124
        #
5125
        #   For each LinkPkgArchive
5126
        #
5127
        foreach my $package ( @{$PKGRULES{$platform}} )
5128
        {
5129
            next unless ( $package->{'type'} eq 'link' );
5130
 
5131
            my $macroName = 'GBE_PACKAGE_'.$package->{'name'};
5132
            $macros{$macroName} = WinFullPath($package->{'base'}) ;
5133
            $macroName = '$(' . $macroName . ')';
5134
 
5135
            for my $path ( @{$package->{'PLIBDIRS'}} )
5136
            {
5137
                push @libpaths, catdir($macroName, $path);
5138
            }
5139
            for my $path ( @{$package->{'PINCDIRS'}} )
5140
            {
5141
                push @incpaths, catdir($macroName, $path);
5142
            }
5143
        }
5144
 
5145
        my $AdditionalIncludeDirectories = join(';', @incpaths );
5146
        my $AdditionalLibraryDirectories = join(';', @libpaths);
5147
        my $PreprocessorDefinitions = 'JATS=1';
5148
 
5149
        #
5150
        #   Create a props file formatted for VS2012
5151
        #
5152
        open (my $XML, '>', $propsFile) || Error ("Cannot create output file: $propsFile", $!);
5153
 
5154
        my $writer = XML::Writer->new(OUTPUT => $XML, UNSAFE => 0, DATA_INDENT => 4, DATA_MODE => 1);
5155
        $writer->xmlDecl("UTF-8");
5156
        $writer->comment('This file is generated by JATS build');
5157
        $writer->comment('Do not edit this file');
5158
        $writer->comment('Do not version control this file');
5159
        $writer->startTag('Project', "ToolsVersion", "4.0", "xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
5160
        $writer->emptyTag('ImportGroup', 'Label' , "PropertySheets");
5161
 
5162
        #
5163
        #   Special Macro for handling production/debug libraries
5164
        #
5165
        $writer->startTag('PropertyGroup', 'Label' , "UserMacros", 'Condition', "'\$(Configuration)' == 'Debug'");
5166
        $writer->dataElement('GBE_TYPE', 'D');
5167
        $writer->endTag('PropertyGroup');
5168
 
5169
        $writer->startTag('PropertyGroup', 'Label' , "UserMacros", 'Condition', "'\$(Configuration)' != 'Debug'");
5170
        $writer->dataElement('GBE_TYPE', 'P');
5171
        $writer->endTag('PropertyGroup');
5172
 
5173
        #
5174
        #   Define macros
5175
        #   
5176
        $writer->startTag('PropertyGroup', 'Label' , "UserMacros");
5177
        foreach my $key ( sort keys %macros)
5178
        {
5179
            $writer->dataElement($key, $macros{$key});
5180
        }
5181
        $writer->endTag('PropertyGroup');
5182
        $macros{'GBE_TYPE'}     = 1;
5183
 
5184
        #
5185
        #   Extend the search paths for includes and libaraies
5186
        #   
5187
        #$writer->emptyTag('ItemDefinitionGroup');
5188
        $writer->startTag('ItemDefinitionGroup');
5189
 
5190
        $writer->startTag('ClCompile');
5191
        $writer->dataElement('AdditionalIncludeDirectories', $AdditionalIncludeDirectories . ';%(AdditionalIncludeDirectories)');
5192
        $writer->dataElement('PreprocessorDefinitions', $PreprocessorDefinitions . ';%(PreprocessorDefinitions)');
5193
        $writer->endTag('ClCompile');
5194
 
5195
        $writer->startTag('Link');
5196
        $writer->dataElement('AdditionalLibraryDirectories', $AdditionalLibraryDirectories . ';%(AdditionalLibraryDirectories)');
5197
        $writer->endTag('Link');
5198
        $writer->endTag('ItemDefinitionGroup');
5199
 
5200
        #
5201
        #   Specify all macro names
5202
        #
5203
        $writer->startTag('ItemGroup');
5204
        foreach my $key ( sort keys %macros)
5205
        {
5206
            $writer->startTag('BuildMacro', 'Include' , $key);
5207
            $writer->dataElement('Value', '$(' . $key . ')');
5208
            $writer->endTag('BuildMacro');
5209
        }
5210
 
5211
        #
5212
        #   Close tags and write the XML file
5213
        #
5214
        $writer->endTag('ItemGroup');
5215
        $writer->endTag('Project');
5216
        $writer->end();
5217
    }
5218
}
5219
 
5220
 
5221
#-------------------------------------------------------------------------------
227 dpurdie 5222
# Function        : Usage
5223
#
5224
# Description     : Display program usage information
5225
#
5226
# Inputs          : args            - Text message to display
5227
#
5228
#                   $opt_help       - Level of verbose ness
5229
#
5230
# Returns         : Does not return
5231
#                   This function will exit
5232
#
5233
sub Usage
5234
{
5235
    my( $msg ) = @_;
5236
    my %usage_args;
5237
 
5238
    #
5239
    #   Create a hash of arguments for the pod2usage function
5240
    #
5241
    $usage_args{'-input'} = __FILE__;
5242
    $usage_args{'-exitval'} = 42;
5243
    $usage_args{'-message'} = "\nbuildlib $msg\n" if $msg;
5244
    $usage_args{'-verbose'} = $opt_help < 3 ? $opt_help - 1 : 3 if ( $opt_help );
5245
 
5246
    #
5247
    #   Generate nice help
5248
    #
5249
    pod2usage(\%usage_args);
5250
}
5251
 
5252
#-------------------------------------------------------------------------------
5253
#   Documentation
5254
#
5255
 
5256
=pod
5257
 
361 dpurdie 5258
=for htmltoc    JATS::build
5259
 
227 dpurdie 5260
=head1 NAME
5261
 
361 dpurdie 5262
build - Build Environment and Makefiles
227 dpurdie 5263
 
5264
=head1 SYNOPSIS
5265
 
5266
jats build [options] [command]
5267
 
5268
     [perl buildlib.pl [options] PWD [command]]
5269
 
5270
 Options:
331 dpurdie 5271
    -help          - Display terse usage
361 dpurdie 5272
    -help -help    - Display verbose usage
331 dpurdie 5273
    -man           - Display internal manual
5274
    -verbose[=n]   - Set level of progress verbosity
5275
    -debug[=n]     - Set the debug level
5276
    -cache         - Cache packages in the local dpkg_package cache
361 dpurdie 5277
    -cache -cache  - Forced refresh dependent packages in the local cache
331 dpurdie 5278
    -package       - Ignore packages that are not available and continue
2078 dpurdie 5279
    -nopackages    - Ignore package processing directives
331 dpurdie 5280
    -forcebuildpkg - Treat LinkPkgArchive directives as BuildPkgArchive
361 dpurdie 5281
                     Also suppress the use of symlinks so that the physical
5282
                     file will be copied locally.
331 dpurdie 5283
    -[no]force     - Force build even if build.pl is not newer
363 dpurdie 5284
                     Default: -force
4778 dpurdie 5285
    -[no]generic   - Build system sanity test
5286
                     Default: Do not test
227 dpurdie 5287
 
5288
 Sticky settings:
331 dpurdie 5289
    -all           - Build for all platforms ignoring GBE_BUILDFILTER
5290
    -expert[=n]    - Relaxing dependency checks on the user makefiles
227 dpurdie 5291
 
5292
 Commands:
2078 dpurdie 5293
    clobber        - Remove generated build system (eg Makefiles).
6133 dpurdie 5294
    interface      - Only (re)build the interface tree.
361 dpurdie 5295
    rootonly       - Only (re)build the root directory.
227 dpurdie 5296
 
5297
=head1 OPTIONS
5298
 
5299
=over 8
5300
 
331 dpurdie 5301
=item B<-help>
227 dpurdie 5302
 
5303
Print a brief help message and exits.
5304
 
5305
=item B<-help -help>
5306
 
5307
Print a detailed help message with an explanation for each option.
5308
 
5309
=item B<-man>
5310
 
5311
Prints the manual page and exits.
5312
 
331 dpurdie 5313
=item B<-verbose[=n]>
227 dpurdie 5314
 
261 dpurdie 5315
Increases program output.
227 dpurdie 5316
 
261 dpurdie 5317
If an argument is provided, then it will be used to set the level, otherwise the
5318
existing level will be incremented. This option may be specified multiple times.
227 dpurdie 5319
 
261 dpurdie 5320
=item B<-debug>
5321
 
227 dpurdie 5322
Increases program output. Enable internal debugging messages to generate detailed
5323
progress information.
5324
 
261 dpurdie 5325
If an argument is provided, then it will be used to set the level, otherwise the
5326
existing level will be incremented. This option may be specified multiple times.
5327
 
331 dpurdie 5328
=item B<-cache>
227 dpurdie 5329
 
5330
This option will cause dependent packages to be cached in the local
5331
dpkg_archive cache.
5332
 
5333
If the option is used twice then the packages will be forcibly refreshed.
5334
 
331 dpurdie 5335
=item B<-package>
227 dpurdie 5336
 
5337
This option will cause the build process to ignore packages that cannot be
5338
located. The package build may fail at a later stage.
5339
 
5340
This option is used by the Auto Build Tool to handle packages that may not be
5341
needed in all builds.
5342
 
2078 dpurdie 5343
=item B<-nopackage>
5344
 
5345
This options will cause all the directives that process external packages to be
5346
ignored.
5347
 
5348
This directive has limited use. It can be used in conjunction with the
5349
'interface' build command in order to create Version Information files in a
5350
sandbox where the required packages do not yet exist.
5351
 
331 dpurdie 5352
=item B<-forcebuildpkg>
227 dpurdie 5353
 
5354
This option will force LinkPkgArchive directives to be treated as
5355
BuildPkgArchive directives. The result is that the 'interface' directory will be
5356
populated with the contents of all dependent packages. Moreover, on a Unix
5357
machine, the files will be copied and not referenced with a soft link.
5358
 
5359
This may be useful for:
5360
 
5361
=over 8
5362
 
361 dpurdie 5363
=item *
227 dpurdie 5364
 
361 dpurdie 5365
Remote Development
227 dpurdie 5366
 
361 dpurdie 5367
=item *
227 dpurdie 5368
 
361 dpurdie 5369
Collecting header files for scanning
5370
 
5371
=item *
5372
 
5373
Local modification of files for test/debug/development
5374
 
227 dpurdie 5375
=back
5376
 
331 dpurdie 5377
=item B<-[no]force>
227 dpurdie 5378
 
331 dpurdie 5379
The '-noforce' option will only perform a build, if the build.pl file
363 dpurdie 5380
has been modified, or the buildfilter has changed, since the last build.
331 dpurdie 5381
 
363 dpurdie 5382
The default operation will always force a build.
331 dpurdie 5383
 
4778 dpurdie 5384
=item B<-[no]generic>
5385
 
5386
If used, this option will perform a sanity test on the build type. If set to 
5387
Generic then the build must be a GENERIC build. If set to noGeneric then the build
5388
must not be a GENERIC build.
5389
 
5390
The default is to not perform the test.
5391
 
5392
This option is intended to be used by the automated build system.
5393
 
331 dpurdie 5394
=item B<-all>
5395
 
227 dpurdie 5396
This option will cause the build process to generate makefiles for all
5397
possible build targets ignoring the use of GBE_BUILDFILTER.
5398
 
5399
This option is sticky. Once used in a build it will be retained when makefiles
5400
are rebuilt.
5401
 
331 dpurdie 5402
=item B<-expert[=n]>
227 dpurdie 5403
 
5404
This option causes the generation of makefiles with relaxed dependancy checks.
5405
 
261 dpurdie 5406
If an argument is provided, then it will be used to set the level, otherwise a
5407
level of '1' will be set.
5408
 
227 dpurdie 5409
The makefiles will have no dependancy between the makefiles and the JATS build
5410
files or the users makefile. If the user's makefile.pl is changed then JATS
5411
will not detect the change and will not rebuild the makefiles. The user manually
5412
force the rebuild with the command 'jats rebuild'.
5413
 
5414
This option should be used with care and with full knowledge of its impact.
5415
 
5416
This option is sticky. Once used in a build it will be retained when makefiles
363 dpurdie 5417
are rebuilt. It will only be lost when the next 'jats build' is performed.
227 dpurdie 5418
 
261 dpurdie 5419
The effect of the option can be changed when the makefiles are processed. This
5420
option simply sets the default' mode of operation.
5421
 
227 dpurdie 5422
=item B<interface>
5423
 
6133 dpurdie 5424
This command will only build, or rebuild, the 'interface' directory.
227 dpurdie 5425
 
261 dpurdie 5426
This command will not build, or rebuild, the root directory. The build
227 dpurdie 5427
process will not recurse through the subdirectories creating makefiles.
5428
 
261 dpurdie 5429
=item B<rootonly>
5430
 
6133 dpurdie 5431
This command will only build, or rebuild, the 'interface' directory and 
5432
the root-level makefiles.
261 dpurdie 5433
 
5434
The build process will not recurse through the subdirectories creating
5435
makefiles. These can be made on-demand by jats if a 'make' command is issued.
5436
 
227 dpurdie 5437
=item B<clobber>
5438
 
5439
This command will remove generated build system files and directories.
5440
 
5441
=back
5442
 
5443
=head1 DESCRIPTION
5444
 
5445
The default build process will parse the user's build.pl file and create the
5446
'interface' directory before creating makefiles for each target platform.
5447
 
5448
The 'build' process simply generates the build sandbox. It does not invoke the
5449
generated makefiles. This must be done by the user in a different phase.
5450
 
5451
The 'build' process need only be invoked if the build.pl file has changed. The
5452
generated makefiles will detected changes to the makefile.pl's and cause them to
5453
be generated as required. The 'build' step sets up the sandboxes external
5454
environment.
5455
 
5456
=head1 INVOCATION
5457
 
5458
This perl library (buildlib.pl) is not designed to be invoked directly by the
5459
user. It should be invoked through a 'build.pl' file. Moreover, for historical
5460
reasons, the build.pl is not easily invoked. It is best to only invoke the
5461
'build' process via the JATS wrapper scripts : jats.bat or jats.sh.
5462
 
331 dpurdie 5463
The build.pl file must be invoked with one fixed arguments, followed by user
227 dpurdie 5464
options and subcommands
5465
 
5466
=over 8
5467
 
361 dpurdie 5468
=item   1
227 dpurdie 5469
 
361 dpurdie 5470
The current working directory
5471
 
227 dpurdie 5472
This could have been derived directly by the program, rather than having it
5473
passed in.
5474
 
361 dpurdie 5475
=item   2
227 dpurdie 5476
 
361 dpurdie 5477
Options and commands may follow the first two mandatory arguments.
5478
 
227 dpurdie 5479
=back
5480
 
5481
The build.pl file must 'require' the buildlib.pl and makelib.pl. The preferred
5482
code is:
5483
 
5484
=over 8
5485
 
5486
    build.pl: First statements
5487
    $MAKELIB_PL     = "$ENV{ GBE_TOOLS }/makelib.pl";
5488
    $BUILDLIB_PL    = "$ENV{ GBE_TOOLS }/buildlib.pl";
5489
 
5490
    require         "$BUILDLIB_PL";
5491
    require         "$MAKELIB_PL";
5492
 
5493
=back
5494
 
5495
=cut
5496
 
5497
1;