Subversion Repositories DevTools

Rev

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

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