Subversion Repositories DevTools

Rev

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

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