Subversion Repositories DevTools

Rev

Rev 229 | Rev 235 | Go to most recent revision | Details | Compare with Previous | 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
 
1241
        foreach ( @BUILD_ACTIVEPLATFORMS  )
1242
        {
1243
            $active_platforms{$_} = 1;
1244
        }
1245
 
1246
        foreach  ( split( ' ', $::GBE_PLATFORM) )
1247
        {
1248
            push @MAKE_PLATFORMS, $_
1249
                if ( $active_platforms{$_} );
1250
        }
1251
 
1252
        Error ("The GBE_PLATFORM filter prevents any targets being made",
1253
               "GBE_PLATFORM: $::GBE_PLATFORM" ) unless ( @MAKE_PLATFORMS );
1254
 
1255
        Log( "Make for ... ". PrintPlatforms(\@MAKE_PLATFORMS, $sep)."\n");
1256
 
1257
    }
1258
 
1259
    return 1;
1260
}
1261
 
1262
 
1263
sub BuildPreviousVersion
1264
{
1265
    my( $version ) = shift;
1266
 
1267
    $BUILDPREVIOUSVERSION = $version;
1268
    Log( "Previous Version ... $BUILDPREVIOUSVERSION\n" );
1269
 
1270
    return 1;
1271
}
1272
 
1273
 
1274
sub BuildInterface
1275
{
1276
    my( $ifdirname ) = @_;
1277
 
1278
 
1279
    #
1280
    #   Clobber the directory - at the end.
1281
    #
1282
    if ( $Clobber )
1283
    {
1284
        #
1285
        #   If this Interface directory contains the Dpackage.cfg file
1286
        #   then JATS has created DPACKAGE and it needs to be clobbered
1287
        #   Flag that it needs to be done later - when we know where it is
1288
        #
1289
        $DeleteDPACKAGE = 1 if ( -f "$ifdirname/Dpackage.cfg" );
1290
 
1291
        push @CLOBBERDIRS, $ifdirname;
1292
        return;
1293
    }
1294
 
1295
    #
1296
    #   In AutoBuildTool mode the entire interface directory
1297
    #   will be deleted. This allows the build to be retried
1298
    #
1299
    if (  defined($::GBE_ABT) )   # clobber mode ?
1300
    {
1301
        if ( -d "$ifdirname" )
1302
        {
1303
            System( "$::GBE_BIN/chmod -fR +w $ifdirname" );
1304
            System( "$::GBE_BIN/rm -rf $ifdirname" );
1305
        }
1306
    }
1307
 
1308
    if ( $ifdirname eq "local" ) {
1309
        System( "$::GBE_BIN/mkdir -p $ifdirname/inc" );
1310
        $BUILDLOCAL = "local";
1311
 
1312
    } else {
1313
        System( "$::GBE_BIN/mkdir -p $ifdirname/include" );
1314
        $BUILDINTERFACE = $ifdirname;
1315
        $::ScmInterface = $ifdirname;
1316
    }
1317
    System( "$::GBE_BIN/mkdir -p $ifdirname/bin" );
1318
    System( "$::GBE_BIN/mkdir -p $ifdirname/lib" );
1319
 
1320
    Log( "Interface .. $ifdirname\n" );
1321
    return 1;
1322
}
1323
 
1324
 
1325
sub BuildDirTree
1326
{
1327
    my( $dirfile, $dirhead ) = @_;
1328
    my( $dirname, $c );
1329
 
1330
    $dirhead = '.'
1331
        unless defined( $dirhead );
1332
 
1333
    if ( $Clobber )                             # clobber mode ?
1334
    {
1335
        push @CLOBBERDIRS, $dirhead unless $dirhead eq '.';
1336
        return;
1337
    }
1338
 
1339
    #
1340
    #   Allow for an empty "dirfile". This will allow a directory to be created
1341
    #   without the overhead of the file
1342
    #
1343
    if ( ! $dirfile )
1344
    {
1345
        Log( "DirTree .... $dirhead\n" );
1346
        System( "$::GBE_BIN/mkdir -p $dirhead" );
1347
    }
1348
    else
1349
    {
1350
        Log( "DirTree .... $dirfile within $dirhead\n" );
1351
        System( "$::GBE_BIN/mkdir -p $dirhead" );
1352
 
1353
        open( DIRFILE, $dirfile ) ||
1354
            Error( "cannot open '$dirfile'" );
1355
 
1356
        while( $dirname = <DIRFILE> )
1357
        {
1358
            chop $dirname;
1359
            $dirname =~ s/#.*//;
1360
            $c = $dirname =~ s/\s*(\S+).*/$1/g;
1361
 
1362
            next unless ( $c == 1 );
1363
 
1364
            if ( ! -d "$dirhead/$dirname" )
1365
            {
1366
                Log( "Dir ........ $dirhead/$dirname\n" );
1367
                System( "$::GBE_BIN/mkdir -p $dirhead/$dirname" );
1368
            }
1369
        }
1370
 
1371
        close( DIRFILE );
1372
    }
1373
    $BUILDDIRTREE = $dirhead;
1374
}
1375
 
1376
#-------------------------------------------------------------------------------
1377
# Function        : IncludePkg
1378
#
1379
# Description     : Examine a fully specified package directory for a file
1380
#                   that will specify packages to be included. This allows
1381
#                   a package to be simply a package of other packages
1382
#
1383
#                   Internal function. Not to be used by users
1384
#
1385
# Inputs          : Name of the package
1386
#                   Full directory path of the package to examine
1387
#
1388
# Returns         : Nothing
1389
#
1390
sub IncludePkg
1391
{
1392
    my ($name, $pkg) = @_;
1393
    my $file = "$pkg/incpkg";
1394
 
1395
    Debug ("IncludePkg: $pkg" );
1396
 
1397
    #
1398
    #   Using a require will ensure that the package is only processed once
1399
    #   even though the function user may be called multiple times.
1400
    #   Also prevents recursion within included packages.
1401
    #
1402
    if ( -f $file  )
1403
    {
1404
        Log( "PackageIncludes. $name\n" ) unless ( $INC{$file} );
1405
        require $file;
1406
    }
1407
}
1408
 
1409
 
