Subversion Repositories DevTools

Rev

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

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