Subversion Repositories DevTools

Rev

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

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