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