Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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