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