1410
sub LinkSandbox
1411
{
1412
    my( $name, $path, $platform ) = @_;
1413
 
1414
    LinkClean();                                # clean previous images
1415
 
1416
    return if ( $Clobber );                     # clobber mode ?
1417
 
1418
    Error ("LinkSandbox() expects three arguments:  @_")
1419
        unless ( $#_ == 2 );
1420
 
1421
    Debug( "LinkSandbox:" );
1422
    Debug( "Package:   $name" );
1423
    Debug( "Version:   $path" );
1424
 
1425
    DataDirective("LinkSandbox");               # This directive allowed here
1426
 
1427
#
1428
#   If GBE_BUILDFILTER exists, Import 'user' platform
1429
#   specification and filter against the BUILD_ACTIVEPLATFORMS.
1430
#
1431
    Log( "LinkSandbox. $name ($path)\n" );
1432
 
1433
    if ( ! -d $path )                           # sandbox exists ?
1434
    {
1435
        Log( "WARNING .... Sandbox $path not available\n" );
1436
    }
1437
    else
1438
    {
1439
        $path = Realpath( $path );
1440
 
1441
        if ( !defined($platform) || $platform eq "*" ) 
1442
        {
1443
            foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
1444
            {
1445
                LinkEntry( $platform, $path, $name, "!sandbox", 1 );
1446
            }
1447
        }
1448
        else
1449
        {
1450
            my(@platforms) = split( ',', $platform );
1451
            @platforms = ExpandPlatforms( @platforms );
1452
 
1453
            foreach my $platform ( @platforms )
1454
            {
1455
                LinkEntry( $platform, $path, $name, "!sandbox", 1 );
1456
            }
1457
        }
1458
    }
1459
}
1460
 
1461
 
1462
#-------------------------------------------------------------------------------
1463
# Function        : LinkPkgArchive
1464
#
1465
# Description     : Include an external package into the build sandbox
1466
#                   by extending the compiler and linker search paths to
1467
#                   include suitable directories found in the package
1468
#
1469
# Inputs          : package name
1470
#                   package version
1471
#
1472
sub LinkPkgArchive
1473
{
1474
    my( $name, $version ) = @_;
1475
 
1476
    return BuildPkgArchive( @_ )
1477
        if ( $ForceBuildPkg );                  # Forcing interface directory
1478
 
1479
    LinkClean();                                # clean previous images
1480
 
1481
    return if ( $Clobber );                     # clobber mode ?
1482
 
1483
    Debug( "LinkPkgArchive:" );
1484
    Debug( "Name:      $name" );
1485
    Debug( "Version:   $version" );
1486
 
1487
    DataDirective("LinkPkgArchive");            # This directive allowed here
1488
 
1489
    #
1490
    #   Ensure that we have do not have multiple definitions
1491
    #
1492
    if ( PackageEntry::Exists( $name, $version ) )
1493
    {
1494
        Log( "Duplicate Package: $name, $version. Duplicate entry ignored\n" );
1495
        return;
1496
    }
1497
 
1498
    if ( $Cache && $::GBE_DPKG_CACHE )
1499
    {
1500
        my $mode = ($Cache > 1) ? "-refresh" : "";
1501
        Log( "LinkPkgArchive . $name ($version) Update Cache\n" );
1502
        System('--NoExit', "$::GBE_PERL $::GBE_TOOLS/cache_dpkg.pl $mode -quiet $name/$version" );
1503
    }
1504
 
1505
    #
1506
    #   Locate the package ONCE
1507
    #
1508
    Log( "LinkPkgArchive . $name ($version)\n" );
1509
    my ($pkg, $local ) = PackageLocate( $name, $version );
1510
    if ( $pkg )
1511
    {
1512
        #
1513
        #   Generate package rules for each active platform
1514
        #
1515
        foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
1516
        {
1517
            LinkEntry( $platform, $pkg, $name, $version, 0 );
1518
        }
1519
    }
1520
}
1521
 
1522
sub LinkClean
1523
{
1524
    if ( $BUILDINTERFACE && ! $BUILDLPA_CLEAN_DONE )
1525
    {                                           # only once
1526
        Debug( "LinkClean" );
1527
 
1528
        foreach my $platform ( @BUILDPLATFORMS )
1529
        {                                       # remove generated images
1530
            System( "$::GBE_BIN/rm -rf $BUILDINTERFACE/$platform.rul" );
1531
        }
1532
 
1533
        $BUILDLPA_CLEAN_DONE = 1;
1534
    }
1535
}
1536
 
1537
 
1538
#-------------------------------------------------------------------------------
1539
# Function        : PackageLocate
1540
#
1541
# Description     : Locate a package
1542
#                   Once located a package will be processed for each
1543
#                   platform, but it need only be located ONCE
1544
#
1545
# Inputs          : package name
1546
#                   package version
1547
#
1548
# Returns         : path to the package
1549
#                   local       1 - From local package repository
1550
#
1551
sub PackageLocate
1552
{
1553
    my ($name, $uversion ) = @_;
1554
    my( @dpkgs, $pdir, $pkg );
1555
    my $local = 1;
1556
    my $sandbox = 1;
1557
    my $isa_cache = 0;
1558
    my $version;
1559
    my ($pn, $pv, $ps ) = SplitPackage ($name, $uversion );
1560
 
1561
    Debug( "PackageLocate: ($name/$uversion)" );
1562
 
1563
    #
1564
    #   Look in each package archive directory
1565
    #
1566
    foreach my $dpkg ( split( $::ScmPathSep, $::GBE_DPKG_SBOX),
1567
                       '--NotSandbox',
1568
                       split( $::ScmPathSep, $::GBE_DPKG_LOCAL),
1569
                       '--NotLocal',
1570
                       split( $::ScmPathSep, $::GBE_DPKG_CACHE),
1571
                       '--NotCache',
1572
                       split( $::ScmPathSep, $::GBE_DPKG),
1573
                       split( $::ScmPathSep, $::GBE_DPKG_STORE) )
1574
    {
1575
 
1576
        #
1577
        #   Detect various tags that have been placed in the search list
1578
        #   to flag the end of the sandbox search and the end of the local
1579
        #   archive search
1580
        #
1581
        if ( $dpkg eq '--NotSandbox' )
1582
        {
1583
            $sandbox = 0;
1584
            next;
1585
        }
1586
        if ( $dpkg eq '--NotLocal' )
1587
        {
1588
            $local = 0;
1589
            $isa_cache = 1;
1590
            next;
1591
        }
1592
        if ( $dpkg eq '--NotCache' )
1593
        {
1594
            $isa_cache = 0;
1595
            next;
1596
        }
1597
 
1598
 
1599
        #
1600
        #   If we are playing in a sandbox, then the version number is
1601
        #   not used. The Package suffix is still used so that we can
1602
        #   differentiate sysbasetypes.xxxxx.mas and sysbasetypes.xxxxx.syd
1603
        #
1604
        if ( $sandbox )
1605
        {
1606
            $version = 'sandbox';
1607
            $version .= '.' . $ps if ( $ps );
1608
        }
1609
        else
1610
        {
1611
            $version = $uversion;
1612
        }
1613
 
1614
        #
1615
        #   Alias support
1616
        #   If the 'version' is '!current' then use a version of:
1617
        #       current
1618
        #       current_<USER_NAME>
1619
        #   This is an old mechanism whose use should not be encouraged
1620
        #
1621
        #..
1622
        if ( $version eq "!current" )
1623
        {                                       # 'current' user
1624
            EnvImport( "USER" );
1625
 
1626
            $pkg = "$dpkg/$name/current";       # default
1627
 
1628
            $pkg = "$dpkg/$name/current.lnk"
1629
                if ( -e "$dpkg/$name/current.lnk" );
1630
 
1631
                                                # USER specific
1632
            $pkg = "$dpkg/$name/current_$::USER"
1633
                if ( -e "$dpkg/$name/current_$::USER" );
1634
 
1635
            $pkg = "$dpkg/$name/current_$::USER.lnk"
1636
                if ( -e "$dpkg/$name/current_$::USER.lnk" );
1637
        }
1638
        else
1639
        {                                       # standard
1640
            $pkg = "$dpkg/$name/$version";
1641
 
1642
            $pkg = "$dpkg/$name/$version.lnk"
1643
                if ( -e "$dpkg/$name/$version.lnk" );
1644
        }
1645
 
1646
        #
1647
        #   Using a soft link
1648
        #   Emulate a link in software. The link file contains one line
1649
        #   which is the real pathname of the package
1650
        #
1651
        if ( $pkg =~ m~(.*)\.lnk$~  )
1652
        {
1653
            #
1654
            #   Warn the user if both a link and a real directory
1655
            #   are both present - the link may well be incorrect
1656
            #
1657
            my $non_link = $1;
1658
            Warning ("Suspect package link: $pkg",
1659
                     "Both a link and a package where found - using the link" )
1660
                                                            if ( -d $non_link );
1661
 
1662
            Debug( "           link found -> $pkg" );
1663
            my $link_src = $pkg;
1664
            open( LNKFILE, "$pkg" ) || Error( "cannot open '$pkg'" );
1665
            $pkg = <LNKFILE>;                   # real path
1666
            close( LNKFILE );
1667
            $pkg = '' unless ( $pkg );
1668
            chomp $pkg;
1669
 
1670
            Error ("Broken link: $pkg",
1671
                   "Source link: $link_src",
1672
                   "Try deleting the .lnk file" ) unless ( -d $pkg );
1673
        }
1674
 
1675
        Debug( "           searching $pkg" );
1676
 
1677
        #   Does the package directory exist?
1678
        #   Terminate the directory name with a "/" to detect hidden spaces
1679
        #..
1680
        $pkg =~ s~//~/~g;
1681
        next unless ( -d "$pkg/" );             # exists ?
1682
 
1683
        #
1684
        #   If the package exists within the dpkg_archive cache then mark the
1685
        #   version as having been used. Used by cache cleanup algorithms
1686
        #
1687
        if ( $isa_cache  )
1688
        {
1689
            TouchFile ( "$pkg/used.cache", "Marks the cache copy as being used");
1690
        }
1691
 
1692
        #
1693
        #   Use the first suitable package found
1694
        #..
1695
 
1696
        Debug( "           importing $pkg" );
1697
        return $pkg, $local;
1698
    }
1699
 
1700
    #
1701
    #   Package not found
1702
    #   This is an error, although it can be bypassed
1703
    #
1704
    Error ("Required package not found: '$name/$version'" ) if $PackageError;
1705
 
1706
    Log( "WARNING .... Package not available: '$name/$version'\n" );
1707
    return undef;
1708
}
1709
 
1710
 
1711
#-------------------------------------------------------------------------------
1712
# Function        : LinkEntry
1713
#
1714
# Description     : Scan a package an locate platform specific directories
1715
#                   Create data structures to capture the information
1716
#                   This function is used by LinkPkgArchive and LinkSandbox
1717
#                   to perfom the bulk of package inclusion work.
1718
#
1719
# Inputs          : platform being processed
1720
#                   path to the package
1721
#                   name of the package
1722
#                   version of the package
1723
#                   sandbox support (non-zero)
1724
#
1725
sub LinkEntry
1726
{
1727
    my( $platform, $pkg, $name, $version, $sandbox ) = @_;
1728
    my( $entry );
1729
 
1730
    #   Create entry record
1731
    #
1732
    #..
1733
    $entry = PackageEntry::New( $pkg, $name, $version, $sandbox, 'link' );
1734
 
1735
    #   Populate includes:
1736
    #
1737
    #   - include/$platform                 (eg include/solaris)
1738
    #   - inc/$platform                     (eg inc/solaris)
1739
    #   - include.$platform                 (eg include.solaris)
1740
    #   - inc.$platform                     (eg inc.solaris)
1741
    #   - include                           (eg include)
1742
    #   - inc                               (eg inc)
1743
    #
1744
    #   plus, product specialisation directores
1745
    #
1746
    #   eg. BuildProduct( 'IDFC', 'WIN32' );
1747
    #
1748
    #   - inc/IDFC_WIN32                    <- derived platform
1749
    #   - inc/IDFC                          <- product
1750
    #   - inc/WIN32                         <- target
1751
    #..
1752
    my $parts = $BUILDINFO{$platform}{PARTS};
1753
 
1754
    foreach my $part ( @$parts )
1755
    {
1756
        $entry->RuleInc( "/include." . $part ) if ( !$sandbox );
1757
        $entry->RuleInc( "/inc." . $part )     if ( !$sandbox );
1758
        $entry->RuleInc( "/include/" . $part ) if ( !$sandbox );
1759
        $entry->RuleInc( "/inc/" . $part );
1760
    }
1761
 
1762
    #
1763
    #   Also search the root include directory - last
1764
    #
1765
    $entry->RuleInc( "/include" )               if ( !$sandbox );
1766
    $entry->RuleInc( "/inc" );
1767
 
1768
    #   Populate libraries:
1769
    #
1770
    #   - lib/lib.$platform[D|P]            (eg lib/lib.sparcD)
1771
    #   - lib/$platform[D|P]                (eg lib/lib.sparc)
1772
    #   - lib.$platform[D|P]                (eg lib.sparcD)
1773
    #
1774
    #   plus, product specialisation directores
1775
    #
1776
    #   eg. BuildProduct( 'IDFC', 'WIN32' );
1777
    #
1778
    #   - lib/IDFC_WIN32                    <- derived platform
1779
    #   - lib/IDFC                          <- product
1780
    #   - lib/WIN32                         <- target
1781
    #..
1782
    $parts = $BUILDINFO{$platform}{PARTS};
1783
 
1784
    foreach my $part ( @$parts )
1785
    {
1786
        $entry->RuleLib("/lib" . ".$part" )     if ( !$sandbox );
1787
        $entry->RuleLib("/lib" . "/lib.$part" ) if ( !$sandbox );
1788
        $entry->RuleLib("/lib" . "/$part" );
1789
    }
1790
 
1791
    #
1792
    #   Some extra places to search
1793
    #   None. This is good as it indicates that all locations are described in PARTS
1794
    #
1795
    #   Do NOT search in /lib. There are no libraries that work on all platforms
1796
    #   Libraries are binaries!
1797
    #
1798
    #    $entry->RuleLib( "/lib" );
1799
 
1800
    #   Tools:
1801
    #
1802
    #   Tools provide an extensible search path for tools and
1803
    #   utilities used to build programs. These are tools that
1804
    #   are executable on the current host machine and are
1805
    #   independent of the toolset.
1806
    #
1807
    #..
1808
    $entry->ExamineToolPath();
1809
    $entry->ExamineThxPath($platform);
1810
    IncludePkg ( $name, $pkg );
1811
    $entry->Cleanup();                          # cleanup tables
1812
 
1813
    #
1814
    #   Add the package entry to the array of such entries for
1815
    #   the current platform. Maintain the discovery order
1816
    #
1817
    #..
1818
    push ( @{$PKGRULES{$platform}}, $entry );
1819
}
1820
 
1821
 
1822
#-------------------------------------------------------------------------------
1823
# Function        : BuildPkgArchive
1824
#
1825
# Description     : Include an external package into the build sandbox
1826
#                   by copying the packages files into the interface directory
1827
#
1828
# Inputs          : package name
1829
#                   package version
1830
#
1831
sub BuildPkgArchive
1832
{
1833
    my( $name, $version ) = @_;
1834
 
1835
    return if ( $Clobber );                     # clobber mode ?
1836
 
1837
    Debug( "BuildPkgArchive:" );
1838
    Debug( "Name:      $name" );
1839
    Debug( "Version:   $version" );
1840
 
1841
    DataDirective("BuildPkgArchive");           # This directive allowed here
1842
 
1843
    #
1844
    #   Ensure that we have do not have multiple definitions
1845
    #
1846
    if ( PackageEntry::Exists( $name, $version ) )
1847
    {
1848
        Log( "Duplicate Package: $name, $version. Duplicate entry ignored\n" );
1849
        return;
1850
    }
1851
 
1852
    if ( $Cache && $::GBE_DPKG_CACHE )
1853
    {
1854
        my $mode = ($Cache > 1) ? "-refresh" : "";
1855
        Log( "BuildPkgArchive . $name ($version) Update Cache\n" );
1856
        System('--NoExit', "$::GBE_PERL $::GBE_TOOLS/cache_dpkg.pl $mode -quiet $name/$version" );
1857
    }
1858
 
1859
    #
1860
    #   Locate the package
1861
    #   Use the first instance of the package that it found
1862
    #
1863
    Log( "BuildPkgArchive . $name ($version)\n" );
1864
    my ( $pkg, $local ) = PackageLocate( $name, $version );
1865
    if ( $pkg )
1866
    {
1867
        #
1868
        #   Create a Package Entry
1869
        #
1870
        my $entry = PackageEntry::New( $pkg, $name, $version, 0, 'build' );
1871
 
1872
        #
1873
        #   Determine if the package needs to be installed:
1874
        #       If the package is a 'local' package then force transfer
1875
        #       If the user has specified --cache then force transfer
1876
        #       If package is newer that copy, then force transfer
1877
        #       If copy does not exist, then force a transfer
1878
        #
1879
        my $tag_dir = "$Cwd/$BUILDINTERFACE/BuildTags";
1880
        my $tag_file = "$tag_dir/${name}_${version}.tag";
1881
 
1882
        my $package_installed;
1883
        $package_installed = 1
1884
            if ( !$local &&
1885
                 !$Cache &&
1886
                 !FileIsNewer( $entry->GetBaseDir('descpkg'), $tag_file ) );
1887
 
1888
        #
1889
        #   Determine the package format and use the appropriate installer
1890
        #   Supported formats
1891
        #       1) Package has a descpkg file (new style)
1892
        #       2) Package has a InstallPkg.sh file (old style)
1893
        #       3) Package has a Install.sh file (old style is it used ??)
1894
        #
1895
        if ( $package_installed ) {
1896
            Verbose ("Package already installed: $name, $version");
1897
 
1898
        } else {
1899
            Log( "                . installing '$pkg'\n" );
1900
            Log( "                . -> " . readlink($pkg) . "\n" ) if ( -l $pkg );
1901
 
1902
            if ( -e "$pkg/descpkg" )
1903
            {
1904
 
1905
                #
1906
                #   If forcing a BuildPkg, then don't use symlinks
1907
                #   to files in dpkg_archive
1908
                #
1909
                my $opts = "";
1910
                $opts = "--NoSymlinks" if ( $ForceBuildPkg );
1911
 
1912
                #
1913
                #   Determine all the Platforms, Products and Targets
1914
                #   that need to be installed
1915
                #
1916
                my $arglist = GenerateInstallArgumentList();
1917
                System( "cd $pkg; $::GBE_PERL $::GBE_TOOLS/installpkg.pl $Cwd/$BUILDINTERFACE $Cwd $opts $arglist");
1918
                Error( "Package installation error" ) if ( $? != 0 );
1919
            }
1920
            elsif ( -e "$pkg/InstallPkg.sh" )
1921
            {
1922
                System( "(cd $pkg; ./InstallPkg.sh $Cwd/$BUILDINTERFACE $Cwd)" );
1923
            }
1924
            elsif ( -e "$pkg/Install.sh" )
1925
            {
1926
                System( "(cd $pkg; ./Install.sh $Cwd/$BUILDINTERFACE $Cwd)" );
1927
            }
1928
            else
1929
            {
1930
                Error ("Unknown package format for package $name/$version found in $pkg");
1931
            }
1932
 
1933
            #
1934
            #   Tag the package as installed - after it has been transferred
1935
            #
1936
            mkdir ( $tag_dir );
1937
            TouchFile( $tag_file );
1938
        }
1939
 
1940
        #
1941
        #   Process package
1942
        #
1943
        IncludePkg ( $name, $pkg );
1944
 
1945
        #
1946
        #   Complete the creation of the package entry
1947
        #   Add the information for all platforms
1948
        #
1949
        $entry->Cleanup();
1950
        for my $platform (@BUILD_ACTIVEPLATFORMS)
1951
        {
1952
            $entry->ExamineToolPath();
1953
            $entry->ExamineThxPath($platform);
1954
            push ( @{$PKGRULES{$platform}}, $entry );
1955
        }
1956
    }
1957
}
1958
 
1959
#-------------------------------------------------------------------------------
1960
# Function        : GenerateInstallArgumentList
1961
#
1962
# Description     : Generate an argument list for the installpkg.pl script
1963
#                   The argument list is of the form
1964
#                       --Platform:xx[:xx[:xx]] --Platform:yy[:yy[:yy]] ...
1965
#                   Where xx is:
1966
#                       * a 'part' of the target platform
1967
#                         Order is: platform, product, ...  target( in that order )
1968
#                       * --Option[=yyy]
1969
#                        An option to be passed to the script. These are bound only
1970
#                        to the enclosed platform.
1971
# Inputs          :
1972
#
1973
# Returns         : See above
1974
#
1975
sub GenerateInstallArgumentList
1976
{
1977
    my @arglist;
1978
 
1979
    #
1980
    #   Generate the argument list as an array
1981
    #
1982
    for (@BUILD_ACTIVEPLATFORMS)
1983
    {
1984
        my @args = '--Platform';
1985
        push @args, @{$BUILDINFO{$_}{PARTS}};
1986
        push @arglist, join (":" , @args );
1987
    }
1988
 
1989
    return "@arglist";
1990
}
1991
 
1992
#-------------------------------------------------------------------------------
1993
# Function        : GeneratePlatformList
1994
#
1995
# Description     : Return a list of platforms that should particiate in this
1996
#                   build. This is a function of
1997
#                       1) Platforms defined in the build.pl file
1998
#                       2) User filter defined in GBE_BUILDFILTER
1999
#
2000
#                   The primary use of this function is to limit the creation
2001
#                   of makefiles to those that have supported compilers on
2002
#                   the underlying machine.
2003
#
2004
#                   GBE_BUILDFILTER is a space seperated string of words
2005
#                   Each word may be one of
2006
#                       OPTION=TAG or OPTION=!TAG
2007
#                       TAG or !TAG. This is the same as --TARGET=TAG
2008
#
2009
#                   Bare tags are taken to be TARGETS.
2010
#
2011
#                   Where OPTION may be one of
2012
#                       --PLATFORM
2013
#                       --PRODUCT
2014
#                       --TARGET
2015
#
2016
#                   Special cases
2017
#                   1) If GBE_BUILDFILTER is empty, then all available platforms are used
2018
#                      The global $All is set, then all available platforms are used
2019
#                   2) If the first word of GBE_BUILDFILTER is a negative filter,
2020
#                      ie is used the !xxxx or yyy=!xxxx construct, then it is assumed
2021
#                      that the filter will start with all available platforms
2022
#                   3) The special word --ALL forces selection of ALL platforms
2023
#                      and may reset any existing scanning
2024
#                   4) GBE_BUILDFILTER is parsed left to right. It is possible to add and
2025
#                      subtract items from the list.
2026
#                   5) OPTIONS are case insensitive
2027
#                      TAGS are case sensitive
2028
#
2029
#
2030
# Inputs          : GBE_BUILDFILTER from the environment
2031
#
2032
# Returns         : An array of platforms to include in the build
2033
#                   Maintains @BUILD_ACTIVEPLATFORMS  - the last calculated result
2034
#                   Ensures that @DEFBUILDPLATFORMS is a subset of @BUILD_ACTIVEPLATFORMS
2035
#
2036
sub GeneratePlatformList
2037
{
2038
    #
2039
    #   Return the cached result for speed
2040
    #   The value need only be calculated once
2041
    #
2042
    unless ( defined @BUILD_ACTIVEPLATFORMS )
2043
    {
2044
        my ($platform_filter);
2045
        my %result;
2046
        my %part_to_platform;
2047
 
2048
        #
2049
        #   Create a data structure to assist in the production of the platform list
2050
        #   The structure will be a hash of hashes of arrays
2051
        #
2052
        #   The first level hash will be keyed by the word TARGET, PRODUCT or PLATFORM
2053
        #   The second level of the hash will keyed by available targets, products or platforms
2054
        #   The value of the field will be an array of platforms that match the keyword
2055
        #
2056
        for my $platform (keys (%::BUILDINFO))
2057
        {
2058
            my $pParts = $::BUILDINFO{$platform};
2059
 
2060
            #
2061
            #   Skip platforms that are known to be unavailable on this build
2062
            #   machine. Self configure
2063
            #
2064
            next if ( $pParts->{NOT_AVAILABLE} );
2065
 
2066
            my $target  = $pParts->{TARGET};
2067
            my $product = $pParts->{PRODUCT};
2068
 
2069
            push @{$part_to_platform{'PLATFORM'}{$platform}}, $platform;
2070
            push @{$part_to_platform{'TARGET'}  {$target}}  , $platform;
2071
            push @{$part_to_platform{'PRODUCT'} {$product}} , $platform;
2072
        }
2073
        #
2074
        #   Determine the source of the filter
2075
        #   If the user provides one, then use it.
2076
        #   Otherwise its taken from the environment.
2077
        #
2078
        #   Global build all platforms - Kill any user filter
2079
        #
2080
        if ( $All )
2081
        {
2082
            $platform_filter = "";
2083
        }
2084
        else
2085
        {
2086
            $platform_filter = "";
2087
            $platform_filter = $::GBE_BUILDFILTER
2088
                if ( defined($::GBE_BUILDFILTER) );
2089
        }
2090
        Debug( "GeneratePlatformList: Filter:$platform_filter" );
2091
 
2092
        #
2093
        #   Detect the special cases
2094
        #       1) No user definition - assume all platforms
2095
        #       2) First word contains a subtractive element
2096
        #
2097
        my (@filter) = split( ' ', $platform_filter );
2098
 
2099
        if ( !scalar @filter || $filter[0] =~ m/^$/ || $filter[0] =~ m/!/ )
2100
        {
2101
            %result = %{$part_to_platform{'PLATFORM'}}
2102
                if exists $part_to_platform{'PLATFORM'} ;
2103
        }
2104
#DebugDumpData( "PartToPlatform", \%part_to_platform );
2105
 
2106
        #
2107
        #   Process each element in the user filter list
2108
        #   Expand platforms into known aliases
2109
        #
2110
        for my $word (@filter)
2111
        {
2112
            my $platform;
2113
            my $hash_name;
2114
 
2115
            if ( $word =~ m/^--ALL/i )
2116
            {
2117
                %result = %{$part_to_platform{'PLATFORM'}};
2118
            }
2119
            elsif ( $word =~ m/^--(TARGET)=(!?)(.*)/i ||
2120
                    $word =~ m/^--(PRODUCT)=(!?)(.*)/i ||
2121
                    $word =~ m/^--(PLATFORM)=(!?)(.*)/i ||
2122
                    ( $word !~ m/^-/ && $word =~ m/()(!?)(.*)/ )
2123
                )
2124
            {
2125
                my $table = uc($1);
2126
                $table = "TARGET"
2127
                    unless ( $1 );
2128
 
2129
                #
2130
                #   Expand PLATFORMs into known aliases
2131
                #   Alias will expand to PLATFORMs so it won't work unless we are
2132
                #   processing PALTFORMs.
2133
                #
2134
                my @taglist = ( $table eq "PLATFORM" ) ? ExpandPlatforms($3) : $3;
2135
 
2136
                #
2137
                #   Add / Remove items from the result
2138
                #
2139
                for my $item ( @taglist )
2140
                {
2141
                    my $plist = $part_to_platform{$table}{$item};
2142
                    for ( @{$plist})
2143
                    {
2144
                        if ( $2 )
2145
                        {
2146
                            delete $result{$_};
2147
                        }
2148
                        else
2149
                        {
2150
                            $result{$_} = 1;
2151
                        }
2152
                    }
2153
                }
2154
            }
2155
            else
2156
            {
2157
                print "GBE_BUILDFILTER filter term not understood: $word\n";
2158
            }
2159
        }
2160
 
2161
        #
2162
        #   Return an array of platforms to process
2163
        #
2164
        @BUILD_ACTIVEPLATFORMS = sort keys %result;
2165
 
2166
        #
2167
        #   Ensure that DEFBUILDPLATFORMS is a subset of build active platforms
2168
        #
2169
        my @NEW_DEFBUILDPLATFORMS;
2170
        foreach ( @DEFBUILDPLATFORMS )
2171
        {
2172
            push @NEW_DEFBUILDPLATFORMS, $_
2173
                if ( exists $result{$_} );
2174
        }
2175
        @DEFBUILDPLATFORMS = @NEW_DEFBUILDPLATFORMS;
2176
    }
2177
 
2178
    Debug("GeneratePlatformList: Result:@BUILD_ACTIVEPLATFORMS");
2179
    return @BUILD_ACTIVEPLATFORMS;
2180
}
2181
 
2182
#-------------------------------------------------------------------------------
2183
# Function        : PrintPlatforms
2184
#
2185
# Description     : Petty print the specified platform list, breaking line
2186
#                   on either a primary key change or length width >78.
2187
#
2188
# Returns         : Formated string
2189
#
2190
# Example Output :
2191
#
2192
#           DDU_LMOS_WIN32 DDU_LMOS_linux_armv4 DDU_LMOS_linux_i386
2193
#           IDFC_LMOS_WIN32 IDFC_LMOS_linux_armv4 IDFC_LMOS_linux_i386
2194
#           LMOS_WCEPSPC_ARM LMOS_WCEPSPC_EMU LMOS_WIN32 LMOS_linux_armv4
2195
#           LMOS_linux_i386
2196
#..
2197
sub PrintPlatforms
2198
{
2199
    my ($platforms, $nl) = @_;
2200
    my ($string) = "";                          # result
2201
 
2202
    if ( defined(@$platforms) )
2203
    {
2204
        my ($key_run) = 0;
2205
        my ($pkey);                             # previous key
2206
 
2207
        #   Perform a simple formatting and determine if there is key 
2208
        #   change greater then 1 or whether the total length exceeds 78.
2209
        #
2210
        #   If the line exceeds 78, the printer shall then reformat 
2211
        #   breaking based on line length and possiblity keys.
2212
        #
2213
        $pkey = "";
2214
        for my $k (sort @$platforms) 
2215
        {
2216
            my ($d);                            # delimitor
2217
 
2218
            if (($d = index( $k, '_' )) != index( $pkey, '_' ) ||
2219
                    substr( $k, 0, $d ) ne substr( $pkey, 0, $d )) {
2220
                $key_run = 1
2221
                    if ($key_run <= 1);         # change, reset run if <= 1
2222
            } else {
2223
                $key_run++;                     # same primary key
2224
            }
2225
 
2226
            $string .= " " if ($pkey);
2227
            $string .= $k;
2228
            $pkey = $k;
2229
        }
2230
 
2231
        #   Reprint if required.
2232
        #
2233
        if (length($nl)+length($string) > 78)
2234
        {
2235
            my ($llen);                         # line length
2236
 
2237
            $llen = length($nl);
2238
 
2239
            $pkey = "";
2240
            $string = "";
2241
 
2242
            for my $k (sort @$platforms)
2243
            {
2244
                my ($klen, $d);                 # key length, delimitor
2245
 
2246
                $klen = length($k);
2247
                if ($pkey ne "")
2248
                {
2249
                    if ($llen + $klen > 78 ||
2250
                        ($key_run > 1 && (
2251
                            ($d = index( $k, '_' )) != index( $pkey, '_' ) ||
2252
                            substr( $k, 0, $d ) ne substr( $pkey, 0, $d ) )) )
2253
                    {                           # line >70 or key change
2254
                        $string .= $nl;
2255
                        $llen = length($nl);
2256
                    }
2257
                    else
2258
                    {
2259
                        $string .= " ";
2260
                        $llen++;
2261
                    }
2262
                }
2263
                $string .= $k;
2264
                $pkey = $k;
2265
                $llen += $klen;
2266
            }
2267
        }    
2268
    }
2269
    return $string;
2270
}
2271
 
2272
 
2273
sub BuildReleaseFile
2274
{
2275
    my ( $BuildFilename, $BuildDir ) = @_;
2276
    my ( $SnapDir );
2277
 
2278
    # Check if archive requested...
2279
    #
2280
    return unless ( $CmdSwitch eq "archive" );
2281
 
2282
    # Build the release archive file...
2283
    #
2284
    $SnapDir = "$ENV{ \"GBE_SNAPSHOT_DIR\" }/";
2285
    $SnapDir = "" unless ($SnapDir ne "/");
2286
 
2287
    Log( "Creating release archive: $SnapDir$BuildFilename.tgz of $Cwd/$BuildDir/\n" );
2288
 
2289
    # GNU tar and zip the build directory NOT following links...
2290
    #
2291
    System( "$::GBE_BIN/tar czf $SnapDir$BuildFilename.tgz $BuildDir" );
2292
 
2293
    Error( "To extract use: $::GBE_BIN/tar xvzf $BuildFilename.tgz" );
2294
}
2295
 
2296
 
2297
sub BuildSnapshot
2298
{
2299
}
2300
 
2301
 
2302
#.. Check if access/permissions setting requested...
2303
#
2304
sub BuildAccessPerms
2305
{
2306
    my( $PermsFilename );
2307
 
2308
    return unless ( $CmdSwitch eq "perms" );
2309
 
2310
    # Set the build access permissions from the shell script...
2311
    $PermsFilename = $CmdParm;
2312
    if ( -e $PermsFilename )
2313
    {
2314
        Log( "Setting build access permissions from $PermsFilename...\n" );
2315
        System( "su root -c \"sh $PermsFilename\"" );
2316
    }
2317
    else
2318
    {
2319
        Log( "ERROR: Could not find file to set the access permissions: $PermsFilename\n" );
2320
    }
2321
    die "\n";
2322
}
2323
 
2324
 
2325
sub BuildSetenv
2326
{
2327
    push( @BUILDSETENV, @_ );
2328
}
2329
 
2330
#-------------------------------------------------------------------------------
2331
# Function        : DataDirective
2332
#
2333
# Description     : Called by data collection directives to ensure that we are
2334
#                   still collecting data and that we have collected other data
2335
#
2336
# Inputs          : $dname              - Directive Name
2337
#
2338
# Returns         : Will error if we are not
2339
#
2340
sub DataDirective
2341
{
2342
    my ($dname) = @_;
2343
 
2344
    Error( "$dname() must appear after BuildName()...")
2345
        if ( $BUILDNAME eq "" );
2346
 
2347
    Error( "$dname() must appear after BuildInterface()...")
2348
        unless( $BUILDINTERFACE );
2349
 
2350
    Error( "$dname() not allowed after BuildDescpkg, BuildIncpkg, BuildVersion or BuildMake")
2351
        if( $BUILDPHASE);
2352
}
2353
 
2354
#-------------------------------------------------------------------------------
2355
# Function        : StartBuildPhase
2356
#
2357
# Description     : Called by directives that deal with the building phases
2358
#                   to perform common initialisation and to ensure that
2359
#                   directives that collect data are no longer called
2360
#
2361
# Inputs          : None
2362
#
2363
# Returns         : May generate an error
2364
#
2365
sub StartBuildPhase
2366
{
2367
    #
2368
    #   Only do it once
2369
    #
2370
    return if ( $BUILDPHASE++  );
2371
 
2372
    #
2373
    #   Calcuate the aliases that are being extracted from targets
2374
    #
2375
    Process_TargetAlias();
2376
 
2377
    #
2378
    #   Sanity test the users packages
2379
    #
2380
    PackageEntry::SanityTest() unless $Clobber;
2381
 
2382
    #
2383
    #   Validate the $Srcdir before its first real use
2384
    #   This is calculated from the user directives
2385
    #
2386
 
2387
    #.. Determine default "source" root
2388
    #
2389
    if ( $Srcdir eq "" )
2390
    {
2391
        Warning( "Both the directories 'src' and 'SRC' exist ....." )
2392
            if ( $ScmHost eq "Unix" && -e "src" && -e "SRC" );
2393
 
2394
        if ( -e "src" ) {
2395
            $Srcdir = "src";
2396
        } else {
2397
            ( -e "SRC" ) ||
2398
                Error( "Neither the directory 'src' nor 'SRC' exist ....." );
2399
            $Srcdir = "SRC";
2400
        }
2401
    }
2402
 
2403
    #
2404
    #   Must have a valid Srcdir
2405
    #
2406
    Error ("Source directory not found: $Srcdir")
2407
        unless ( $Srcdir && -d $Srcdir );
2408
 
2409
    return $Srcdir;
2410
}
2411
 
2412
#-------------------------------------------------------------------------------
2413
# Function        : BuildPackageLink
2414
#
2415
# Description     : Create a soft link from sandbox_dpkg_archive to the package
2416
#                   being created by this build
2417
#
2418
#                   For backward compatability.
2419
#                   If GBE_DPKG_SBOX is not defined, then use GBE_DPKG_LOCAL
2420
#
2421
#                   This will allow multiple components to work together
2422
#
2423
#                   Note: When called in Clobber-mode the link will be deleted
2424
#
2425
# Inputs          : $BUILDNAME              - The package name
2426
#                   $BUILDNAME_PROJECT      - Project extension
2427
#                   $::GBE_DPKG_SBOX        - Path of sandbox_dpkg_archive
2428
#                   $::GBE_DPKG_LOCAL       - Path of local_dpkg_archive
2429
#                   $::GBE_DPKG             - Main repository
2430
#
2431
# Returns         : Nothing
2432
#
2433
sub BuildPackageLink
2434
{
2435
    my $target_archive;
2436
    my $target_archive_name;
2437
    my $link_file;
2438
    my $tag;
2439
 
2440
    #
2441
    #   Determine the path (and name) of the target archive
2442
    #   Use sandbox_dpkg_archive if it exists
2443
    #   Use local_dpkg_acrhive for backward compatability (should be removed after JATS 2.64.2+)
2444
    #
2445
    if ( $target_archive = $::GBE_DPKG_SBOX )
2446
    {
2447
        $target_archive_name = "sandbox_dpkg_archive";
2448
        $tag = "Sandbox";
2449
 
2450
        $link_file  = 'sandbox';
2451
        $link_file .= '.' . $BUILDNAME_PROJECT if ( $BUILDNAME_PROJECT );
2452
        $link_file .= '.lnk';
2453
    }
2454
    elsif ( $target_archive = $::GBE_DPKG_LOCAL )
2455
    {
2456
        $target_archive_name = "local_dpkg_archive";
2457
        $link_file = "$BUILDVERSION.lnk";
2458
        $tag = "Local";
2459
    }
2460
    else
2461
    {
2462
        Verbose("Cannot locate local or sandbox archive")
2463
            unless $Clobber;
2464
        return;
2465
    }
2466
 
2467
    #
2468
    #   Santity test
2469
    #   Target must be a directory
2470
    #
2471
    unless ( -d $target_archive )
2472
    {
2473
        Warning("$target_archive_name is not a dirertory: $target_archive")
2474
            unless $Clobber;
2475
        return;
2476
    }
2477
 
2478
    my $link_dir = "$target_archive/$BUILDNAME_PACKAGE";
2479
    my $link_path = "$link_dir/$link_file";
2480
 
2481
    if ( $Clobber )
2482
    {
2483
        unlink $link_path;          # Delete the link
2484
        rmdir $link_dir;            # Delete only if empty
2485
    }
2486
    else
2487
    {
2488
        Log( "Local Link . $BUILDNAME_PACKAGE/$link_file ($tag)\n");
2489
        unlink $link_path;
2490
        mkdir $link_dir;
2491
        open  LNK,">$link_path" || Error( "Cannot open: $link_path" );
2492
        print LNK "$Cwd/pkg/$BUILDNAME_PACKAGE\n";
2493
        close LNK;
2494
    }
2495
}
2496
 
2497
#-------------------------------------------------------------------------------
2498
# Function        : BuildSandboxData
2499
#
2500
# Description     : Create data structures to allow this package to be built
2501
#                   within a multi-package sandbox.
2502
#
2503
#                   This will allow multiple components to work together
2504
#
2505
#                   Note: When called in Clobber-mode the link will be deleted
2506
#
2507
# Inputs          : $BUILDNAME              - The package name
2508
#                   $BUILDNAME_PROJECT      - Project extension
2509
#                   $::GBE_DPKG_SBOX        - Path of sandbox_dpkg_archive
2510
#                   $::GBE_DPKG             - Main repository
2511
#
2512
# Returns         : Nothing
2513
#
2514
sub BuildSandboxData
2515
{
2516
    my $sandbox_dpkg_archive = $::GBE_DPKG_SBOX;
2517
    return unless ( $sandbox_dpkg_archive );
2518
 
2519
    unless ( -d $sandbox_dpkg_archive )
2520
    {
2521
        Error("sandbox_dpkg_archive is not a dirertory: $sandbox_dpkg_archive")
2522
            unless $Clobber;
2523
        return;
2524
    }
2525
 
2526
    #
2527
    #   Create a name for this package in the sandbox
2528
    #   Must use the package name and extension. Don't use the version
2529
    #   information as this will not be correct
2530
    #
2531
    #   PACKAGE/sandbox.PRJ.cfg
2532
    #
2533
    my $link_dir = "$sandbox_dpkg_archive/$BUILDNAME_PACKAGE";
2534
    my $link_file = 'sandbox';
2535
       $link_file .= '.' . $BUILDNAME_PROJECT if ( $BUILDNAME_PROJECT );
2536
       $link_file .= '.cfg';
2537
    my $link_path = "$link_dir/$link_file";
2538
 
2539
    if ( $Clobber )
2540
    {
2541
        unlink $link_path;          # Delete the link
2542
        rmdir $link_dir;            # Delete only if empty
2543
    }
2544
    else
2545
    {
2546
        Log( "Sandbox cfg. $link_file\n");
2547
        unlink $link_path;
2548
        mkdir $link_dir;
2549
 
2550
        #
2551
        #   Create the sandbox config data structure
2552
        #
2553
        my %sandbox_info = (
2554
            BUILDDIR     => $Cwd,
2555
            INTERFACEDIR => $BUILDINTERFACE,
2556
            );
2557
 
2558
        #
2559
        #   Write out the Parsed Config File with new information
2560
        #
2561
        my $fh = ConfigurationFile::New( $link_path );
2562
        $fh->Header( "buildlib (version $::BuildVersion)",
2563
                                  "Sandbox configuration" );
2564
 
2565
        #
2566
        #   Dump out the configuration information
2567
        #
2568
        $fh->Dump( [\%sandbox_info], [qw(*sandbox_info)] );
2569
        $fh->Close();
2570
    }
2571
}
2572
 
2573
 
2574
#-------------------------------------------------------------------------------
2575
# Function        : BuildMake
2576
#
2577
# Description     : Generate the makefiles
2578
#                   This directive MUST be the last directive in the build.pl
2579
#                   file. The directive triggers the processing of all the
2580
#                   information that has been collected
2581
#
2582
#
2583
# Inputs          : None
2584
#
2585
# Returns         : Nothing
2586
#
2587
 
2588
sub BuildMake
2589
{
2590
    my( $argc, $platform );
2591
 
2592
    #
2593
    #   Must have a valid $BUILDINTERFACE
2594
    #   Normally this is held in the interface directory, but this is not
2595
    #   always created. If there is no $BUILDINTERFACE, then use the
2596
    #   build directory
2597
    #
2598
    $BUILDINTERFACE = "." unless ( $BUILDINTERFACE );
2599
 
2600
    #.. Starting the build phase. No more data collection
2601
    #
2602
        StartBuildPhase();
2603
 
2604
    sub DeleteCfg
2605
    {
2606
        #
2607
        #   Delete files that will be re-created
2608
        #   Some of these files are read and written.
2609
        #   Errors in the files are solved by deleting the files now.
2610
        #
2611
        unlink "$BUILDINTERFACE/build.cfg";
2612
        unlink "$BUILDINTERFACE/Makefile.cfg";
2613
        unlink glob ("$BUILDINTERFACE/Makefile*.cfg");
2614
        unlink "$BUILDINTERFACE/Buildfile.cfg";
2615
        unlink "$BUILDINTERFACE/Dpackage.cfg";
2616
    }
2617
 
2618
    if ( $Clobber )                             # clobber mode ?
2619
    {
2620
        if ( -e "Makefile.gbe" )
2621
        {
2622
            JatsCmd ( 'jmake', 'unmakefiles');
2623
            unlink "Makefile.gbe";
2624
        }
2625
 
2626
        DeleteCfg();
2627
 
2628
        #
2629
        #   JATS creates a 'pkg' directory for the target package
2630
        #
2631
        push @CLOBBERDIRS, "pkg";
2632
 
2633
        #
2634
        #   Deployment creates a 'build/deploy' directory
2635
        #
2636
        push @CLOBBERDIRS, "build/deploy";
2637
 
2638
        #
2639
        #   Delete interface directories and other directories that have been
2640
        #   marked to be clobberd
2641
        #
2642
        foreach my $dir ( @CLOBBERDIRS )
2643
        {
2644
            next if ( $dir eq '.' );
2645
            next if ( $dir eq '..' );
2646
            if ( -d $dir )
2647
            {
2648
                System( "$::GBE_BIN/chmod -fR +w $dir" );
2649
                System( "$::GBE_BIN/rm -rf $dir" );
2650
            }
2651
        }
2652
 
2653
        foreach my $file ( @CLOBBERFILES )
2654
        {
2655
            if ( -f $file )
2656
            {
2657
                System( "$::GBE_BIN/chmod -fR +w $file" );
2658
                System( "$::GBE_BIN/rm -f $file" );
2659
            }
2660
        }
2661
 
2662
        #
2663
        #   DPACKAGE may be a user file, Only delete it if we created it
2664
        #
2665
        unlink "$Srcdir/DPACKAGE" if $DeleteDPACKAGE;
2666
 
2667
        BuildPackageLink();
2668
        BuildSandboxData();
2669
        return;
2670
    }
2671
 
2672
    #.. Build support files
2673
    #
2674
    DeleteCfg();
2675
    BuildConfig();
2676
    BuildRuleFiles();
2677
    BuildSharedLibFiles();
2678
    LinkClean();                                # clean previous images
2679
    WriteParsedBuildConfig();
2680
    BuildPackageLink();
2681
    BuildSandboxData();
2682
 
2683
    #
2684
    #  ONLY (re)building interface dir
2685
    #
2686
    return
2687
        if ( $Interface );
2688
 
2689
    #---------------------------------------------------------------------------
2690
    #
2691
    #.. Make bootstrap "makefile",
2692
    #   Simulate a top level makefile
2693
    #       Pass argumenst to makelib
2694
    #       Sumulate SubDir() operations
2695
    #       Sumulate a Platform(*);
2696
    #
2697
    #       Due to the normal way that makelib.pl is executed,
2698
    #       the following substitutions are done.
2699
    #
2700
    @ARGV = ();
2701
    $0 = "makefile.pl ";
2702
    push @ARGV, "$Cwd";                         # current working directory
2703
    push @ARGV, "$::MAKELIB_PL";                # makelib.pl image
2704
 
2705
    push @ARGV, "-D1"                           # debug
2706
        if ($::ScmDebug);
2707
 
2708
    push @ARGV, "-V"                            # verbose
2709
        if ($::ScmVerbose);
2710
 
2711
    push @ARGV, "--expert"                      # expert mode
2712
        if ($Expert);
2713
                                                # interface
2714
    push @ARGV, "--interface=$BUILDINTERFACE"
2715
        if ($BUILDINTERFACE ne "");
2716
 
2717
    push @ARGV, "--all"                         # build all platforms
2718
        if ($All);
2719
 
2720
    Debug( "ARGV:      @ARGV" );
2721
 
2722
    #.. (re)Build root makefile
2723
    #
2724
    $ScmBuildlib = 0;                           # clear Buildlib flag for 'makelib.pl'
2725
    RootMakefile();                             # inform 'makelib.pl'
2726
    MakeLibInit();                              # run initialisation
2727
 
2728
 
2729
    #.. Register subdir(s)
2730
    #
2731
    UniquePush (\@BUILDSUBDIRS, $Srcdir );
2732
    SubDir( @BUILDSUBDIRS );
2733
    Platform( @BUILD_ACTIVEPLATFORMS );
2734
 
2735
    #.. (re)build src makefiles and associated information
2736
    #
2737
    my @cmds = ('jmake', 'rebuild');
2738
    push @cmds, 'NORECURSE=1' if ( $RootOnly );
2739
 
2740
    JatsCmd ( @cmds);
2741
}
2742
 
2743
 
2744
#-------------------------------------------------------------------------------
2745
# Function        : BuildVersion
2746
#
2747
# Description     : Generate version.c and version.h files
2748
#
2749
# Inputs          : Options
2750
#                       --Prefix=prefix         Text prepended to variables created
2751
#                                               as a part of the "C" versions
2752
#                       --Type=type             Type of "C" style data
2753
#                                               Allowed types are: array
2754
#                       --Defs=name             Generate a "C" definitions file.
2755
#                                               This file simply contains definitions
2756
#                       --Defs                  Same as --Defs=defs
2757
#                       --Style=style           Output file style
2758
#                                               Supported styles:
2759
#                                                   "C" - Default
2760
#                                                   "CSharp"
2761
#                                                   "WinRC"
2762
#                       --File=name             Specifies the output file name
2763
#                                               Default is determined by the style
2764
#
2765
#                   Also allows for an 'old' style format in which
2766
#                   the first three arguments are prefix,type and defs
2767
# Returns         :
2768
#
2769
 
2770
sub BuildVersion
2771
{
2772
    my ( $Prefix, $Type, $Mode ) = @_;
2773
    my $ModePrefix;
2774
    my $Style = "C";
2775
    my $FileName;
2776
    my $VersionFiles;
2777
 
2778
    StartBuildPhase();                          # Starting the build phase. No more data collection
2779
 
2780
    if ( defined($Prefix) && $Prefix =~ /^--/ )
2781
    {
2782
        $Prefix = undef;
2783
        $Type = undef;
2784
        $Mode = undef;
2785
        foreach  ( @_ )
2786
        {
2787
            if (      /^--Prefix=(.*)/ ) {
2788
                $Prefix = $1;
2789
                $VersionFiles = 1;
2790
 
2791
            } elsif ( /^--Type=(.*)/ ) {
2792
                $Type = $1;
2793
                $VersionFiles = 1;
2794
 
2795
            } elsif ( /^--Defs=(.*)/ ) {
2796
                $Mode = $1;
2797
                $ModePrefix = "_$1";
2798
 
2799
            } elsif ( /^--Defs$/ ) {
2800
                $Mode = 'defs';
2801
                $ModePrefix = "";
2802
 
2803
            } elsif ( /^--Style=(.*)/ ) {
2804
                $Style = $1;
2805
 
2806
            } elsif ( /^--File=(.*)/ ) {
2807
                $FileName = $1;
2808
 
2809
            } else {
2810
                Error ("BuildVersion: Unknown option: $_");
2811
 
2812
            }
2813
        }
2814
    }
2815
    else
2816
    {
2817
        #
2818
        #   Old style positional arguments.
2819
        #
2820
        $VersionFiles = 1;
2821
        if ( defined( $Mode ) )
2822
        {
2823
            if ( $Mode =~ m/^defs(=(.*))?$/i )
2824
            {
2825
                $Mode       = $2 ? $2    : 'defs';
2826
                $ModePrefix = $2 ? "_$2" : "";
2827
            }
2828
            else
2829
            {
2830
                Error ("BuildVersion: Bad Mode argument. Need 'defs' or 'defs=name'");
2831
            }
2832
        }
2833
    }
2834
 
2835
    #
2836
    #   Determine the style of version file to create
2837
    #
2838
    if ( $Style =~ /^CSharp/i ) {
2839
        BuildVersionCSharp( $FileName );
2840
 
229 dpurdie 2841
    } elsif ( $Style =~ /^Properties/i ) {
2842
        BuildVersionProperties( $FileName, $Prefix );
2843
 
227 dpurdie 2844
    } elsif ( $Style =~ /^WinRC/i ) {
2845
        BuildVersionWinRC( $FileName );
2846
 
2847
    } elsif ( $Style eq "C" ) {
2848
        BuildVersionC    ( $Prefix, $Type )     if ( $VersionFiles );
2849
        BuildVersionCdefs( $Mode, $ModePrefix ) if ( $Mode );
2850
 
2851
    } else {
2852
        Error("BuildVersion: Unknown style: $Style");
2853
    }
2854
}
2855
 
2856
#-------------------------------------------------------------------------------
2857
# Function        : BuildDescpkg
2858
#
2859
# Description     : Create a package description file
2860
#                   The format of this file matches that generated by JANTS
2861
#                   Take care when extending the format
2862
#
2863
#                   NOTE: It turns out that JANTS is not a standard and the
2864
#                         implementors (of JANTS) kept on changing it.
2865
#
2866
# Inputs          :
2867
#
2868
# Returns         :
2869
#
2870
sub BuildDescpkg
2871
{
2872
    StartBuildPhase();                          # Starting the build phase. No more data collection
2873
 
2874
    my $pkgfile = "$Srcdir/descpkg";
2875
    if ( $Clobber )                             # clobber mode ?
2876
    {
2877
        System( "$::GBE_BIN/rm -f $pkgfile" );
2878
        return;
2879
    }
2880
 
2881
    open( DESCPKG, ">$pkgfile" ) ||
2882
        Error( "cannot create $pkgfile" );
2883
 
2884
    print DESCPKG "Package Name: $BUILDNAME_PACKAGE\n";
2885
    print DESCPKG "Version:      $BUILDVERSION\n";
2886
    print DESCPKG "Released By:  $::USER\n";
2887
    print DESCPKG "Released On:  $::CurrentTime\n";
2888
    print DESCPKG "Path:         $Cwd\n";
2889
    print DESCPKG "Jats Version: $::GBE_VERSION\n";
2890
    print DESCPKG "Jats Path:    $::GBE_CORE\n";
2891
    print DESCPKG "\n";
2892
    print DESCPKG "Build Dependencies:\n";
2893
    print DESCPKG "\n";
2894
 
2895
    foreach my $tag ( PackageEntry::GetPackageList )
2896
    {
2897
        my ($name, $version, $type) = PackageEntry::GetPackageData($tag);
2898
 
2899
        my @attributes;
2900
 
2901
        push @attributes, "name=\"$name\"";
2902
        push @attributes, "version=\"$version\"";
2903
        push @attributes, "build=\"true\"" if $type =~ /Build/i;
2904
 
2905
        print DESCPKG "<sandbox @attributes/>\n";
2906
    }
2907
    close DESCPKG;
2908
}
2909
 
2910
#-------------------------------------------------------------------------------
2911
# Function        : BuildIncpkg
2912
#
2913
# Description     : Create a package inclusion file
2914
#
2915
# Inputs          :
2916
#
2917
# Returns         :
2918
#
2919
sub BuildIncpkg
2920
{
2921
    StartBuildPhase();                          # Starting the build phase. No more data collection
2922
    if ( $Clobber )                             # clobber mode ?
2923
    {
2924
        System( "$::GBE_BIN/rm -f $Srcdir/incpkg" );
2925
        return;
2926
    }
2927
 
2928
    my $fh = ConfigurationFile::New( "$Srcdir/incpkg" );
2929
    $fh->Header( "buildlib (Version $BuildVersion)",
2930
                              "Package inclusion list" );
2931
 
2932
    foreach my $tag ( PackageEntry::GetPackageList )
2933
    {
2934
        my ($name, $version, $type) = PackageEntry::GetPackageData($tag);
2935
        $type = ($type =~ /build/i) ? "Build" : "Link";
2936
 
2937
        $fh->Write( "${type}PkgArchive( '$name', '$version' );\n" );
2938
    }
2939
 
2940
    $fh->Close();
2941
}
2942
 
2943
#-------------------------------------------------------------------------------
2944
# Function        : BuildConfig
2945
#
2946
# Description     : Create the file interface/build.cfg
2947
#                   This file contains information gathered by the build process
2948
#                   that is to be used when makefiles are created and re-created
2949
#
2950
# Inputs          : None
2951
#
2952
# Returns         : Nothing
2953
#
2954
sub BuildConfig()
2955
{
2956
    Error( "No BuildInterface directive encountered\n" )
2957
        unless ($BUILDINTERFACE);
2958
 
2959
    my $fh = ConfigurationFile::New( "$BUILDINTERFACE/build.cfg");
2960
    $fh->Header( "buildlib (Version $BuildVersion)",
2961
                              "Makelib configuration file", "
2962
\$ScmBuildMachType              = \"$::GBE_MACHTYPE\";
2963
\$ScmInterfaceVersion           = \"$::InterfaceVersion\";
2964
\$ScmBuildName                  = \"$BUILDNAME\";
2965
\$ScmBuildPackage               = \"$BUILDNAME_PACKAGE\";
2966
\$ScmBuildVersion               = \"$BUILDNAME_VERSION\";
2967
\$ScmBuildProject               = \"$BUILDNAME_PROJECT\";
2968
\$ScmBuildVersionFull           = \"$BUILDVERSION\";
2969
\$ScmBuildPreviousVersion       = \"$BUILDPREVIOUSVERSION\";
2970
\$ScmProjectSupport             = \"$Project\";
2971
\$ScmLocal                      = \"$BUILDLOCAL\";
2972
\$ScmDeploymentPatch            = \"$DEPLOY_PATCH\";
2973
\$ScmSrcDir                     = \"$Srcdir\";
2974
\$ScmBuildSrc                   = \"$ScmBuildSrc\";
2975
\$ScmExpert                     = \"$Expert\";
2976
");
2977
 
2978
#.. Alias
2979
#
2980
    $fh->DumpData(
2981
        "\n# Aliases.\n#\n",
2982
        "ScmBuildAliases", \%BUILDALIAS );
2983
 
2984
#.. Products
2985
#
2986
    $fh->DumpData(
2987
        "# Product mapping.\n#\n",
2988
        "ScmBuildProducts", \%BUILDPRODUCT_PARTS );
2989
 
2990
#.. Create ScmBuildPlatforms
2991
#
2992
    my( @platforms_merged, %platform_args ) = ();
2993
 
2994
    UniquePush ( \@platforms_merged, @BUILDPLATFORMS );
2995
 
2996
    foreach my $key ( keys %BUILDPRODUCT ) {
2997
        my( @list ) = split( ' ', $BUILDALIAS{ $key } || '' );
2998
        my( $platform );
2999
 
3000
        foreach my $elem ( @list ) {
3001
            if ( $elem =~ /^--/ ) {             # argument
3002
                HashJoin( \%platform_args, $;, $platform, $elem )
3003
                    if ( defined($platform) );
3004
                next;
3005
            }
3006
            $platform = $elem;                  # platform
3007
            UniquePush( \@platforms_merged, $elem );
3008
        }
3009
    }
3010
 
3011
#.. Create ScmBuildPlatforms
3012
#   Contains per platform options extracted from alias and platform args
3013
#
3014
    my %ScmBuildPlatforms;
3015
    foreach my $key ( @platforms_merged ) {
3016
 
3017
        my( @arguments ) = ();
3018
        UniquePush( \@arguments, split( /$;/, $BUILDPLATFORMARGS{ $key } ))
3019
            if ( exists $BUILDPLATFORMARGS{ $key } );
3020
 
3021
        UniquePush( \@arguments, split( /$;/, $platform_args{ $key } ))
3022
            if ( exists $platform_args{ $key } );
3023
 
3024
        $ScmBuildPlatforms{$key} = join "$;", @arguments;
3025
    }
3026
 
3027
    $fh->DumpData(
3028
        "# Platform and global argument list.\n#\n",
3029
        "ScmBuildPlatforms", \%ScmBuildPlatforms );
3030
 
3031
 
3032
# .. Create BuildPkgRules
3033
#
3034
#    This most of the information contained within %PKGRULES, which
3035
#    requires additional processing within makelib.
3036
#
3037
    my %ScmBuildPkgRules;
3038
    foreach my $platform ( keys %PKGRULES )
3039
    {
3040
        foreach my $package ( @{$PKGRULES{$platform}} )
3041
        {
3042
            my %entry;
3043
 
3044
            $entry{ROOT}     = $package->{'base'};
3045
            $entry{NAME}     = $package->{'name'};
3046
            $entry{VERSION}  = $package->{'version'};
3047
            $entry{DNAME}    = $package->{'dname'};
3048
            $entry{DVERSION} = $package->{'dversion'};
3049
            $entry{DPROJ}    = $package->{'dproj'};
3050
            $entry{TYPE}     = $package->{'type'};
3051
            $entry{CFGDIR}   = $package->{'cfgdir'} if ( defined( $package->{'cfgdir'} ) );
3052
 
3053
 
3054
            foreach my $dir (qw (PINCDIRS PLIBDIRS TOOLDIRS THXDIRS) )
3055
            {
3056
                $entry{$dir} = $package->{$dir} ;
3057
            }
3058
 
3059
            push @{$ScmBuildPkgRules{$platform}}, \%entry;
3060
        }
3061
    }
3062
 
3063
    $fh->DumpData(
3064
        "# Imported packages.\n#\n",
3065
        "ScmBuildPkgRules", \%ScmBuildPkgRules );
3066
 
3067
#
3068
#   BUILDPLATFORMS,
3069
#       The value that is saved only contains the active platforms
3070
#
3071
#   DEFBUILDPLATFORMS,
3072
#       The value that is matchs the wildcard specification for Platform 
3073
#       directives.
3074
#
3075
    $fh->DumpData(
3076
        "# A list of platforms active within the view.\n#\n",
3077
        "BUILDPLATFORMS", \@BUILD_ACTIVEPLATFORMS );
3078
 
3079
    $fh->DumpData(
3080
        "# A list of default platforms within the view.\n#\n",
3081
        "DEFBUILDPLATFORMS", \@DEFBUILDPLATFORMS );
3082
 
3083
#
3084
#   BUILDTOOLS
3085
#       A list of toolset extension paths
3086
#
3087
    $fh->DumpData(
3088
        "# A list of paths with toolset extension programs.\n#\n",
3089
        "BUILDTOOLSPATH", \@BUILDTOOLS );
3090
 
3091
#
3092
#   BUILDPLATFORM_PARTS
3093
#       A subset of BUILDINFO exported as BUILDPLATFORM_PARTS
3094
#       This exists only for backward compatability with existing code
3095
#       in external packages ( deployfiles).
3096
#
3097
#   Only save those parts that are part of the current build
3098
#   This will prevent users attempting to build for platforms that have not
3099
#   been correctly constructed.
3100
#
3101
    my %active =  map { ${_} => 1 } @BUILD_ACTIVEPLATFORMS;
3102
    my %active_buildplatform_parts;
3103
    my %active_build_info;
3104
    foreach ( keys %BUILDINFO )
3105
    {
3106
        next unless ( $active{$_} );
3107
        $active_buildplatform_parts{$_} = $BUILDINFO{$_}{PARTS};
3108
        $active_build_info{$_}          = $BUILDINFO{$_};
3109
    }
3110
 
3111
    $fh->DumpData(
3112
        "# Parts of all platforms.\n#\n",
3113
        "BUILDPLATFORM_PARTS", \%active_buildplatform_parts );
3114
#
3115
#   BUILDINFO
3116
#       Complete TARGET Information
3117
#
3118
    $fh->DumpData(
3119
        "# Extended build information.\n#\n",
3120
        "BUILDINFO", \%active_build_info );
3121
 
3122
 
3123
#
3124
#   Close out the file
3125
#
3126
    $fh->Close();
3127
}
3128
 
3129
#-------------------------------------------------------------------------------
3130
# Function        : WriteParsedBuildConfig
3131
#
3132
# Description     : Write all the parsed build.pl data to a single file
3133
#                   Its all in there for use
3134
#
3135
# Inputs          : 
3136
#
3137
# Returns         : 
3138
#
3139
sub WriteParsedBuildConfig
3140
{
3141
    my $cfg_file = "$::BUILDINTERFACE/Buildfile.cfg";
3142
    my %cf_build_info = ();
3143
 
3144
    #
3145
    #   Examine the symbol table and capture most of the entries
3146
    #
3147
    foreach my $symname (keys %main::)
3148
    {
3149
        next if ( $symname =~ m/::/  );                 # No Typeglobs
3150
        next if ( $symname =~ m/^cf_build_info/  );     # Not myself
3151
        next unless ( $symname =~ m/^[A-Za-z]/  );      # No system type names
3152
        next if ( $symname =~ m/^SIG$/  );              # Useless
3153
        next if ( $symname =~ m/^ENV$/  );              # Don't keep the user ENV
3154
        next if ( $symname =~ m/^INC$/  );              # Don't keep the INC paths
3155
        next if ( $symname =~ m/^DEFINES/  );           # Don't keep
3156
        next if ( $symname =~ m/^TOOLSETRULES/  );      # Don't keep
3157
 
3158
        local *sym = $main::{$symname};
3159
 
3160
        $cf_build_info{"\$$symname"} =  $::sym if defined $::sym;
3161
        $cf_build_info{"\@$symname"} = \@::sym if defined @::sym;
3162
        $cf_build_info{"\%$symname"} = \%::sym if defined %::sym;
3163
    }
3164
 
3165
    #
3166
    #   Dump out the configuration information
3167
    #
3168
    my $fh = ConfigurationFile::New( "$cfg_file" );
3169
    $fh->Header( "buildlib (version $::BuildVersion)",
3170
                              "Buildfile configuration" );
3171
    $fh->Dump( [\%cf_build_info], [qw(*cf_build_info)] );
3172
    $fh->Close();
3173
}
3174
 
3175
 
3176
#-------------------------------------------------------------------------------
3177
# Function        : BuildRuleFiles
3178
#
3179
# Description     : Create a set of rule files in the interface directory
3180
#                   These will be included directly into makefiles to
3181
#                   extend library and header search paths to the Linked
3182
#                   archives
3183
#
3184
#                   One file is created for each platform to simplify the
3185
#                   inclusion rules
3186
#
3187
#
3188
#                   The PKGRULES data structure is of the form:
3189
#
3190
#                   A hash, by platform, of an array of package information
3191
#                   Each block of package information is a hash containing
3192
#                       'name'      -  short name of the package
3193
#                       'version'   -  short name of the package
3194
#                       'base'      - path of the package root
3195
#                       'PINCDIRS'  - Array of included directories
3196
#                       'PLIBDIRS'  - Array of library directories
3197
#
3198
#                   Arrays are used to preserve the user specified search
3199
#                   order, both of packages and directories within each
3200
#                   package
3201
#
3202
# Inputs          :
3203
#
3204
# Returns         :
3205
#
3206
sub BuildRuleFiles
3207
{
3208
    #
3209
    #   A file is generated for each platform
3210
    #   Within this lines are generated for each package
3211
    #
3212
    foreach my $platform ( keys %PKGRULES )
3213
    {
3214
        my $pPlatform = $PKGRULES{$platform};
3215
 
3216
        my $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/$platform.rul", '--NoEof', '--Type=mak' );
3217
        $fh->Header( "Buildlib ($BuildVersion)","Package import specification" );
3218
 
3219
        $fh->Write ( "PINCDIRS\t=\t\t" . "# includes\n" );
3220
        $fh->Write ( "PLIBDIRS\t=\t\t" . "# libraries\n" );
3221
        $fh->Write ( "\n" );
3222
 
3223
        #
3224
        #   For each Available package accessable to this platform
3225
        #
3226
        foreach my $package ( @{$pPlatform} )
3227
        {
3228
            my $name = $package->{'name'} . '/' . $package->{'version'};
3229
            my $base = $package->{'base'};
3230
 
3231
            $fh->Write ( "##########################################################\n");
3232
            $fh->Write ( "# Source:  $name\n" );
3233
            $fh->Write ( "#\n" );
3234
 
3235
            #
3236
            #   List include and library directories
3237
            #
3238
            for my $type (qw (PINCDIRS PLIBDIRS) )
3239
            {
3240
                for my $path ( @{$package->{$type}} )
3241
                {
3242
                    $fh->Write ( "$type\t+= $base$path\n" );
3243
                }
3244
            }
3245
            $fh->Write ( "\n" );
3246
        }
3247
        $fh->Close();
3248
    }
3249
}
3250
 
3251
#-------------------------------------------------------------------------------
3252
# Function        : BuildSharedLibFiles
3253
#
3254
# Description     : Create a file in the interface directory that will specify
3255
#                   the locations of shared libraries.
3256
#
3257
#                   Note: Always create a file as makefile targets depend on it.
3258
#
3259
#                   This is a bit ugly.
3260
#
3261
#                   There needs be an association between the build machine and
3262
#                   the target platform. Need to know if the current target is
3263
#                   native to the current build machine. If it is then we can
3264
#                   run tests on the machine and we then need to extend the
3265
#                   search path for the target.
3266
#
3267
#                   The BUILDINFO{EXT_SHARED} is used to control the creation of
3268
#                   the files by specifying the extension of the file.
3269
#
3270
# Inputs          : None
3271
#
3272
# Returns         :
3273
#
3274
sub BuildSharedLibFiles
3275
{
3276
    if ( $ScmHost eq "DOS" || $ScmHost eq "WIN" ) {
3277
        BuildSharedLibFiles_WIN(@_);
3278
 
3279
    } elsif ( $ScmHost eq "Unix" ) {
3280
        BuildSharedLibFiles_Unix(@_);
3281
 
3282
    } else {
3283
        Error("Cannot build. Unknown machine type: $ScmHost",
3284
              "Need WIN, DOS or Unix" );
3285
    }
3286
}
3287
 
3288
#-------------------------------------------------------------------------------
3289
# Function        : BuildSharedLibFiles_WIN
3290
#
3291
# Description     : Implementation of BuildSharedLibFiles for Windows
3292
#
3293
# Inputs          : None
3294
#
3295
sub BuildSharedLibFiles_WIN
3296
{
3297
 
3298
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
3299
    {
3300
        next unless ( exists $BUILDINFO{$platform}{EXT_SHARED} );
3301
        my @dos_paths = BuildSharedLibFiles_list( $platform, $BUILDINFO{$platform}{EXT_SHARED} );
3302
 
3303
        #
3304
        #   Create a .bat file for WIN32
3305
        #   This may be consumed by user wrapper programs
3306
        #
229 dpurdie 3307
        #   Features: No Echo
3308
        #             Use of SETLOCAL to prevent pollution of environment
3309
        #
227 dpurdie 3310
        my $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/set_$platform.bat", '--NoEof', '--Type=bat' );
229 dpurdie 3311
        $fh->Write ( "\@echo off\n");
227 dpurdie 3312
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
229 dpurdie 3313
        $fh->Write ( "\nSETLOCAL\n");
227 dpurdie 3314
        foreach ( reverse @dos_paths )
3315
        {
3316
            $_ =~ s~/~\\~g;
3317
            $fh->Write ( "PATH=$_;\%PATH\%\n" );
3318
        }
3319
        $fh->Write ( "\n%*\n" );
229 dpurdie 3320
        $fh->Write ( "\nENDLOCAL\n");
231 dpurdie 3321
        $fh->Write ( "EXIT /B %ERRORLEVEL%\n");
227 dpurdie 3322
        $fh->Close();
3323
 
3324
        #
3325
        #   Create a .sh file for WIN32
3326
        #   This may be consumed by a shell - as used within JATS
3327
        #
3328
        $fh = ::ConfigurationFile::New( "$BUILDINTERFACE/set_$platform.sh", '--NoEof', '--Type=sh' );
3329
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
3330
        foreach ( reverse @dos_paths )
3331
        {
3332
            tr~\\/~/~s;
3333
            $fh->Write ( "PATH=$_\\;\$PATH\n" );
3334
        }
3335
        $fh->Write ( "\n\$*\n" );
3336
        $fh->Close();
3337
    }
3338
}
3339
 
3340
#-------------------------------------------------------------------------------
3341
# Function        : BuildSharedLibFiles_Unix
3342
#
3343
# Description     : Implementation of BuildSharedLibFiles for Unix
3344
#                   Extend the Shared Library search path via LD_LIBRARY_PATH
3345
#
3346
# Inputs          : None
3347
#
3348
sub BuildSharedLibFiles_Unix
3349
{
3350
    foreach my $platform ( @BUILD_ACTIVEPLATFORMS )
3351
    {
3352
        next unless ( exists $BUILDINFO{$platform}{EXT_SHARED} );
3353
        my @unix_paths = BuildSharedLibFiles_list( $platform, $BUILDINFO{$platform}{EXT_SHARED} );
3354
 
3355
        #
3356
        #   Create a .sh file for Unix
3357
        #
229 dpurdie 3358
        my $file = "$BUILDINTERFACE/set_$platform.sh";
3359
        my $fh = ::ConfigurationFile::New( $file , '--NoEof', '--Type=sh' );
227 dpurdie 3360
        $fh->Header( "Buildlib ($BuildVersion)","Shared Library Paths" );
3361
        foreach ( reverse @unix_paths )
3362
        {
3363
            $fh->Write ( "export LD_LIBRARY_PATH=$_:\$LD_LIBRARY_PATH\n" );
3364
        }
3365
        $fh->Write ( "\n\$*\n" );
3366
        $fh->Close();
229 dpurdie 3367
 
3368
        #
3369
        #   Make the file executable under unix
3370
        #
3371
        chmod 0755, $file;
227 dpurdie 3372
    }
3373
}
3374
 
3375
#-------------------------------------------------------------------------------
3376
# Function        : BuildSharedLibFiles_list
3377
#
3378
# Description     : Determine a list of Shared Library paths that can be used
3379
#                   by the current target
3380
#
3381
# Inputs          : $platform       - Current platform
3382
#                   $so             - Shared object extensions
3383
#
3384
# Returns         : List of search paths
3385
#
3386
sub BuildSharedLibFiles_list
3387
{
3388
    my ($platform, $so ) = @_;
3389
    my @paths;
3390
    my @parts = @{$BUILDINFO{$platform}{PARTS}};
3391
 
3392
    #
3393
    #   Paths from the current build
3394
    #       Local directory         - for installed components
3395
    #       Interface directory     - for BuildPkgArchives
3396
    #
3397
    if ( $BUILDLOCAL )
3398
    {
3399
        foreach ( @parts )
3400
        {
3401
            push @paths, AbsPath("$BUILDLOCAL/lib/$_");
3402
        }
3403
    }
3404
 
3405
    foreach ( @parts )
3406
    {
3407
            push @paths, AbsPath("$BUILDINTERFACE/lib/$_");
3408
    }
3409
 
3410
    #
3411
    #   For each LinkPkgArchive
3412
    #
3413
    foreach my $package ( @{$PKGRULES{$platform}} )
3414
    {
3415
        next unless ( $package->{'type'} eq 'link' );
3416
 
3417
        my $base = $package->{'base'};
3418
        for my $path ( @{$package->{'PLIBDIRS'}} )
3419
        {
3420
            my @so_libs = glob ( "$base$path/*$so");
3421
            next unless scalar @so_libs;
3422
 
3423
            push @paths, $base . $path;;
3424
        }
3425
    }
3426
 
3427
    #
3428
    #   Returns paths found
3429
    #
3430
    return @paths;
3431
}
3432
 
3433
#-------------------------------------------------------------------------------
3434
# Function        : Usage
3435
#
3436
# Description     : Display program usage information
3437
#
3438
# Inputs          : args            - Text message to display
3439
#
3440
#                   $opt_help       - Level of verbose ness
3441
#
3442
# Returns         : Does not return
3443
#                   This function will exit
3444
#
3445
sub Usage
3446
{
3447
    my( $msg ) = @_;
3448
    my %usage_args;
3449
 
3450
    #
3451
    #   Create a hash of arguments for the pod2usage function
3452
    #
3453
    $usage_args{'-input'} = __FILE__;
3454
    $usage_args{'-exitval'} = 42;
3455
    $usage_args{'-message'} = "\nbuildlib $msg\n" if $msg;
3456
    $usage_args{'-verbose'} = $opt_help < 3 ? $opt_help - 1 : 3 if ( $opt_help );
3457
 
3458
    #
3459
    #   Generate nice help
3460
    #
3461
    pod2usage(\%usage_args);
3462
}
3463
 
3464
#-------------------------------------------------------------------------------
3465
#   Documentation
3466
#
3467
 
3468
=pod
3469
 
3470
=head1 NAME
3471
 
3472
jats sandbox bootstrap
3473
 
3474
=head1 SYNOPSIS
3475
 
3476
jats build [options] [command]
3477
 
3478
     [perl buildlib.pl [options] PWD [command]]
3479
 
3480
 
3481
 Options:
3482
    --help          - Display terse usage
3483
    --help --help   - Display verbose usage
3484
    --man           - Display internal manual
3485
    -V              - Turn on verbose mode
3486
    -D[<level>]     - Set the debug level
3487
    --nolog         - Do not generate/update Changelog
3488
    --cache         - Cache packages in the local dpkg_package cache
3489
    --cache --cache - Forced refresh dependent packages in the local cache
3490
    --project       - Generate support files for external tools
3491
    --package       - Ignore packages that are not available and continue
3492
    --forcebuildpkg - Treat LinkPkgArchive directives as BuildPkgArchive
3493
                      Also suppress the use of symlinks so that the phsical
3494
                      file will be copied locally.
3495
 
3496
 Sticky settings:
3497
    --all           - Build for all platforms ignoring GBE_BUILDFILTER
3498
    --expert        - Relaxing dependency checks on the user makefiles
3499
 
3500
 Commands:
3501
    changelog       - Only update ChangeLog.
3502
    interface       - Only (re)build the interface tree, including ChangeLog.
3503
    rootonly        - Only (re)build the root directory.
3504
    clobber         - Remove generated build system (eg Makefiles).
3505
 
3506
 
3507
=head1 OPTIONS
3508
 
3509
=over 8
3510
 
3511
=item B<--help>
3512
 
3513
Print a brief help message and exits.
3514
 
3515
=item B<-help -help>
3516
 
3517
Print a detailed help message with an explanation for each option.
3518
 
3519
=item B<-man>
3520
 
3521
Prints the manual page and exits.
3522
 
3523
=item B<-V>
3524
 
3525
Increases program output. This option may be specified multiple times
3526
 
3527
=item B<-D[<level>]
3528
 
3529
Increases program output. Enable internal debugging messages to generate detailed
3530
progress information.
3531
 
3532
=item B<--nolog>
3533
 
3534
Do not generate or update the ChangeLog maintained when a CVS directory is detected
3535
in the build directory.
3536
 
3537
=item B<--cache>
3538
 
3539
This option will cause dependent packages to be cached in the local
3540
dpkg_archive cache.
3541
 
3542
If the option is used twice then the packages will be forcibly refreshed.
3543
 
3544
=item B<--project>
3545
 
3546
This option is used to indicate that the build.pl is being processed by a full
3547
JATS environment and not by any pre-existing mechanism.
3548
 
3549
This option will prevent the generation of configuration batch files that are
3550
not required by the full environment.
3551
 
3552
=item B<--package>
3553
 
3554
This option will cause the build process to ignore packages that cannot be
3555
located. The package build may fail at a later stage.
3556
 
3557
This option is used by the Auto Build Tool to handle packages that may not be
3558
needed in all builds.
3559
 
3560
=item B<--forcebuildpkg>
3561
 
3562
This option will force LinkPkgArchive directives to be treated as
3563
BuildPkgArchive directives. The result is that the 'interface' directory will be
3564
populated with the contents of all dependent packages. Moreover, on a Unix
3565
machine, the files will be copied and not referenced with a soft link.
3566
 
3567
This may be useful for:
3568
 
3569
=over 8
3570
 
3571
=item * Remote Development
3572
 
3573
=item * Collecting header files for scanning
3574
 
3575
=item * Local modification of files for test/debug/development
3576
 
3577
=back
3578
 
3579
=item B<--all>
3580
 
3581
This option will cause the build process to generate makefiles for all
3582
possible build targets ignoring the use of GBE_BUILDFILTER.
3583
 
3584
This option is sticky. Once used in a build it will be retained when makefiles
3585
are rebuilt.
3586
 
3587
=item B<--expert>
3588
 
3589
This option causes the generation of makefiles with relaxed dependancy checks.
3590
 
3591
The makefiles will have no dependancy between the makefiles and the JATS build
3592
files or the users makefile. If the user's makefile.pl is changed then JATS
3593
will not detect the change and will not rebuild the makefiles. The user manually
3594
force the rebuild with the command 'jats rebuild'.
3595
 
3596
This option should be used with care and with full knowledge of its impact.
3597
 
3598
This option is sticky. Once used in a build it will be retained when makefiles
3599
are rebuilt. The effect of the option can only be removed by performing a full
3600
build.
3601
 
3602
=item B<changelog>
3603
 
3604
This command will only update the CVS change log.
3605
 
3606
=item B<interface>
3607
 
3608
This command will only build, or rebuild, the 'interface' directory and the
3609
changelog ( if required ).
3610
 
3611
This command will only build, or rebuild, the root directory. The build
3612
process will not recurse through the subdirectories creating makefiles.
3613
 
3614
=item B<clobber>
3615
 
3616
This command will remove generated build system files and directories.
3617
 
3618
=back
3619
 
3620
=head1 DESCRIPTION
3621
 
3622
The default build process will parse the user's build.pl file and create the
3623
'interface' directory before creating makefiles for each target platform.
3624
 
3625
The 'build' process simply generates the build sandbox. It does not invoke the
3626
generated makefiles. This must be done by the user in a different phase.
3627
 
3628
The 'build' process need only be invoked if the build.pl file has changed. The
3629
generated makefiles will detected changes to the makefile.pl's and cause them to
3630
be generated as required. The 'build' step sets up the sandboxes external
3631
environment.
3632
 
3633
=head1 INVOCATION
3634
 
3635
This perl library (buildlib.pl) is not designed to be invoked directly by the
3636
user. It should be invoked through a 'build.pl' file. Moreover, for historical
3637
reasons, the build.pl is not easily invoked. It is best to only invoke the
3638
'build' process via the JATS wrapper scripts : jats.bat or jats.sh.
3639
 
3640
The build.pl file must be invoked with two fixed arguments, followed by user
3641
options and subcommands
3642
 
3643
=over 8
3644
 
3645
=item   1 The current working directory
3646
 
3647
This could have been derived directly by the program, rather than having it
3648
passed in.
3649
 
3650
=item   2 The absolute path to buildlib.pl (this library)
3651
 
3652
In practice this value is not used, but is provided for historical reasons.
3653
 
3654
=item   3 Options and commands may follow the first two mandatory arguments.
3655
 
3656
=back
3657
 
3658
The build.pl file must 'require' the buildlib.pl and makelib.pl. The preferred
3659
code is:
3660
 
3661
=over 8
3662
 
3663
    build.pl: First statements
3664
    $MAKELIB_PL     = "$ENV{ GBE_TOOLS }/makelib.pl";
3665
    $BUILDLIB_PL    = "$ENV{ GBE_TOOLS }/buildlib.pl";
3666
 
3667
    require         "$BUILDLIB_PL";
3668
    require         "$MAKELIB_PL";
3669
 
3670
=back
3671
 
3672
=cut
3673
 
3674
1;