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; -*-
261 dpurdie 2
# Copyright (C) 1998-2008 ERG Transit Systems, All rights reserved
227 dpurdie 3
#
4
# Module name   : makelib.pl2
5
# Module type   : Makefile system
6
#
7
# Description:
8
#       This modules builds the platform definition makefiles(s)
9
#
10
# Notes:                *** DO NOT DETAB ***
11
#       Beware the use of space v's tab characters within the
12
#       makefile generation sessions.
13
#
14
##############################################################################
15
# Globals:
16
#  $ScmVersion          Makelib.pl2 version
17
#  $ScmRoot             Command line parameter that gives the root directory
18
#                       location for this directory tree.
19
#  $ScmMakelib          Command line parameter that points to the location
20
#                       of THIS script.  ie. location of makelib.pl.
21
#  $ScmPlatform         Current platform
22
#  $ScmProduct          Current product (if any)
23
#  $ScmTarget           Resulting target (derived from Platform)
24
#  @ScmPlatformArgs     Platform arguments
25
#  $ScmToolset          Toolset
26
#  @ScmToolsetArgs      Toolset arguments
27
#  $ScmDebug            Debug level
28
#  $ScmVerbose          Verbose setting
29
#  $ScmSourceTypes      Source types, aliasing for C, C++ and assembler
30
#                       source.
31
#  @CFLAGS              List containing all of the defined C flags
32
#  @CXXFLAGS            List containing all of the defined C++ flags
33
#  @ASFLAGS             List containing all of the defined assembler flags
34
#  @CLINTFLAGS          List containing all of the defined C lint flags
35
#  @CXXLINTFLAGS        List containing all of the defined C++ lint flags
36
#  @{G|L}_INCDIRS       List containing all of include paths
37
#  @{G|L}_SRCDIRS       List containing all of source search paths
38
#  @{G|L}_LIBDIRS       List containing all of library search paths
39
#  @LDFLAGS             List containing all of the defined linker flags
40
#  @SRCS                List of ALL source files. ie. C/C++ and other (eg .x)
41
#                       Key is source file, value is source path
42
#  @OBJS                List of ALL (non-shared) object files.
289 dpurdie 43
#  %SHOBJ_LIB           List of ALL shared library object files and associated library.
227 dpurdie 44
#  %OBJSOURCE           List of ALL object files
45
#                       from that should result from later makes.
46
#                       Key is objectfile, value is source file
47
#  %OBJREFS             List of ALL object files, built options.
48
#  @PROGOBJS            List of ALL application object files.
49
#  %SRC_ARGS            List of arguments that are to be used when making the
50
#                       nominated source.  Key is the source name, the
51
#                       value is a string of arguments to apply.  The
52
#                       arguments are '$;' separated.
53
#  %SRC_TYPE            Source file type (user override).
54
#  @CHDRS               List of C header files.
55
#  @CSRCS               List of C files
56
#                       Key is objectfile, value is source file
57
#  @CXXSRCS             List of C++ files
58
#  @ASHDRS              List of assembler include files (.inc)
59
#  @ASSRCS              List of assembler source files
60
#  @GENERATED           List of files that should result from a 'generate'
61
#                       make rule.  The programmer is expected to provide
62
#                       the necessary rule(s).
63
#  @RULES               List of additional make rules the programmer
64
#                       has specified to be included in the make.
65
#  %INSTALL_HDRS        List of headers that are to be installed for later
66
#                       "public" consumption.
67
#  %INSTALL_CLSS        List of Java classes or JAR files that are to be installed
68
#                       for later "public" consumption.
69
#  @LIBS                List of libraries that are to be built.
289 dpurdie 70
#  $LIBS                Ref to a collection of static library descriptors
71
#                       Indexed by lib name
227 dpurdie 72
#  %INSTALL_LIBS        List of libraries that are to be installed for later
73
#                       public consumption.
74
#  @MLIBS               List of libraries that are to be built via merging
289 dpurdie 75
#  $MLIBS               Ref to a collection of merged lib descriptors
227 dpurdie 76
#  @SHLIBS              List of shared libraries that are to be built.
289 dpurdie 77
#  $SHLIBS              Ref to collection of shared library information
227 dpurdie 78
#  %INSTALL_SHLIBS      List of libraries that are to be installed for later
79
#                       public consumption.
80
#  @PROGS               List of programs (binary executables) that are
81
#                       to be built
289 dpurdie 82
#  $PROGS               Ref to collection of program information
227 dpurdie 83
#  %SCRIPTS             List of scripts to 'create' (key) and whether they
84
#                       should be made executable or not (value).  Script
85
#                       set to executable is denoted by the value being
86
#                       defined AND true.
87
#  %INSTALL_PROGS       List of programs for "public" cosumption to install
88
#                       where (key) is the file and where to install it
89
#                       to vs. (value) which is composed of the original
90
#                       location of the file, the destination directory
91
#                       and a list of service providers this file applies to.
92
# $ProjectBase          Base of the user's project. This variable is designed to
93
#                       be used by the user.
94
#....
95
 
255 dpurdie 96
require 5.006_001;
227 dpurdie 97
use strict;
98
use warnings;
261 dpurdie 99
use Getopt::Long;
227 dpurdie 100
use Data::Dumper;
271 dpurdie 101
use JatsError;
227 dpurdie 102
use JatsEnv;
103
use MakeEntry;
104
use JatsLocateFiles;
105
use JatsDPackage;
271 dpurdie 106
use MakeIf;
289 dpurdie 107
use ToolsetPrinter;
108
use MakeObject;
227 dpurdie 109
 
110
 
111
our $ScmVersion             = "2.34";
112
our $ScmGlobal              = 0;
113
our $ScmExpert              = 0;
114
our $ScmInterface           = "interface";      # default 'interface'
115
our $ScmPackage             = 1;                # package active by default.
116
our $ScmProcessingRootMake  = 0;                # Processing root makefile.pl
117
our $ScmPlatformSeen        = 0;                # Platform directive has been seen
118
 
119
our $ScmToolsetVersion      = "";               # version of toolset
120
our $ScmToolsetGenerate     = 1;                # generate active by default.
121
our $ScmToolsetProgDependancies = 1;            # 1: Write program dependancies
122
                                                # 0: Don't write progdeps. Prog is Phony
289 dpurdie 123
our $ScmToolsetSingleType   = 0;                # Toolset does not support Debug and Production
227 dpurdie 124
our $ScmToolsetProgSource   = ();               # Toolset Program Source
125
our $ScmRoot                = "";
126
our $ScmMakelib             = "";
127
our $ScmPlatform            = "";
128
our $ScmMachType            = "";
129
our $ScmSrcDir              = "";
130
our @ScmPlatformDirs        = ();
131
our @ScmPlatformArgs        = ();
289 dpurdie 132
our $ScmBuildType           = 0;                # 0, P, D. 0 == P and D
227 dpurdie 133
our $ScmProduct             = "";
134
our $ScmTarget              = "";
135
our $ScmTargetHost          = "";
136
our $ScmToolset             = "";
137
our @ScmToolsetArgs         = ();
138
our @ScmDepends             = ();
139
our %ScmSourceTypes         = ();
140
our $ScmDeploymentPatch     = "";
141
our $ProjectBase            = "";               # Base of the user's project
142
our $ScmNoToolsTest         = "";               # Supress compiler tests
143
our $ScmDependTags          = 0;                # Create dependancy scanning tag
144
 
145
our @CFLAGS                 = ();
146
our @CFLAGS_DEBUG           = ();
147
our @CFLAGS_PROD            = ();
148
our @CLINTFLAGS             = ();
149
our @CLINTFLAGS_DEBUG       = ();
150
our @CLINTFLAGS_PROD        = ();
151
our @CXXFLAGS               = ();
152
our @CXXFLAGS_DEBUG         = ();
153
our @CXXFLAGS_PROD          = ();
154
our @CXXLINTFLAGS           = ();
155
our @CXXLINTFLAGS_DEBUG     = ();
156
our @CXXLINTFLAGS_PROD      = ();
157
our @ASFLAGS                = ();
267 dpurdie 158
our @ASFLAGS_DEBUG          = ();
159
our @ASFLAGS_PROD           = ();
227 dpurdie 160
our @LDFLAGS                = ();
267 dpurdie 161
our @LDFLAGS_DEBUG          = ();
162
our @LDFLAGS_PROD           = ();
227 dpurdie 163
 
164
our @INCDIRS                = ();
165
our @NODEPDIRS              = ();
166
our @S_INCDIRS              = ();
167
our @G_INCDIRS              = ();
168
our @L_INCDIRS              = ();
169
our @SRCDIRS                = ();
170
our @S_SRCDIRS              = ();
171
our @G_SRCDIRS              = ();
172
our @L_SRCDIRS              = ();
173
our @LIBDIRS                = ();
174
our @S_LIBDIRS              = ();
175
our @G_LIBDIRS              = ();
176
our @L_LIBDIRS              = ();
177
 
178
our %SRCS                   = ();
179
our %SRC_ARGS               = ();
180
our %SRC_TYPE               = ();
181
our %SRC_DEPEND             = ();
182
our %SCRIPTS                = ();
183
our @COPYIN                 = ();
184
our @INITS                  = ();
185
our @DEFINES                = ();
186
our @OBJS                   = ();
187
our %SHOBJ_LIB              = ();
188
our @PROGOBJS               = ();
289 dpurdie 189
our @TESTPROGOBJS           = ();
227 dpurdie 190
our %OBJSOURCE              = ();
191
our @CHDRS                  = ();
192
our @CSRCS                  = ();
193
our @CXXSRCS                = ();
194
our @ASHDRS                 = ();
195
our @ASSRCS                 = ();
196
our @GENERATED              = ();
197
our @GENERATED_NOTSRC       = ();
198
our @RULES                  = ();
199
our @TOOLSETRULES           = ();
200
our @TOOLSETDIRS            = ();
201
our @TOOLSETDIRTREES        = ();
202
our @TOOLSETGENERATED       = ();
203
our @USERGENERATED          = ();
204
our @TOOLSETOBJS            = ();
205
our @TOOLSETLIBS            = ();
206
our @TOOLSETPROGS           = ();
207
our %INSTALL_HDRS           = ();
208
our %INSTALL_CLSS           = ();
209
 
210
our @LIBS                   = ();
289 dpurdie 211
our $LIBS                   = ();
227 dpurdie 212
our %LIB_PKG                = ();
213
our %LIB_INS                = ();
214
our %INSTALL_LIBS           = ();
215
 
216
our @MLIBS                  = ();
289 dpurdie 217
our $MLIBS                  = ();
227 dpurdie 218
 
219
our @SHLIBS                 = ();
289 dpurdie 220
our $SHLIBS                 = ();
227 dpurdie 221
our @SHLIB_TARGETS          = ();
222
our %SHLIB_PKG              = ();
223
our %SHLIB_INS              = ();
224
our %INSTALL_SHLIBS         = ();
225
 
289 dpurdie 226
our $TESTPROGS              = ();
227
our @TESTPROGS              = ();
227 dpurdie 228
 
289 dpurdie 229
our $PROGS                  = ();           # Simplify tracking of progs
227 dpurdie 230
our @PROGS                  = ();
289 dpurdie 231
our @PROGS_EXTRA            = ();           # Look at doing better !!
227 dpurdie 232
our %PROG_PKG               = ();
233
our %PROG_INS               = ();
234
our %INSTALL_PROGS          = ();
235
 
236
our %PACKAGE_DIST           = ();
237
our %PACKAGE_SETS           = ();
238
our %PACKAGE_HDRS           = ();
239
our %PACKAGE_LIBS           = ();
240
our %PACKAGE_CLSS           = ();
241
our %PACKAGE_SHLIBS         = ();
242
our %PACKAGE_PROGS          = ();
243
our %PACKAGE_FILES          = ();
244
 
245
our @PACKAGE_VARS           = ( '%PACKAGE_CLSS',  '%PACKAGE_FILES', '%PACKAGE_HDRS',
246
                                '%PACKAGE_LIBS',  '%PACKAGE_PROGS', '%PACKAGE_SHLIBS' );
247
our @INSTALL_VARS           = ( '%INSTALL_CLSS',  '%INSTALL_HDRS',  '%INSTALL_LIBS',
248
                                '%INSTALL_PROGS', '%INSTALL_SHLIBS');
249
 
250
our @LINTLIBS               = ();
251
our @LINTSHLIBS             = ();
252
 
253
our @TESTS_TO_RUN           = ();
254
our @TESTPROJECT_TO_URUN    = ();
255
our @TESTPROJECT_TO_ARUN    = ();
256
my  $TESTS_TO_AUTORUN       = undef;
263 dpurdie 257
my  $TESTS_TO_RUN           = undef;
227 dpurdie 258
 
259
#our $CurrentTime           = "";
260
#our $CurrentDate           = "";
261
#our $Cwd                   = "";
262
 
263
our @GENERATE_FILES         = ();
264
our %DEPLOYPACKAGE          = ();
267 dpurdie 265
our $DEPLOYPACKAGE          = 0;
261 dpurdie 266
our %MakeTags;
227 dpurdie 267
 
268
#
269
#   Some toolset options that affect the generation of the makefile
270
#
271
our $UseAbsObjects          = 0;                # Default is relative paths to objects
272
our $UseRelativeRoot        = 0;                # Default is absolute paths to build root
299 dpurdie 273
our $DPackageDirective      = 0;
227 dpurdie 274
 
271 dpurdie 275
#
276
#   Arrays of hook functions
277
#
278
our %MF_RegisterSrcHooks;                       # Hook source file discovery
279
 
280
 
227 dpurdie 281
###############################################################################
282
#
283
#   Packaging and Installation Information
284
#   Held in a structure as its used in a few places
285
#   Items
286
#       PBase   - Package Base directory. Used for user overrides
287
#       IBase   - Local Install Base directory
288
#       Dir     - Default directory suffix for components. Added to Pbase and IBase
289
#
290
#
291
our %PackageInfo = (
292
    'File' => { 'PBase' => '$(PKGDIR)'       ,'IBase' => '$(LOCALDIR)'       , 'Dir' => '' },
293
    'Hdr'  => { 'PBase' => '$(INCDIR_PKG)'   ,'IBase' => '$(INCDIR_LOCAL)'   , 'Dir' => ''},
294
    'Lib'  => { 'PBase' => '$(LIBDIR_PKG)'   ,'IBase' => '$(LIBDIR_LOCAL)'   , 'Dir' => '/$(GBE_PLATFORM)'},
295
    'Prog' => { 'PBase' => '$(BINDIR_PKG)'   ,'IBase' => '$(BINDIR_LOCAL)'   , 'Dir' => '/$(GBE_PLATFORM)$(GBE_TYPE)'},
296
    'Jar'  => { 'PBase' => '$(CLSDIR_PKG)'   ,'IBase' => '$(CLSDIR_LOCAL)'   , 'Dir' => ''},
241 dpurdie 297
    'Tool' => { 'PBase' => '$(PKGDIR)'       ,'IBase' => '$(LOCALDIR)'       , 'Dir' => '/tools/bin/$(GBE_HOSTMACH)'},
227 dpurdie 298
    );
299
 
300
MakeLib2Init();                                 # Runtime initialisation
301
 
302
sub MakeLib2Init
303
{
304
#.. Test environment
305
#
306
    EnvImport( "GBE_CORE" );
307
    EnvImport( "GBE_BIN" );
308
    EnvImport( "GBE_PERL" );
309
    EnvImport( "GBE_TOOLS" );
310
    EnvImport( "GBE_CONFIG" );
311
    EnvImport( "GBE_MACHTYPE" );
312
 
313
#.. Common stuff
314
#
315
    require "$::GBE_TOOLS/common.pl";           # Common stuff
316
    push( @ScmDepends, "$::GBE_TOOLS/common.pl" );
317
 
318
    CommonInit( "makelib2" );
319
    Debug( "version:   $ScmVersion" );
320
 
321
#.. Cache arguments
322
#
323
    CommandLine();
324
 
325
#.. Build defaults
326
#
327
    $ScmSourceTypes{ ".h" }     = ".h";
328
    $ScmSourceTypes{ ".hpp" }   = ".h";
329
    $ScmSourceTypes{ ".c" }     = ".c";
330
    $ScmSourceTypes{ ".C" }     = ".c";
331
    $ScmSourceTypes{ ".cpp" }   = ".cc";
332
    $ScmSourceTypes{ ".cc" }    = ".cc";
333
    $ScmSourceTypes{ ".asm" }   = ".asm";
334
    $ScmSourceTypes{ ".x" }     = "--Ignore";
335
    $ScmSourceTypes{ ".ini" }   = "--Ignore";
336
    $ScmSourceTypes{ ".sh" }    = "--Ignore";
337
    $ScmSourceTypes{ ".pl" }    = "--Ignore";
338
    $ScmSourceTypes{ ".awk" }   = "--Ignore";
339
 
340
#.. Get the stuff from the build configuration file
341
#
342
    ConfigLoad();
343
 
344
    if ( defined(%::ScmBuildPlatforms) )        # Interface/build.cfg
345
    {
346
        AddPlatformArg( split( /$;/, $::ScmBuildPlatforms{ $ScmPlatform } ));
347
    }
348
 
349
    if ( defined(%::ScmBuildIncludes) )         # Interface/build.cfg
350
    {
351
        my( @includes ) = split( ',', $::ScmBuildIncludes{ $ScmPlatform } );
352
        my( $global ) = $ScmGlobal;
353
 
354
        $ScmGlobal = 1;                         # Follow defs are "global's" ...
355
        foreach my $elem ( @includes )
356
        {
357
            AddIncDir( "*", $elem ) if ($elem);
358
        }
359
        $ScmGlobal = $global;                   # Restore global status ...
360
    }
361
 
362
    if ( defined(%::ScmBuildLibraries) )        # Interface/build.cfg
363
    {
364
        my( @libraries ) = split( ',', $::ScmBuildLibraries{ $ScmPlatform } );
365
        my( $global ) = $ScmGlobal;
366
 
367
        $ScmGlobal = 1;                         # Follow defs are "global's" ...
368
        foreach my $elem ( @libraries )
369
        {
370
            AddLibDir( "*", $elem ) if ($elem);
371
        }
372
        $ScmGlobal = $global;                   # Restore global status ...
373
    }
374
 
375
#.. Determine the value of $ScmMachType
376
#   In the makefile GBE_MACHTYPE will be set to $ScmMachType.
377
#
378
#   There is an compatibility issue here.
379
#   A lot of (legacy) package.pl files use GBE_MACHTYPE to specify platform
380
#   specfic directories and names. This is not to be encouraged.
381
#
382
#   Allow for a platformm specific override
383
#
384
    if ( exists( $::BUILDINFO{$ScmPlatform}{'SCMMACHTYPE'} ))
385
    {
386
        $ScmMachType = $::BUILDINFO{$ScmPlatform}{'SCMMACHTYPE'};
387
        Verbose("Override ScmMachType: $ScmMachType");
388
    }
389
    else
390
    {
391
        $ScmMachType = $ScmPlatform;
392
    }
393
 
394
 
395
#.. Get the stuff from the Package definition file
396
#   A convention is that package.pl provide a package name via $Pbase
397
#   This may be different to the BUILDNAME. Generate a default $Pbase
398
#   to allow the package.pl to use the package name part of the buildname
399
#
400
    $::Pbase = $::ScmBuildPackage;
401
    if ( -f "$ScmRoot/package.pl" )
402
    {
403
        Warning ("package.pl file used. Use is being deprecated");
404
 
405
        my( $global ) = $ScmGlobal;             # Follow defs are "global's" ...
406
        $ScmGlobal = 1;
407
        require "$ScmRoot/package.pl";
408
        $ScmGlobal = $global;                   # Restore global status ...
409
 
410
        if ( defined ($::ScmBuildPackage) && defined ($::Pbase) )
411
        {
412
            #   Special case.
413
            #   $Pbase is set to ".". Set $Pbase to the Build Name to force
414
            #   construction of a well formatted package.
415
            #
416
            $::Pbase = $::ScmBuildPackage
417
                if ( $::Pbase eq "." );
418
 
419
            #
420
            #   Error if Pbase has changed
421
            #
422
            Error ("Pbase is not the same as the BuildName (Check package.pl)",
423
                   "Pbase    : $::Pbase",
424
                   "BuildName: $::ScmBuildPackage")
425
                if ( $::Pbase ne $::ScmBuildPackage );
426
        }
427
    }
289 dpurdie 428
 
429
    #
430
    #   Create objects to keep track of Libraies and Programs
431
    #
432
    $LIBS       = MakeObject::NewType( 'Library',       \@LIBS,     '$(LIBDIR)/', \&GenLibName);
433
    $MLIBS      = MakeObject::NewType( 'MergedLibrary', \@MLIBS,    '$(LIBDIR)/', \&GenLibName);
434
    $SHLIBS     = MakeObject::NewType( 'SharedLibrary', \@SHLIBS,   '$(LIBDIR)/', \&GenLibName);
435
    $PROGS      = MakeObject::NewType( 'Program',       \@PROGS,    '$(BINDIR)/', \&GenProgName);
436
    $TESTPROGS  = MakeObject::NewType( 'TestProgram',   \@TESTPROGS,'$(BINDIR)/', \&GenProgName);
227 dpurdie 437
}
438
 
261 dpurdie 439
#-------------------------------------------------------------------------------
289 dpurdie 440
# Function        : GenLibName
441
#
442
# Description     : Helper function to generate a (static) library name
443
#                   Used by MakeObject::NewType
444
#
445
#                   If the toolset doesn't support Debug and Prod, then
446
#                   The library name will not have the suffix
447
#
448
# Inputs          : arg0        - Base name of the library
449
#
450
# Returns         : Name of the library as used in the makefiles
451
#                   Does not include base directory
452
#
453
sub GenLibName
454
{
455
    if ( $ScmToolsetSingleType ) {
456
        return "$_[0].$::a"
457
    } else {
458
        return "$_[0]\$(GBE_TYPE).$::a"
459
    }
460
}
461
 
462
#-------------------------------------------------------------------------------
463
# Function        : GenProgName
464
#
465
# Description     : Helper function to generate a program name
466
#                   Used by MakeObject::NewType
467
#
468
# Inputs          : arg0        - Base name of the library
469
#
470
# Returns         : Name of the program as used in the makefiles
471
#                   Does not include base directory
472
#
473
sub GenProgName
474
{
475
    return "$_[0]$::exe"
476
}
477
 
478
 
479
#-------------------------------------------------------------------------------
261 dpurdie 480
# Function        : CommandLine
481
#
482
# Description     : Process the command line.
483
#                   Arguments describes below
484
#
485
# Arguments       : ARG0        - Root of the project
486
#                   ARG1        - Path to this script
487
#                   ARG2        - Target Platform
488
#
489
#                   Options follow
490
#                       --interface=name    - Name of interface dir
491
#                       --arg=xxx           - Platform argument
492
#
493
#                   Otherwise display a usage message
494
#
495
# Returns         : Nothing
496
#
227 dpurdie 497
sub CommandLine
498
{
261 dpurdie 499
    Verbose ("Command Line: @ARGV");
227 dpurdie 500
 
261 dpurdie 501
    #
502
    #   Extract options first
503
    #
504
    my $opt_help = 0;
505
    my $result = GetOptions (
506
                "help+"         => \$opt_help,
507
                "interface=s"   => \$::ScmInterface,
508
                "arg=s"         => sub{ AddPlatformArg( "--$_[1]") }
509
                );
510
    Usage() if ( $opt_help || !$result );
511
 
512
    #
513
    # Need 3 Arguments
514
    #
227 dpurdie 515
    $ScmRoot     = ${ARGV[0]};
261 dpurdie 516
    $ScmRoot     = RelPath( $ScmRoot );
227 dpurdie 517
    $ProjectBase = $ScmRoot;
518
 
519
    $ScmMakelib  = ${ARGV[1]};
520
    $ScmPlatform = ${ARGV[2]};
521
    $ScmTarget   = $ScmPlatform;
522
 
523
    Message ("[$ScmPlatform] Generate Makefile");
524
    Debug( "root\t=$ScmRoot" );
525
    Debug( "makelib\t=$ScmMakelib" );
526
    Debug( "platform\t=$ScmPlatform" );
527
}
528
 
529
#   Usage ---
530
#       Command line usage help.
531
#..
532
 
533
sub Usage
534
{
261 dpurdie 535
    Error ( "Usage: perl makefile.pl2 <ROOTDIR> <makelib.pl2> <PLATFORM> [options ...]",
536
            "Valid options:",
537
            "    --interface=name  Set interface directory",
538
            "    --arg=text        Specify platform argument",
539
            );
227 dpurdie 540
}
541
 
542
 
543
#-------------------------------------------------------------------------------
544
# Function        : SubDir
545
#
546
# Description     : Include a sub-makefile
547
#                   When called when processing by this script this directive
548
#                   does nothing. The processing will be done by makelib.pl
549
#
550
#                   This directive MUST occur before the Platform directive
551
#
552
# Inputs          : None that are used
553
#
554
# Returns         : Nothing
555
#
556
 
557
sub SubDir
558
{
559
    Error ("SubDir directive not allowed after the Platform directive")
560
        if ( $ScmPlatformSeen );
561
}
562
 
563
 
564
###############################################################################
565
#   Platform support
566
###############################################################################
567
 
568
sub Platform
569
{
570
    my( $global, $file );
571
 
572
    Debug( "Platform( $ScmPlatform, @ScmPlatformArgs )" );
573
 
574
#.. Sanity test
575
#
576
    Error ("Platform directive is not allowed in common makefile.pl")
577
        if ( $ScmProcessingRootMake );
578
 
579
    Error ("Only one Platform directive is allowed")
580
        if ( $ScmPlatformSeen );
581
    $ScmPlatformSeen = 1;
582
 
583
#.. Arguments
584
#
585
    $ScmTargetHost = $::ScmHost;                # default
586
 
587
#.. Common configuration
588
#
589
    $global = $ScmGlobal;                       # Follow defs are "global's" ...
590
    $ScmGlobal = 1;
591
 
592
#.. Common rules (ScmHost specific)
593
#
594
    push( @ScmDepends, "$ScmMakelib" );         # parent
595
 
596
    $file = Require( "$::GBE_CONFIG", "Rules", "Common rules " );
597
    push( @ScmDepends, "$file" );
598
 
599
#.. Platform (defines ScmToolset)
600
#
601
    if ( defined( %::ScmBuildProducts ) &&      # interface/build.cfg
602
            $::ScmBuildProducts{ $ScmPlatform } )
603
    {
604
        my( @args ) = split( ',', $::ScmBuildProducts{ $ScmPlatform } );
605
 
606
        $ScmProduct = $args[0];
607
        $ScmTarget = $args[1];
608
 
609
        Debug( " mapping to product $ScmProduct" );
610
 
611
                                                # Platform/target specific
612
        MakeIf::PackageDirs( \@ScmPlatformDirs, $ScmPlatform, $ScmTarget );
613
        push @ScmPlatformDirs, "$::GBE_CONFIG"; # .. plus default
614
 
615
        @ScmPlatformArgs = ( "--product=$ScmProduct", @ScmPlatformArgs );
616
        $file = Require( "PLATFORM", $ScmTarget,
617
                    "Platform definition ", @ScmPlatformDirs );
618
    }
619
    else                                        # standard
620
    {
621
        Debug( " native platform" );
622
 
623
                                                # Platform specific
624
        MakeIf::PackageDirs( \@ScmPlatformDirs, $ScmPlatform );
625
        push @ScmPlatformDirs, "$::GBE_CONFIG"; # .. plus default
626
 
627
        $file = Require( "PLATFORM", $ScmPlatform,
628
                    "Platform definition ", @ScmPlatformDirs );
629
    }
630
    push( @ScmDepends, "$file" );
631
 
632
    Error( "Toolset undefined for platform $ScmPlatform ...")
633
        unless( $ScmToolset );
634
 
635
#.. Toolset
636
#
637
    $file = Require( "$::GBE_CONFIG/TOOLSET", $ScmToolset, "Toolset definition " );
638
    push( @ScmDepends, "$file" );
639
 
640
#.. Package definitions
641
#
642
#   a)  Firstly the static buildlib.pl generated search paths, which
643
#       are $ScmPlatform specific.
644
#
645
#   b)  Secondly the global DPACKAGE definitions, which may pull in
646
#       $ScmTarget specific definitions.
647
#
648
    if ( -e "$ScmRoot/$ScmInterface/$ScmPlatform.rul" )
299 dpurdie 649
    {
227 dpurdie 650
        Defines( "$ScmRoot/$ScmInterface", "$ScmPlatform.rul" );
651
    }
652
 
653
    MakeIf::PackageLoad( $ScmPlatform );        # DPACKAGE's (if any)
654
 
655
 
656
#.. Package extensions
657
#   Import, into the current package, files of the form gbe/DIRECTIVES
658
#   These allow the JATS directives to be extended by the contents of a package
659
#   without the need to update the core JATS release.
660
#
661
#   Intended use: Associate a directive with a tool script, such that the
662
#   new directive simplifies the use of the tool script.
663
#
664
#
665
#   First: Extend the Perl Search Space to include the toolset extensions
666
#          Although the directives are in gbe/DIRECTIVES/*.pm, they may need
667
#          to reference other packages that are not.
668
#
311 dpurdie 669
#           Look in the 'interface' and 'link' packages
670
#           The 'build' packages are duplicated into the 'interface'
671
#
227 dpurdie 672
    for my $path ( ToolExtensionPaths() )
673
    {
674
        UniquePush (\@INC, $path)
675
            if (glob( "$path/*.pm") || glob( "$path/*/*.pm"));
676
    }
677
 
678
    for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} })
679
    {
311 dpurdie 680
        next if ( $entry->{'TYPE'} eq 'build' );
227 dpurdie 681
        my $cfgdir = $entry->{'CFGDIR'};
682
        next unless ( $cfgdir );
683
        my $base_dir = $entry->{'ROOT'} . $cfgdir . '/DIRECTIVES';
684
        next unless ( -d $base_dir );
685
        foreach my $file  ( glob ("$base_dir/*.pm") )
686
        {
687
            push( @ScmDepends, "$file" );
688
            require $file;
689
        }
690
    }
691
 
692
    #
271 dpurdie 693
    #   Include local toolset extensions
694
    #   These are rooted in the build directory and are not to be confused with
695
    #   extensions that may be packaged
696
    #
697
    my $local_base_dir = "$ScmRoot/gbe/DIRECTIVES";
698
    if ( -d $local_base_dir )
699
    {
700
        foreach my $file  ( glob ("$local_base_dir/*.pm") )
701
        {
702
            push( @ScmDepends, "$file" );
703
            require $file;
704
        }
705
    }
706
 
707
    #
227 dpurdie 708
    #   All makefile.pl's will include a makefile.pl found in the build
709
    #   root directory ( The same directory as build.pl ). This makefile.pl
710
    #   is a little bit different - It should not "require "$ARGV[1]", nor
711
    #   should it use a Platform directive.
712
    #
713
    #   Note: This makefile is processed AFTER the toolset has been initialised
714
    #         so that toolset extensions are available to the directives
715
    #
716
    $file = "$ScmRoot/makefile.pl";
717
    if ( -e $file ) {
718
        $ScmProcessingRootMake = 1;
719
        require "$file";
720
        $ScmProcessingRootMake = 0;
721
        push( @ScmDepends, "$file" );
722
    }
723
 
724
    #
289 dpurdie 725
    #   Sanity Test for platforms that do not support both debug and production
726
    #   builds at the same time. This information is flagged by the toolset
727
    #   which we have now loaded.
728
    #
729
    if ( $ScmToolsetSingleType  )
730
    {
731
        unless ( $ScmBuildType )
732
        {
733
            Error ("The toolset used by the \"$ScmPlatform\" platform does not support",
734
                   "both Production and Debug Builds" );
735
        }
736
    }
737
 
738
    #
227 dpurdie 739
    #   Restore global status ...
740
    #
741
    $ScmGlobal = $global;
742
}
743
 
744
 
745
sub PlatformRequire
746
{
747
    my( $script, @arguments ) = @_;
748
    my( $file );
749
 
750
    Debug( "PlatformRequire($script, @arguments)" );
751
 
752
    push( @ScmPlatformArgs, @arguments );       # additional arguments
753
 
754
    $file = Require( "PLATFORM", $script,
755
                "PlatformRequire ", @ScmPlatformDirs );
756
 
757
    push( @ScmDepends, "$file" );
758
}
759
 
760
 
761
sub PlatformInclude
762
{
763
    my( $script, @arguments ) = @_;
764
    my( $file );
765
 
766
    Debug( "PlatformInclude( @_ )" );
767
 
768
    $file = Require2( \@arguments, "PLATFORM", $script,
769
                "PlatformInclude ", @ScmPlatformDirs );
770
 
771
    push( @ScmDepends, "$file" );
772
}
773
 
774
 
775
sub PlatformDefine
776
{
777
    Debug2( "PlatformDefine(@_)" );
778
 
779
    Define( @_ );
780
}
781
 
782
 
783
sub PlatformDefines
784
{
785
    my( $script ) = @_;
786
    my( $line );
787
 
788
    Debug2( "PlatformDefine(@_)" );
789
 
790
    $script = Exists( "PLATFORM", $script,      # locate image
791
                "PlatformDefines", @ScmPlatformDirs );
792
 
271 dpurdie 793
    push( @DEFINES, "# PlatformDefines from: $script" );
285 dpurdie 794
    open( my $fh, '<', $script ) || Error( "Opening $script" );
795
    while (<$fh>) {
227 dpurdie 796
        $_ =~ s/\s*(\n|$)//;                    # kill trailing whitespace & nl
797
        push( @DEFINES, $_ );
798
    }
799
    push( @ScmDepends, "$script" );             # makefile dependencies
285 dpurdie 800
    close( $fh );
227 dpurdie 801
}
802
 
803
 
804
sub PlatformEntry
805
{
806
    my( $prelim, $postlim, $prefix, $postfix, @elements ) = @_;
807
 
285 dpurdie 808
    my $str = "$prelim";
809
    foreach my $element ( @elements )
227 dpurdie 810
    {
811
        $str .= "${prefix}${element}${postfix}";
812
    }
813
    $str .= "$postlim";
814
    PlatformDefine( $str );
815
}
816
 
817
 
818
#
819
#   Add arguments to the ScmPlatformArgs, but remove "Global" arguments
820
#       --OnlyDebug
821
#       --OnlyProduction
822
#
289 dpurdie 823
#   Capture OnlyDebug and OnlyProd information
824
#   Will be sanitized by caller.
825
#
227 dpurdie 826
sub AddPlatformArg
827
{
828
    Debug("AddPlatformArg: @_" );
289 dpurdie 829
    foreach  ( @_ )
830
    {
831
        if ( m~^--OnlyDebug~ ) {
832
            $ScmBuildType = 'D';
833
        } elsif ( m~--OnlyProd~ ) {
834
            $ScmBuildType = 'P';
835
        } else {
836
            UniquePush( \@::ScmPlatformArgs, @_ );
837
        }
838
    }
227 dpurdie 839
 
840
    Debug("AddPlatformArg: Result: @::ScmPlatformArgs" );
841
    1;
842
}
843
 
844
###############################################################################
845
# Toolset support
846
#
847
#   Toolset( 'platform [, ... ]', name, [arg, ... ] )
848
#       Specify the toolset for a platform
849
#
850
#   ToolDefine( )
851
#   ToolDefines( )
852
#       Specifies toolset defines for insertion into the target makefile.
853
#
854
#   ToolsetDir
855
#       Define toolset created directory(s) for removal during
856
#       'clean' operations.
857
#
858
#   ToolsetGenerate
859
#       Define toolset created file(s) for removal during
860
#       'clean' operations.
861
#
862
#   ToolsetObj
863
#       Define toolset created object(s) for removal during
864
#       'clean' operations.
865
#
866
#   ToolsetLib
867
#       Define toolset created library(s) for removal during
868
#       'clean' operations.
869
#
870
#   ToolsetProg
871
#       Define toolset created prog(s) for removal during
872
#       'clean' operations.
873
#
874
#   ToolsetRule( )
875
#   ToolsetRules( )
876
#       Specifies toolset rules for insertion into the target makefile.
877
#
878
##############################################################################
879
 
880
sub Toolset
881
{
882
    my( $platforms, $toolset, @arguments ) = @_;
883
 
884
    Debug2( "Toolset(@_)" );
885
 
886
    return if ( ! ActivePlatform($platforms) );
887
 
888
    $ScmToolset = $toolset;
889
    @ScmToolsetArgs = @arguments;
890
}
891
 
892
 
893
sub ToolsetRequire
894
{
895
    my( $script, @arguments ) = @_;
896
    my( $file );
897
 
898
    Debug2( "ToolsetRequire(@_)" );
899
 
900
    @ScmToolsetArgs = @arguments;
901
    $file = Require( "",
902
                     $script,
903
                     "ToolsetRequire",
904
                     "$::GBE_CONFIG/TOOLSET", @::BUILDTOOLSPATH );
905
    push( @ScmDepends, "$file" );
906
}
907
 
908
 
909
sub ToolsetDefine
910
{
911
    Debug2( "ToolsetDefine(@_)" );
912
 
913
    Define( @_ );
914
}
915
 
916
 
917
sub ToolsetDefines
918
{
919
    Debug2( "ToolsetDefines(@_)" );
920
 
261 dpurdie 921
    Defines( "$::GBE_CONFIG/TOOLSET", @_ );
227 dpurdie 922
}
923
 
924
 
925
sub ToolsetDir
926
{
927
    Debug2( "ToolsetDir(@_)" );
928
 
261 dpurdie 929
    UniquePush ( \@TOOLSETDIRS, @_ );
227 dpurdie 930
}
931
 
932
 
933
sub ToolsetDirTree
934
{
935
    Debug2( "ToolsetDirTree(@_)" );
936
 
261 dpurdie 937
    UniquePush ( \@TOOLSETDIRTREES, @_);
227 dpurdie 938
}
939
 
940
 
941
sub ToolsetGenerate
942
{
943
    Debug2( "ToolsetGenerate(@_)" );
944
 
945
    UniquePush( \@TOOLSETGENERATED, @_ );
946
}
947
 
948
 
949
sub ToolsetObj
950
{
951
    Debug2( "ToolsetObj(@_)" );
952
 
261 dpurdie 953
    foreach my $obj ( @_ )
227 dpurdie 954
    {
261 dpurdie 955
        UniquePush( \@TOOLSETOBJS, "$obj.$::o"  );
227 dpurdie 956
    }
957
}
958
 
959
 
960
sub ToolsetLib
961
{
962
    Debug2( "ToolsetLib(@_)" );
963
 
261 dpurdie 964
    foreach my $lib ( @_ )
227 dpurdie 965
    {
289 dpurdie 966
        UniquePush( \@TOOLSETLIBS, GenLibName( $lib ) );
227 dpurdie 967
    }
968
}
969
 
970
 
971
sub ToolsetProg
972
{
973
    Debug2( "ToolsetProg(@_)" );
974
 
261 dpurdie 975
    foreach my $prog ( @_ )
227 dpurdie 976
    {
289 dpurdie 977
        UniquePush( \@TOOLSETPROGS, GenProgName( $prog ) );
227 dpurdie 978
    }
979
}
980
 
981
 
982
sub ToolsetRule
983
{
984
    Debug2( "ToolsetRule(@_)" );
985
 
986
    push( @TOOLSETRULES, @_ );
987
}
988
 
989
 
990
sub ToolsetRules
991
{
992
    my( $script ) = @_;
993
    my( $line );
994
 
995
    Debug2( "ToolsetRules(@_)" );
996
 
997
    $script = Exists( "$::GBE_CONFIG/TOOLSET", $script, "ToolsetRules" );
271 dpurdie 998
    push( @TOOLSETRULES, "# ToolsetRules from: $script" );
285 dpurdie 999
    open( my $fh, '<', $script ) || Error( "Opening $script" );
1000
    while (<$fh>) {
227 dpurdie 1001
        $_ =~ s/\s*(\n|$)//;                    # kill trailing whitespace & newline
1002
        push( @TOOLSETRULES, $_ );
1003
    }
1004
    push( @ScmDepends, "$script" );             # makefile dependencies
285 dpurdie 1005
    close( $fh );
227 dpurdie 1006
}
1007
 
1008
 
1009
###############################################################################
1010
# User interface:
1011
#
1012
#   AddFlags( 'platform [, ... ]', 'flags' [, 'flag' ... ] )
1013
#       This subroutine takes the C and C++ compiler flags
1014
#       specified adding them to a global list for later
1015
#       inclusion in the built makefile.
1016
#
1017
#   AddCFlags( 'platform [, ... ]', 'flags' [, 'flag' ... ] )
1018
#       This subroutine takes the C compiler flags
1019
#       specified adding them to a global list for later
1020
#       inclusion in the built makefile.
1021
#
1022
#   AddCXXFlags( 'platform [, ... ]', 'flags' [, 'flag' ... ] )
1023
#       This subroutine takes the C++ compiler flags
1024
#       specified adding them to a global list for later
1025
#       inclusion in the built makefile.
1026
#
1027
#   AddLintFlags( 'platform [, ... ]', 'flags' [, ... ] )
1028
#       This subroutine takes the Lint flags specified
1029
#       adding them to a global list for later inclusion
1030
#       in the built makefile.
1031
#
1032
#   AddASFlags( 'platform [, ... ]', 'flags' [, ... ] )
1033
#       This subroutine takes the Assemler flags specified
1034
#       adding them to a global list for later inclusion
1035
#       in the built makefile.
1036
#
1037
#   AddLDFlags( 'platform [, ... ]', 'flags' [, ... ] )
1038
#       This subroutine takes the Linker flags specified
1039
#       adding them to a global list for later inclusion
1040
#       in the built makefile.
1041
#
1042
#   AddDir
1043
#       This subroutine takes the directories specified adding
1044
#       them to a global include and source directory list for
1045
#       later inclusion in the built makefile.
1046
#
1047
#   AddIncDir( 'platform [, ... ]', 'dir' [, ... ] )
1048
#       This subroutine takes the include file directories
1049
#       specified adding them to a global list for later
1050
#       inclusion in the built makefile.
1051
#
1052
#   AddSrcDir( 'platform [, ... ]', 'dir' [, ... ] )
1053
#       This subroutine takes the source file directories
1054
#       specified adding them to a global list used to resolve
1055
#       Src() definitions.
1056
#
1057
#   AddLibDir( 'platform [, ... ]', 'dir' [, ... ] )
1058
#       This subroutine takes the library directories
1059
#       specified adding them to a global list for later
1060
#       inclusion in the built makefile.
1061
#
1062
#   AddSourceType( 'ext', '.c|.cc|.asm' )
1063
#       This subroutine takes the extension(s) specified by the
1064
#       programmer and adds them to a global list for later
1065
#       inclusion in the built makefile.  This list contains
1066
#       the extensions to be recognised as 'C', 'C++' or
1067
#       assembler file types.
1068
#
1069
#   AddSourceFile( 'platform [, ... ]', 'file' [, ... ] )
1070
#       This subroutine takes the non-standard source file(s)
1071
#       and adds them add it to either C, C++ or assembler
1072
#       sources and the object list.
1073
#
1074
#   Init( 'platform [, ... ]', 'rule' )
1075
#       Initialisation rule
1076
#
1077
#   Generate( 'platform [, ... ]', 'file' [, ... ] )
1078
#       This subroutine is used to add the list of given
1079
#       source files to the generate sources list, and if
1080
#       the generated source is of type C, C++ or assember
1081
#       also adds it to either C, C++ or assembler sources and
1082
#       the object lists.
1083
#
1084
#       --c             Treat as a C source file.
1085
#       --cpp           Treat as a C++ source file.
1086
#       --asm           Treat as a assembler source file.
1087
#
1088
#   Rule( 'platform [, ... ]', definition )
1089
#       This subroutine is used to add the non-standard make
1090
#       rules required to build the system.  eg. any rules
1091
#       necessary to produce a .cc & .h file from a .x file.
1092
#
1093
#   Src( 'platform [, ... ]', 'file' [, ... ], [ 'arg' [, ...]] )
1094
#       This subroutine is used to add the list of given source
1095
#       files to the sources list, and if the source is of type
1096
#       C, C++ or assember also adds it to either C, C++ or
1097
#       assembler sources and the object lists.  The optional
1098
#       list of arguments is assigned to all source files.
1099
#
1100
#       --c             Treat as a C source file.
1101
#       --cpp           Treat as a C++ source file.
1102
#       --asm           Treat as a assembler source file.
1103
#       --Shared        Shared, produces position-independent
1104
#                       code (on targets where required).
1105
#
1106
#   Lib( 'platform [, ... ]', 'name', 'obj' [, ... ] [, '-arg' [, ... ]] )
1107
#       This subroutine takes a library definition list and adds
1108
#       the  entries to the 3 libraries definition lists. 'name'
1109
#       of the library to be created.  List of the object files
1110
#       'obj' that make up this library.  List of special
1111
#       arguments 'arg' to pass to the librarian.
1112
#
1113
#   MergeLibrary( 'platform [, ... ]', 'name', 'lib' [, ... ] )
1114
#       This subroutine takes a library merge list and adds
1115
#       the  entries to the 2 merge libraries definition lists. 'name'
1116
#       of the library to be created.  List of the libraries to be merged
1117
#
1118
#   LocalScript( 'platform [, ... ]', name, ['1'] )
1119
#   Script( 'platform [, ... ]', name, ['1'] )
1120
#       This subroutine takes a list that defines the name of
1121
#       the script to be placed in the platform 'bin' directory,
1122
#       and an optional second element that defines whether the
1123
#       script should be made executable or not.
1124
#
1125
#   Prog( 'platform [, ... ]', 'name', ['obj', ... ],
1126
#               ['-llib', ... ], ['options'] )
1127
#       This subroutine takes a list that defines which program
1128
#       (binary) is to be made, what libraries and object it is
1129
#       made from, and any special commands required to perform
1130
#       the program creation.
1131
#
1132
#       @PROGS          Updated list of programs to create
1133
#
1134
#   TestProg( 'platform [, ... ]', 'name', ['obj', ... ],
1135
#               ['-llib', ... ], ['options'] )
1136
#       This subroutine takes a list that defines which test program
1137
#       (binary) is to be made, what libraries and object it is
1138
#       made from, and any special commands required to perform
1139
#       the program creation.
1140
#
1141
#       @TESTPROGS      Updated list of programs to create
1142
#
1143
#   InstallHdr( 'platform [, ... ]', 'file' [, ...], ['-arg'] )
1144
#       This subroutine takes the given list of files and adds them
1145
#       to the install header files list.  Files in this list will be
1146
#       installed into the 'local header directory' area for public
1147
#       consumption.  This is generally API files for other modules
1148
#       to use.
1149
#
1150
#       --Strip         Strip directory from source
1151
#       --Full          Install using full path
1152
#       --Subdir=subdir Install within the specified sub-directory
1153
#       --Prefix=subdir   "       "     "      "      "     "
1154
#
1155
#   InstallLib( 'platform [, ... ]', 'file', ['subdir'] )
1156
#       This subroutine takes the given list of files and adds them
1157
#       to the install libraries files list.  Files in this list will
1158
#       be installed into the 'local library directory' area for
1159
#       public consumption.
1160
#
1161
#   InstallProg( 'platform [, ... ]', 'file', ['subdir'] ) )
1162
#       This subroutine takes a list that defines the executable file
1163
#       that is to be installed.  The file in this list will be
1164
#       installed into the 'local executable directory' specified for
1165
#       public consumption.
1166
#
1167
###############################################################################
1168
 
1169
 
1170
sub Include                                     # User include
1171
{
1172
    my( $path, $name ) = @_;
1173
    my( $file );
1174
 
1175
    $file = Require( $path, $name, "Include" );
1176
    push( @ScmDepends, "$file" );
1177
}
1178
 
1179
sub ForceCCompile
1180
{
1181
    CompileOptions( $_[0], 'compile_as_c' );            # Backward compatability
1182
}
1183
 
1184
#-------------------------------------------------------------------------------
1185
#   Create a data structure to define the global compiler options
1186
#    The hash is keyed by compiler option
1187
#    The value contains another hash.
1188
#       The key is a makefile variable to set ( or remove )
1189
#       The value is the value to assign to the makefile variable
1190
#       If the value is 'undef' then the variable will be deleted
1191
#
1192
#   Keys of the form key=value are also supported
1193
#
1194
#   If the value is a CODE reference, then routine will be called with the key
1195
#   and value as arguments. The return value will be utilised.
1196
#
1197
our %ScmCompilerOptions =
1198
    (
1199
        'strict_ansi'           => { 'USE_STRICT_ANSI'    => '1' },
1200
        'no_strict_ansi'        => { 'USE_STRICT_ANSI'    => '' },      # Default
1201
 
1202
        'profile'               => { 'USE_PROFILE'        => '1' },
1203
        'no_profile'            => { 'USE_PROFILE'        => '' },       # Default
1204
 
1205
 
1206
        'prod_no_optimise'      => { 'PROD_USE_OPTIMISE'   => '' },
1207
        'prod_no_debuginfo'     => { 'PROD_USE_DEBUGINFO'  => '' },     # Default
1208
        'prod_optimise'         => { 'PROD_USE_OPTIMISE'   => '1' },    # Default
1209
        'prod_debuginfo'        => { 'PROD_USE_DEBUGINFO'  => '1' },
1210
 
1211
        'debug_no_optimise'     => { 'DEBUG_USE_OPTIMISE'  => '' },     # Default
1212
        'debug_no_debuginfo'    => { 'DEBUG_USE_DEBUGINFO' => '' },
1213
        'debug_optimise'        => { 'DEBUG_USE_OPTIMISE'  => '1' },
1214
        'debug_debuginfo'       => { 'DEBUG_USE_DEBUGINFO' => '1' },    # Default
1215
 
1216
        'compile_as_cpp'        => { 'FORCE_CC_COMPILE'    => '1',
1217
                                     'FORCE_C_COMPILE'     => undef },
1218
        'compile_as_c'          => { 'FORCE_C_COMPILE'     => '1',
1219
                                     'FORCE_CC_COMPILE'    => undef },
267 dpurdie 1220
 
1221
        'no_define_source_file' => { 'DISABLE__SOURCE__' => '1' },
1222
        'define_source_file'    => { 'DISABLE__SOURCE__' => undef },    # Default
1223
 
227 dpurdie 1224
    );
1225
 
1226
#
1227
#   The toolset can extend the options by setting the following hash
1228
#
1229
our %ScmToolsetCompilerOptions = ();
1230
 
1231
#
1232
#   Define default compiler options
1233
#   These are makefile variables that will be assigned
1234
#
1235
our %ScmCompilerOpts =
1236
    (
1237
        'USE_STRICT_ANSI'       => '',
1238
        'USE_PROFILE'           => '',
1239
        'PROD_USE_DEBUGINFO'    => '',
1240
        'PROD_USE_OPTIMISE'     => '1',
1241
        'DEBUG_USE_OPTIMISE'    => '',
1242
        'DEBUG_USE_DEBUGINFO'   => '1',
1243
    );
1244
 
1245
 
1246
sub CompileOptions
1247
{
1248
    my( $platforms, @elements ) = @_;
1249
    return if ( ! ActivePlatform($platforms) );
1250
 
1251
    for (@elements)
1252
    {
1253
        my $oref;
1254
 
1255
        #
1256
        #   The toolset option may be a text string or a definition
1257
        #       Name        - A text string
1258
        #       Name=Value  - A value
1259
        #
1260
        my $value;
1261
        my $key = $_;
1262
        if ( $key =~ m~(.*=)(.*)~ )
1263
        {
1264
            $key = $1;
1265
            $value = $2 || '';
1266
        }
247 dpurdie 1267
        $key = lc( $key );
227 dpurdie 1268
 
1269
        #
1270
        #   Examine the global flags
1271
        #   Then the toolset extensions
1272
        #   Then just drop it
1273
        #
1274
        unless ( $oref = ($ScmCompilerOptions{$key} || $ScmToolsetCompilerOptions{$key}) )
1275
        {
1276
            Warning ("Compile Option ignored: $_");
1277
            next;
1278
        }
1279
 
1280
        #
1281
        #   Parse the definition and adjust makefile variables as required
1282
        #   Set the value of a make variable or remove the definition
1283
        #
1284
        #   If the user value is a code reference, then call the code
1285
        #   and use the returned value as the value.
1286
        #
1287
        while ( (my($ukey, $uvalue)) = each %{$oref} )
1288
        {
1289
            if ( defined( $uvalue) )
1290
            {
1291
                if ( ref($uvalue) eq "CODE" )
1292
                {
255 dpurdie 1293
                    $uvalue = &$uvalue( $key, $value, $ukey);
227 dpurdie 1294
                    unless ( defined $uvalue )
1295
                    {
1296
                        Warning ("Compile Option ignored: $_");
1297
                        next;
1298
                    }
1299
                }
247 dpurdie 1300
                elsif ( defined $value )
1301
                {
1302
                    $uvalue = $value;
1303
                }
227 dpurdie 1304
 
1305
                $ScmCompilerOpts{$ukey} = $uvalue;
1306
            }
1307
            else
1308
            {
1309
                delete $ScmCompilerOpts{$ukey};
1310
            }
1311
        }
1312
    }
1313
}
1314
 
1315
#-------------------------------------------------------------------------------
1316
# Function        : AddFlags
1317
#                   AddCFlags
1318
#                   AddCXXFlags
1319
#                   AddASFlags
1320
#                   AddLDFlags
1321
#                   AddLintFlags
1322
#
1323
# Description     : Add target specfic flags to the C compiler
1324
#                   This SHOULD only be used to add Defines to the compiler
1325
#                   but it can be absued.
1326
#
1327
# Inputs          : $platform       - Platforms for which the directive is active
1328
#                   ...             - list of flags to add
1329
#
1330
#                   Embedded options include:
1331
#                       --Debug     - Following options are added to the debug build
1332
#                       --Prod      - Following options are added to the production build
1333
#
1334
# Returns         : Nothing
1335
#
1336
 
1337
sub AddFlags
1338
{
1339
    my( $platforms, @elements ) = @_;
1340
 
1341
    AddCFlags( $platforms, @elements );
1342
    AddCXXFlags( $platforms, @elements );
1343
}
1344
 
1345
sub AddCFlags
1346
{
1347
    my( $platforms, @elements ) = @_;
1348
 
1349
    Debug2( "AddCFlags($platforms, @elements)" );
1350
    return if ( ! ActivePlatform($platforms) );
1351
 
1352
    WarnIfNastyFlag( @elements );
1353
    __AddFlags( "CFLAGS", \@elements,
1354
                \@CFLAGS, \@CLINTFLAGS,
1355
                \@CFLAGS_DEBUG, \@CLINTFLAGS_DEBUG,
1356
                \@CFLAGS_PROD,  \@CLINTFLAGS_PROD );
1357
}
1358
 
1359
sub AddCXXFlags
1360
{
1361
    my( $platforms, @elements ) = @_;
1362
 
1363
    Debug2( "AddCXXFlags($platforms, @elements)" );
1364
    return if ( ! ActivePlatform($platforms) );
1365
 
1366
    WarnIfNastyFlag( @elements );
1367
    __AddFlags( "CXXFLAGS", \@elements,
1368
               \@CXXFLAGS, \@CXXLINTFLAGS,
1369
               \@CXXFLAGS_DEBUG, \@CXXLINTFLAGS_DEBUG,
1370
               \@CXXFLAGS_PROD,  \@CXXLINTFLAGS_PROD );
1371
}
1372
 
1373
sub AddASFlags
1374
{
1375
    my( $platforms, @elements ) = @_;
1376
 
1377
    Debug2( "AddASFlags($platforms, @elements)" );
1378
 
1379
    return if ( ! ActivePlatform($platforms) );
1380
 
267 dpurdie 1381
    __AddFlags( "ASFLAGS", \@elements,
1382
                \@ASFLAGS, undef,
1383
                \@ASFLAGS_DEBUG, undef,
1384
                \@ASFLAGS_PROD, undef );
227 dpurdie 1385
}
1386
 
1387
sub AddLDFlags
1388
{
1389
    my( $platforms, @elements ) = @_;
1390
 
1391
    Debug2( "AddLDFlags($platforms, @elements)" );
1392
 
1393
    return if ( ! ActivePlatform($platforms) );
1394
 
1395
    foreach  ( @elements )
1396
    {
267 dpurdie 1397
        next if ( m~^--(Debug|Prod)~ );
227 dpurdie 1398
        Warning("Use of linker flag discouraged (will be used): $_");
1399
    }
267 dpurdie 1400
    __AddFlags( "LDFLAGS", \@elements,
1401
                \@LDFLAGS, undef,
1402
                \@LDFLAGS_DEBUG, undef,
1403
                \@LDFLAGS_PROD, undef );
227 dpurdie 1404
 
1405
}
1406
 
1407
sub AddLintFlags
1408
{
1409
    my( $platforms, @elements ) = @_;
1410
 
1411
    return if ( ! ActivePlatform($platforms) );
1412
 
1413
    Debug2( "AddLintFlags($platforms, @elements)" );
1414
 
1415
    __AddFlags( "LINTFLAG", \@elements,
1416
                \@CLINTFLAGS, \@CXXLINTFLAGS,
1417
                \@CLINTFLAGS_DEBUG, \@CXXLINTFLAGS_DEBUG,
1418
                \@CLINTFLAGS_PROD, \@CXXLINTFLAGS_PROD  );
1419
}
1420
 
1421
 
1422
#-------------------------------------------------------------------------------
1423
# Function        : __AddFlags
1424
#
1425
# Description     : Generic flag adding to lists routine
1426
#                   Internal use only
1427
#
1428
#                   Supports --Debug and --Prod options
1429
#                   if the appropriate list is present.
1430
#
1431
# Inputs          : Lots
1432
#                   References to compiler and lint flags for
1433
#                   common, debug and product builds.
1434
#
1435
#                   Not all the lists are needed.
1436
#
1437
# Returns         : Nothing
1438
#
1439
sub __AddFlags
1440
{
1441
    my ($textname, $eref,
1442
                   $f_all,      $flint_all,
1443
                   $f_debug,    $flint_debug,
1444
                   $f_prod,     $flint_prod ) = @_;
1445
 
1446
    #
1447
    #   Start added flags to the ALL lists
1448
    #
1449
    my $list = $f_all;
1450
    my $lintlist = $flint_all;
1451
    my $nowarn = 0;
1452
 
1453
    #
1454
    #   Process flags up front
1455
    #
1456
    $nowarn = 1 if ( grep (/^--NoWarn$/, @$eref) );
1457
 
1458
    #
1459
    #   Process all the user arguments
1460
    #
1461
    ADD:
1462
    foreach my $element ( @$eref )
1463
    {
1464
        #
1465
        #   Skip flags
1466
        #
1467
        if ( $element eq '--NoWarn' )
1468
        {
1469
            next;
1470
        }
1471
 
1472
        #
1473
        #   Detect --Debug and --Prod options and swap
1474
        #   lists accordingly.
1475
        #
1476
        if ( $element eq '--Debug' )
1477
        {
1478
            Error ("--Debug not supported for $textname") unless ( $f_debug );
1479
            $list = $f_debug;
1480
            $lintlist = $flint_debug;
1481
            next;
1482
        }
1483
 
1484
        if ( $element eq '--Prod' )
1485
        {
1486
            Error ("--Prod not supported for $textname") unless ( $f_prod );
1487
            $list = $f_prod;
1488
            $lintlist = $flint_prod;
1489
            next;
1490
        }
1491
 
1492
        #
1493
        #   Scan all the lists for a possible duplicates
1494
        #
1495
        foreach my $temp ( @$f_all, @$f_debug, @$f_prod ) {
1496
            if ($temp eq $element) {
1497
                Warning( "Duplicate $textname ignored '$element'") unless $nowarn;
1498
                next ADD;
1499
            }
1500
        }
1501
 
1502
        #
1503
        #   Add the flag to the compiler and lint lists
1504
        #
1505
        push( @$list, $element ) if $list;
1506
        push( @$lintlist, $element ) if $lintlist;
1507
    }
1508
}
1509
 
1510
sub WarnIfNastyFlag
1511
{
1512
    foreach  ( @_ )
1513
    {
1514
        Warning("Use of compiler flags discouraged (will be used): $_")
1515
            unless ( m/^-[DU]/ || m/^--Debug/ || m/^--Prod/ || /^--NoWarn/ );
1516
    }
1517
}
1518
 
1519
 
1520
sub AddDir
1521
{
1522
    AddIncDir( @_);
1523
    AddSrcDir( @_ );
1524
}
1525
 
1526
 
1527
sub AddIncDir
1528
{
1529
    _AddDir( 'AddIncDir', 'INCDIR', \@INCDIRS, \@S_INCDIRS, \@G_INCDIRS, \@L_INCDIRS, @_ );
1530
}                                                           
1531
 
1532
sub AddSrcDir                                               
1533
{                                                           
1534
    _AddDir( 'AddSrcDir', 'SRCDIR', \@SRCDIRS, \@S_SRCDIRS, \@G_SRCDIRS, \@L_SRCDIRS, @_ );
1535
}                                                           
1536
 
1537
sub AddLibDir                                               
1538
{                                                           
1539
    _AddDir( 'AddLibDir', 'LIBDIR', \@LIBDIRS, \@S_LIBDIRS, \@G_LIBDIRS, \@L_LIBDIRS, @_ );
1540
}
1541
 
1542
#-------------------------------------------------------------------------------
1543
# Function        : _AddDir
1544
#
1545
# Description     : Internal routine to add a directory to list of directories
1546
#                   Common code to simplify implementation of other directives
1547
#
1548
# Inputs          : $name           - Name of function
1549
#                   $udir           - User name of dir list
1550
#                   $dirref         - Reference to directory array
1551
#                   $s_dirref       - Reference to system directory array
1552
#                   $g_dirref       - Reference to global directory array
1553
#                   $l_dirref       - Reference to local directory array
1554
#                   @args           - User arguments
1555
#                                       - platforms
1556
#                                       - Directories and --Options
1557
#
1558
sub _AddDir
1559
{
1560
    my( $name, $udir, $dirref, $s_dirref, $g_dirref, $l_dirref, $platforms, @elements ) = @_;
1561
 
1562
    Debug ( "$name($platforms, @elements)" );
1563
    Error ( "$name: Insufficient arguments") unless ( @elements );
1564
    return if ( ! ActivePlatform($platforms) );
1565
 
1566
    #
1567
    #   Cleanup user parameters
1568
    #
1569
    foreach ( @elements )
1570
    {
1571
        s/^\s+//;                               # Remove leading space
1572
        s/\s+$//;                               # Remove trailing spaces
1573
        s~/$~~;                                 # Remove trailing /
1574
        s~//~/~g;                               # Remove multiple /
1575
    }
1576
 
1577
#.. Collect arguments
1578
    my $tlist_ref = $ScmGlobal ? $g_dirref : $l_dirref; # "current" scope ....
1579
    my $nowarn = 0;
1580
    my $nodepend = 0;
1581
    my @dirs;
1582
 
1583
    foreach ( @elements )
1584
    {
1585
        if ( ! /^--/ ) {                        # Collect directories
1586
            push @dirs, $_;
1587
 
1588
        } elsif (/^--Local$/) {                 # "local" scope ....
1589
            $tlist_ref = $l_dirref;
1590
 
1591
        } elsif (/^--Global$/) {                # "global" scope ...
1592
            $tlist_ref = $g_dirref;
1593
 
1594
        } elsif (/^--System$/) {                # "system" scope ...
1595
            $tlist_ref = $s_dirref;
1596
 
1597
        } elsif (/^--NoDepend$/) {              # Split from dependency list
1598
            if ( $udir eq 'INCDIR' ) {          # AddIncDir only
1599
                $nodepend = 1;
1600
            }
1601
 
1602
        } elsif (/^--NoWarn$/) {                # Disable warnings
1603
            $nowarn = 1;
1604
 
1605
        } elsif (/^--(.*)/) {
1606
            Message( "$name: unknown option $_ -- ignored\n" );
1607
 
1608
        }
1609
    }
1610
 
1611
    Error ( "$name: No directory specified: ($platforms, @elements)" )
1612
        unless ( @dirs );
1613
 
1614
 
1615
#.. Push source path(s)
1616
    foreach ( @dirs )
1617
    {
1618
        #
1619
        #   Add to complete list of directories
1620
        #   Warn on duplicates
1621
        #
1622
        unless ( UniquePush( $dirref, $_) )
1623
        {
1624
            Warning( "Duplicate $udir ignored '$_'" )
1625
                unless ( $nowarn );
1626
            next;
1627
        }
1628
 
1629
        #
1630
        #   Check that the directory actually exists
1631
        #   If the path contains a $(XXXXX) then it can't be checked
1632
        #
1633
        if ( index( $_, '$' ) == -1 )
1634
        {
1635
            Warning( "$name. Directory not found: $_",
1636
                     "Current directory         : $::Cwd",
1637
                     "Cannot resolved Directory : " . AbsPath($_),
1638
                       )
1639
                unless ( $nowarn || -d $_ );
1640
        }
1641
 
1642
        #
1643
        #   Add to suitable list
1644
        #
1645
        push @{$tlist_ref}, $_;
1646
 
1647
        #
1648
        #   Add to the no dependancy list (ie generated depend file)
1649
        #   Only used by AddIncDir, accepted by AddSrcDir
1650
        #
1651
        push( @NODEPDIRS, $_ )
1652
            if ($nodepend);
1653
    }
1654
}
1655
 
1656
 
1657
sub AddProg
1658
{
1659
    my( $platforms, @progs ) = @_;
1660
 
1661
    Debug2( "AddProg($platforms, @progs)" );
1662
 
1663
    return if ( ! ActivePlatform($platforms) );
1664
 
285 dpurdie 1665
    foreach my $prog (@progs)
227 dpurdie 1666
    {
289 dpurdie 1667
        my $pProg = $PROGS->Get($prog);
227 dpurdie 1668
        Warning( "Duplicate prog ignored '$prog'" )
289 dpurdie 1669
            if ( $pProg );
1670
        $pProg = $PROGS->NewAdd($prog)
227 dpurdie 1671
    }
1672
}
1673
 
1674
 
1675
sub AddSourceType
1676
{
1677
    my( $ext, $type ) = @_;
1678
 
1679
    Debug2( "AddSourceType(@_)" );
1680
 
1681
    #
1682
    #   Default Source Type (C)
1683
    #
1684
    $type = ".c" unless ( $type );
1685
 
1686
    Error ("Source type '$ext' not allowed")
1687
        if ( $ext !~ /^\.\w+$/ );
1688
 
1689
    $type = lc($type)
1690
        if ( $::ScmHost ne "Unix" );
1691
    $ScmSourceTypes{ $ext } = $type;
1692
}
1693
 
1694
 
1695
sub AddSourceFile
1696
{
1697
    my( $platforms, @elements ) = @_;
1698
 
1699
    Debug2( "AddSourceFile($platforms, @elements)" );
1700
    return if ( ! ActivePlatform($platforms) );
1701
 
285 dpurdie 1702
    foreach my $path ( @elements )
227 dpurdie 1703
    {
1704
        __AddSourceFile( 1, $path );
1705
    }
1706
}
1707
 
1708
 
1709
#-------------------------------------------------------------------------------
1710
# Function        : __AddSourceFile
1711
#
1712
# Description     : Internal function
1713
#                   Add a source file to internal lists
1714
#
1715
#                   Assumes that the current platform is ACTIVE
1716
#
1717
# Inputs          : push    0: Don't push onto OBJS (non-shared objfiles)
1718
#                   path    Filename.extension
1719
#                   obj     object file name (optional)
1720
#                   type    Type of file. "" -> auto detect
1721
#
1722
# Returns         : True        - File is a 'known' source file
1723
#                   False       - File is not a 'known' source file
1724
#
1725
sub __AddSourceFile
1726
{
1727
    my( $push, $path, $obj, $type ) = @_;
271 dpurdie 1728
    my( $filename, $ext, $srcfile, $is_obj, $ext_type, $result );
227 dpurdie 1729
 
271 dpurdie 1730
    $filename = StripDir($path);                # file name
227 dpurdie 1731
 
1732
    $ext  = StripFile($path);                   # extension
1733
    $ext = lc($ext)
1734
        if ( $::ScmHost ne "Unix" );
1735
 
271 dpurdie 1736
    if (! ($srcfile = $SRCS{$filename})) {
227 dpurdie 1737
        $srcfile = $path;                       # generated
1738
    }
1739
 
271 dpurdie 1740
    $obj  = StripExt( $filename )               # Base name of object file
227 dpurdie 1741
        if ( ! defined($obj) || $obj eq "" );
1742
 
1743
    $type = ""                                  # optional type
1744
        if ( ! defined( $type ) );
1745
 
1746
    #
1747
    #   Push file onto a suitable source file list
1748
    #
1749
    $result = 0;
1750
    $ext_type = "";                             # map extension
1751
    $ext_type = $ScmSourceTypes{ $ext }
1752
        if ( exists( $ScmSourceTypes{ $ext } ) );
1753
    $result = 1 if ( $ext_type );
1754
 
1755
    if ( $type eq "" && defined $::ScmToolsetProgSource{$ext} )
1756
    {
1757
        Debug( "SourceFile: $path is ToolsetProgSource   -> $srcfile" );
1758
        push( @CSRCS, $srcfile );
1759
        $result = 1;
1760
    }
1761
    elsif ( ($type eq "" && $ext_type eq ".h") || ($type eq ".h") )
1762
    {
1763
        Debug( "SourceFile: $path is .h   -> $srcfile" );
1764
        push( @CHDRS, $srcfile );
1765
    }
1766
    elsif ( ($type eq "" && $ext_type eq ".inc") || ($type eq ".inc") )
1767
    {
1768
        Debug( "SourceFile: $path is .inc -> $srcfile" );
1769
        push( @ASHDRS, $srcfile );
1770
    }
1771
    elsif ( ($type eq "" && $ext_type eq ".c") || ($type eq ".c") )
1772
    {
1773
        Debug( "SourceFile: $path is .c   -> $srcfile=$obj" );
1774
        push( @CSRCS, $srcfile );
1775
        $is_obj = 1;
1776
    }
1777
    elsif ( ($type eq "" && $ext_type eq ".cc") || ($type eq ".cc") )
1778
    {
1779
        Debug( "SourceFile: $path is .cc  -> $srcfile=$obj" );
1780
        push( @CXXSRCS, $srcfile );
1781
        $is_obj = 1;
1782
    }
1783
    elsif ( ($type eq "" && $ext_type eq ".asm") || ($type eq ".asm") )
1784
    {
1785
        Debug( "SourceFile: $path is .asm -> $srcfile=$obj" );
1786
        push( @ASSRCS, $srcfile );
1787
        $is_obj = 1;
1788
    }
1789
    elsif ( $ext_type eq "--Ignore" )
1790
    {   # ignored ...
1791
        #   .x      "rpcgen" source files
1792
        #   .ini    Configuration
1793
        #   .sh     Shell script
1794
    }
1795
    else
1796
    {
1797
        Debug( "SourceFile: $path is unknown file type" );
1798
 
1799
        #
1800
        #   Insert source files with unknown extensions onto lists
1801
        #   of there own type
1802
        #
1803
        if ( $ext )
1804
        {
1805
            (my $varname = uc ( $ext . 'SRCS')) =~ s~\.~~g;
1806
            no strict 'refs';
1807
            push @$varname, $srcfile;
1808
            use strict 'refs';
1809
        }
1810
    }
1811
 
1812
    #
271 dpurdie 1813
    #   See if there is a hook function for this type of source file
1814
    #   Invoke user function to perform additional processing on the file
1815
    #
1816
    if ( %MF_RegisterSrcHooks )
1817
    {
1818
        my @listeners;
1819
        push @listeners, @{$MF_RegisterSrcHooks{$ext}} if ( exists $MF_RegisterSrcHooks{$ext} );
1820
        push @listeners, @{$MF_RegisterSrcHooks{'*'}}  if ( exists $MF_RegisterSrcHooks{'*'} );
1821
        while ( @listeners )
1822
        {
1823
            Debug( "RegisterSrcHook: Invoke SrcHook function" );
1824
            my ($fname, @args) = @{shift @listeners};
1825
            &$fname ( $srcfile ,$filename, $obj, $ext ,@args );
1826
        }
1827
    }
1828
 
1829
    #
227 dpurdie 1830
    #   Object files are saved in
1831
    #       OBJSOURCE   - Generate a recipe to create the object
1832
    #       OBJS        - A list of ALL non-shared object files
1833
    #
1834
    if ( $is_obj && $::o )
1835
    {
1836
        $OBJSOURCE{ "$obj" } = $srcfile;
1837
        push( @OBJS, $obj )
1838
            if ($push);
1839
    }
1840
 
1841
    #
1842
    #   Indicate to the user that the file is a 'known' source file
1843
    #   This implies that the file is required early in the build process
1844
    #   and may need to be generated early.
1845
    #
1846
    return $result;
1847
}
1848
 
1849
#-------------------------------------------------------------------------------
1850
# Function        : SetValue
1851
#
1852
# Description     : Defines a variable that can be used within the makefile.pl
1853
#                   Use sparingly
1854
#                   An attempt to formalise a mechanism that is used anyway, but
1855
#                   with correct platform detection
1856
#
1857
# Inputs          : $platform       - Platform selector
1858
#                   $name           - Name to set
1859
#                   $value          - Value to set
1860
#                   options         - Options
1861
#                                       --NoWarn
1862
#                                       --Project=xxxx[,xxxx]+
1863
#                                       --
1864
#
1865
sub SetValue
1866
{
1867
    my( $platforms, @elements ) = @_;
1868
    my $name;
1869
    my $value;
1870
    my $nowarn;
1871
    my $nomoreswicthes = 0;
1872
 
1873
    Debug2( "SetValue($platforms, @elements)" );
1874
 
1875
    return if ( ! ActivePlatform($platforms) );
1876
 
1877
    #
1878
    #   Process elements extracting values and options
1879
    #
1880
    foreach ( @elements )
1881
    {
1882
        if ( m/^--$/ ) {
1883
            $nomoreswicthes = ! $nomoreswicthes;
1884
            next;
1885
        }
1886
 
1887
        if ( m/^--/ && ! $nomoreswicthes )
1888
        {
1889
 
1890
            if ( m/^--NoWarn/ ) {
1891
                $nowarn = 1;
1892
 
1893
            } elsif ( m/^--Project=(.*)/ ) {
1894
                return unless ( ActiveProject( $1) );
1895
 
1896
            } else {
1897
                Error ("SetValue: Unknown option: $_");
1898
 
1899
            }
1900
 
1901
        } elsif ( ! defined $name ) {
1902
            $name = $_;
1903
 
1904
        } elsif ( ! defined $value ) {
1905
            $value = $_;
1906
 
1907
        } else {
1908
            Error ("SetValue: $name. Too many parameters" );
1909
 
1910
        }
1911
    }
1912
 
1913
    #
1914
    #   Warn if the named variable already exists
1915
    #   It may be a JATS internal or it may be a user.
1916
    #
1917
    unless ( $nowarn )
1918
    {
1919
        no strict 'refs';
1920
        Warning("SetValue: $name. Redefined") if defined ( $$name );
1921
        use strict 'refs';
1922
    }
1923
 
1924
    #
1925
    #   Set the value
1926
    #
1927
    no strict 'refs';
1928
    $$name = $value;
1929
    use strict 'refs';
1930
}
1931
 
1932
#-------------------------------------------------------------------------------
1933
# Function        : SetList
1934
#
1935
# Description     : Defines a list variable that can be used within the makefile.pl
1936
#                   Use sparingly
1937
#                   An attempt to formalise a mechanism that is used anyway, but
1938
#                   with correct platform detection
1939
#
1940
# Inputs          : $platform       - Platform selector
1941
#                   $name           - Name to set
1942
#                   $value,...      - Values to set
1943
#                   options         - Options
1944
#                                       --NoWarn
1945
#                                       --Project=xxxx[,xxxx]+
1946
#                                       --Unique
1947
#                                       --Clear
1948
#                                       --Append
1949
#                                       --
1950
#
1951
my %SetList_names;
1952
sub SetList
1953
{
1954
    my( $platforms, @elements ) = @_;
1955
    my $name;
1956
    my @value;
1957
    my $nowarn;
1958
    my $unique;
1959
    my $clear;
1960
    my $nomoreswicthes = 0;
1961
 
1962
    Debug2( "SetList($platforms, @elements)" );
1963
 
1964
    return if ( ! ActivePlatform($platforms) );
1965
 
1966
    #
1967
    #   Process elements extracting values and options
1968
    #
1969
    foreach ( @elements )
1970
    {
1971
        if ( m/^--$/ ) {
1972
            $nomoreswicthes = ! $nomoreswicthes;
1973
            next;
1974
        }
1975
 
1976
        if ( m/^--/ && ! $nomoreswicthes )
1977
        {
1978
            if ( m/^--NoWarn/ ) {
1979
                $nowarn = 1;
1980
 
1981
            } elsif ( m/^--Project=(.*)/ ) {
1982
                return unless ( ActiveProject( $1) );
1983
 
1984
            } elsif ( m/^--Unique/ ) {
1985
                $unique = 1;
1986
 
1987
            } elsif ( m/^--Clear/ ) {
1988
                $clear = 1;
1989
 
1990
            } elsif ( m/^--Append/ ) {
1991
                $clear = 0;
1992
 
1993
            } else {
1994
                Error ("SetList: Unknown option: $_");
1995
            }
1996
        } elsif ( ! defined $name ) {
1997
            $name = $_;
1998
 
1999
        } else {
2000
            push @value, $_;
2001
 
2002
        }
2003
    }
2004
 
2005
    Error ("SetList: No name specified") unless ( $name );
2006
 
2007
    #
2008
    #   Warn if the named variable already exists
2009
    #   It may be a JATS internal or it may be a user.
2010
    #
2011
    #   Only do this iff the name is not known to this function
2012
    #   Keep a list a names that have been set.
2013
    #
2014
    if ( ! $SetList_names{$name} && ! $nowarn )
2015
    {
2016
        no strict 'refs';
2017
        Warning("SetList: $name. Defined outside the ScanList/SetList directive","May clash with Jats internals") if defined ( @$name );
2018
        use strict 'refs';
2019
    }
2020
    $SetList_names{$name} = 1;
2021
 
2022
    #
2023
    #   Clear list
2024
    #
2025
    if ( $clear )
2026
    {
2027
        no strict 'refs';
2028
        @$name = ();
2029
        use strict 'refs';
2030
    }
2031
 
2032
    #
2033
    #   Set the value
2034
    #
2035
    no strict 'refs';
2036
    if ( $unique ) {
2037
        UniquePush( \@$name, @value);
2038
    } else {
2039
        push @$name, @value;
2040
    }
2041
    use strict 'refs';
2042
}
2043
 
2044
#-------------------------------------------------------------------------------
2045
# Function        : ScanList
2046
#
2047
# Description     : Create a list by scanning for files in a directory
2048
#                   The files may be in a local directory or within a package
2049
#                   Care must be taken when using a package as the results
2050
#                   may differ bewteen BuildPkgArchive and LinkPkgArchive
2051
#
2052
#                   Interworks with SetList
2053
#
2054
# Inputs          : $platform       - Platform selector
2055
#                   $name           - Name to set
2056
#                   $value,...      - Values to set
2057
#                   options         - Options
2058
#                                       --NoWarn
2059
#                                       --Project=xxxx[,xxxx]+
2060
#                                       --Unique
2061
#                                       --Clear
2062
#                                       --Append
2063
#
2064
#                                       --Package=xxxx[,ext]
2065
#                                       --Dir=xxx
2066
#
2067
#                                       --Subdir=yyy
2068
#                                       --DirListOnly
2069
#                                       --FileListOnly
2070
#                                       --Recurse
2071
#                                       --NoRecurse
2072
#
2073
#                                       --FilterIn=xxx
2074
#                                       --FilterInRe=xxx
2075
#                                       --FilterOut=xxx
2076
#                                       --FilterOutRe=xxx
2077
#
2078
# Returns         :
2079
#
2080
sub ScanList
2081
{
2082
    my( $platforms, @elements ) = @_;
2083
    my $name;
2084
    my $package;
2085
    my $dir;
2086
    my $subdir;
2087
    my @set_args;
2088
    my $search = JatsLocateFiles->new('Recurse','FullPath' );
2089
 
2090
    Debug2( "ScanList($platforms, @elements)" );
2091
 
2092
    return if ( ! ActivePlatform($platforms) );
2093
 
2094
    #
2095
    #   Process elements extracting values and options
2096
    #
2097
    foreach ( @elements )
2098
    {
2099
        if ( m/^--Unique|--Clear|--Append|--NoWarn/ ) {
2100
            push @set_args, $_;
2101
 
2102
        } elsif ( m/^--Project=(.*)/ ) {
2103
            return unless ( ActiveProject( $1) );
2104
 
2105
        } elsif ( m/^--Package=(.*)/ ) {
2106
            $package = $1;
2107
 
2108
        } elsif ( m/^--Dir=(.*)/ ) {
2109
            $dir = $1;
2110
 
2111
        } elsif ( m/^--Subdir=(.*)/ ) {
2112
            $subdir = $1;
2113
 
2114
        } elsif ( $search->option( $_ ) ) {
2115
            Verbose ("Search Option: $_" );
2116
 
2117
        } elsif ( m/^--/ ) {
2118
            Error ("ScanList: Unknown option: $_");
2119
 
2120
        } elsif ( ! defined $name ) {
2121
            $name = $_;
2122
 
2123
        } else {
2124
                Error ("ScanList $name: Unknown option: $_");
2125
 
2126
        }
2127
    }
2128
 
2129
    Error ("ScanList: No variable name specified") unless ( $name );
2130
    Error ("ScanList: Must Specify --Dir or --Package") unless ( $dir || $package );
2131
    Error ("ScanList: --Dir and --Package are mutually exclusive") if ( $dir && $package );
2132
 
2133
    #
2134
    #   Locate the base of the scan
2135
    #   This may be either a package name or a local directory
2136
    #
2137
    #   Its no use allowing the user to use OBJ/LIB/BIN directories as the
2138
    #   directories MUST exist at build time. Don't really want the user doing
2139
    #   that level of poking out of a package
2140
    #
2141
    if ( $package )
2142
    {
2143
        $dir = GetPackageBase( "ScanList", $package );
2144
        Error ("ScanList: Package not found: $package") unless ( $dir );
2145
    }
2146
    else
2147
    {
2148
        Error ("ScanList: Root directory not found: $dir") unless ( -d $dir );
2149
    }
2150
    if ( $subdir )
2151
    {
2152
        $dir .= "/" . $subdir;
2153
        Error ("ScanList: Sub directory not found: $subdir") unless ( -d $dir );
2154
    }
2155
 
2156
    #
2157
    #   Use SetList to do the rest of the work
2158
    #
2159
    SetList( $platforms, $name, @set_args, '--', $search->search($dir) );
2160
}
2161
 
2162
 
2163
sub Init
2164
{
2165
    push( @INITS, @_ );
2166
}
2167
 
2168
#-------------------------------------------------------------------------------
2169
# Function        : Generate
2170
#
2171
# Description     : Legacy Function - don't use unless you have too.
2172
#                   Flags files that are to be generated during the
2173
#                   early 'generate' make phase. Will also add named files
2174
#                   to various internal lists
2175
#
2176
#                   Intended to be used in conjunction with the 'Rule' directive
2177
#                   to flag header and source files that need to be created early
2178
#                   in the build process.
2179
#
2180
# Inputs          : See GenerateSrcFile
2181
#
2182
# Returns         : 
2183
#
2184
sub Generate
2185
{
2186
    my( $platforms, @elements ) = @_;
2187
 
2188
    Debug2( "Generate($platforms, @elements)" );
2189
 
2190
    return if ( ! ActivePlatform($platforms) );
2191
    Message("Generate directive used. Consider replacing with GenerateFiles");
2192
 
2193
    #
2194
    #   Use Non-warning version to do the hard work
2195
    #
2196
    GenerateSrcFile( 1, @elements );
2197
}
2198
 
2199
#-------------------------------------------------------------------------------
2200
# Function        : Generated
2201
#
2202
# Description     : Legacy Function - don't use unless you have too.
2203
#                   Flags files that are generated by misc Rules
2204
#
2205
#                   Intended to be used in conjunction with the 'Rule' directive
2206
#                   to mark files that have been generated, so that they can be
2207
#                   cleaned up.
2208
#
2209
#                   Note the difference to the 'Generate' directive which will
2210
#                   ensure that the Rule will be run in the 'generate' phase,
2211
#                   this directive doesn't.
2212
#
2213
# Inputs          : Files with internal Makefile Paths and codes
2214
#                   Eg: Generated( '*', "\$(LIBDIR)/libcsf\$(GBE_TYPE).\${a}" );
2215
#                   See why its YUK!
2216
#
2217
# Returns         : 
2218
#
2219
sub Generated
2220
{
2221
    my( $platforms, @elements ) = @_;
2222
    my( @args );
2223
 
2224
    return if ( ! ActivePlatform($platforms) );
2225
    Debug2( "Generated($platforms, @elements)" );
2226
 
2227
    #.. Collect arguments
2228
    #
2229
    foreach ( @elements )
2230
    {
2231
        if ( /^-(.*)/ )
2232
        {
2233
            Debug( "Gen: arg $_" );
2234
            push ( @args, $_);
2235
        }
2236
    }
2237
 
2238
    #.. Push source file(s)
2239
    #
2240
    foreach ( @elements )
2241
    {
2242
        if ( ! /^-(.*)/ )
2243
        {
2244
            Debug( "Generated: $_ (@args)" );
2245
            push (@USERGENERATED, $_);
2246
 
2247
            #
2248
            #   Add the file to the list of known source files
2249
            #   This will allow them to be packaged
2250
            #
2251
            GenerateSrcFile (0, $_ );
2252
        }
2253
    }
2254
}
2255
 
2256
 
2257
#-------------------------------------------------------------------------------
2258
# Function        : GenerateSrcFile
2259
#
2260
# Description     : Internal Function (No $platform)
2261
#                   Determine how to handle a 'Generated' file
2262
#
2263
#
2264
# Inputs          : $generated          - 0: Don't add to GENERATED List
2265
#                                         1: Add to GENERATED List
2266
#                                         2: Add to GENERATED List, if a source file
2267
#                   FileName(s)         - Name of one or more files to process
2268
#                                         All files are processed in the same way
2269
#                                         These file may contain Makefile prefixes
2270
#                                         ie: $(OBJDIR)/file.obj
2271
#                   Options:
2272
#                       --c             - Hint: Its a "C" file
2273
#                       --cpp           - Hint: Its a C++ file
2274
#                       --asm           - Hint: Its an ASM file
2275
#                       -*              - Save as argument attached to the file
2276
#
303 dpurdie 2277
# Returns         : Number of 'source' file
227 dpurdie 2278
#
2279
sub GenerateSrcFile                             # Internal Function - no $platform
2280
{
2281
    my( $generated, @elements ) = @_;
2282
    my( $type, @args );
303 dpurdie 2283
    my $result = 0;
227 dpurdie 2284
 
2285
    Debug2( "GenerateSrcFile($generated,@elements)" );
2286
 
2287
    #.. Collect arguments
2288
    #
2289
    $type = "";
2290
    foreach ( @elements )
2291
    {
2292
        if ( /^--c$/ ) {
2293
            Debug( "Gen: --c" );
2294
            $type = ".c";
2295
 
2296
        } elsif ( /^--cpp$/ ) {
2297
            Debug( "Gen: --cpp" );
2298
            $type = ".cc";
2299
 
2300
        } elsif ( /^--asm$/ ) {
2301
            Debug( "Gen: --asm" );
2302
            $type = ".asm";
2303
 
2304
        } elsif ( /^-(.*)/ ) {
2305
            Debug( "Src: arg $_" );
2306
            push @args, $_;
2307
        }
2308
    }
2309
 
2310
    #.. Process source file(s)
2311
    #
2312
    #   Determine if file is already a known SRCS file - skip if already known
2313
    #   Update SRCS data
2314
    #   Update SRC_TYPE data
2315
    #   Update SRC_ARGS data
2316
    #   Add the file to a suitable source file list ie: @CHDRS,...
2317
    #   Flag as a GENERATED file - These will be processed during the 'generate' phase
2318
    #
2319
    foreach my $source ( @elements )
2320
    {
2321
        next if ( $source =~ /^-(.*)/ );                # Not a source file
2322
 
2323
        my $basename = StripDir( $source );
2324
        Debug( "Generate: $source=$basename (@args)" );
2325
 
2326
        if ($SRCS{ $basename }) {
2327
            Warning( "Duplicate src ignored '$source'" );
2328
            next;
2329
        }
2330
        $SRCS{ $basename } = $source;
2331
 
2332
        HashJoin( \%SRC_ARGS, $;, $basename, @args )
2333
            if (@args);
2334
 
2335
        $SRC_TYPE{ $basename } = $type
2336
            if ($type);
2337
 
2338
        #
2339
        #   Add the file to any source file lists that it may like to know
2340
        #   about this file.
2341
        #
2342
        #   If the file was a known source file, then it may need to be generated
2343
        #   very early in the build process.
2344
        #
2345
        my $src_file_type = __AddSourceFile( 1, $basename );
285 dpurdie 2346
        if ($generated == 1 || ($src_file_type && $generated > 1) )
227 dpurdie 2347
        {
2348
            push(@GENERATED, $source);
303 dpurdie 2349
            $result++;
227 dpurdie 2350
        }
2351
        else
2352
        {
2353
            push(@GENERATED_NOTSRC, $source);
2354
        }
2355
    }
303 dpurdie 2356
 
2357
    return $result;
227 dpurdie 2358
}
2359
 
2360
#-------------------------------------------------------------------------------
2361
# Function        : GenerateFiles
2362
#
2363
# Description     : Generate files in a controlled manner using a specified
2364
#                   tool to perform the task
2365
#
2366
# Inputs          : $1      - platform specifier '*' (comma delemitered)
2367
#                   $2      - Tool Name
2368
#                   $3...   - Command line argument to generate files with embedded information
2369
#                           - or options. Multiple command line arguments will be joind with
2370
#                             a single space
2371
#
2372
#                   The generated files will be placed in the OBJ directory for
2373
#                   the current target platform. This allows different files to
2374
#                   be generated for each platform, without collision.
2375
#
2376
#                   The full name of the generated files will be added to the list of
2377
#                   source files. Thus the user does not need to know the
2378
#                   full name of the file - it will be tracked by JATS.
2379
#
2380
#                   If a generated file is a header file, then the OBJ directory
2381
#                   will be added as AddIncDir() so that the header files can be
2382
#                   extracted
2383
#
2384
#                   If a generated file is a "C"/"C++" source file, then it will
2385
#                   compiled and the object file made available
2386
#
2387
#                   The tool name may be:
2388
#                       --Tool=name  or "name"
2389
#                               Look in the tool paths in Packages
2390
#                               Look in the JATS tool directory for named script
2391
#                               Look in the JATS bin directory for the named exe
2392
#                               Look in the users path ( and generate a warning )
2393
#                               Give up and hope magic happens later
2394
#                       --Script=name
2395
#                               Resolve the name using known Src paths
2396
#                               The script may be generated and need not exist
2397
#                               at the time the makefile is created.
2398
#                       --Shell
2399
#                               The command line argument is a shell script that
2400
#                               will be passed to a simple shell.
263 dpurdie 2401
#                       --Prog=name
2402
#                               Resolve to a program generated within this makefile
227 dpurdie 2403
#
2404
#
2405
#                   The command line argument contains keywords to allow
2406
#                   information to be extracted from the line. Keywords are:
2407
#
2408
#                       --Generated(xxx)        - xxx is a generated file
2409
#                                                 It will be placed in the OBJDIR
2410
#                       --GeneratedCommon(xxx)  - xxx is a generated file
2411
#                                                 File will be placed in the local directory
2412
#                                                 and will be shared by by all platforms
2413
#                       --GeneratedObject(xxx)  - xxx is a generated object file
2414
#                                                 It will be placed in the OBJDIR and will
2415
#                                                 have a suitable object suffix appended
2416
#                       --GeneratedProg(xxx)    - xxx is a generated program file
2417
#                                                 It will be placed in the BINDIR
2418
#                       --Prerequisite(xxx)     - xxx is a prerequisite file
2419
#                                                 The full name of the file will be located
2420
#                                                 and used within the command. The file will
2421
#                                                 be added to the list of recipe prerequisites
2422
#                       --GeneratedDirectory(xxx)
2423
#                       --GeneratedCommonDirectory(xxx)
2424
#                       --GeneratedObjectDirectory(xxx)
2425
#                       --GeneratedProgDirectory(xxx)
2426
#                                               - xxx is a generated file, but is not placed
2427
#                                                 on the command line. It is flagged as
2428
#                                                 a generated files
2429
#                       --PackageBase(xxx)      - xxx is a package. The keyword will be replaced
2430
#                                                 with the pathname to the package. If the package
2431
#                                                 has been copied in the the interface directory
2432
#                                                 then the interface directory will be used.
2433
#                       --PackageInfo(xxx,--opt)- xxx is a package. The keyword will be replaced
2434
#                                                 with the information requested.
2435
#                                                 Options are:
2436
#                                                   --path
2437
#                                                   --version
2438
#                                                   --fullversion
2439
#                                                   --project
2440
#
2441
#                       Where "xxx" may be of the form:
2442
#                           name,option[,option]
2443
#
2444
#                       Flag options are:
2445
#                           --file             - The file part of the full name
2446
#                           --dir              - The directory part of the full name
2447
#                           --abspath          - Abs path
2448
#                           --absdrive         - Abs path with drive letter
2449
#
2450
#                       --Var(Name,opt)         - Name is the name of a recognised varable
2451
#                                                 Refer to ExpandGenVar function for details
2452
#                                                 of Name and available options
2453
#                                                 The expanded text will be replaced with an
2454
#                                                 suitable makefile variables that will be
2455
#                                                 replaced at run-time.
2456
#
2457
#                   The keyword will be replaced with the resolved name. This may be a file,
2458
#                   a directory or other text.
2459
#
2460
#                   Options do not alter command line text. They do affect the way the command is
2461
#                   processed.
2462
#                   Options include:
2463
#                       --Prereq=name           - The name of a file to add as a prerequisite
2464
#                                                 The file does not form part of the command line
2465
#                       --Created=name          - The name of a file to treat as a generated file
2466
#                       --CreatedCommon=name      The file does not form part of the command line 
2467
#                       --CreatedObject=name
2468
#                       --CreatedProg=name
2469
#
2470
#                       --NoVarTag              - Modifes --Var operation to suppress tags
2471
#                       --NoWarn                - Don't warn if no prerequistes found
2472
#                       --NoGenerate            - Don't warn if no generated files are found
2473
#                                                 Will create a dummy rule name and the recipe will
2474
#                                                 always be executed during the 'GenerateFiles' phase
2475
#                       --UnknownPreq           - Prerequisites are not fully known.
2476
#                                                 Rebuild the target whenever it is required.
2477
#                       --AutoGenerate          - Examine the generated file to determine when the
2478
#                                                 tools is to be run.
261 dpurdie 2479
#                                                 Must be before any options that declare
2480
#                                                 creation of files.
227 dpurdie 2481
#                       --Text=<text>           - Display text for command
2482
#
263 dpurdie 2483
#                       --Clean[=arg]           - Call script with arg[-clean] for cleaning.
2484
#                       --PreDelete             - Delete generated files before running the command
227 dpurdie 2485
#
2486
#               Eg: GenerateFiles ( '*', "--Tool=mod_if.pl",
2487
#                                        "-src --Prerequisite(udh_module.cfg)",
2488
#                                        "-direct -hdr --Generated(udp.h) -quiet" );
2489
#
2490
my $NoGenIndex = 0;
2491
sub GenerateFiles
2492
{
2493
    my ( $platforms, $tool, @args) = @_;
2494
 
2495
    return if ( ! ActivePlatform($platforms) );
2496
 
2497
    Debug2( "GenerateFiles:($platforms, $tool, @args)" );
2498
 
2499
    my @preq_files;
2500
    my $preq_unknown;
2501
    my @gen_files;
2502
    my $shell_script;
2503
    my $shell_cmds;
2504
    my @tool_args;
2505
    my $no_warn;
2506
    my $clean_tag;
2507
    my $text;
2508
    my $gtype = 1;
303 dpurdie 2509
    my @has_source;
227 dpurdie 2510
    my @var_opts;
261 dpurdie 2511
    my @genreq_seen;
263 dpurdie 2512
    my $predelete;
227 dpurdie 2513
 
2514
    #
2515
    #   Process the first argument - this describes the program that will be used
2516
    #   to generate the files. It may be:
2517
    #       --Tool          - A Jats Tool or Plugin
2518
    #       --Script        - A shell script file
2519
    #       --Shell         - Raw shell commands
2520
    #       --Prog          - A program created within the Makefile
2521
    #
2522
    #
2523
    if ( $tool =~ /^--Tool=(.*)/ || $tool =~ /^([^-].*)/)
2524
    {
2525
        $tool = $1;
2526
        my $tool_no_prereq = 0;
2527
 
2528
        #
2529
        #   Process the Tool name and determine the location of the tool
2530
        #   Support --Tool=name and "name"
2531
        #   Locate the tool one of the many well known locations
2532
        #       1) Tool paths from Package Archives
2533
        #       2) JATS tool and binaries
2534
        #       3) User PATH (!YUK)
2535
        #
2536
 
2537
        #
2538
        #   Create a list of known extensions to scan
2539
        #   Basically present so that we can use .exe files without the .exe name
2540
        #
2541
        my @extension_list;
2542
        push @extension_list, '.exe' if ( $::ScmHost ne "Unix" );
2543
        push @extension_list, '.pl', '.sh', '.ksh', '';
2544
 
2545
        TOOL_SEARCH:
2546
        {
2547
            #
2548
            #   Locate tool with package
2549
            #
2550
            if ( my $fname = ToolExtensionProgram( $tool, @extension_list ))
2551
            {
2552
                $tool = $fname;
2553
                last TOOL_SEARCH;
2554
            }
2555
 
2556
            #
2557
            #   Search the JATS tools and Bin directory
2558
            #   Retain the symbolic name of the JATS directory
2559
            #
2560
            for my $ext ( @extension_list )
2561
            {
2562
                foreach my $jdir ( qw( / /DEPLOY/ /LOCAL/ ) )
2563
                {
2564
                    if ( -f "$::GBE_TOOLS$jdir$tool$ext" )
2565
                    {
2566
                        $tool = "\$(GBE_TOOLS)$jdir$tool$ext";
2567
                        last TOOL_SEARCH;
2568
                    }
2569
                }
2570
 
2571
                if ( -f "$::GBE_BIN/$tool$ext" )
2572
                {
2573
                    $tool = "\$(GBE_BIN)/$tool$ext";
2574
                    last TOOL_SEARCH;
2575
                }
2576
            }
2577
 
2578
            #
2579
            #   Has the user provided an absolute PATH
2580
            #   This is not good, but for testing we can use it
2581
            #
2582
            if ( $tool =~ m~^/~ || $tool =~ m~^.:~ )
2583
            {
2584
                Warning("Absolute path program specified. Uncontrolled tool: $tool");
2585
                for my $ext ( @extension_list )
2586
                {
2587
                    if ( -f "$tool$ext" )
2588
                    {
2589
                        $tool = "$tool$ext";
2590
                        last TOOL_SEARCH;
2591
                    }
2592
                }
2593
            }
2594
 
2595
            #
2596
            #   May have a relative path to a local tool
2597
            #
2598
            if ( -f $tool )
2599
            {
2600
                UniquePush (\@preq_files, $tool);
2601
                last TOOL_SEARCH;
2602
            }
2603
 
2604
            #
2605
            #   Search the users PATH
2606
            #   Generate a warning if the program is found. These programs are
2607
            #   not nice as they are not really controlled.
2608
            #
2609
            for my $dir (split( $::ScmPathSep, $ENV{'PATH'} ) )
2610
            {
2611
                for my $ext ( @extension_list )
2612
                {
2613
                    if ( -f "$dir/$tool$ext" )
2614
                    {
2615
                        Warning("External program found in the user's PATH. Uncontrolled tool: $tool");
2616
                        $tool = "$dir/$tool$ext";
2617
 
2618
                        #
2619
                        #   Do not make the program a pre-requisite if we are running
2620
                        #   under Windows. This avoids two problems:
2621
                        #       1) May have spaces in pathname
2622
                        #       2) May have driver letter in pathname
2623
                        #
2624
                        $tool_no_prereq = 1 if ( $::ScmHost eq "WIN" );
2625
                        last TOOL_SEARCH;
2626
                    }
2627
                }
2628
            }
2629
 
2630
            #
2631
            #   Specified progrom not found
2632
            #   Generate a warning and use the raw name
2633
            #
2634
            Warning("Tool not found: $tool");
2635
            $tool_no_prereq = 1;
2636
        }
2637
        UniquePush (\@preq_files, $tool) unless ($tool_no_prereq);
2638
 
2639
    } elsif ( $tool =~ /^--Script=(.*)/ ) {
2640
 
2641
        #
2642
        #   Locate the script in a known source directory and make
2643
        #   the script a prerequisite of the target files, since the
2644
        #   script may be generated.
2645
        #
2646
        $tool = MakeSrcResolve ( $1 );
2647
        UniquePush (\@preq_files, $tool);
2648
 
2649
    } elsif ( $tool =~ /^--Shell$/ ) {
2650
        #
2651
        #   The user has provided a shell script within the command body
2652
        #   This will be executed directly by a shell
2653
        #   directores will need to use a "/" separator
2654
        #
2655
        $tool = "InternalShell";
2656
        $shell_script = 1;
2657
        $shell_cmds = 1;
2658
 
2659
 
2660
    } elsif ( $tool =~ /^--Prog=(.*)$/ ) {
2661
        #
2662
        #   Using a program that has been created within this script
2663
        #
2664
        my $prog = $1;
289 dpurdie 2665
        if ( my $pProg = $PROGS->Get($prog) )
227 dpurdie 2666
        {
289 dpurdie 2667
            $tool = $pProg->getPath()
227 dpurdie 2668
                unless ( $tool = $SRCS{$prog} );
2669
        UniquePush (\@preq_files, $tool);
2670
        }
2671
        else
2672
        {
2673
            Error ("Unknown program: $prog");
2674
        }
2675
 
2676
    } else {
2677
 
2678
        #
2679
        #   Currently generate a warning and then use the raw tool name
2680
        #
2681
        Error ("Unknown TOOL syntax: $tool");
2682
    }
2683
 
2684
    #
2685
    #   May need to quote the path
2686
    #   If the toolpath contains spaces then ugliness can occur - so quote the program
2687
    #
2688
    $tool = '"' . $tool . '"'
2689
        if ( (! $shell_script ) && $tool =~ m~\s~ );
2690
 
2691
    #
2692
    #   Determine special startup for various programs
2693
    #       Perl  - use known implemenatation
2694
    #       Shell - use known implemenatation
2695
    #       Otherwise - simply run it
2696
    #
2697
    #   Windows: Shell and Perl don't need '\' in paths
2698
    #
2699
    if ( $tool =~ /\.pl$/ )
2700
    {
2701
        $tool = "\$(GBE_PERL) $tool";
2702
        $shell_script = 1;
2703
    }
2704
    elsif ( $tool =~ /\.k?sh$/ )
2705
    {
2706
        $tool = "\$(GBE_BIN)/sh $tool";
2707
        $shell_script = 1;
2708
    }
2709
    Debug( "GenerateFiles: Tool: $tool" );
2710
 
2711
 
2712
    #
2713
    #   Process the remaining arguments
2714
    #   These will be command line arguments or options/flags
2715
    #   Command line arguments are concatenated together
2716
    #
2717
    for my $arg (@args)
2718
    {
263 dpurdie 2719
        if ( $arg =~ /^--PreDelete$/ )
2720
        {
2721
            #
2722
            #   Delete generated files before running the generation process
2723
            #   Some programs refuse to overwrite existing files
2724
            #
2725
            $predelete = 1;
2726
            next;
2727
        }
2728
 
227 dpurdie 2729
        if ( $arg =~ /^--NoVarTag$/ )
2730
        {
2731
            #
2732
            #   Modify the operation of --Var to supress the tags
2733
            #   Should be usd early as will only affect following --Var usage
2734
            #
2735
            push @var_opts, "--notag";
2736
            next;
2737
        }
2738
 
2739
        if ( $arg =~ /^--NoWarn$/ )
2740
        {
2741
            #
2742
            #   Supress warnings - No prequisites found
2743
            #   This is acceptable, but normally a tool should take an input
2744
            #   and create some output from it.
2745
            #
2746
            $no_warn = 1;
2747
            next;
2748
        }
2749
 
2750
        if ( $arg =~ /^--NoGenerate$/ )
2751
        {
2752
            #
2753
            #   Tool does generate a definable output
2754
            #   Should only be used internally
2755
            #
2756
            #   Need to create a dummy name for the rule
2757
            #   Use a base name and a number
2758
            #
2759
            my $dummy_target = 'generate_files_' . $NoGenIndex;
2760
            UniquePush (\@gen_files, $dummy_target );
2761
            UniquePush (\@GENERATED, $dummy_target);
2762
            next;
2763
        }
2764
 
2765
        if ( $arg =~ /^--UnknownPreq/ )
2766
        {
2767
            #
2768
            #   Indicate that the prequisites are not known, or too complex to
2769
            #   describe. ie: All files in a directory. May be used by packaging
2770
            #   tools.
2771
            #   The recipe will be run EVERY time we want to use the target.
2772
            #
2773
            $preq_unknown = 1;
2774
            $no_warn = 1;
2775
            next;
2776
        }
2777
 
2778
        if ( $arg =~ /^--AutoGenerate/ )
2779
        {
2780
            #
2781
            #   Determine when to run the tool based on the types of files that
2782
            #   are generated. Existance of a source file will force the tool
2783
            #   to be run during the 'generate' phase, othewise the tool will be run
2784
            #   when the generated components are required.
2785
            #
2786
            $gtype = 2;
261 dpurdie 2787
            Warning ("AutoGenerate MUST occur before options that declare generation of files",
2788
                     "Have seen:", @genreq_seen)
2789
                if (@genreq_seen);
227 dpurdie 2790
            next;
2791
        }
2792
 
2793
        if ( $arg =~ /^--Prereq=(.*)/ )
2794
        {
2795
            #
2796
            #   Specify a prerequisite file, that is not a part of the command line
2797
            #   Simply add the files to the list of preq files
2798
            #
2799
            my $fn = LocatePreReq ($1);
2800
            UniquePush ( \@preq_files, $fn );
2801
            Debug( "GenerateFiles: ExtraPrereq: $fn" );
2802
            next;
2803
        }
2804
 
2805
        if ( $arg =~ /^--Created(.*)=(.*)/ )
2806
        {
2807
            #
2808
            #   Specify a generated file, that is not a part of the command line
2809
            #   Add the files to the list of generated files
2810
            #
2811
            my $type = $1;
2812
            my $fn = $2;
2813
 
2814
            $fn .= '.' . $::o
2815
                if ( $type =~ m/Object/ );
2816
 
2817
            $fn = "\$(OBJDIR)/$fn"
2818
                if ( $type !~ m/Common/ );
2819
            $fn = "\$(BINDIR)/$fn"
2820
                if ( $type =~ m/Prog/ );
2821
 
2822
            #
2823
            #   Examine the file and see if it needs to be compiled
2824
            #   Add to the list of source files
2825
            #
261 dpurdie 2826
            push @genreq_seen, $arg;
303 dpurdie 2827
            if ( UniquePush (\@gen_files, $fn) )
2828
            {
2829
                if ( GenerateSrcFile ( $gtype, $fn  ) && $gtype == 2 )
2830
                {
2831
                    push @has_source, $fn;
2832
                }
2833
            }
227 dpurdie 2834
            Debug( "GenerateFiles: ExtraCreated: $fn" );
2835
            next;
2836
        }
2837
 
2838
        if ( $arg =~ /^--Clean($|=(.*))/ )
2839
        {
2840
            #
2841
            #   Detect Clean option
2842
            #
2843
            $clean_tag = $2 ? $2 : '-clean';
2844
 
2845
            #
2846
            #   Shell command with a --Clean will only
2847
            #   be run during a clean phase. They should not have any prereq
2848
            #   and should not generate any files, so simplify the interface.
2849
            #
2850
            push @args, '--NoWarn', '--NoGenerate'
2851
                if ( $shell_cmds );
2852
 
2853
            next;
2854
        }
2855
 
2856
        if ( $arg =~ /^--Text=(.*)/ )
2857
        {
2858
            #
2859
            #   Display this text when executing commands
2860
            #
2861
            $text = $1;
2862
            next;
2863
        }
2864
 
2865
 
2866
        #   Not an option. Must be an argument to the tool/program
2867
        #   Process the tool arguments and extract file information
2868
        #   Extract all fields of the form:
2869
        #           --xxxxx(yyyyyy[,zzzzz])
2870
        #           --xxxxx{yyyyyyy}
2871
        #           --xxxxx[yyyyyyy] to allow embedded brackets
2872
        #
2873
        while ( $arg =~ m/--(\w+)               # --CommandWord         $1
2874
                                (               # Just for grouping
2875
                                \((.*?)\)   |   # Stuff like (yyyyy)    $3
2876
                                {(.*?)}     |   # or    like {yyyyy}    $4
2877
                                \[(.*?)\]       # or    like [yyyyy]    $5
2878
                                )/x )           # Allow comments and whitespace
2879
        {
2880
            my $cmd = $1;                       # The command
2881
            my $ufn = $3 || $4 || $5;           # User filename + options
2882
            my $mb = $-[0];                     # Match begin offset
2883
            my $me = $+[0];                     # Match end
2884
            my $flags = '';                     # Optional flags ( --dir or --file )
2885
            my $raw_arg = $ufn;                 # Raw arguments
285 dpurdie 2886
            my $all = substr( $arg, $mb, $me ); # All of match. Avoid use of $&
2887
 
227 dpurdie 2888
 
2889
            Error ("GenerateFiles. Empty element not allowed: $all")
2890
                unless ( defined($ufn) );
2891
 
2892
            $ufn =~ s/\s+$//;
2893
            $ufn =~ s/^\s+//;
2894
            $ufn =~ s~//~/~g;                   # Remove multiple /
2895
            if ( $ufn =~ m/(.*?),(.*)/ )        # Extract out any flags
2896
            {
2897
                $ufn = $1;
2898
                $flags = $2;
2899
            }
2900
 
2901
            my $fn = $ufn ;                     # Replacement filename
2902
            Error ("GenerateFiles. Empty element not allowed: $all" )
2903
                if ( length ($ufn) <= 0 );
2904
 
2905
            #
2906
            #   Process found user command
2907
            #
2908
            if ( $cmd =~ /^Generated/ )
2909
            {
2910
                my $use_dir = "";
2911
                #
2912
                #   Generated filename
2913
                #       Determine the target directory
2914
                #       Determine the full name of the file.
2915
                #       Flag the file as generated
2916
                #
2917
                if ( $cmd =~ /Prog/ )
2918
                {
2919
                    #
2920
                    #   Generated Prog are generated in the BIN directory
2921
                    #   Ensure the directory exists by using its symbolic name
2922
                    #   as a prerequisite.
2923
                    #
2924
                    $use_dir = "\$(BINDIR)";
2925
                    UniquePush (\@preq_files, "\$(GBE_BINDIR)");
2926
                }
2927
                elsif ( $cmd !~ /Common/ )
2928
                {
2929
                    #
2930
                    #   Files that are not Common are generated in the
2931
                    #   object directory. This directory must exist, so it
2932
                    #   symbolic name GBE_OBJDIR is made a prerequisite too.
2933
                    #
2934
                    #   If the file is a header file, then add the directory
2935
                    #   to the include search path too.
2936
                    #
2937
                    $use_dir = "\$(OBJDIR)";
2938
                    UniquePush (\@preq_files, "\$(GBE_OBJDIR)");
2939
                    AddIncDir( $platforms , "\$(OBJDIR)", '--NoWarn' )
2940
                        if ( $ScmSourceTypes{ StripFile($fn) } && $ScmSourceTypes{ StripFile($fn) } eq ".h" );
2941
                }
2942
 
2943
 
2944
                #
2945
                #   Append a toolset specfic object file name suffix
2946
                #   for Object files only
2947
                #
2948
                $fn .= ".$::o"
2949
                    if ( $cmd =~ /Object/ );
2950
 
2951
                #
2952
                #   Merge directory and filename parts
2953
                #
2954
                $fn = $use_dir . ( $use_dir ? "/" : ""  ) . $fn;
2955
 
2956
                #
2957
                #   Save for later user
2958
                #   Flag the file as a generated file
2959
                #
261 dpurdie 2960
                push @genreq_seen, $cmd;
303 dpurdie 2961
                if ( UniquePush (\@gen_files, $fn) )
2962
                {
2963
                    if ( GenerateSrcFile ( $gtype, $fn  ) && $gtype == 2 )
2964
                    {
2965
                        push @has_source, $fn;
2966
                    }
2967
                }
227 dpurdie 2968
 
2969
                #
2970
                #   Use the directory or the full name
2971
                #   If using the directory then ensure that we have a name
2972
                #   even if its "."
2973
                #
2974
                $fn = ($use_dir) ? "$use_dir" : "."
2975
                    if ( $cmd =~ /Directory/ );
2976
 
2977
                Debug( "GenerateFiles: Generate: $fn" );
2978
 
2979
            }
2980
            elsif ( $cmd =~ /^Prereq/ )
2981
            {
2982
                #
2983
                #   Prerequisite filename
2984
                #       Resolve the full name of the file. It may be known
2985
                #       as a source file (possibly generated) or it may be
2986
                #       located in a known source directory
2987
                #
2988
                $fn = LocatePreReq ($ufn);
2989
                UniquePush (\@preq_files, $fn);
2990
 
2991
                Debug( "GenerateFiles: Prereq: $fn" );
2992
 
2993
            }
2994
            elsif ( $cmd =~ /^PackageBase/ )
2995
            {
2996
                $fn = GetPackageBase( "GenerateFiles", $raw_arg );
2997
                UniquePush (\@preq_files, $fn);
2998
            }
2999
            elsif ( $cmd =~ /^PackageInfo/ )
3000
            {
3001
                $fn = GetPackageInfo( "GenerateFiles", $raw_arg );
3002
            }
3003
            elsif ( $cmd =~ /^Var/ )
3004
            {
3005
                $fn = ExpandGenVar( "GenerateFiles", $raw_arg, @var_opts );
3006
                $flags = '';
3007
            }
3008
            else
3009
            {
3010
                Warning ("GenerateFiles: Unknown replacement command: $cmd");
3011
                $fn = $ufn;
3012
            }
3013
 
3014
            #
3015
            #   Process path modification flags
3016
            #
3017
            $fn = ProcessPathName( $fn, $flags );
3018
 
3019
            #
3020
            #   Minor kludge under windows. Ensure directores have a "\" sep
3021
            #   Unless the user has specified a straight shell command
3022
            #
303 dpurdie 3023
            $fn = "\$(subst /,\\,$fn)"
227 dpurdie 3024
                if ( $::ScmHost eq "WIN" && ! defined($shell_script) );
3025
 
3026
            #
3027
            #   Replace the found string with the real name of the file
3028
            #   Note: 4 argument version of substr is not always available
3029
            #         so we must do it the hard way
3030
            #               substr( $arg, $mb, $me - $mb, $fn);
3031
            #
3032
            $arg = substr( $arg, 0, $mb ) . $fn . substr( $arg, $me );
3033
 
3034
            Debug2( "GenerateFiles: subs: $all -> $fn" );
3035
        }
3036
 
3037
        #
3038
        #   Save the tool arguments in an array
3039
        #
3040
        push @tool_args, $arg;
3041
    }
3042
 
3043
 
3044
    #
3045
    #   Sanity test. Ensure that some file have been marged as generated
3046
    #                Warn if no prerequisites found
3047
    #
303 dpurdie 3048
    Warning( "GenerateFiles. --AutoGenerate option has no effect",
3049
             "The following files are 'source' files",  @has_source ) if ( @has_source );
227 dpurdie 3050
    Warning( "No Prerequisite files found in $tool",@tool_args) unless ( $no_warn || $#preq_files >= 0 );
3051
    Error  ( "No generated files found in $tool",@tool_args) unless ($#gen_files >= 0);
3052
 
3053
 
3054
    #
3055
    #   Save information
3056
    #   Will be used to create makefile statements later
3057
    #
3058
    my %gen_data;
3059
 
3060
    $gen_data{'index'}      = $NoGenIndex++;
3061
    $gen_data{'shell'}      = $shell_cmds;
3062
    $gen_data{'gen'}        = \@gen_files;
3063
    $gen_data{'preq'}       = \@preq_files;
3064
    $gen_data{'tool'}       = $tool;
3065
    $gen_data{'toolargs'}   = \@tool_args;
3066
    $gen_data{'clean'}      = $clean_tag;
3067
    $gen_data{'text'}       = $text || $gen_files[0];
3068
    $gen_data{'preq_sus'}   = 1 if ( $preq_unknown );
263 dpurdie 3069
    $gen_data{'predelete'}  = 1 if ( $predelete );
227 dpurdie 3070
 
3071
    push(@GENERATE_FILES, \%gen_data);
3072
 
3073
    Debug2( "GenerateFiles: cmd: $tool @tool_args" );
3074
}
3075
 
3076
#-------------------------------------------------------------------------------
3077
# Function        : MakePerlModule
3078
#
3079
# Description     : Build Perl Module(s) using the Perl Build System
3080
#                   This is a thin wrapper around a specialised script
3081
#
3082
#                   The user can do the same job with correct use of
3083
#                   a GenerateFiles, but this is a lot tidier.
3084
#
3085
# Inputs          : $1      - platform specifier '*' (comma delemitered)
3086
#                   $*      - Paths to Perl Modules[,command options]
3087
#                             Options to the BuildPerl script
3088
#
3089
# Returns         :
3090
#
3091
sub MakePerlModule
3092
{
3093
    my ( $platforms, @args) = @_;
3094
 
3095
    return if ( ! ActivePlatform($platforms) );
3096
 
3097
    Debug2( "MakePerlModule:($platforms, @args)" );
3098
    my @opts;
3099
 
3100
    #
3101
    #   Extract options from paths to Perl Packages
3102
    #   Package names do not start with a '-'
3103
    #
3104
    foreach my $arg ( @args )
3105
    {
3106
        if ( $arg =~ /^-/ ) {
3107
            push @opts, $arg;
3108
 
3109
        } else {
3110
            #
3111
            #   Perl Package Directory Name
3112
            #   This may also contain embedded command to the Make command
3113
            #   These will be seperated with a comma
3114
            #       ie: module,-options=fred
3115
            #
3116
            my ($name,$options) = split( ',', $arg );
3117
            push @opts, "-PerlPackage=$arg";
3118
            push @opts, "--Prereq=$name/Makefile.PL";
3119
        }
3120
    }
3121
 
3122
    #
3123
    #   Invoke GenerateFiles with a bunch of additional arguments
3124
    #
3125
    GenerateFiles ($platforms, "--Tool=jats_buildperl.pl",
3126
                          '--Var(MachType)',                        # Build Machine type
3127
                          '--Var(PackageDir)',                      # Package dir
3128
                          '--NoGenerate',                           # Don't know the output
3129
                          '--Text=Make Perl Module',                # Pretty print
3130
                          '--NoWarn',
3131
                          '--Clean=-clean_build',                   # Jats clean support
3132
                          '--NoVarTag',                             # No more Tags
3133
                          @opts,
3134
                          );
3135
}
3136
 
3137
#-------------------------------------------------------------------------------
3138
# Function        : MakeLinuxDriver
3139
#
3140
# Description     : Build a Linux Device Driver using the Linux Device Driver
3141
#                   Build System
3142
#                   This is a thin wrapper around a specialised script
3143
#
3144
#                   The user can do the same job with correct use of
3145
#                   a GenerateFiles, but this is a lot tidier.
3146
#
3147
# Inputs          : $1      - platform specifier '*' (comma delemitered)
3148
#                   $2      - name of the driver. No extension
3149
#                   $*      - Driver sources
3150
#                             Options to the script
3151
#
3152
# Returns         :
3153
#
3154
sub MakeLinuxDriver
3155
{
3156
    my ( $platforms, $driver_name, @args) = @_;
3157
 
3158
    return if ( ! ActivePlatform($platforms) );
3159
 
285 dpurdie 3160
    Error ("No driver name specified") unless ( $driver_name );
227 dpurdie 3161
    Debug2( "MakeLinuxDriver:($platforms, $driver_name ,@args)" );
3162
    my @srcs;
3163
    my @opts;
3164
 
3165
    #
3166
    #   Extract options from source files
3167
    #   Package names do not start with a '-'
3168
    #
3169
    foreach my $arg ( @args )
3170
    {
3171
         if ( $arg =~ /^--Define=(.)/ ) {
3172
            push @opts, $arg;
3173
 
3174
         } elsif ( $arg =~ /^-/ ) {
3175
            push @opts, $arg;
3176
            Warning ("MakeLinuxDriver: Unknown option: $arg. Passed to script");
3177
 
3178
        } else {
3179
            push @srcs, $arg;
3180
            push @opts, "--Prereq=$arg";
3181
        }
3182
    }
3183
 
3184
    #
3185
    #   Cleanup the drive name
3186
    #
3187
    $driver_name =~ s~\.ko$~~;
3188
 
3189
    #
3190
    #   Remove the specified sources from the list of object files
3191
    #   that will be build. This will ensure that some internal rules are
3192
    #   not generated.
3193
    #
3194
    foreach ( @srcs )
3195
    {
3196
        my $file = StripExt(StripDir( $_ ));
3197
        delete $OBJSOURCE{ $file };
3198
        @OBJS = grep(!/^$file$/, @OBJS);
3199
    }
3200
 
3201
    #
3202
    #   Invoke GenerateFiles with a bunch of additional arguments
3203
    #   At runtime the include directories will be added as
3204
    #   absolute paths
3205
    #
3206
    GenerateFiles ($platforms, "--Tool=jats_buildlinux.pl",
3207
                    "-Output=--GeneratedProg($driver_name.ko)",
3208
                    "-Driver=$driver_name",
3209
                    "-GccPath=\$(GCC_CC)",
3210
                    "-Arch=\$(HOST_CPU)",
3211
                    "-LeaveTmp=\$(LEAVETMP)",
3212
                    "-Verbose=\$(CC_PRE)",
3213
                    "-Type=\$(GBE_TYPE)",
3214
                    "-Platform=\$(GBE_PLATFORM)",
3215
                    '$(patsubst %,-Incdir=%,$(INCDIRS))',
3216
                    @opts,
3217
                    @srcs
3218
                    );
3219
}
3220
 
3221
#-------------------------------------------------------------------------------
3222
# Function        : GetPackageBase
3223
#
3224
# Description     : Helper routine
3225
#                   Given a package name, determine the base address of the
3226
#                   package
3227
#
3228
# Inputs          : $dname         - Directive name     (Reporting)
3229
#                   $name          - Required package
3230
#                                    Allows two forms:
3231
#                                       package_name
3232
#                                       package_name,ext
3233
#
3234
# Returns         : Path to the directory in which the files are installed
3235
#                   This may be the interface directory
3236
#
3237
sub GetPackageBase
3238
{
3239
    my ($dname, $fname) = @_;
3240
    my $pkg;
3241
    my ($name, $ext) = split(',', $fname);
3242
 
3243
    $pkg = GetPackageEntry( $name, $ext );
3244
    Error ("$dname: Package not found: $fname") unless ( $pkg );
3245
 
3246
    #
3247
    #   If a BuildPkgArchive then use the interface directory
3248
    #
3249
    return ( $pkg->{'TYPE'} eq 'link' ) ? $pkg->{'ROOT'} : '$(INTERFACEDIR)';
3250
}
3251
 
3252
#-------------------------------------------------------------------------------
3253
# Function        : GetPackageInfo
3254
#
3255
# Description     : Helper routine
3256
#                   Given a package name, return some information about the package
3257
#                   Only one information item is allowed with each call
3258
#
3259
# Inputs          : $dname         - Directive name     (Reporting)
3260
#                   $name          - Required package
3261
#                                    Allows two forms:
3262
#                                       package_name
3263
#                                       package_name,ext
3264
#                                    Selector
3265
#                                       --path
3266
#                                       --version
3267
#                                       --fullversion
3268
#                                       --project
3269
#
3270
# Returns         : Package information
3271
my %GetPackageInfo = qw(path ROOT
3272
                        version DVERSION
3273
                        fullversion VERSION
3274
                        project DPROJ);
3275
sub GetPackageInfo
3276
{
3277
    my ($dname, $args) = @_;
3278
    my $pkg;
3279
    my $name;
3280
    my $ext;
3281
    my $info;
3282
 
3283
    foreach ( split(',', $args) )
3284
    {
3285
        if ( m/^--(.*)/ ) {
3286
            Error( "$dname: Too many info requests: $args") if ( $info );
3287
            $info = $GetPackageInfo{$1};
3288
            Error( "$dname: Unknown info type: $_") unless ($info);
3289
        } elsif ( $ext ) {
3290
            Error("$dname: Too many names: $args");
3291
        } elsif ( $name ) {
3292
            $ext = $_;
3293
        } else {
3294
            $name = $_;
3295
        }
3296
    }
3297
 
3298
    $pkg = GetPackageEntry( $name, $ext );
3299
    Error ("$dname: Package not found: $args") unless ( $pkg );
3300
 
3301
    #
3302
    #   If a BuildPkgArchive then use the interface directory
3303
    #
3304
    if ( $info eq 'ROOT' &&  $pkg->{'TYPE'} eq 'link' )
3305
    {
3306
        return ( '$(INTERFACEDIR)');
3307
    }
3308
    return ( $pkg->{$info} );
3309
}
3310
 
3311
#-------------------------------------------------------------------------------
3312
# Function        : GetPackageEntry
3313
#
3314
# Description     : Return the package class pointer given a package name
3315
#
3316
# Inputs          : $name          - Required package
3317
#                   $ext           - Option package extension
3318
#
3319
# Returns         : Class pointer
3320
#
3321
sub GetPackageEntry
3322
{
3323
    my ($name, $ext) = @_;
3324
    $ext = '' unless ( $ext );
3325
 
3326
    for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} })
3327
    {
3328
        next unless ( $entry->{'NAME'} eq $name );
3329
        next if ( $ext && $entry->{'DPROJ'} ne $ext );
3330
        return $entry;
3331
    }
285 dpurdie 3332
    return;
227 dpurdie 3333
}
3334
 
3335
#-------------------------------------------------------------------------------
3336
# Function        : ExpandGenVar
3337
#
3338
# Description     : Expand a known variable for the Generate Files option
3339
#
3340
# Inputs          : $dname         - Directive name     (Reporting)
3341
#                   $arg           - Raw argument
3342
#                                    This of the form of
3343
#                                       Tag[,--option]+
3344
#                                    Tags are specified in %ExpandGenVarConvert
3345
#
3346
#                                   Options are:
3347
#                                       --tag
3348
#                                       --notag
3349
#                                       --tag=<SomeTag>
3350
#                                       --absdrive
3351
#                                       --abspath
285 dpurdie 3352
#                                       --default=text
227 dpurdie 3353
#                                   Not all options are avalaible on all variables
3354
#                   @opts           - Options
3355
#                                       --notag     - Default is --notag
3356
#
3357
# Returns         : String
3358
#
3359
 
3360
#
3361
#   Create a Hash to simplify the process of converting Var names
3362
#   into makefile variables.
3363
#
3364
my %ExpandGenVarConvert = (
3365
    'BuildName'         => '$(GBE_PBASE)',
3366
    'BuildVersion'      => '$(BUILDVER)',
3367
    'BuildVersionNum'   => '$(BUILDVERNUM)',
3368
 
3369
    'PackageDir'        => '$(PKGDIR),+',
3370
    'PackagePkgDir'     => '$(PKGDIR)/pkg/pkg.$(GBE_PLATFORM),+',
3371
    'PackageIncDir'     => '$(INCDIR_PKG),+',
3372
    'PackageLibDir'     => '$(LIBDIR_PKG)/$(GBE_PLATFORM),+',
3373
    'PackageBinDir'     => '$(BINDIR_PKG)/$(GBE_PLATFORM)$(GBE_TYPE),+',
3374
 
3375
    'PackageToolDir'    => '$(PKGDIR)/tools,+',
3376
    'PackageToolBin'    => '$(PKGDIR)/tools/bin/$(GBE_HOSTMACH),+',
3377
    'PackageToolScript' => '$(PKGDIR)/tools/scripts,+',
3378
 
3379
    'LibDir'            => '$(LIBDIR),+',
3380
    'BinDir'            => '$(BINDIR),+',
3381
    'ObjDir'            => '$(OBJDIR),+',
3382
 
3383
    'InterfaceDir'      => '$(INTERFACEDIR),+',
3384
    'InterfaceIncDir'   => '$(INCDIR_INTERFACE),+',
3385
    'InterfaceLibDir'   => '$(LIBDIR_INTERFACE)/$(GBE_PLATFORM),+',
3386
    'InterfaceBinDir'   => '$(BINDIR_INTERFACE)/$(GBE_PLATFORM)$(GBE_TYPE),+',
3387
 
3388
    'LocalDir'          => '$(LOCALDIR),+',
3389
    'LocalIncDir'       => '$(INCDIR_LOCAL),+',
3390
    'LocalLibDir'       => '$(LIBDIR_LOCAL)/$(GBE_PLATFORM),+',
3391
    'LocalBinDir'       => '$(BINDIR_LOCAL)/$(GBE_PLATFORM)$(GBE_TYPE),+',
3392
 
3393
    'Platform'          => '$(GBE_PLATFORM)',
3394
    'Product'           => '$(GBE_PRODUCT)',
3395
    'Target'            => '$(GBE_TARGET)',
3396
 
3397
    'Type'              => '$(GBE_TYPE)',
3398
    'Arch'              => '$(HOST_CPU)',
3399
    'Architecture'      => '$(HOST_CPU)',
3400
    'MachType'          => '$(GBE_HOSTMACH)',
3401
    'BuildRoot'         => '$(GBE_ROOT),+',
3402
 
3403
 
3404
    'Verbose'           => '$(CC_PRE)',
3405
    'LeaveTmp'          => '$(LEAVETMP)',
3406
    'Cwd'               => '$(CURDIR)',
3407
 
3408
    'CompilerPath'      => '$(SCM_COMPILERPATH)',
3409
    );
3410
 
3411
sub ExpandGenVar
3412
{
3413
    my ($dname, $args, @uopts) = @_;
3414
    my $expansion;
3415
    my $prefix='';
3416
    my ($tag, @opts) = split('\s*,\s*', $args);
3417
    my $no_prefix;
285 dpurdie 3418
    my $default_value;
3419
    my $allow_none;
227 dpurdie 3420
 
285 dpurdie 3421
    #
3422
    #   Parse options lists
3423
    #       Options provided by the caller
3424
    #       Options embedded in the argument
227 dpurdie 3425
    foreach ( @uopts )
3426
    {
3427
        if ( m/^--notag$/ ) {
3428
            $no_prefix = 1;
3429
        } else{
3430
            Error ("$dname: Unknown option: $_")
3431
        }
3432
    }
3433
 
285 dpurdie 3434
    foreach ( @opts )
3435
    {
3436
        if ( m/^--default=(.+)/i ) {
3437
            $default_value = $1;
3438
        } elsif ( m/^--allownone$/i ) {
3439
            $allow_none = 1;
3440
        }
3441
    }
3442
 
227 dpurdie 3443
    #
3444
    #   Perform run-time update on the %ExpandGenVarConvert
3445
    #   Most of it can be initialised at startup - but not all of it.
3446
    #
3447
    $ExpandGenVarConvert{CompilerPath} = undef unless $::ScmToolsetCompilerPath;
3448
    $ExpandGenVarConvert{Product}      = '$(GBE_PLATFORM)' unless $ScmProduct;
3449
 
3450
    #
3451
    #   Look up a hash of conversions
3452
    #   Could allow for a code ref, but not needed yet
3453
    #
3454
    Error ("$dname: Unknown expansion --Var($tag)")
3455
        unless ( exists $ExpandGenVarConvert{$tag} );
3456
 
285 dpurdie 3457
    #
3458
    #   Handle undefined expansions
3459
    #   Only 'CompilerPath', but it can be a pain in user land
3460
    #
3461
    $expansion = $ExpandGenVarConvert{$tag};
3462
    unless ( defined $expansion  )
3463
    {
3464
        return '' if ( $allow_none );
3465
        $expansion = $default_value;
3466
        Error ("$dname: Expansion --Var($tag) not be supported by toolset: $ScmToolset")
3467
            unless ( $expansion );
3468
    }
227 dpurdie 3469
 
285 dpurdie 3470
 
227 dpurdie 3471
    ($expansion,my $is_path) = split (',', $expansion );
3472
 
3473
    #
3474
    #   Process options
3475
    #   Assume that a tag will be provided
3476
    #
3477
    $prefix =  $no_prefix ? '' : "-$tag=";
3478
    foreach my $opt ( @opts )
3479
    {
3480
        if ( $opt =~ /^--tag=(.*)/i ) {
3481
            $prefix = "$1=";
3482
 
3483
        } elsif ( $opt =~ m/^--tag$/i ) {
3484
            $prefix = "-$tag=";
3485
 
3486
        } elsif ( $opt =~ m/^--notag/i ) {
3487
            $prefix = '';
3488
 
3489
        } elsif ( $is_path && $opt =~ /--abspath|--absdrive/i ) {
3490
            $expansion = '$(CURDIR)/' . $expansion;
3491
 
285 dpurdie 3492
        } elsif ( $opt =~ m/^--default=(.+)/i ) {
3493
            # Already processed
3494
        } elsif ( $opt =~ m/^--allownone$/i ) {
3495
            # Already processed
227 dpurdie 3496
        } else {
3497
            Error ("$dname: Unsupported option($opt) for --Var(@_)");
3498
        }
3499
    }
3500
 
3501
    Debug ("ExpandGenVar: args $args --> $prefix$expansion");
3502
    return $prefix . $expansion;
3503
 
3504
}
3505
 
3506
#-------------------------------------------------------------------------------
3507
# Function        : ProcessPathName
3508
#
3509
# Description     : Massage a pathname according to a set of flags
3510
#
3511
# Inputs          : $fn         - Patchname to massage
3512
#                   $flags      - Flags in a string
3513
#                                   --dir       - only the directory part ( or a "." )
3514
#                                   --file      - only the file part
3515
#                                   --abspath   - Absolute path
3516
#                                   --absdrive  - Absolute path with drive letter(WIN)
3517
#
3518
# Returns         : Massaged pathname
3519
#
3520
sub ProcessPathName
3521
{
3522
    my ( $fn, $flags ) = @_;
3523
    #
3524
    #   Process flags
3525
    #       --dir           - only the directory part ( or a "." )
3526
    #       --file          - only the file part
3527
    #       --abspath       - Absolute path
3528
    #       --absdrive      - Absolute path with drive letter(WIN)
3529
    #
3530
    if ( $flags =~ /--dir/ )
3531
    {
3532
        $fn = '.'
3533
            unless ( $fn =~ s~/[^/]*$~~);
3534
    }
3535
 
3536
    if ( $flags =~ /--file/ )
3537
    {
3538
        $fn =~ s~.*/~~;
3539
    }
3540
 
3541
    if ( $flags =~ /--abspath/ )
3542
    {
3543
        $fn = AbsPath( $fn );
3544
    }
3545
    elsif ( $flags =~ /--absdrive/ )
3546
    {
3547
        $fn = AbsPath( $fn );
3548
        if ( $::ScmHost eq "WIN" )
3549
        {
3550
            $fn = $::CwdDrive . '/' . $fn
3551
                unless ( $fn =~ m~^\w:/~  );
3552
            $fn =~ s~//~/~g;
3553
        }
3554
    }
3555
 
3556
  return $fn;
3557
}
3558
 
3559
#-------------------------------------------------------------------------------
3560
# Function        : LocatePreReq
3561
#
3562
# Description     : Locate a file known to JATS
3563
#                   There are many places to search
3564
#                       1) Src files - specified with a Src directive
3565
#                       2) Scripts - specified with a script directive
3566
#                       3) Search - Files in the specified search path
3567
#                       4) Programs specified with a 'Prog' directive
3568
#
3569
#                   Should also look in other locations (Libs, SharedLibs)
3570
#                   Not done yet. May be issues of a name clash if a program
3571
#                   and a library have the same name.
3572
#
3573
# Inputs          : Name to locate
3574
#
3575
# Returns         : Full pathname of file
3576
#
3577
sub LocatePreReq
3578
{
3579
    my ( $name ) = @_;
3580
    Debug ("LocatePreReq:Looking for $name");
3581
    #
3582
    #   Try a Src file first
3583
    #
3584
    if ( exists $SRCS{ $name } )
3585
    {
3586
        return $SRCS{ $name };
3587
    }
3588
 
3589
    #
3590
    #   Try a script
3591
    #
3592
    if ( exists $SCRIPTS{ $name } )
3593
    {
3594
        return $SCRIPTS{ $name };
3595
    }
3596
 
3597
    #
3598
    #   Try a PROG
3599
    #
289 dpurdie 3600
    if ( my $pProg = $PROGS->Get($name) )
227 dpurdie 3601
    {
289 dpurdie 3602
        return $pProg->getPath();
227 dpurdie 3603
    }
3604
 
3605
    #
3606
    #   Try searching for the file
3607
    #   Uses Data from AddSrcDir
3608
    #
3609
    #   Done: last because it generates warning messages
3610
    #
3611
    return MakeSrcResolve( $name );
3612
}
3613
 
3614
#-------------------------------------------------------------------------------
3615
# Function        : ToolExtensionPaths
3616
#
3617
# Description     : Return a list of toolset extension directories
3618
#                   The data will have been discovered by the build process
3619
#                   and will have been saved for the makefile creation phase
3620
#
3621
# Inputs          : None
3622
#
3623
# Returns         : Return an ordered unique list
3624
#
3625
sub ToolExtensionPaths
3626
{
3627
    Debug( "ToolExtensionPaths:", @::BUILDTOOLSPATH );
3628
    return @::BUILDTOOLSPATH;
3629
}
3630
 
3631
#-------------------------------------------------------------------------------
3632
# Function        : ToolExtensionProgram
3633
#
3634
# Description     : Determine if the named program exists within the PATH
3635
#                   that also includes the toolset extension
3636
#
3637
# Inputs          : program             - Name of program
3638
#                   elist               - An array of possible program extensions
3639
#
3640
# Returns         : Full path the to program or undef
3641
#
3642
sub ToolExtensionProgram
3643
{
3644
    my ($program, @elist ) = @_;
3645
 
3646
    #
3647
    #   If elist is empty then insert a defined entry
3648
    #
3649
    push @elist, '' unless ( @elist );
3650
 
3651
    #
3652
    #   Scan all toolset directories
3653
    #   for the program
3654
    #
3655
    for my $dir ( ToolExtensionPaths() )
3656
    {
3657
        for my $ext ( @elist )
3658
        {
3659
            my $tool = "$dir/$program$ext";
3660
            Debug2( "ToolsetExtensionProgram: Look for: $tool" );
3661
 
3662
            return $tool if ( -f $tool );
3663
        }
3664
    }
3665
}
3666
 
3667
sub Define
3668
{
3669
    Debug2( "Define(@_)" );
3670
 
3671
    push( @DEFINES, @_ );
3672
}
3673
 
3674
 
3675
sub Defines
3676
{
3677
    my( $path, $script ) = @_;
3678
    my( $line );
3679
 
3680
    Debug2( "Defines($path, $script)" );
3681
 
3682
    $script = Exists( $path, $script, "Defines" );
271 dpurdie 3683
    push( @DEFINES, "# Defines from: $script" );
285 dpurdie 3684
    open( my $fh, '<', $script ) || Error( "Opening $script" );
3685
    while (<$fh>) {
227 dpurdie 3686
        $_ =~ s/\s*(\n|$)//;                    # kill trailing whitespace & nl
3687
        push( @DEFINES, $_ );
3688
    }
3689
    push( @ScmDepends, "$script" );             # makefile dependencies
285 dpurdie 3690
    close( $fh );
227 dpurdie 3691
}
271 dpurdie 3692
#-------------------------------------------------------------------------------
3693
# Function        : Rule
3694
#
3695
# Description     : Add a Rule and Recipe to the generated makefile
3696
#                   This is not encouraged as it has been misused to create
3697
#                   unreadable and unmaintainable makefiles.
3698
#
3699
#                   Rules will be added to the makefile after the rules and
3700
#                   recipes created by JATS directives
3701
#
3702
# Inputs          : $platform               - Platform predicate
3703
#                   @rule                   - Array of rules to add
3704
#
3705
# Returns         : 
3706
#
227 dpurdie 3707
sub Rule
3708
{
3709
    my( $platforms, @rule ) = @_;
3710
 
3711
    return if ( ! ActivePlatform($platforms) );
3712
 
3713
    push( @RULES, @rule );
3714
    Message("Rule directive used. Consider replacing with GenerateFiles");
3715
}
3716
 
271 dpurdie 3717
#-------------------------------------------------------------------------------
3718
# Function        : Rules
3719
#
3720
# Description     : Add a file of Rules and Recipes to the generated makefile
3721
#                   Used internally ONLY as there is no platform predicate
3722
#                   Similar to 'Rule()'
3723
#
3724
# Inputs          : $path                   - path to script
3725
#                   $script                 - File fo Rules
3726
#
3727
# Returns         : 
3728
#
227 dpurdie 3729
sub Rules
3730
{
3731
    my( $path, $script ) = @_;
3732
    my( $line );
3733
 
3734
    $script = Exists( $path, $script, "Rules" );
271 dpurdie 3735
    push( @RULES, "# Rules from: $script" );
285 dpurdie 3736
    open( my $fh, '<', $script ) || Error( "Opening $script" );
3737
    while (<$fh>) {
227 dpurdie 3738
        $_ =~ s/\s*(\n|$)//;                    # kill trailing whitespace & nl
3739
        push( @RULES, $_ );
3740
    }
3741
    push( @ScmDepends, "$script" );             # makefile dependencies
285 dpurdie 3742
    close( $fh );
227 dpurdie 3743
}
3744
 
271 dpurdie 3745
#-------------------------------------------------------------------------------
3746
# Function        : AddRule
3747
#
3748
# Description     : Inernal function
3749
#                   Add a line to the Rules area
3750
#
3751
# Inputs          : @elements                   - Array of lines to add
3752
#
3753
# Returns         : Nothing
3754
#
3755
sub AddRule
3756
{
3757
    push( @RULES, @_ );
3758
}
227 dpurdie 3759
 
271 dpurdie 3760
#-------------------------------------------------------------------------------
3761
# Function        : Src
3762
#
3763
# Description     : This directive is used to identify files to JATS
3764
#                   Once a file has been identified as a 'Source' file, then it
3765
#                   can be used by name, without the need to locate the file again.
3766
#                   This implies that filenames must be unique.
3767
#                   The directories cannot be used to make files of the same name
3768
#                   unqiue - this is not the JATS way
3769
#
3770
#                   Source files will be classified as one of:
3771
#                       c, c++, header, assembler or other
3772
#
3773
#
3774
# Inputs          : $platform               - Active Platform Predicate
3775
#                   @elements               - A list of files and options
3776
#
3777
#                   Valid options are:
3778
#                       --c                 - Specifies the type of file
3779
#                       --cpp
3780
#                       --h, --headers
3781
#                       --asm
3782
#                       --FromPackage       - Search packages for the file
3783
#                       --List=xxx          - Append file to a named list
3784
#                       --Depends=xxx       - Manually name a dependency
3785
#
3786
#                   Options are processed before file elements
3787
#                   Thus options apply to all files in the list
3788
#
3789
# Returns         : Nothing
3790
#
227 dpurdie 3791
sub Src
3792
{
3793
    my( $platforms, @elements ) = @_;
3794
    my( $type, @args, $source, $basename, $from_package, @lists );
3795
    my( @depends, @srcs );
3796
 
3797
    $platforms = '' unless ( $platforms );
3798
    Debug2( "Src($platforms, @elements)" );
3799
 
3800
    #
3801
    #   Ensure that there is a file within the list
3802
    #
3803
    Warning( "Src directive does not specify any files: Src($platforms, @elements)" )
3804
        unless (grep( /^[^-]/, @elements ) );
3805
 
3806
    return if ( ! ActivePlatform($platforms) );
3807
 
3808
    #
3809
    #   Remove spaces from both ends of the arguments.
3810
    #   It is easier to remove spaces now than to detect them later
3811
    #
3812
    foreach ( @elements )
3813
    {
3814
        s/^\s+//;
3815
        s/\s+$//;
3816
        s~//~/~g;                               # Remove multiple /
3817
    }
3818
 
3819
    #.. Collect arguments
3820
    #
3821
    $type = "";
3822
    foreach ( @elements )
3823
    {
3824
        if ( /^--c$/ )
3825
        {
3826
            Debug( "Src: --c" );
3827
            $type = ".c";
3828
        }
3829
        elsif ( /^--cpp$/ )
3830
        {
3831
            Debug( "Src: --cpp" );
3832
            $type = ".cc";
3833
        }
3834
        elsif ( /^--h$/ || /^--header$/ )
3835
        {
3836
            Debug( "Src: --h" );
3837
            $type = ".h";
3838
        }
3839
        elsif ( /^--asm$/ )
3840
        {
3841
            Debug( "Src: --asm" );
3842
            $type = ".asm";
3843
        }
3844
        elsif ( /^--FromPackage$/ )
3845
        {
3846
            $from_package = 1;
3847
        }
3848
        elsif ( /^--List=(.*)/ )
3849
        {
3850
            my $list_name = $1;
3851
            Error( "Bad list name: $list_name" )
3852
                unless ( $list_name =~ m/^[A-Za-z]\w+/ );
3853
            push @lists, $list_name;
3854
        }
3855
        elsif ( /^--Depends=(.*)/ )
3856
        {
3857
            foreach ( split( ',', $1) )
3858
            {
3859
                my $full = MakeSrcResolveExtended( $from_package, $_ );
3860
                push @depends, $full;
3861
            }
3862
        }
3863
        elsif ( /^-(.*)/ )
3864
        {
3865
            Debug( "Src: arg $_" );
3866
            push @args, $_;
3867
        }
3868
        else
3869
        {
3870
            push @srcs, $_;
3871
            Warning ("Src files contains a '\\' character: $_" ) if (m~\\~);
3872
        }
3873
    }
3874
 
3875
    #.. Push source file(s)
3876
    foreach ( @srcs )
3877
    {
3878
        if ( ! /^-(.*)/ )
3879
        {
3880
            $source = MakeSrcResolveExtended( $from_package, $_ );
3881
            $basename = StripDir( $source );
3882
            Debug( "Src: $_ -> $source=$basename (@args),(@depends)" );
3883
 
3884
            if ( $SRCS{ $basename } ) {
3885
                Warning( "Duplicate src ignored '$source'");
3886
                next;
3887
            }
3888
            $SRCS{ $basename } = $source;
3889
 
3890
            HashJoin( \%SRC_ARGS, $;, $basename, @args )
3891
                if (@args);
3892
 
3893
            HashJoin( \%SRC_DEPEND, $;, $basename, @depends )
3894
                if ( @depends );
3895
 
3896
            $SRC_TYPE{ $basename } = $type
3897
                if ($type);
3898
 
3899
 
3900
            foreach (@lists) {
3901
                my $lname_short = "LIST_$_";
3902
                my $lname_full = "LIST_FULL_$_";
3903
 
3904
                no strict 'refs';
3905
 
3906
                push @$lname_short,$basename;
3907
                push @$lname_full ,$source;
3908
 
3909
                use strict 'refs';
3910
            }
3911
 
3912
            __AddSourceFile( 1, $source, "", $type );
3913
        }
3914
    }
3915
}
3916
 
3917
 
3918
###############################################################################
3919
#  sub LibNameSplit
3920
#      Just a little help to deal with major/minor stuff for shared libs -
3921
#      given the name of the library as the argument, split out major and minor
3922
#      parts and return the basename, i.e name without major and minor and
3923
#      the pair of major and minor.
3924
###############################################################################
3925
 
3926
sub LibNameSplit
3927
{
3928
    my ( @bits ) = split('\.', $_[0]);
3929
    my ( $major, $minor );
3930
 
3931
    if ($#bits >= 1) {
3932
        $major = $bits[0]; $minor = $bits[1];
3933
    } elsif ($#bits >= 0) {
3934
        $major = $bits[0]; $minor = 0;
3935
    } else {
3936
        $major = 1; $minor = 0;
3937
    }
3938
    Debug( "LibName: $@_[0] ($major.$minor)" );
3939
    return ($major, $minor);
3940
}
3941
 
3942
#-------------------------------------------------------------------------------
3943
# Function        : Lib
3944
#
3945
# Description     : Generate a static library
3946
#
3947
# Inputs          : Platform specifier
3948
#                   Name of the library
3949
#                   Arguemnts ...
3950
#
3951
# Returns         :
3952
#
3953
sub Lib
3954
{
3955
    my( $platforms, $lib, @args ) = @_;
3956
    return if ( ! ActivePlatform($platforms) );
3957
 
3958
    Error ("Lib: Library name not defined") unless ( $lib );
3959
 
3960
    #
3961
    #   May be a shared library or a static library - for historic reasons
3962
    #   If the user has specified a --Shared then its a shared library
3963
    #
3964
    return SharedLib( @_ )
3965
        if ( grep (/^--Shared/, @args) );
3966
 
3967
    #
3968
    #   Does this toolset support libraries
3969
    #
3970
    Error ("Libraries are not supported") unless ( defined $::a );
3971
 
3972
    #.. Fully qualify library path for addition to library list.
3973
    $lib = "lib$lib"
3974
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
3975
    Debug( "Lib: $lib" );
3976
 
3977
    #
289 dpurdie 3978
    #   Create a new object to describe the library
227 dpurdie 3979
    #   Ensure that only one such lib exists
289 dpurdie 3980
    #   Add the library to the list of static libraries
227 dpurdie 3981
    #
3982
    Error( "Library of the same name already defined: $lib" )
289 dpurdie 3983
        if ( $LIBS->Get($lib) );
3984
    $LIBS->NewAdd($lib);
227 dpurdie 3985
 
3986
    #
3987
    #   Process arguments
3988
    #
3989
    push( @LINTLIBS, $lib );
3990
    _LibArgs( $lib, @args );
3991
}
3992
 
3993
 
3994
#-------------------------------------------------------------------------------
3995
# Function        : SharedLib
3996
#
3997
# Description     : Generate a shared library
3998
#
3999
# Inputs          : Platform specifier
4000
#                   Name of the library
4001
#                   Arguemnts ...
4002
#
4003
# Returns         :
4004
#
4005
sub SharedLib
4006
{
4007
    my( $platforms, $lib, @args ) = @_;
4008
 
4009
    return if ( ! ActivePlatform($platforms) );
4010
 
4011
    Error ("SharedLib: Library name not defined") unless ( $lib );
4012
    Error ("Shared Libraries are not supported") unless ( defined $::so );
4013
 
4014
#.. Fully qualify library path for addition to library list.
4015
    $lib = "lib$lib"
4016
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4017
    Debug( "ShLib: $lib" );
4018
 
4019
    #
4020
    #   Ensure that only one such lib exists
4021
    #
289 dpurdie 4022
    Error( "Library of the same name already defined: $lib" )
4023
        if ( $SHLIBS->Get($lib) );
4024
    $SHLIBS->NewAdd($lib);
293 dpurdie 4025
 
227 dpurdie 4026
    #
4027
    #   If the user has not specified a --Shared parameter then provide one
4028
    #
4029
    push @args, "--Shared=Current"
4030
        unless ( grep (/^--Shared/, @args) );
4031
 
4032
    #
4033
    #   Process arguments
4034
    #
4035
    push( @LINTSHLIBS, $lib );
4036
    _SharedLibArgs( $lib, @args );
4037
}
4038
 
4039
 
4040
#-------------------------------------------------------------------------------
4041
# Function        : LibArgs
4042
#
4043
# Description     : Add arguments to an existing library directive
4044
#
4045
# Inputs          : Platform specifier
4046
#                   Name of the library
4047
#                   Arguemnts ...
4048
#
4049
# Returns         :
4050
#
4051
sub LibArgs
4052
{
4053
    my( $platforms, $lib, @args ) = @_;
4054
    return if ( ! ActivePlatform($platforms) );
4055
 
4056
#.. Fully qualify library path for addition to library list.
4057
    $lib = "lib$lib"
4058
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4059
    Debug( "LibArgs: $lib" );
4060
 
4061
    #
4062
    #   Process the arguments
4063
    #
4064
    _LibArgs( $lib, @args );
4065
}
4066
 
4067
 
4068
#-------------------------------------------------------------------------------
4069
# Function        : _LibArgs
4070
#
4071
# Description     : Process static library arguments
4072
#                   Internal use only
4073
#
4074
# Inputs          : Name of the library
4075
#                   Arguments to process
4076
#
4077
sub _LibArgs
4078
{
4079
    my( $lib, @elements) = @_;
4080
    my $obj;
4081
 
4082
    #
289 dpurdie 4083
    #   Ensure that only one such lib exists
4084
    #
4085
    my $libp = $LIBS->Get($lib);
4086
    Error("Library name not defined: $lib")
4087
        unless ( $libp );
4088
 
4089
    #
227 dpurdie 4090
    #   Process each element
4091
    #
4092
    foreach (@elements)
4093
    {
4094
        if ( /^--Shared/ )
4095
        {
4096
            Error( "--Shared not valid for a static library" );
4097
        }
4098
 
4099
        if ( /^-l(.*)/ || /^--l(.*)/ || /^-L(.*)/ || /^--L(.*)/ )
4100
        {
4101
        #.. Target library specified - add to library list.
4102
        #
4103
            Warning( "$_ within non shared library specification" );
4104
            next;
4105
        }
4106
 
4107
        if ( /^--if(.*)/ )
4108
        {
4109
            Warning( "$_ within non shared library specification" );
4110
            next;
4111
        }
4112
 
4113
        if ( /^--(.*)/ )
4114
        {
4115
            Debug( "LibArgs: arg $_" );
4116
 
4117
            #.. Argument specified - add to argument list
4118
            #
289 dpurdie 4119
            $libp->addItem('ARGS', $_);
4120
 
227 dpurdie 4121
            next;
4122
        }
4123
 
4124
        if ( defined %::ScmToolsetProgSource )
4125
        {
4126
            #
4127
            #   Toolset provides support for some file types
4128
            #   to be passed directly to the librarian builder
4129
            #
4130
            my $ext  = StripFile($_);
4131
            if ( exists ($::ScmToolsetProgSource{$ext}) )
4132
            {
4133
                my $full_path = MakeSrcResolve ( $_ );
4134
                my $flag = $::ScmToolsetProgSource{$ext};
4135
                Debug( "LibArgs: src $_" );
289 dpurdie 4136
                $libp->addItem('ARGS', "$flag$full_path" );
227 dpurdie 4137
                next;
4138
            }
4139
        }
4140
 
4141
        if ( $::o )
4142
        {
4143
        #.. Object specified - add to object list.
4144
        #
4145
            $obj = _LibObject( "", $_ );
4146
 
4147
        #.. Add to object list.
4148
        #   Note:   Object path must be explicit as several
4149
        #           toolsets add additional objects.
4150
        #
289 dpurdie 4151
            $libp->addItem('OBJS', "\$(OBJDIR)/$obj" );
227 dpurdie 4152
            next;
4153
        }
4154
 
4155
        #
4156
        #   Don't know how to handle this type of argument
4157
        #
4158
        Error ("LibArgs: Don't know how to handle: $_" );
4159
    }
4160
}
4161
 
4162
 
4163
#-------------------------------------------------------------------------------
4164
# Function        : SharedLibArgs
4165
#
4166
# Description     : Add arguments to an existing shared library directive
4167
#
4168
# Inputs          : Platform specifier
4169
#                   Name of the library
4170
#                   Arguemnts ...
4171
#
4172
# Returns         :
4173
#
4174
sub SharedLibArgs
4175
{
4176
    my( $platforms, $lib, @args ) = @_;
4177
    return if ( ! ActivePlatform($platforms) );
4178
 
4179
#.. Fully qualify library path for addition to library list.
4180
    $lib = "lib$lib"
4181
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4182
    Debug( "ShLibArgs: $lib" );
4183
 
4184
    _SharedLibArgs( $lib, @args );
4185
}
4186
 
4187
 
4188
#-------------------------------------------------------------------------------
4189
# Function        : _SharedLibArgs
4190
#
4191
# Description     : Process shared library arguments
4192
#                   Internal use only
4193
#
4194
# Inputs          : Name of the library
4195
#                   Arguments to process
4196
#
4197
sub _SharedLibArgs
4198
{
4199
    my ( $lib, @elements) = @_;
4200
 
289 dpurdie 4201
    my $libp = $SHLIBS->Get($lib);
4202
    Error("Library name not defined: $lib")
4203
        unless ( $libp );
4204
 
227 dpurdie 4205
    #
289 dpurdie 4206
    #.. Collect --Shared arguments
227 dpurdie 4207
    #
4208
    foreach (@elements)
4209
    {
289 dpurdie 4210
        next unless ( /^--Shared/ );
4211
 
4212
        my $shared;
227 dpurdie 4213
        if ( /^--Shared$/ )
4214
        {
4215
        #.. Shared library, default library version 1.0
4216
        #
4217
            $shared = "1.0";
4218
        }
4219
        elsif ( /^--Shared=Current$/ )
4220
        {
4221
        #.. Shared library, using 'current' build version
4222
        #
4223
            $shared = $::ScmBuildVersion;
289 dpurdie 4224
            $shared = "1.0" if ($shared eq "");
227 dpurdie 4225
        }
4226
        elsif ( /^--Shared=(.*)/ )
4227
        {
4228
        #.. Shared library, specific version
4229
        #
4230
            my($M, $m) = LibNameSplit($1);
289 dpurdie 4231
            $shared = "$M.$m";
4232
        }
227 dpurdie 4233
 
289 dpurdie 4234
        #
4235
        #   Update the shared Names
4236
        #
4237
        if ( defined $shared )
4238
        {
227 dpurdie 4239
            Warning( "multiple --Shared arguments" )
289 dpurdie 4240
                if ($libp->{ VERSION });
227 dpurdie 4241
            Debug( "ShLibArgs: shared $_ ($shared)" );
289 dpurdie 4242
            $libp->{ VERSION } = $shared;
227 dpurdie 4243
        }
289 dpurdie 4244
        else
4245
        {
4246
            Error ("ShLibArgs: --Shared argument not understood");
4247
        }
227 dpurdie 4248
    }
4249
 
4250
 
4251
#.. Parse all of the object and argument entries.
4252
#
4253
    foreach (@elements)
4254
    {
289 dpurdie 4255
        next if ( /^--Shared(.*)/ );
227 dpurdie 4256
 
4257
        if ( /^[-]{1,2}([lL])(.*)/ )
4258
        {
4259
        #.. Target library specified - add to library list.
4260
        #
4261
            Debug( "ShLibArgs: lib  -$1$2" );
289 dpurdie 4262
            $libp->addItem('LIBS', "-$1$2" );
227 dpurdie 4263
            next;
4264
        }
4265
 
4266
        if ( /^--if(.*)/ )
4267
        {
4268
        #.. Library conditional - add to library list.
4269
        #
4270
            Debug( "ShLibArgs: cond $_" );
289 dpurdie 4271
            $libp->addItem('LIBS', $_);
227 dpurdie 4272
            next;
4273
        }
4274
 
4275
        if ( /^-(.*)/ )
4276
        {                           
4277
        #.. Argument specified - add to argument list
4278
        #
4279
            Debug( "ShLibArgs: arg  $_" );
289 dpurdie 4280
            $libp->addItem('ARGS', $_);
227 dpurdie 4281
            next;
4282
        }
4283
 
4284
        if ( defined %::ScmToolsetProgSource )
4285
        {
4286
            #
4287
            #   Toolset provides support for some file types
4288
            #   to be passed directly to the program builder
4289
            #
4290
            my $ext  = StripFile($_);
4291
            if ( exists ($::ScmToolsetProgSource{$ext}) )
4292
            {
4293
                my $full_path = MakeSrcResolve ( $_ );
4294
                my $flag = $::ScmToolsetProgSource{$ext};
4295
                Debug( "ShLibArgs: src $_" );
289 dpurdie 4296
                $libp->addItem('ARGS', "$flag$full_path");
227 dpurdie 4297
                next;
4298
            }
4299
        }
4300
 
4301
        if ( $::o )
4302
        {
4303
        #.. Object specified - add to object list.
4304
        #
4305
            my ($obj) = _LibObject( $lib, $_ );
4306
 
4307
        #.. Add to object list.
4308
        #   Note:   Object path must be explicit as several
4309
        #           toolsets add additional objects.
4310
        #
4311
            $SHOBJ_LIB{ $obj } = $lib;
289 dpurdie 4312
            $libp->addItem('OBJS', "\$(OBJDIR)/$obj");
227 dpurdie 4313
            next;
4314
        }
4315
 
4316
        #
4317
        #   Don't know how to handle this type of argument
4318
        #
4319
        Error ("SharedLib: Don't know how to handle: $_" );
4320
    }
4321
}
4322
 
4323
 
4324
#-------------------------------------------------------------------------------
4325
# Function        : _LibObject
4326
#
4327
# Description     : Process library object file
4328
#                   Common processing routine for static and shared library
4329
#                   Internal use only
4330
#
4331
# Inputs          : shared  - Name of the shared library is shared, if defined
4332
#                   fname   - Name of file
4333
#
4334
# Returns         : Name of the object file
4335
#
4336
sub _LibObject
4337
{
4338
    my ($shared, $fname) = @_;
4339
    my ($file, $ext, $obj, $srcfile, $delete_obj);
4340
 
4341
    #.. Object specified - add to object list.
4342
    #
4343
    $file = StripExt($fname);                   # file name, without extension
4344
    $ext  = StripFile($fname);                  # extension
4345
 
4346
    if ($shared) {
4347
        $obj = "$shared/$file";                 # library specific subdir
4348
    } else {
4349
        $obj = "$file";
4350
    }
4351
 
4352
    Debug( "LibObjs: obj [$shared]$fname ($file$ext)" );
4353
 
4354
    #.. Unqualified object name
4355
    #
4356
    if ( $ext eq "" )
4357
    {
4358
        #
4359
        #   Object file not covered by a "Src" statement
4360
        #   Assume that it will be created
4361
        #
4362
        unless ( $srcfile = $OBJSOURCE{ "$file" } )
4363
        {
4364
            #
4365
            #   If the object is "generated" then it will be is the
4366
            #   SRCS list
4367
            #
4368
            unless ( $srcfile = $SRCS{"$file.$::o"} )
4369
            {
4370
                Warning( "No source for object '$fname' ($file)" );
4371
            }
4372
        }
4373
        $delete_obj = 1;
4374
    }
4375
 
4376
    #.. Qualified object name (ie has extension)
4377
    #       Strip extension and resolve ...
4378
    #       Assume that the named file can be built into an object file
4379
    #
4380
    else
4381
    {
4382
        #.. Resolve
4383
        #
4384
        if ( !($srcfile = $OBJSOURCE{ "$file" }) )
4385
        {
4386
            $srcfile = MakeSrcResolve( $fname );
4387
            $SRCS{ $fname } = $srcfile;
4388
            __AddSourceFile( 0, $fname, $obj );
4389
            $delete_obj = 1;
4390
        }
4391
    }
4392
 
4393
    #.. Delete generated object file
4394
    #   Ensure that the object file is added to the delete list
4395
    #   Add it to the ToolsetObj deletion list as the main OBJ deleltion
4396
    #   list will aready have been processed
4397
    #
4398
    ToolsetObj( "\$(OBJDIR)/$obj" )
4399
        if ( $delete_obj );
4400
 
4401
 
4402
    #.. Shared library objects,
4403
    #       Must explicitly relate source and object, as shared libraries
4404
    #       objects are built within a library specific subdirs.
4405
    #
4406
    $OBJSOURCE{ $obj } = $srcfile
4407
        if ( $shared );
4408
 
4409
    return $obj;
4410
}
4411
 
4412
 
4413
# MergeLibrary
4414
#   Merge a list of libraries into one library
4415
#
4416
sub MergeLibrary
4417
{
4418
    my( $platforms, $lib, @elements ) = @_;
4419
 
4420
    return if ( ! ActivePlatform($platforms) );
4421
 
4422
 
4423
#.. Fully qualify library path for addition to library list.
4424
    $lib = "lib$lib"
4425
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4426
    Debug( "MergeLibrary: $lib" );
4427
 
289 dpurdie 4428
    #
4429
    #   Create a new object to describe the library
4430
    #   Ensure that only one such lib exists
4431
    #   Add the library to the list of static libraries
4432
    #
4433
    Error( "Merged Library of the same name already defined: $lib" )
4434
        if ( $MLIBS->Get($lib) );
4435
    my $libp = $MLIBS->NewAdd($lib);
4436
 
227 dpurdie 4437
#.. Parse all of the object and argument entries.
4438
#
4439
    foreach (@elements)
4440
    {
4441
        if ( /^--(.*)/ )
4442
        {
289 dpurdie 4443
            $libp->addItem('ARGS', $_);
227 dpurdie 4444
        }
4445
        else
4446
        {
4447
            my ($llib);
4448
 
4449
            #
4450
            #   Collect the source libraries
4451
            #   These must have been installed and will be in a known area
4452
            #   Create full names for the libaries
4453
            #
4454
            if ( $ScmTargetHost eq "Unix" ) {
4455
                $llib = "lib$_";                # Prefix "lib" ....
4456
                $lib =~ s/^liblib/lib/;         # @LIBS already has lib added
4457
            } else {
4458
                $llib = $_;
4459
            }
4460
 
4461
            Debug( "MergeLibrary: merge $llib" );
289 dpurdie 4462
            $libp->addItem('LIBS', $llib);
227 dpurdie 4463
        }
4464
    }
4465
}
4466
 
4467
#-------------------------------------------------------------------------------
4468
# Function        : Script
4469
#
4470
# Description     : Locate a script for test purposes
4471
#
4472
# Inputs          : $platforms      - Platform selector
4473
#                   $script         - A single script name
4474
#                   $execute        - Flag to indicate that the script is to
4475
#                                     marked as executable when used in a TestProg
4476
#                                     This flag is NOT used as the script will
4477
#                                     be forced executable
4478
#
4479
# Returns         : Nothing
4480
#
4481
sub Script
4482
{
4483
    my( $platforms, $script, $execute ) = @_;
4484
 
4485
    Debug2( "Script(@_)" );
4486
 
4487
    return if ( ! ActivePlatform($platforms) );
4488
 
4489
    #
4490
    #   Locate the script as a source file
4491
    #
4492
    my $file = MakeSrcResolve ( $script );
4493
    $script = StripDir( $file );
4494
    $SCRIPTS{ $script } = $file;
4495
}
4496
 
4497
#-------------------------------------------------------------------------------
4498
# Function        : RunTest
4499
#
4500
# Description     : Define a test to be run with the 'run_tests' and 'run_unit_tests'
4501
#
4502
# Inputs          : $platform       - Enabled for these platforms
4503
#                   $prog           - Program to run
4504
#                                     This SHOULD return a non-zero exit status
4505
#                                     on error. The program may be a 'TestProg'
4506
#                                     or a 'Script'.
4507
#                   @elements       - Options and test arguments
4508
#                                     Options are:
4509
#                                       --Auto          - Non interactive unit test
4510
#                                       --Unit          - Same and --Auto
4511
#                                       --CopyIn=file   - A file to be copied into
4512
#                                                         The test directory.
4513
#
4514
#                                     Non Options are passed to the test program.
4515
#                                     --PackageBase(xxx)    - Base of package
4516
#                                     --PackageInfo(xxx)    - Package information
4517
#                                     --File(xxx)           - Resolved name of file
4518
#                                     --Var(xxx)            - Expanded variable
4519
#                                     --Local(xxx)          - File within the local directory
4520
#
4521
# Returns         : Nothing
4522
#
4523
 
4524
sub RunTest
4525
{
4526
    my( $platforms, $prog, @elements ) = @_;
4527
    my $command = './';                 # program prefix / command
4528
    my $winprog = 1;                    # 1: Convert / -> \ (WIN32 only)
4529
    my $framework;
4530
    my @framework_opts;
4531
    my @copy = ();
4532
    my $auto;
4533
 
4534
    return if ( ! ActivePlatform($platforms) );
4535
 
4536
    #
4537
    #   Scan @elements and extract useful information
4538
    #   Need to process twice as some args will modify the
4539
    #   processing done later
4540
    #
4541
    my @args;
4542
    foreach ( @elements )
4543
    {
4544
        if ( m/^--FrameWork=(.+)/ ) {
4545
            $framework = $1;
4546
 
4547
        } elsif ( m/^--Auto/ || m/^--Unit/) {
4548
            $auto = 1;
4549
 
4550
        } elsif ( m/^--CopyIn=(.*)/ ) {
4551
            push @copy, MakeSrcResolve ( $1 );
4552
 
4553
 
4554
        } elsif ( $framework && m/^--\w+=(.+)/ ) {
4555
            push @framework_opts, $_;
4556
 
4557
        } else {
4558
            push @args, $_;
4559
        }
4560
    }
4561
    @elements = @args;
4562
    @args = ();
4563
 
4564
    #
4565
    #   Determine the source of the test prog
4566
    #   If using a plug-in framework, then we don;'t know
4567
    #   If not, then may be a script or a TESTPROGS
4568
    #
4569
 
4570
    unless ( $framework )
4571
    {
289 dpurdie 4572
        if ( $TESTPROGS->Get($prog) || $PROGS->Get($prog)  ) {
227 dpurdie 4573
            #
4574
            #   Append a suitable EXE suffix
4575
            #
289 dpurdie 4576
            $prog = GenProgName( $prog );
227 dpurdie 4577
 
4578
        } elsif ( exists $SCRIPTS{$prog} ) {
4579
            #
4580
            #   Script names are raw
4581
            #   Perl script are invoked directly
4582
            #
4583
            $command = "\$(GBE_PERL) -w "
4584
                if ( $prog =~ /\.pl$/ );
4585
 
4586
            #
4587
            #   Pass / to shells
4588
            #
4589
            $winprog = 0
4590
                unless ( $prog =~ m~\.bat$~ )
4591
 
4592
        } else {
4593
            Warning("RunTest program not known: $prog",
261 dpurdie 4594
                  "It is not a TestProg, Prog or a Script",
4595
                  "The test may fail" );
227 dpurdie 4596
        }
4597
    }
4598
 
4599
    #
4600
    #   Extract and process options
4601
    #
4602
    my @uargs = ();
4603
    my @preq_files;
4604
 
4605
    foreach my $arg (@elements) {
4606
        #
4607
        #   Process the tool arguments and extract file information
4608
        #   Extract all fields of the form:
4609
        #           --xxxxx(yyyyyy[,zzzzz])
4610
        #           --xxxxx{yyyyyyy}
4611
        #           --xxxxx[yyyyyyy] to allow embedded brackets
4612
        #
4613
        while ( $arg =~ m/--(\w+)               # --CommandWord         $1
4614
                                (               # Just for grouping
4615
                                \((.*?)\)   |   # Stuff like (yyyyy)    $3
4616
                                {(.*?)}     |   # or    like {yyyyy}    $4
4617
                                \[(.*?)\]       # or    like [yyyyy]    $5
4618
                                )/x )           # Allow comments and whitespace
4619
        {
4620
            my $cmd = $1;                       # The command
4621
            my $ufn = $3 || $4 || $5;           # User filename + options
4622
            my $mb = $-[0];                     # Match begin offset
4623
            my $me = $+[0];                     # Match end
4624
            my $flags = '';                     # Optional flags ( --dir or --file )
4625
            my $raw_arg = $ufn;                 # Raw arguments
285 dpurdie 4626
            my $all = substr( $arg, $mb, $me ); # All of match. Avoid use of $&
227 dpurdie 4627
 
4628
            Error ("RunTest. Empty element not allowed: $all")
4629
                unless ( defined($ufn) );
4630
 
4631
            $ufn =~ s/\s+$//;
4632
            $ufn =~ s~//~/~g;                   # Remove multiple /
4633
            if ( $ufn =~ m/(.*?),(.*)/ )        # Extract out any flags
4634
            {
4635
                $ufn = $1;
4636
                $flags = $2;
4637
            }
4638
 
4639
            my $fn = $ufn ;                     # Replacement filename
4640
            Error ("RunTest. Empty element not allowed: $all" )
4641
                if ( length ($ufn) <= 0 );
4642
 
4643
            #
4644
            #   Process found user command
4645
            #
4646
            if ( $cmd =~ /^File/ )
4647
            {
4648
                #
4649
                #   Prerequisite filename
4650
                #       Resolve the full name of the file. It may be known
4651
                #       as a source file (possibly generated) or it may be
4652
                #       located in a known source directory
4653
                #
4654
                $fn = MakeSrcResolve ( $ufn );
4655
                UniquePush (\@preq_files, $fn);
4656
 
4657
                Debug( "RunTest: Prereq: $fn" );
4658
 
4659
            }
4660
            elsif ( $cmd =~ /^PackageBase/ )
4661
            {
4662
                $fn = GetPackageBase( "RunTest", $raw_arg );
4663
                UniquePush (\@preq_files, $fn);
4664
            }
4665
            elsif ( $cmd =~ /^PackageInfo/ )
4666
            {
4667
                $fn = GetPackageInfo( "RunTest", $raw_arg );
4668
            }
4669
            elsif ( $cmd =~ /^Var/ )
4670
            {
4671
                $fn = ExpandGenVar( "RunTest", $raw_arg );
4672
                $flags = '';
4673
            }
4674
            elsif ( $cmd =~ /^Local/ )
4675
            {
4676
                $fn = '$(LOCALDIR)/' . $ufn ;
4677
                UniquePush (\@preq_files, $fn);
4678
            }
4679
            else
4680
            {
4681
                Warning ("RunTest: Unknown replacement command: $cmd");
4682
                $fn = $ufn;
4683
            }
4684
 
4685
            #
4686
            #   Process path modification flags
4687
            #       --dir           - only the directory part ( or a "." )
4688
            #       --file          - only the file part
4689
            #       --abspath       - Absolute path
4690
            #       --absdrive      - Absolute path with drive letter(WIN)
4691
            #
4692
            $fn = ProcessPathName( $fn, $flags );
4693
 
4694
            #
4695
            #   The program is going to be executed within a subdirectory
4696
            #   so add one more level of indirection to the path, but only if
4697
            #   the path is relative
4698
            #
4699
            unless ( $fn =~ m~^/|\w:/~  )
4700
            {
4701
                $fn = '../' . $fn;
4702
                $fn =~ s~/.$~~;
4703
            }
4704
 
4705
            #
4706
            #   Minor kludge under windows. Ensure directores have a "\" sep
4707
            #   Unless the user has specified a straight shell command
4708
            #
303 dpurdie 4709
            $fn = "\$(subst /,\\,$fn)"
227 dpurdie 4710
                if ( $::ScmHost eq "WIN" && $winprog );
4711
 
4712
            #
4713
            #   Replace the found string with the real name of the file
4714
            #   Note: 4 argument version of substr is not always available
4715
            #         so we must do it the hard way
4716
            #               substr( $arg, $mb, $me - $mb, $fn);
4717
            #
4718
            $arg = substr( $arg, 0, $mb ) . $fn . substr( $arg, $me );
4719
 
4720
            Debug2( "RunTest: subs: $all -> $fn" );
4721
        }
4722
        push(@uargs, "'$arg'");
4723
    }
4724
 
4725
    #
4726
    #   Create the test entry
4727
    #   This is a structure that will be placed in an array
4728
    #   The array preserves order and uniqness
4729
    #
4730
    my %test_entry;
4731
    $test_entry{'framework'}= $framework if ( $framework );
4732
    $test_entry{'framework_opts'}= \@framework_opts if ( $framework );
4733
    $test_entry{'command'}  = $command . $prog unless ( $framework);
4734
 
4735
    $test_entry{'prog'}     = $prog;
4736
    $test_entry{'copyprog'} = 1;
4737
    $test_entry{'args'}     = \@uargs;
4738
    $test_entry{'auto'}     = $auto if ( $auto );
4739
    $test_entry{'copyin'}   = \@copy;
4740
    $test_entry{'copyonce'} = ();
4741
    $test_entry{'preq'}     = \@preq_files;
4742
    $test_entry{'testdir'}  = 'BINDIR';
4743
 
4744
    push ( @TESTS_TO_RUN, \%test_entry );
4745
 
4746
    #
4747
    #   Flag Auto Run processing required
4748
    #
4749
    $TESTS_TO_AUTORUN = 1 if ( $auto );
4750
}
4751
 
4752
 
4753
sub TestProg
4754
{
4755
    my( $platforms, $prog, @elements ) = @_;
4756
 
4757
    Debug2( "TestProg($platforms, $prog, @elements)" );
4758
 
4759
    return if ( ! ActivePlatform($platforms) );
4760
 
4761
    Error ("TestProg: Program name not defined") unless ( $prog );
4762
    Error ("Programs are not supported") unless ( defined $::exe );
4763
 
289 dpurdie 4764
    #
4765
    #   Create a new Prog object, or retrieve any existing one
4766
    #
4767
    my $pProg = $TESTPROGS->Get($prog);
4768
    $pProg = $TESTPROGS->NewAdd($prog)
4769
        unless ( $pProg );
227 dpurdie 4770
 
4771
#.. Parse all of the object, library and argument entries
4772
    Debug( "TestProg: $prog" );
4773
    foreach (@elements)
4774
    {
4775
        if ( /^[-]{1,2}([lL])(.*)/ )
4776
        {
4777
        #.. Target Library specified - add to library list.
4778
        #  
4779
            Debug( "TestProg: lib  -$1$2" );
289 dpurdie 4780
            $pProg->addItem('LIBS', "-$1$2");
227 dpurdie 4781
            next;
4782
        }
4783
 
4784
        if ( /^--if(.*)/ )
4785
        {
4786
        #.. Library conditional - add to library list.
4787
        #
4788
            Debug( "TestProg: cond $_" );
289 dpurdie 4789
            $pProg->addItem('LIBS', $_);
227 dpurdie 4790
            next;
4791
        }
4792
 
4793
        if ( /^-(.*)/ )
4794
        {
4795
        #.. Argument specified - add to argument list
4796
        #
4797
            Debug( "TestProg: arg $_" );
289 dpurdie 4798
            $pProg->addItem('ARGS', $_);
227 dpurdie 4799
            next;
4800
        }
4801
 
4802
        if ( defined %::ScmToolsetProgSource )
4803
        {
4804
            #
4805
            #   Toolset provides support for some file types
4806
            #   to be passed directly to the program builder
4807
            #
4808
            my $ext  = StripFile($_);
4809
            if ( exists ($::ScmToolsetProgSource{$ext}) )
4810
            {
4811
                my $full_path = MakeSrcResolve ( $_ );
4812
                my $flag = $::ScmToolsetProgSource{$ext};
4813
                Debug( "TestProg: src $_" );
289 dpurdie 4814
                $pProg->addItem('ARGS', "$flag$full_path");
227 dpurdie 4815
                next;
4816
            }
4817
        }
4818
 
4819
        if ( $::o )
4820
        {
4821
        #.. Object specified - add to object list.
4822
        #
4823
            my $obj = _LibObject( "", $_ );
4824
 
4825
        #.. Add to program object list.
289 dpurdie 4826
            $pProg->addItem('OBJS', "\$(OBJDIR)/$obj");
227 dpurdie 4827
            next;
4828
        }
4829
 
4830
        #
4831
        #   Don't know how to handle this type of argument
4832
        #
4833
        Error ("TestProg: Don't know how to handle: $_" );
4834
    }
4835
}
4836
 
4837
 
4838
sub Prog
4839
{
4840
    my( $platforms, $prog, @elements ) = @_;
4841
 
4842
    Debug2( "Prog($platforms, $prog, @elements)" );
4843
 
4844
    return if ( ! ActivePlatform($platforms) );
4845
 
4846
    Error ("Prog: Program name not defined") unless ( $prog );
4847
    Error ("Programs are not supported") unless ( defined $::exe );
4848
 
289 dpurdie 4849
    #
4850
    #   Create a new Prog object, or retrieve any existing one
4851
    #
4852
    my $pProg = $PROGS->Get($prog);
4853
    $pProg = $PROGS->NewAdd($prog)
4854
        unless ( $pProg );
227 dpurdie 4855
 
4856
#.. Parse all of the object, library and argument entries
4857
    Debug( "Prog: $prog" );
4858
    foreach (@elements)
4859
    {
4860
        if ( /^[-]{1,2}([lL])(.*)/ )
4861
        {
4862
        #.. Target Library specified - add to library list.
4863
        #  
4864
            Debug( "Prog: lib  -$1$2" );
289 dpurdie 4865
            $pProg->addItem('LIBS', "-$1$2");
227 dpurdie 4866
            next;
4867
        }
4868
 
4869
        if ( /^--if(.*)/ )
4870
        {
4871
        #.. Library conditional - add to library list.
4872
        #
4873
            Debug( "Prog: cond $_" );
289 dpurdie 4874
            $pProg->addItem('LIBS', $_);
227 dpurdie 4875
            next;
4876
        }
4877
 
4878
        if ( /^-(.*)/ )
4879
        {
4880
        #.. Argument specified - add to argument list
4881
        #
4882
            Debug( "Prog: arg $_" );
289 dpurdie 4883
            $pProg->addItem('ARGS', $_);
227 dpurdie 4884
            next;
4885
        }
4886
 
4887
        if ( defined %::ScmToolsetProgSource )
4888
        {
4889
            #
4890
            #   Toolset provides support for some file types
4891
            #   to be passed directly to the program builder
4892
            #
4893
            my $ext  = StripFile($_);
4894
            if ( exists ($::ScmToolsetProgSource{$ext}) )
4895
            {
4896
                my $full_path = MakeSrcResolve ( $_ );
4897
                my $flag = $::ScmToolsetProgSource{$ext};
4898
                Debug( "Prog: src $_" );
289 dpurdie 4899
                $pProg->addItem('ARGS', "$flag$full_path");
227 dpurdie 4900
                next;
4901
            }
4902
        }
4903
 
4904
        if ( $::o )
4905
        {
4906
        #.. Object specified - add to object list.
4907
        #
4908
            my $obj = _LibObject( "", $_ );
4909
 
4910
        #.. Add to program object list.
289 dpurdie 4911
            $pProg->addItem('OBJS', "\$(OBJDIR)/$obj");
227 dpurdie 4912
            next;
4913
        }
4914
 
4915
        #
4916
        #   Don't know how to handle this type of argument
4917
        #
4918
        Error ("Prog: Don't know how to handle: $_" );
4919
    }
4920
}
4921
 
4922
#-------------------------------------------------------------------------------
4923
# Function        : ProgAddExtra
4924
#
4925
# Description     : This (internal) function allows a toolset to list additional
4926
#                   binaries as a part of a program. This will ensure that the
4927
#                   binaries are generated in the 'make_prog' phase with the main
4928
#                   program.
4929
#
4930
#                   The files are not listed for packaging, by this function
4931
#
4932
#                   The function does not ensure that the files are not already
4933
#                   listed as a @PROG ( as @PROGS is not fully resolved at this point )
4934
#
4935
# Inputs          :     $name               - Tag name of program being built
4936
#                                             Not used (yet)
4937
#                       $prog               - Fully resolved path to a file
4938
#
4939
# Returns         : Nothing
4940
#
4941
sub ProgAddExtra
4942
{
4943
    my ($name, $prog) = @_;
4944
    Debug2( "ProgAddExtra($name: $prog)" );
4945
 
4946
    UniquePush(\@PROGS_EXTRA, $prog);
4947
}
4948
 
4949
#-------------------------------------------------------------------------------
4950
# Function        : MakeProject
4951
#
4952
# Description     : A nasty directive that is intended to build a Microsoft
4953
#                   project for WINCE, WIN32 and .NET builds.
4954
#
4955
#                   There are many constraints:
4956
#                       Cannot be mixed with multi-platform builds
4957
#                       Some parameters are tool specific
4958
#
267 dpurdie 4959
#                   Allow programs to be Installed as well as Packaged
4960
#                   The 'Progect' is treated' as a program and it doesn't work
4961
#                   to well if we Install libraries.
227 dpurdie 4962
#
267 dpurdie 4963
#                   Only Reason to Install Programs is to allow the Cab Maker
4964
#                   to locate them.
4965
#
227 dpurdie 4966
# Inputs          : Platform        - Active platform
4967
#                   Project         - Project Name with extension
4968
#                   Options         - Many options
4969
#
4970
# Returns         :
4971
#
4972
our %PROJECTS;                          # Project information
4973
my  @PROJECTS_ORDER;
4974
sub MakeProject
4975
{
4976
    my( $platforms, $proj, @elements ) = @_;
4977
 
4978
    Debug2( "MakeProject($platforms, $proj, @elements)" );
4979
 
4980
    return if ( ! ActivePlatform($platforms) );
4981
 
4982
    #
4983
    #   Sanity test
4984
    #
4985
    Error ("MakeProject: Project name not defined") unless ( $proj );
4986
 
4987
    #
4988
    #   Take the project name and convert it into a full path
4989
    #
4990
    my $project = MakeSrcResolve ( $proj );
4991
    $proj = StripDir( $project );
237 dpurdie 4992
    Error ("Project File Not found: $project") unless ( -f $project );
227 dpurdie 4993
 
4994
    my $basedir = StripFileExt( $project );
4995
 
4996
    #
4997
    #   Collect user arguments
4998
    #   They are all processed within the toolset
4999
    #
5000
    my @tool_options;
5001
    foreach ( @elements )
5002
    {
5003
        if ( m/^--Debug/ ) {
5004
            $PROJECTS{$proj}{'Debug'} = 1;
5005
 
5006
        } elsif ( m/^--Prod/ ) {
5007
            $PROJECTS{$proj}{'Prod'} = 1;
5008
 
267 dpurdie 5009
        } elsif ( m/^--(Package|Install)ProgDebug=(.*)/ ) {
5010
            _PackageFromProject( $1, $proj, $basedir,'Prog', 'D', $2 );
227 dpurdie 5011
 
267 dpurdie 5012
        } elsif ( m/^--(Package|Install)Prog(Prod)*=(.*)/ ) {
5013
            _PackageFromProject( $1, $proj, $basedir, 'Prog', 'P', $3 );
227 dpurdie 5014
 
267 dpurdie 5015
        } elsif ( m/^--(Package)LibDebug=(.*)/ ) {
5016
            _PackageFromProject( $1, $proj, $basedir, 'Lib', 'D', $2 );
227 dpurdie 5017
 
267 dpurdie 5018
        } elsif ( m/^--(Package)Lib(Prod)*=(.*)/ ) {
5019
            _PackageFromProject( $1, $proj, $basedir, 'Lib', 'P', $3 );
227 dpurdie 5020
 
267 dpurdie 5021
        } elsif ( m/^--(Package)SharedLibDebug=(.*)/ ) {
5022
            _PackageFromProject( $1, $proj, $basedir, 'Lib', 'D', $2 );
227 dpurdie 5023
 
267 dpurdie 5024
        } elsif ( m/^--(Package)SharedLib(Prod)*=(.*)/ ) {
5025
            _PackageFromProject( $1, $proj, $basedir, 'Lib', 'P', $3 );
227 dpurdie 5026
 
267 dpurdie 5027
        } elsif ( m/^--(Package)Hdr=(.*)/ ) {
5028
            _PackageFromProject( $1, $proj, $basedir, 'Hdr', undef, $2 );
227 dpurdie 5029
 
267 dpurdie 5030
        } elsif ( m/^--(Package)File=(.*)/ ) {
5031
            _PackageFromProject( $1, $proj, $basedir, 'File', undef, $2 );
227 dpurdie 5032
 
267 dpurdie 5033
        } elsif ( m/^--(Package)Tool(Prod)*=(.*)/ ) {
5034
            _PackageFromProject( $1, $proj, $basedir, 'Tool', 'P', $3 );
241 dpurdie 5035
 
267 dpurdie 5036
        } elsif ( m/^--(Package)ToolDebug=(.*)/ ) {
5037
            _PackageFromProject( $1, $proj, $basedir, 'Tool', 'D', $2 );
241 dpurdie 5038
 
267 dpurdie 5039
        } elsif ( m/^--(Package|Install)/ ) {
5040
            Error("MakeProject. Unknown $1 option: $_");
227 dpurdie 5041
 
5042
        } else {
5043
            push @tool_options, $_;
5044
        }
5045
    }
5046
 
5047
    #
5048
    #   Save the information
5049
    #
5050
    $PROJECTS{$proj}{'options'} = \@tool_options;
5051
    $PROJECTS{$proj}{'name'} = $proj;
5052
    $PROJECTS{$proj}{'project'} = $project;
5053
    $PROJECTS{$proj}{'basedir'} = $basedir;
5054
    UniquePush (\@PROJECTS_ORDER, $proj);
5055
 
5056
    #
5057
    #   Validate some of the arguments
5058
    #
5059
    Error ("Makeproject. Conflicting options --Debug and --Prod" )
5060
        if ( $PROJECTS{$proj}{'Debug'}  && $PROJECTS{$proj}{'Prod'} );
5061
}
5062
 
5063
#-------------------------------------------------------------------------------
5064
# Function        : _PackageFromProject
5065
#
5066
# Description     : Save Packaged data from the project
5067
#
267 dpurdie 5068
# Inputs          : $tgt        - Install or Package
5069
#                   $proj       - Name of the project
227 dpurdie 5070
#                   $base       - Base directory of files
5071
#                   $etype      - Type of Package (Progs, Libs, ... )
5072
#                   $type       - Debug or Production or both
5073
#                   $items      - Item to add. It may be comma seperated
5074
#
267 dpurdie 5075
my %PackageToData = ( 'Package' =>
5076
                        { 'Hdr'   => \%PACKAGE_HDRS,
5077
                          'Lib'   => \%PACKAGE_LIBS,
5078
                          'Prog'  => \%PACKAGE_PROGS,
5079
                          'File'  => \%PACKAGE_FILES,
5080
                          'Tool'  => \%PACKAGE_FILES,
5081
                          '_BASE' => 'PBase',
5082
                        },
5083
                      'Install' =>
5084
                        { 'Hdr'   => \%INSTALL_HDRS,
5085
                          'Lib'   => \%INSTALL_LIBS,
5086
                          'Prog'  => \%INSTALL_PROGS,
5087
                          'File'  => undef,
5088
                          'Tool'  => undef,
5089
                          '_BASE' => 'IBase',
5090
                        },
227 dpurdie 5091
                    );
5092
 
5093
sub _PackageFromProject
5094
{
267 dpurdie 5095
    my( $tgt, $proj, $base, $etype, $type, $items ) = @_;
227 dpurdie 5096
    my $subdir = '';
5097
 
5098
    #
267 dpurdie 5099
    #   Sanity test
5100
    #
5101
    $type = '' unless ( $type );
5102
    Error ("INTERNAL. Bad packaging option: $tgt")   unless ( exists $PackageToData{$tgt} );
5103
    Error ("INTERNAL. Bad packaging option: $etype") unless ( exists $PackageToData{$tgt}{$etype} );
5104
    Error ("Unsupported packaging combination: $tgt$etype$type=$items") unless ( defined $PackageToData{$tgt}{$etype} );
5105
 
5106
    #
5107
    #   Determine the index into the 'PackageInfo' structure
5108
    #   This provides the symbolic name for the target package path
5109
    #   for Package or Install
5110
    #
5111
    #   The key '_BASE' is internal. Used only to provide this information
5112
    #
5113
    my $tbase = $PackageToData{$tgt}{'_BASE'};
5114
 
5115
    #
227 dpurdie 5116
    #   Process options
5117
    #
5118
    foreach my $item ( split (/,/, $items ) )
5119
    {
5120
        next unless ( $item =~ m/^--/ );
5121
        if ( $item =~ m/^--Subdir=(.*)/ )
5122
        {
5123
            $subdir = '/' . $1;
5124
            $subdir =~ s~//~/~g;
5125
            $subdir =~ s~/$~~g;
5126
        }
5127
        else
5128
        {
5129
            Warning( "MakeProject: Unknown packaging option ignored: $_" );
5130
        }
5131
    }
5132
 
5133
    #
5134
    #   Process files
5135
    #
5136
    foreach my $item ( split (/,/, $items ) )
5137
    {
5138
        next if ( $item =~ m/^--/ );
5139
 
267 dpurdie 5140
        my $tdir = $PackageInfo{$etype}{$tbase} . $PackageInfo{$etype}{'Dir'} . $subdir ;
227 dpurdie 5141
        my $fname = StripDir( $item );
5142
        my $target = $tdir . '/' . $fname;
5143
 
5144
        $item = "$base/$item" if ( $base );
5145
 
5146
        #
5147
        #   Do not use $(GBE_TYPE) in the target name
5148
        #   The existing package mechanism does not handle different
5149
        #   production and debug file naming mechanism, whereas the project
5150
        #   must. Convert $(GBE_TYPE) into P or D to ensure uniquness
5151
        #
5152
        $target =~ s~\$\(GBE_TYPE\)~$type~ if ($type);
5153
 
5154
        #
5155
        #   Create a PACKAGE entry suitable for processing by the normal packaging
5156
        #   routines. This is complicated because the Projects do not adhere to
267 dpurdie 5157
        #   the JATS file name conventions
227 dpurdie 5158
        #
5159
        my %package_entry;
5160
        $package_entry{'src'}   = $item;
5161
        $package_entry{'dir'}   = $tdir;
267 dpurdie 5162
        $package_entry{'set'}   = 'ALL' if ($tgt eq 'Package');
227 dpurdie 5163
        $package_entry{'type'}  = $type if ($type);
5164
 
267 dpurdie 5165
        $PackageToData{$tgt}{$etype}->{$target} = {%package_entry};
227 dpurdie 5166
    }
5167
}
5168
 
5169
#-------------------------------------------------------------------------------
5170
# Function        : MakeAnt
5171
#
5172
# Description     : A nasty directive to create JAR files via ANT
5173
#                   There are several limitations
5174
#                   This is closely related to the MakeProject directive
5175
#
5176
#
5177
# Inputs          : Platform            - Active platform
5178
#                   buildfile           - Name of the build.xml file
5179
#                   Options             - A few options
5180
#                                         --Jar=file
5181
#                                               Generated JAR file(s)
5182
#                                         --GeneratedFile=file
5183
#                                               Other generated files
5184
#                                               Used to flag JNI that must
5185
#                                               Occur early
5186
#                                          --AutoTest=<name>
5187
#                                               Supports unitAutomated unit test
5188
#                                               by calling build target <name>
5189
#                                          --UnitTest=<name>
5190
#                                               Supports unit test
5191
#                                               by calling build target <name>
5192
#                                          --PackageBase
5193
#                                               Provides path to base of all packages
5194
#
5195
# Returns         :
5196
#
5197
our %JAR_FILES;
5198
sub MakeAnt
5199
{
5200
    my( $platforms, $proj, @elements ) = @_;
5201
 
5202
    Debug2( "MakeAnt($platforms, $proj, @elements)" );
5203
 
5204
    return if ( ! ActivePlatform($platforms) );
5205
 
5206
    #
5207
    #   Sanity test
5208
    #
5209
    Error ("MakeAnt: build.xml name not defined") unless ( $proj );
5210
 
5211
    #
5212
    #   Take the project name and convert it into a full path
5213
    #
5214
    my $project;
5215
    $project = MakeSrcResolve ( $proj );
5216
    $proj = StripDir( $project );
237 dpurdie 5217
    Error ("Build File Not found: $project") unless ( -f $project );
227 dpurdie 5218
 
5219
    my $basedir = StripFileExt( $project );
5220
 
5221
    #
5222
    #   Collect user arguments
5223
    #   They are all processed within the toolset
5224
    #
5225
    my @tool_options;
5226
    my @generated;
5227
    my $unit_tests;
5228
    my $auto_tests;
5229
    my $package_base;
5230
 
5231
    foreach ( @elements )
5232
    {
5233
        if ( m/^--Debug/ ) {
5234
            $PROJECTS{$proj}{'Debug'} = 1;
5235
 
5236
        } elsif ( m/^--Prod/ ) {
5237
            $PROJECTS{$proj}{'Prod'} = 1;
5238
 
5239
        } elsif ( m/^--Jar=(.*)/ ) {
5240
            my $tgt = $1;
5241
               $tgt = "$basedir/$tgt" if ( $basedir );
5242
            my $fn = StripDir( $1 );
5243
            $JAR_FILES{$fn} = $tgt;
5244
            GenerateSrcFile( 0, $tgt );
5245
 
5246
        } elsif ( m/^--GeneratedFile=(.*)/ ) {
5247
            my $tgt = $1;
5248
            $tgt = "$basedir/$tgt" if ( $basedir );
5249
            push @generated, $tgt;
5250
            GenerateSrcFile( 2, $tgt );
5251
 
5252
        } elsif ( m/^--UnitTest=(.*)/ ) {
5253
            $unit_tests = $1
5254
 
5255
        } elsif ( m/^--AutoTest=(.*)/ ) {
5256
            $auto_tests = $1
5257
 
5258
        } elsif ( m/^--PackageBase/ ) {
5259
            $package_base = 1;
5260
 
5261
 
5262
        } elsif ( m/^--/ ) {
5263
            Error("MakeAnt. Unknown option ignored: $_");
5264
 
5265
        } else {
5266
            push @tool_options, $_;
5267
        }
5268
    }
5269
 
5270
    #
5271
    #   Extend option arguments to include the base dir of packages
5272
    #   Create definitions of the form PACKAGE_<name>
5273
    #
5274
    for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} })
5275
    {
5276
        next unless ( $entry->{'TYPE'} eq 'link' );
5277
        my $dir = $entry->{'ROOT'};
5278
        my $name = $entry->{'NAME'};
5279
        unless ( $package_base )
5280
        {
5281
            $dir .= '/jar';
5282
            next unless ( -d $dir );
5283
        }
5284
        push @tool_options, "-DPACKAGE_$name=$dir";
5285
    }
5286
    #
5287
    #   Extend options to include the base dir of the created package
5288
    #   Allows careful use for direct packaging of artifacts
5289
    #
5290
    push @tool_options, '-DPACKAGEDIR=$(PWD)/$(PKGDIR)';
5291
 
5292
    #
5293
    #   Save the information
5294
    #
5295
    $PROJECTS{$proj}{'options'} = \@tool_options;
5296
    $PROJECTS{$proj}{'generated'} = \@generated if ( @generated );
5297
    $PROJECTS{$proj}{'name'}    = $proj;
5298
    $PROJECTS{$proj}{'project'} = $project;
5299
    $PROJECTS{$proj}{'basedir'} = $basedir;
5300
    $PROJECTS{$proj}{'type'}    = 'ant';
5301
    $PROJECTS{$proj}{'unittest'} = $unit_tests if ( $unit_tests );
5302
    $PROJECTS{$proj}{'autotest'} = $auto_tests if ( $auto_tests );
5303
    UniquePush (\@PROJECTS_ORDER, $proj);
5304
 
5305
    $TESTS_TO_AUTORUN = 1 if ( $auto_tests );
263 dpurdie 5306
    $TESTS_TO_RUN = 1 if ( $unit_tests || $auto_tests );
227 dpurdie 5307
 
5308
    #
5309
    #   Validate some of the arguments
5310
    #
5311
    Error ("MakeAnt. Conflicting options --Debug and --Prod" )
5312
        if ( $PROJECTS{$proj}{'Debug'}  && $PROJECTS{$proj}{'Prod'} );
5313
}
5314
 
5315
###############################################################################
5316
#
5317
#   Installation/Packaging util functions
5318
#
5319
#-------------------------------------------------------------------------------
5320
# Function        : __TargetDir
5321
#
5322
# Description     : Internal function to process common arguments for
5323
#                   the PackageXxx directives
5324
#
5325
# Inputs          : flags           - Indicate how to handle this argument
5326
#                   base            - Base directory for this type of package
5327
#                   argument        - Argument to process
5328
#                   pdir            - Reference to resultant directory
5329
#                   ptype           - Reference to resultant type (P or D)(optional)
5330
#
5331
# Returns         : 0               - Agument not consumed
5332
#                   1               - Argument consumed
5333
#                   2               - Skip this directive
5334
#
5335
my $T_TYPE  = 0x0001;                           # Postfix GBE_TYPE
5336
my $T_PKG   = 0x0002;                           # Special --Dir handling
5337
my $T_MACH  = 0x0004;                           # Allow --Machine too
5338
my $T_GBE   = 0x0008;                           # Allow --Gbe too
5339
my $T_FILE  = 0x0010;                           # Suffix or prefix subdir
5340
 
5341
sub __TargetDir
5342
{
5343
    my( $flags, $base, $argument, $pdir, $ptype ) = @_;
5344
    my $dir  = "";
5345
    my $consumed = 0;
5346
 
5347
    #
5348
    #   Generate basic parts
5349
    #   Note Product will default to Platform
5350
    #
5351
    my $str_platform = '$(GBE_PLATFORM)';
5352
    my $str_product = $ScmProduct ? '$(GBE_PRODUCT)' : '$(GBE_PLATFORM)';
5353
    my $str_target = '$(GBE_TARGET)';
5354
    my $str_common = '$(GBE_OS_COMMON)';
5355
 
5356
    my $str_common_avail = 0;
5357
       $str_common_avail = 1 if ( exists( $::BUILDINFO{$ScmPlatform}{OS_COMMON} ));
5358
 
5359
 
5360
    #
5361
    #   Add requested suffix
5362
    #
5363
    if ($flags & $T_TYPE)
5364
    {
5365
        $str_platform .= '$(GBE_TYPE)';
5366
        $str_product  .= '$(GBE_TYPE)';
5367
        $str_target   .= '$(GBE_TYPE)';
5368
        $str_common   .= '$(GBE_TYPE)';
5369
    }
5370
 
5371
    #
5372
    #   Process the argument
5373
    #
5374
    $_ = $argument;
5375
    if ( /^--Debug/ ) {                         # In the Debug build only
5376
        if ( $ptype ) {
5377
            $$ptype = "D";
5378
            $consumed = 1;
5379
        }
5380
 
5381
    } elsif ( /^--Prod$/ || /^--Production$/ ) { # In the Production build only
5382
        if ( $ptype ) {
5383
            $$ptype = "P";
5384
            $consumed = 1;
5385
        }
5386
 
5387
    } elsif (/^--Prefix=(.*)/) {                # Prefix with subdir
5388
        $dir = "$base/$1";
5389
 
5390
    } elsif (/^--Subdir=(.*)/) {                # same as 'prefix'
5391
        $dir = "$base/$1";
5392
 
5393
    } elsif (/^--Platform$/) {                  # Platform installation
5394
        $dir = "$base/$str_platform";
5395
 
5396
    } elsif (/^--Platform=(.*?),(.*)/) {        # prefix and suffix with platform specific subdir
5397
        $dir = "$base/$1/$str_platform/$2";
5398
 
5399
    } elsif (/^--Platform=(.*)/) {              # prefix with platform specific subdir
5400
        if ($flags & $T_FILE) {
5401
            $dir = "$base/$1/$str_platform";
5402
        } else {
5403
            $dir = "$base/$str_platform/$1";
5404
        }
5405
 
5406
    } elsif (/^--Product$/) {                   # Product installation
5407
        $dir = "$base/$str_product";
5408
 
5409
    } elsif (/^--Product=(.*?),(.*)/) {         # prefix and suffix with product specific subdir
5410
        $dir = "$base/$1/$str_product/$2";
5411
 
5412
    } elsif (/^--Product=(.*)/) {               # prefix with product specific subdir
5413
        if ($flags & $T_FILE) {
5414
            $dir = "$base/$1/$str_product";
5415
        } else {
5416
            $dir = "$base/$str_product/$1";
5417
        }
5418
 
5419
    } elsif (/^--Target$/) {                    # Target installation
5420
        $dir = "$base/$str_target";
5421
 
5422
    } elsif (/^--Target=(.*?),(.*)/) {          # prefix and suffix with target specific subdir
5423
        $dir = "$base/$1/$str_target/$2";
5424
 
5425
    } elsif (/^--Target=(.*)/) {                # prefix with target specific subdir
5426
        if ($flags & $T_FILE) {
5427
            $dir = "$base/$1/$str_target";
5428
        } else {
5429
            $dir = "$base/$str_target/$1";
5430
        }
5431
 
5432
    } elsif (/^--OsCommon/) {
5433
 
5434
        unless ( $str_common_avail ) {
5435
            Warning("Packaging option --OsCommon not supported on this platform($ScmPlatform). Directive skipped");
5436
            $consumed = 2;
5437
 
5438
        } elsif (/^--OsCommon$/) {                  # OS installation
5439
            $dir = "$base/$str_common";
5440
 
5441
        } elsif (/^--OsCommon=(.*?),(.*)/) {        # prefix and suffix with target specific subdir
5442
            $dir = "$base/$1/$str_common/$2";
5443
 
5444
        } elsif (/^--OsCommon=(.*)/) {              # prefix with target specific subdir
5445
            if ($flags & $T_FILE) {
5446
                $dir = "$base/$1/$str_common";
5447
            } else {
5448
                $dir = "$base/$str_common/$1";
5449
            }
5450
        }
5451
 
5452
    } elsif (/^--Derived=(.*?),(.*?),(.*)/) {   # Derived target + prefix + subdir
5453
        $dir = "$base/$2/$1_$str_platform/$3";
5454
 
5455
    } elsif (/^--Derived=(.*?),(.*)/) {         # Derived target + subdir
5456
        if ($flags & $T_FILE) {
5457
            $dir = "$base/$2/$1_$str_platform";
5458
        } else {
5459
            $dir = "$base/$1_$str_platform/$2";
5460
        }
5461
 
5462
    } elsif (/^--Derived=(.*)/) {               # Derived target
5463
        $dir = "$base/$1_$str_platform";
5464
 
5465
    } elsif ($flags & $T_MACH && /^--Machine(([=])(.*))?$/) {   # Allow Machine and Machine=xxx specfic target
5466
        #
5467
        #   Special: Append machine type to user dir
5468
        #            Intended to create tools/bin/win32 and tools/bin/sparc directories
5469
        my $path = ( defined( $3) ) ? "/$3" : "";
5470
        $dir = "$base$path/\$(GBE_HOSTMACH)";
5471
 
5472
    } elsif ($flags & $T_GBE && /^--Gbe(([=])(.*))?$/) {   # Allow Gbe and Gbe=xxx specfic target
5473
        my $path = ( defined( $3) ) ? "/$3" : "";
5474
        $dir = "$base/gbe$path";
5475
 
5476
    } elsif (/^--Dir=(.*)/) {                   # prefix with target specific subdir
5477
        Error ('Packaging directive with --Dir option does not specify a directory.',
5478
               'Possible bad use of option of the form:--Dir=$xxx',
5479
               'Note: Use of package.pl and this construct is deprecated') unless ( $1 );
241 dpurdie 5480
        my $udir = $1;
5481
 
5482
        #
5483
        #   Remove leading ./
5484
        #   Check for leading ../
5485
        while ( $udir =~ s{^\./}{} ){};
5486
 
5487
        if ( $udir =~ m~^\.\./~ )
5488
        {
5489
            Warning("Packaging directive with --Dir option contains relative path (removed)", "Option: $_");
5490
            while ( $udir =~ s{^\.\./}{} ){};
5491
        }
227 dpurdie 5492
        if ($flags & $T_PKG) {
241 dpurdie 5493
            $dir = __PkgDir( $udir );
227 dpurdie 5494
        } else {
241 dpurdie 5495
            $dir = "\$(LOCALDIR)/$udir";
227 dpurdie 5496
        }
5497
    }
5498
 
5499
    return ($consumed) if ($dir eq "");
5500
    $dir =~ s~//~/~g;
5501
    $dir =~ s~/$~~;
5502
    $$pdir = $dir;
5503
    return (1);
5504
}
5505
 
5506
 
5507
#   __PkgDir ---
5508
#       Convert --Dir Package directives, removing leading subdir if
5509
#       matching the global $Pbase value.
5510
#
5511
#       Required as PKGDIR has the value 'GBE_ROOT/pkg/$Pbase'.
5512
#       Required to maintain compatability with older (package.pl) constructs
5513
#..
5514
 
5515
sub __PkgDir
5516
{
5517
    my( $dir ) = @_;
5518
    my $org = $dir;
5519
 
245 dpurdie 5520
    $dir =~ s~^\Q$::Pbase\E[/]?~~;
227 dpurdie 5521
    Debug2( "  PkgDir: converted \"$org\" to \"$dir\"" );
5522
 
5523
    $dir = "\$(PKGDIR)/$dir";
5524
    return $dir;
5525
}
5526
 
5527
 
5528
#   getMajorMinor ---
5529
#       Just a little help to deal with major/minor stuff for shared libs -
5530
#       given the name of the library as the argument, split out major and
5531
#       minor parts and return the basename, i.e name without major and minor
5532
#       and the pair of major and minor.
5533
#..
5534
 
285 dpurdie 5535
sub getMajorMinor
227 dpurdie 5536
{
5537
    my @bits = split ('\.', $_[0]);
5538
    my $stop;
5539
    my $major;
5540
    my $minor;
5541
 
5542
    if ( $#bits > 2 )
5543
    {
5544
        $stop = $#bits - 2;
5545
        $major = $bits[$#bits-1];
5546
        $minor = $bits[$#bits];
5547
    }
5548
    elsif ($#bits > 1)
5549
    {
5550
        $stop = $#bits-1;
5551
        $major = $bits[$#bits];
5552
        $minor=0;
5553
    }
5554
    else
5555
    {
5556
        $stop = $#bits; $major = 1; $minor = 0;
5557
    }
5558
 
5559
    my $base = $bits[0];
5560
    for ( my $i=1; $i <= $stop; $i++ ) {
5561
        $base = join ('.', $base, $bits[$i]);
5562
    }
5563
 
5564
    return ($base, $major, $minor);
5565
}
5566
 
5567
###############################################################################
5568
#
5569
#   Installation
5570
#
5571
 
5572
sub InstallHdr
5573
{
5574
    my( $platforms, @elements ) = @_;
5575
    my( $base, $dir, $srcfile, $full, $abs, $strip, $package );
5576
    my( $len, $name, $basename );
5577
 
5578
    Debug2( "InstallHdr($platforms, @elements)" );
5579
 
5580
    return if ( ! ActivePlatform($platforms) );
5581
    Warning ("InstallHdr: Needs local directory specified in build.pl") unless ( $::ScmLocal );
5582
 
5583
#.. Arguments
5584
#
5585
    $base = $PackageInfo{'Hdr'}{'IBase'};       # Base of target
5586
    $dir = $base . $PackageInfo{'Hdr'}{'Dir'};  # Installation path (default)
5587
    $full = $abs = $strip = 0;
5588
 
285 dpurdie 5589
    foreach ( @elements )
227 dpurdie 5590
    {
5591
                                                # Standard targets
5592
        my $rv = __TargetDir(0, $base, $_, \$dir);
5593
        next if ( $rv == 1 );
5594
        return if ( $rv == 2 );
5595
 
5596
        if (/^--Full/) {                        # using full (resolved) path
5597
            $full = 1;
5598
 
5599
        } elsif (/^--Abs$/) {                   # Override SRCS() checks
5600
            $abs = 1;
5601
 
5602
        } elsif (/^--Strip$/) {                 # Strip path from source files
5603
            $strip = 1;
5604
 
5605
                                                # Package
5606
        } elsif (/^--Package$/ || /^--Package=(.*)/) {
5607
            $package = 1;
5608
 
5609
        } elsif (/^--(.*)/) {
5610
            Message( "InstallHdr: unknown option $_ -- ignored\n" );
5611
        }
5612
    }
5613
 
5614
#.. Files
5615
#
285 dpurdie 5616
    foreach ( @elements )
227 dpurdie 5617
    {
5618
        my %package_entry;
5619
        if ( ! /^--(.*)/ )
5620
        {
5621
            $name = $_;
5622
            $basename = StripDir( $name );
5623
            if ( $full )
5624
            {
5625
                if ($abs || !($srcfile = $SRCS{ $basename }) ||
5626
                        ($len = rindex($srcfile, "/")) == -1)
5627
                {
5628
                    $dir = $base;
5629
                    $srcfile = $name;
5630
                }
5631
                else
5632
                {
5633
                    if ( m#^\./# ) {
5634
                        $dir = substr($srcfile, 3, $len);
5635
                    } else {
5636
                        $dir = substr($srcfile, 0, $len);
5637
                    }
5638
                    $dir = "$base/$dir";
5639
                }
5640
            }
5641
            else
5642
            {
5643
                if ($abs || ! ($srcfile = $SRCS{ $basename })) {
5644
                    $srcfile = $name;
5645
                }
5646
            }
5647
 
5648
            $name = $basename
5649
                if ( $strip );
5650
 
5651
            Debug( "InstallHdr( $dir/$name, src: $srcfile, dest: $dir)" );
5652
 
5653
            $package_entry{'src'} = $srcfile;
5654
            $package_entry{'dir'} = StripFileExt( "$dir/$name" );
5655
            $INSTALL_HDRS{ "$dir/$name" } = {%package_entry};
5656
        }
5657
    }
5658
 
5659
#.. Package
5660
#
5661
    PackageHdr( @_ )                            # auto package
5662
        if ( $package );
5663
}
5664
 
5665
 
5666
sub InstallLib
5667
{
5668
    my( $platforms, @elements ) = @_;
5669
    my( $base, $dir, $package );
5670
    my( $lib, $strip );
289 dpurdie 5671
    my $org_lib;
227 dpurdie 5672
 
5673
    Debug2( "InstallLib($platforms, @elements)" );
5674
 
5675
    return if ( ! ActivePlatform($platforms) );
5676
    Warning ("InstallLib: Needs local directory specified in build.pl") unless ( $::ScmLocal );
5677
 
5678
#.. Arguments
5679
#
5680
    $base = $PackageInfo{'Lib'}{'IBase'};       # Base of target
5681
    $dir = $base . $PackageInfo{'Lib'}{'Dir'};  # Installation path (default)
5682
 
285 dpurdie 5683
    foreach ( @elements )
227 dpurdie 5684
    {
5685
                                                # Standard targets
5686
        my $rv = __TargetDir(0, $base, $_, \$dir);
5687
        next if ( $rv == 1 );
5688
        return if ( $rv == 2 );
5689
 
5690
        if (/^--Package$/ || /^--Package=(.*)/) {
5691
            $package = 1;
5692
 
5693
        } elsif (/^--Strip$/) {                 # Strip path from source files
5694
            $strip = 1;
5695
 
5696
        } elsif (/^--(.*)/) {
5697
            Message( "InstallLib: unknown option $_ -- ignored\n" );
5698
        }
5699
    }
5700
 
5701
#.. Files
5702
#
285 dpurdie 5703
    foreach ( @elements )
227 dpurdie 5704
    {
5705
        my %package_entry;
5706
        if ( ! /^--(.*)/ )
5707
        {
5708
            $_ = basename ($_)
5709
                if ( $strip );
289 dpurdie 5710
            $org_lib = $_;                      # Original name
227 dpurdie 5711
 
5712
            if ( $ScmTargetHost eq "Unix" ) {
5713
                $lib = "lib$_";                 # Prefix "lib" ....
5714
                $lib =~ s/^liblib/lib/;         # @LIBS already has lib added
5715
            } else {
5716
                $lib = $_;
5717
            }
5718
 
289 dpurdie 5719
            if (  my $libp = $SHLIBS->Get($lib) )
227 dpurdie 5720
            {
5721
                Debug( "InstallLib( $dir/$lib\$(GBE_TYPE).$::so, " .
5722
                    "src: \$(LIBDIR)/$lib\$(GBE_TYPE).$::so, dest: $dir)" );
5723
 
5724
                #
5725
                #   Create a "placekeeper" entry within $INSTALL_SHLIBS
5726
                #   The exact format of the name of the shared library is
5727
                #   toolset specific. Create an entry to allow the toolset
5728
                #   to extend the packaging information when the shared library
5729
                #   recipe is constructed.
5730
                #
289 dpurdie 5731
                my $ver = $libp->{ VERSION };
227 dpurdie 5732
                my $name = "$dir/$lib.$ver.PlaceKeeper";
5733
 
5734
                $package_entry{'placekeeper'} = 1;
5735
                $package_entry{'version'} = $ver;
5736
                $package_entry{'lib'} = $lib;
5737
                $package_entry{'dir'} = $dir;
289 dpurdie 5738
 
5739
                push @{$SHLIB_INS{$lib}}, $name;
227 dpurdie 5740
                $INSTALL_SHLIBS{$name} = {%package_entry};
5741
            }
5742
 
289 dpurdie 5743
            #
5744
            #   Clean up the package_entry
5745
            #   Insert common items
5746
            #
5747
            %package_entry = ();
5748
            $package_entry{'lib'} = $lib;
5749
            $package_entry{'dir'} = $dir;
5750
 
227 dpurdie 5751
            if ( my $libfile = $SRCS{$lib} )
5752
            {
5753
                #
5754
                #   Allow the user to package a sourced file as a library
289 dpurdie 5755
                #   But must be the un-massaged name of the file.
227 dpurdie 5756
                #
289 dpurdie 5757
                $package_entry{'dst'} = "$dir/$org_lib";
5758
                $package_entry{'src'} = $libfile;
5759
            }
5760
            elsif ( $LIBS->Get($lib) )
5761
            {
5762
                #
5763
                #   Install a library known to the makefile
5764
                #
5765
                my $libp = $LIBS->Get($lib);
227 dpurdie 5766
 
289 dpurdie 5767
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
5768
                $package_entry{'src'}    = $libp->getPath();
227 dpurdie 5769
            }
289 dpurdie 5770
            elsif ( ! $SHLIBS->Get($lib) )
227 dpurdie 5771
            {
289 dpurdie 5772
                #
5773
                #   Not a known shared lib
5774
                #   Not a known static lib
5775
                #   Not a 'sourced' file
5776
                #   Assume the a static library has magically appeared
5777
                #   in the standard LIB directory. May have been placed there
5778
                #   by a 'rule'
5779
                #
5780
                my $libp = $LIBS->New($lib);
227 dpurdie 5781
 
289 dpurdie 5782
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
5783
                $package_entry{'src'}    = $libp->getPath();
5784
            }
227 dpurdie 5785
 
289 dpurdie 5786
            #
5787
            #   Add entry to various lists if required
5788
            #
5789
            PackageLib_AddEntry ('InstallLib', \%LIB_INS, \%INSTALL_LIBS, \%package_entry )
5790
                if ( exists $package_entry{'dst'} );
227 dpurdie 5791
        }
5792
    }
5793
 
5794
#.. Package
5795
#
5796
    PackageLib( @_ )                            # auto package
5797
        if ( $package );
5798
}
5799
 
5800
 
5801
sub InstallJar
5802
{
5803
    my( $platforms, @elements ) = @_;
5804
    my( $base, $dir, $package );
5805
    my( $jar );
5806
 
5807
    Debug2( "InstallJar($platforms, @elements)" );
5808
 
5809
    return if ( ! ActivePlatform($platforms) );
5810
    Warning ("InstallJar: Needs local directory specified in build.pl") unless ( $::ScmLocal );
5811
 
5812
#.. Arguments
5813
#
5814
    $base = $PackageInfo{'Jar'}{'IBase'};       # Base of target
5815
    $dir = $base . $PackageInfo{'Jar'}{'Dir'};  # Installation path (default)
5816
 
285 dpurdie 5817
    foreach ( @elements )
227 dpurdie 5818
    {
5819
                                                # Standard targets
5820
        my $rv = __TargetDir(0, $base, $_, \$dir);
5821
        next if ( $rv == 1 );
5822
        return if ( $rv == 2 );
5823
 
5824
        if (/^--Package$/ || /^--Package=(.*)/) {
5825
            $package = 1;
5826
 
5827
        } elsif (/^--(.*)/) {
5828
            Message( "InstallJar: unknown option $_ -- ignored\n" );
5829
        }
5830
    }
5831
 
5832
 
5833
#.. Files
5834
#
285 dpurdie 5835
    foreach ( @elements )
227 dpurdie 5836
    {
5837
        my %package_entry;
5838
        if ( ! /^--(.*)/ )
5839
        {
5840
            $jar = $_;
5841
            my $src;
5842
            my $dest;
5843
 
5844
            if ( $JAR_FILES{$jar} )
5845
            {
5846
                $src = $JAR_FILES{$jar};
5847
                $dest = $jar;
5848
            }
5849
            else
5850
            {
5851
                $src = "\$(CLSDIR)/$jar\$(GBE_TYPE).jar";
5852
                $dest = "$jar\$(GBE_TYPE).jar";
5853
            }
5854
 
5855
 
5856
            Debug( "InstallJar( $dir/$dest, " .
5857
                "src: $src, dest: $dir)" );
5858
 
5859
            $package_entry{'src'} = $src;
5860
            $package_entry{'dir'} = $dir;
5861
            $INSTALL_CLSS{ "$dir/$dest" } = {%package_entry};
5862
 
5863
        }
5864
    }
5865
 
5866
#.. Package
5867
#
5868
    PackageJar( @_ )                            # auto package
5869
        if ( $package );
5870
}
5871
 
5872
 
5873
sub InstallProg
5874
{
5875
    my( $platforms, @elements ) = @_;
5876
    my( $base, $dir, $package );
5877
    my( $prog );
5878
 
5879
    Debug2( "InstallProg($platforms, @elements)" );
5880
 
5881
    return if ( ! ActivePlatform($platforms) );
5882
    Warning ("InstallProg: Needs local directory specified in build.pl") unless ( $::ScmLocal );
5883
 
5884
#.. Arguments
5885
#
5886
    $base = $PackageInfo{'Prog'}{'IBase'};       # Base of target
5887
    $dir = $base . $PackageInfo{'Prog'}{'Dir'};  # Installation path (default)
5888
 
285 dpurdie 5889
    foreach ( @elements )
227 dpurdie 5890
    {
5891
                                                # Standard targets
5892
        my $rv = __TargetDir($T_TYPE, $base, $_, \$dir);
5893
        next if ( $rv == 1 );
5894
        return if ( $rv == 2 );
5895
 
5896
        if (/^--Package$/ || /^--Package=(.*)/) {
5897
            $package = 1;
5898
 
5899
        } elsif (/^--(.*)/) {
5900
            Message( "InstallProg: unknown option $_ -- ignored\n" );
5901
        }
5902
    }
5903
 
5904
#.. Files
5905
#
285 dpurdie 5906
    foreach ( @elements )
227 dpurdie 5907
    {
5908
        my %package_entry;
5909
        if ( ! /^--(.*)/ )
5910
        {
5911
            my $ext = "";
5912
            $prog = $_;
5913
 
5914
            #
5915
            #   If the named target is a program then append the correct
5916
            #   extension. Otherwise assume that the target is either a script
5917
            #   or a some other file - and don't append an extension
5918
            #
5919
            $ext = $::exe
289 dpurdie 5920
                if ( $PROGS->Get($prog) );
227 dpurdie 5921
 
5922
            #
5923
            #   A "file" that is specified with a "Src" directive may be
5924
            #   installed as though it were a program
5925
            #
5926
            my $progfile;
5927
            $progfile = "\$(BINDIR)/$prog$ext"
5928
                unless ( $progfile = $SRCS{$prog} );
5929
 
5930
            Debug( "InstallProg( $dir/$prog$ext, " .
5931
                 "src: $progfile, dest: $dir)" );
5932
 
5933
            push @{$PROG_INS{$prog}}, "$dir/$prog$ext";
5934
 
5935
            $package_entry{'src'} = $progfile;
5936
            $package_entry{'dir'} = $dir;
5937
            $INSTALL_PROGS{ "$dir/$prog$ext" } = {%package_entry};
5938
        }
5939
    }
5940
 
5941
#.. Package
5942
#
5943
    PackageProg( @_ )                           # auto package
5944
        if ( $package );
5945
}
5946
 
5947
 
5948
###############################################################################
5949
#
5950
#   Packaging
5951
#
5952
sub PackageDist
5953
{
5954
    my( $name, @elements ) = @_;
5955
 
5956
    Debug2( "PackageDist($name, @elements)" );
5957
 
5958
    foreach ( @elements )
5959
    {
5960
    #.. Distribution sets
5961
    #
5962
        HashJoin( \%PACKAGE_DIST, $;, $name, "$_" );
5963
 
5964
    #.. Summary of distribution sets
5965
    #
267 dpurdie 5966
        $PACKAGE_SETS{ $_ }{'TAG'} = 1
5967
            if ( ! exists $PACKAGE_SETS{ $_ }{'TAG'} );
227 dpurdie 5968
    }
5969
}
5970
 
311 dpurdie 5971
#-------------------------------------------------------------------------------
5972
# Function        : PackageFile
5973
#
5974
# Description     : Directive to package files
5975
#                   Not to be used to package libraries, executables, headers
5976
#                   as this should be done by specialised directives
5977
#
5978
#                   Use to package other files
5979
#                   Can package an entire tree (ugly)
5980
#
5981
# Inputs          : 
5982
#
5983
#
227 dpurdie 5984
sub PackageFile
5985
{
5986
    my( $platforms, @elements ) = @_;
5987
    my( $base, $dir, $full, $abs, $path, $dist, $strip, $exefile, $type );
5988
    my( $name, $basename, $len, $srcfile );
5989
    my( $dir_tree, @dir_tree_exclude, @dir_tree_include, $strip_base );
5990
 
5991
    Debug2( "PackageFile($platforms, @elements)" );
5992
 
5993
    return if ( !$ScmPackage );                 # Packaging enabled ?
5994
    return if ( ! ActivePlatform($platforms) );
5995
 
5996
#.. Arguments
5997
#
5998
    $dist = "ALL";                                  # Default set (ALL)
5999
    $base = $PackageInfo{'File'}{'PBase'};          # Base of target
6000
    $dir = $base . $PackageInfo{'File'}{'Dir'};     # Installation path (default)
6001
    $full = $abs = 0;
6002
    $strip = 0;
6003
    $strip_base = 0;
6004
    $exefile = 0;
6005
 
285 dpurdie 6006
    foreach ( @elements )
227 dpurdie 6007
    {
6008
        my $rv = __TargetDir($T_PKG|$T_MACH|$T_GBE|$T_FILE, $base, $_, \$dir, \$type);
6009
        next if ( $rv == 1 );
6010
        return if ( $rv == 2 );
6011
 
6012
        if (/^--Full/) {                        # Using full (resolved) path
6013
            $full = 1;
6014
 
6015
        } elsif (/^--Set=(.*)/) {               # Distribution set
6016
            $dist = "$1";
6017
 
6018
        } elsif (/^--Package$/) {               # Package .. call by InstallFile
6019
        } elsif (/^--Package=(.*)/) {
6020
            $dist = "$1";
6021
 
6022
        } elsif (/^--Abs$/) {                   # Override SRCS() checks
6023
            $abs = 1;
6024
 
6025
        } elsif (/^--Strip$/) {                 # Strip path from source files
6026
            $strip = 1;
6027
 
6028
        } elsif (/^--Executable$/) {            # Mark the file as executable
6029
            $exefile = "X";
6030
 
6031
        } elsif ( /^--DirTree=(.*)/ ) {
6032
            Error("DirTree. Multiple directories not allowed.") if ( $dir_tree );
6033
            $dir_tree = $1;
6034
 
6035
            Error("DirTree cannot extend outside current subtree. '..' not allowed.",
6036
                  "Directory: $dir_tree") if ( $dir_tree =~ m~\.\.~ );
6037
            Error("DirTree. Absolute paths are not allowed",
6038
                  "Directory: $dir_tree") if ( $dir_tree =~ m~^/~ || $dir_tree =~ m~^.\:~ );
6039
            Error("DirTree. Directory not found",
6040
                  "Directory: $dir_tree") unless  ( -d $dir_tree );
6041
 
6042
        } elsif ( /^--FilterOut=(.*)/ ) {
6043
            push @dir_tree_exclude, $1;
6044
 
6045
        } elsif ( /^--FilterIn=(.*)/ ) {
6046
            push @dir_tree_include, $1;
6047
 
6048
        } elsif ( /^--StripDir/ ) {
6049
            $strip_base = 1;
6050
 
6051
        } elsif (/^--(.*)/) {
6052
            Message( "PackageFile: unknown option $_ -- ignored\n" );
6053
        }
6054
    }
6055
 
6056
 
6057
    #.. DirTree expansion
6058
    #   Note: Uses REs, not simple globs
6059
    #         Use JatsLocateFiles to do the hard work
6060
    if ( $dir_tree )
6061
    {
6062
        my $search = JatsLocateFiles->new('Recurse', 'FullPath' );
6063
        $search->filter_in_re ( $_ ) foreach ( @dir_tree_include );
6064
        $search->filter_out_re( $_ ) foreach ( @dir_tree_exclude );
6065
        @elements = $search->search ( $dir_tree );
6066
        $strip_base = length( $dir_tree ) if ( $strip_base );
6067
    }
6068
 
6069
#.. Files
6070
#
285 dpurdie 6071
    foreach ( @elements )
227 dpurdie 6072
    {
6073
        my %package_entry;
299 dpurdie 6074
        $name = $_;
6075
 
227 dpurdie 6076
        #
299 dpurdie 6077
        #   Trap special files
6078
        #       DPACKAGE - but only if we have a DPackageLibrary directive
6079
        #                  in the same makefile.
6080
        #
6081
        if ( m~^DPACKAGE$~ && $DPackageDirective ) {
6082
            $name = 'DPACKAGE.' . $::GBE_MACHTYPE;
6083
        }
6084
 
6085
        #
227 dpurdie 6086
        #   Special cases: Provide make-style $ escape processing.
6087
        #       Allow files with a $ in the name
6088
        #       Allow files with a space in the name
263 dpurdie 6089
        #   Only for file names that don't look like $(GBE_...) as these
6090
        #   may be generated internally
227 dpurdie 6091
        #
301 dpurdie 6092
        unless ( $name =~ m~\$\(GBE_.+\)~ )
263 dpurdie 6093
        {
301 dpurdie 6094
            $name =~ s~\$~\$\$~g;
6095
            $name =~ s~ ~\\ ~g;
263 dpurdie 6096
        }
227 dpurdie 6097
 
6098
        if ( ! /^--(.*)/ )
6099
        {
6100
            $basename = StripDir( $name );
6101
            if ( $full )
6102
            {
6103
                if ($abs || ! ($srcfile = $SRCS{ $basename }) ||
6104
                        ($len = rindex($srcfile, "/")) == -1)
6105
                {
6106
                    #
6107
                    #   Either: --Abs
6108
                    #           the file is NOT known to JATS
6109
                    #           the file is known and and it does NOT contains a "/"
6110
                    #   Result: Use simple dir and name
6111
                    #
6112
                    $dir = $base;
6113
                    $srcfile = $name;
6114
                }
6115
                else
6116
                {
6117
                    #
6118
                    #   Using Full directory path.
6119
                    #   Ensure that ProjectBase is removed as this may have
6120
                    #   been added if the file was found in a directory with it
6121
                    #
6122
                    $srcfile = $1
6123
                        if ( $srcfile =~ m~^$ProjectBase/(.*)~ );
6124
 
6125
 
6126
                    if ( m#^\./# ) {
6127
                        $dir = substr($srcfile, 3, $len);
6128
                    } else {
6129
                        $dir = substr($srcfile, 0, $len);
6130
                    }
6131
                    $dir = "$base/$dir";
6132
                }
6133
            }
6134
            else
6135
            {
6136
                if ($abs || ! ($srcfile = $SRCS{ $basename })) {
6137
                    $srcfile = $name;
6138
                }
6139
            }
6140
 
6141
            $name = $basename
6142
                if ( $strip );
6143
 
6144
            if ( $strip_base )
6145
            {
6146
                $name = substr $name, $strip_base;
6147
                $name =~ s~^/~~;
6148
            }
6149
 
6150
            $dir =~ s~//~/~g;
6151
            $dir =~ s~/$~~;
6152
 
6153
            #
6154
            #   Sanity test the source filename
6155
            #   User may have misused an option
6156
            #
6157
            if ( ( $srcfile =~ m/=/ ) || ( $srcfile =~ m/^-/ ) || ( $srcfile =~ m~/-~ )  )
6158
            {
6159
               Warning ("PackageFile: Suspect source filename: $srcfile");
6160
            }
6161
 
6162
            Debug( "PackageFile( $dir/$name, " .
6163
                "src: $srcfile, dest: $dir, dist: $dist, exe: $exefile )" );
6164
 
6165
            $package_entry{'src'} = $srcfile;
6166
            $package_entry{'dir'} = StripFileExt( "$dir/$name" );
6167
            $package_entry{'set'} = $dist;
6168
            $package_entry{'exe'} = $exefile if $exefile;
6169
            $package_entry{'type'} = $type if ( $type );
6170
 
6171
            $PACKAGE_FILES{ "$dir/$name" } = {%package_entry};
6172
        }
6173
    }
6174
}
6175
 
6176
sub PackageHdr
6177
{
6178
    my( $platforms, @elements ) = @_;
6179
    my( $base, $dir, $full, $abs, $path, $dist, $strip );
6180
    my( $name, $basename, $len, $srcfile );
6181
 
6182
    Debug2( "PackageHdr($platforms, @elements)" );
6183
 
6184
    return if ( !$ScmPackage );                 # Packaging enabled ?
6185
    return if ( ! ActivePlatform($platforms) );
6186
 
6187
#.. Arguments
6188
#
6189
    $dist = "ALL";                                  # Default set (ALL)
6190
    $base = $PackageInfo{'Hdr'}{'PBase'};           # Base of target
6191
    $dir = $base . $PackageInfo{'Hdr'}{'Dir'};      # Installation path (default)
6192
    $full = $abs = 0;
6193
    $strip = 0;
6194
 
285 dpurdie 6195
    foreach ( @elements )
227 dpurdie 6196
    {
6197
        my $rv = __TargetDir($T_PKG, $base, $_, \$dir);
6198
        next if ( $rv == 1 );
6199
        return if ( $rv == 2 );
6200
 
6201
        if (/^--Full/) {                        # Using full (resolved) path
6202
            $full = 1;
6203
 
6204
        } elsif (/^--Set=(.*)/) {               # Distribution set
6205
            $dist = "$1";
6206
 
6207
        } elsif (/^--Package$/) {               # Package .. call by InstallHdr
6208
        } elsif (/^--Package=(.*)/) {
6209
            $dist = "$1";
6210
 
6211
        } elsif (/^--Abs$/) {                   # Override SRCS() checks
6212
            $abs = 1;
6213
 
6214
        } elsif (/^--Strip$/) {                 # Strip path from source files
6215
            $strip = 1;
6216
 
6217
        } elsif (/^--(.*)/) {
6218
            Message( "PackageHdr: unknown option $_ -- ignored\n" );
6219
        }
6220
    }
6221
 
6222
#.. Files
6223
#
285 dpurdie 6224
    foreach ( @elements )
227 dpurdie 6225
    {
6226
        my %package_entry;
6227
        if ( ! /^--(.*)/ )
6228
        {
6229
            $name = $_;
6230
            $basename = StripDir( $name );
6231
            if ( $full )
6232
            {
6233
                if ($abs || ! ($srcfile = $SRCS{ $basename }) ||
6234
                        ($len = rindex($srcfile, "/")) == -1)
6235
                {
6236
                    $dir = $base;
6237
                    $srcfile = $name;
6238
                }
6239
                else
6240
                {
6241
                    $srcfile = $1
6242
                        if ( $srcfile =~ m~^$ProjectBase/(.*)~ );
6243
 
6244
                    if ( m#^\./# ) {
6245
                        $dir = substr($srcfile, 3, $len);
6246
                    } else {
6247
                        $dir = substr($srcfile, 0, $len);
6248
                    }
6249
                    $dir = "$base/$dir";
6250
                }
6251
            }
6252
            else
6253
            {
6254
                if ($abs || ! ($srcfile = $SRCS{ $basename })) {
6255
                    $srcfile = $name;
6256
                }
6257
            }
6258
 
6259
            $name = $basename
6260
                if ( $strip );
6261
 
6262
            Debug( "PackageHdr( $dir/$name, " .
6263
                "src: $srcfile, dest: $dir, dist: $dist )" );
6264
 
6265
            $package_entry{'src'} = $srcfile;
6266
            $package_entry{'dir'} = StripFileExt( "$dir/$name" );
6267
            $package_entry{'set'} = $dist;
6268
 
6269
            $PACKAGE_HDRS{ "$dir/$name" } = {%package_entry};
6270
        }
6271
    }
6272
}
6273
 
6274
 
6275
sub PackageLib
6276
{
6277
    my( $platforms, @elements ) = @_;
6278
    my( $base, $dir, $dist, $type );
6279
    my( $lib, $org_lib, %extras, $strip );
6280
 
6281
    Debug2( "PackageLib($platforms, @elements)" );
6282
 
6283
    return if ( !$ScmPackage );                 # Packaging enabled ?
6284
    return if ( ! ActivePlatform($platforms) );
6285
 
6286
#.. Arguments
6287
#
6288
    $dist = "ALL";                              # Default set (ALL)
6289
    $base = $PackageInfo{'Lib'}{'PBase'};       # Base of target
6290
    $dir = $base . $PackageInfo{'Lib'}{'Dir'};  # Installation path (default)
6291
    $type = "";
6292
 
285 dpurdie 6293
    foreach ( @elements )
227 dpurdie 6294
    {
6295
                                                # Standard targets
6296
        my $rv = __TargetDir($T_PKG, $base, $_, \$dir, \$type);
6297
        next if ( $rv == 1 );
6298
        return if ( $rv == 2 );
6299
 
6300
        if (/^--Set=(.*)/) {                    # Distribution set(s)
6301
            $dist = "$1";
6302
 
6303
        } elsif (/^--Package$/) {               # Package .. call by PackageLib
6304
        } elsif (/^--Package=(.*)/) {
6305
            $dist = "$1";
6306
 
6307
        } elsif (/^--Extras=(.*)/) {            # Extras=[none, .. ,all]
6308
            foreach my $elem ( split( ',', $1 ) )
6309
            {
6310
                Error ("PackageLib: Unknown Extras mode: $elem")
6311
                    unless ( grep m/$elem/, qw(none stub map lint debug all) );
6312
                $extras{$elem} = 1;
6313
            }
6314
            %extras = () if ( $extras{'all'} );
6315
 
6316
        } elsif (/^--Strip$/) {                 # Strip path from source files
6317
            $strip = 1;
6318
 
6319
        } elsif (/^--(.*)/) {
6320
            Message( "PackageLib: unknown option $_ -- ignored\n" );
6321
        }
6322
    }
6323
 
6324
#.. Files
6325
#
285 dpurdie 6326
    foreach ( @elements )
227 dpurdie 6327
    {
6328
        my %package_entry;
6329
        if ( ! /^--(.*)/ )
6330
        {
6331
            $_ = StripDir( $_ )
6332
                if ( $strip );
6333
 
6334
            $org_lib = $_;                      # Original name
6335
            if ( $ScmTargetHost eq "Unix" ) {
6336
                $lib = "lib$_";                 # Prefix "lib" ....
6337
                $lib =~ s/^liblib/lib/;         # @LIBS already has lib added
6338
            } else {
6339
                $lib = $_;
6340
            }
6341
 
289 dpurdie 6342
            if (  my $libp = $SHLIBS->Get($lib) )
227 dpurdie 6343
            {
6344
                Debug( "PackageLib( $dir/$lib\$(GBE_TYPE).$::so, " .
6345
                    "src: \$(LIBDIR)/$lib\$(GBE_TYPE).$::so, dest: $dir, dist: $dist, type: $type )" );
6346
 
6347
                #
6348
                #   Create a "placekeeper" entry within $PACKAGE_SHLIBS
6349
                #   The exact format of the name of the shared library is
6350
                #   toolset specific. Create an entry to allow the toolset
6351
                #   to extend the packaging information when the shared library
6352
                #   recipe is constructed.
6353
                #
6354
                #
289 dpurdie 6355
                my $ver = $libp->{ VERSION };
227 dpurdie 6356
                my $name = "$dir/$lib.$ver.PlaceKeeper";
6357
 
6358
                $package_entry{'placekeeper'} = 1;
6359
                $package_entry{'version'} = $ver;
6360
                $package_entry{'lib'} = $lib;
6361
                $package_entry{'dir'} = $dir;
6362
                $package_entry{'set'} = $dist;
6363
                $package_entry{'type'} = $type if ( $type );
6364
                $package_entry{'extras'} = {%extras} if ( scalar %extras );
289 dpurdie 6365
 
6366
                push @{$SHLIB_PKG{$lib}}, $name;
227 dpurdie 6367
                $PACKAGE_SHLIBS{$name} = {%package_entry};
6368
            }
6369
 
289 dpurdie 6370
            #
6371
            #   Clean up the package_entry
6372
            #   Insert common items
6373
            #
6374
            %package_entry = ();
6375
            $package_entry{'lib'} = $lib;
6376
            $package_entry{'dir'} = $dir;
6377
            $package_entry{'set'} = $dist;
6378
            $package_entry{'extras'} = {%extras} if ( scalar %extras );
6379
            $package_entry{'type'} = $type if ( $type );
6380
 
227 dpurdie 6381
            if ( my $libfile = $SRCS{$org_lib} )
6382
            {
6383
                #
6384
                #   Allow the user to package a sourced file as a library
6385
                #   But must be the un-massaged name of the file.
6386
                #
289 dpurdie 6387
                $package_entry{'dst'} = "$dir/$org_lib";
6388
                $package_entry{'src'} = $libfile;
6389
            }
6390
            elsif ( $LIBS->Get($lib) )
6391
            {
6392
                #
6393
                #   Package up a library known to the makefile
6394
                #
6395
                my $libp = $LIBS->Get($lib);
227 dpurdie 6396
 
289 dpurdie 6397
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
6398
                $package_entry{'src'}    = $libp->getPath();
227 dpurdie 6399
            }
289 dpurdie 6400
            elsif ( ! $SHLIBS->Get($lib) )
227 dpurdie 6401
            {
289 dpurdie 6402
                #
6403
                #   Not a known shared lib
6404
                #   Not a known static lib
6405
                #   Not a 'sourced' file
6406
                #   Assume the a static library has magically appeared
6407
                #   in the standard LIB directory. May have been placed there
6408
                #   by a 'rule'
6409
                #
6410
                my $libp = $LIBS->New($lib);
227 dpurdie 6411
 
289 dpurdie 6412
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
6413
                $package_entry{'src'}    = $libp->getPath();
6414
            }
227 dpurdie 6415
 
289 dpurdie 6416
            #
6417
            #   Add entry to various lists if required
6418
            #
6419
            PackageLib_AddEntry ('PackageLib', \%LIB_PKG, \%PACKAGE_LIBS, \%package_entry )
6420
                if ( exists $package_entry{'dst'} );
227 dpurdie 6421
        }
6422
    }
6423
}
6424
 
289 dpurdie 6425
#-------------------------------------------------------------------------------
6426
# Function        : PackageLib_AddEntry
6427
#
6428
# Description     : Helper function to add a package entry
6429
#                   to the lists
6430
#
6431
# Inputs          : $directive          - Directive name
6432
#                   $pList              - Ref to array list to maintain
6433
#                   $pHash              - Ref to hash to maintain
6434
#                   $pData              - Packaging Data
6435
#                                         Must Take a copy.
6436
#
6437
# Returns         : 
6438
#
227 dpurdie 6439
 
289 dpurdie 6440
sub PackageLib_AddEntry
6441
{
6442
    my ($directive, $pList, $pHash, $pData) = @_;
6443
 
6444
    my $lib = delete $pData->{'lib'};
6445
    my $dst = delete $pData->{'dst'};
6446
 
6447
    Error ("INTERNAL PackageLib_AddEntry: lib or dst not defined")
6448
        unless ( $lib && $dst );
6449
 
6450
    Debug( "$directive( ",$dst,
6451
            ", src: " ,$pData->{'src'},
6452
            ", dest: ",$pData->{'dir'},
6453
            ", dist: ",$pData->{'set'},
6454
            ", type: ",$pData->{'type'} || '',
6455
            " )" );
6456
 
6457
    push @{$pList->{$lib }}, $dst;
6458
    $pHash->{$dst } = {%$pData};
6459
}
6460
 
6461
 
227 dpurdie 6462
sub PackageProg
6463
{
6464
    my( $platforms, @elements ) = @_;
6465
    my( $base, $dir, $dist, $type );
6466
    my( $prog, %extras, $strip );
6467
 
6468
    Debug2( "PackageProg($platforms, @elements)" );
6469
 
6470
    return if ( !$ScmPackage );                 # Packaging enabled ?
6471
    return if ( ! ActivePlatform($platforms) );
6472
 
6473
#.. Arguments
6474
#
6475
    $dist = "ALL";                              # Default set (ALL)
6476
    $base = $PackageInfo{'Prog'}{'PBase'};       # Base of target
6477
    $dir = $base . $PackageInfo{'Prog'}{'Dir'};  # Installation path (default)
6478
    $type = "";
6479
 
285 dpurdie 6480
    foreach ( @elements )
227 dpurdie 6481
    {
6482
                                                # Standard targets
6483
        my $rv = __TargetDir($T_PKG|$T_TYPE, $base, $_, \$dir, \$type);
6484
        next if ( $rv == 1 );
6485
        return if ( $rv == 2 );
6486
 
6487
        if (/^--Set=(.*)/) {                    # Distribution set(s)
6488
            $dist = "$1";
6489
 
6490
        } elsif (/^--Package$/) {               # Package .. call by PackageLib
6491
        } elsif (/^--Package=(.*)/) {
6492
            $dist = "$1";
6493
 
6494
        } elsif (/^--Tool(([=])(.*))?$/) {      # Allow Tool and Tool=xxx specfic target
6495
            my $path = ( defined( $3) ) ? "/$3" : "";
261 dpurdie 6496
            $dir = "\$(PKGDIR)$path/\$(GBE_HOSTMACH)";
227 dpurdie 6497
 
6498
        } elsif (/^--Extras=(.*)/) {            # Extras=[none, .. ,all]
6499
            foreach my $elem ( split( ',', $1 ) )
6500
            {
6501
                Error ("PackageLib: Unknown Extras mode: $elem")
6502
                    unless ( grep m/$elem/, qw(none stub map lint debug all) );
6503
                $extras{$elem} = 1;
6504
            }
6505
            %extras = () if ( $extras{'all'} );
6506
 
6507
        } elsif (/^--Strip$/) {                 # Strip path from source files
6508
            $strip = 1;
6509
 
6510
        } elsif (/^--(.*)/) {
6511
            Message( "PackageProg: unknown option $_ -- ignored\n" );
6512
        }
6513
    }
6514
 
6515
#.. Files
6516
#
285 dpurdie 6517
    foreach ( @elements )
227 dpurdie 6518
    {
6519
        my %package_entry;
6520
        if ( m~descpkg~ ) {
6521
            PackageFile($platforms, @elements);
6522
 
6523
        } elsif ( ! /^--(.*)/ ) {
6524
            $_ = StripDir( $_ )
6525
                if ( $strip );
6526
 
6527
            my $ext = "";
6528
            $prog = $_;
6529
 
6530
            #
6531
            #   If the named target is a program then append the correct
6532
            #   extension. Otherwise assume that the target is either a script
6533
            #   or a some other file - and don't append an extension
6534
            #
6535
            #   A program may not have any object files, only libraries
6536
            #
6537
            $ext = $::exe
289 dpurdie 6538
                if ( $PROGS->Get($prog) );
227 dpurdie 6539
 
6540
            #
6541
            #   A "file" that is specified with a "Src" directive may be
6542
            #   installed as though it were a program
6543
            #
6544
            my $progfile;
6545
            $progfile = "\$(BINDIR)/$prog$ext"
6546
                unless ( $progfile = $SRCS{$prog} );
6547
 
6548
            Debug( "PackageProg( $dir/$prog$ext, " .
6549
                 "src: $progfile, dest: $dir, dist: $dist, type: $type )" );
6550
 
6551
            my $target = "$dir/$prog$ext";
6552
            push @{$PROG_PKG{$prog}}, $target;
6553
 
6554
            $package_entry{'src'}   = $progfile;
6555
            $package_entry{'dir'}   = $dir;
6556
            $package_entry{'set'}   = $dist;
6557
            $package_entry{'extras'}= {%extras} if ( scalar %extras );
6558
            $package_entry{'type'}  = $type if ( $type );
6559
 
6560
            $PACKAGE_PROGS{$target} = {%package_entry};
6561
        }
6562
    }
6563
}
6564
 
6565
 
6566
sub PackageJar
6567
{
6568
    my( $platforms, @elements ) = @_;
6569
    my( $base, $dir, $dist, $type );
6570
    my( $jar );
6571
 
6572
    Debug2( "PackageJar($platforms, @elements)" );
6573
 
6574
    return if ( !$ScmPackage );                 # Packaging enabled ?
6575
    return if ( ! ActivePlatform($platforms) );
6576
 
6577
#.. Arguments
6578
#
6579
    $dist = "ALL";                              # Default set (ALL)
6580
    $base = $PackageInfo{'Jar'}{'PBase'};       # Base of target
6581
    $dir = $base . $PackageInfo{'Jar'}{'Dir'};  # Installation path (default)
6582
    $type = "";
6583
 
285 dpurdie 6584
    foreach ( @elements )
227 dpurdie 6585
    {
6586
                                                # Standard targets
6587
        my $rv = __TargetDir($T_PKG, $base, $_, \$dir, \$type);
6588
        next if ( $rv == 1 );
6589
        return if ( $rv == 2 );
6590
 
6591
        if (/^--Set=(.*)/) {                    # Distribution set(s)
6592
            $dist = "$1";
6593
 
6594
        } elsif (/^--Package$/) {               # Package .. call by InstallJar
6595
        } elsif (/^--Package=(.*)/) {
6596
            $dist = "$1";
6597
 
6598
        } elsif (/^--(.*)/) {
6599
            Message( "PackageJar: unknown option $_ -- ignored\n" );
6600
        }
6601
    }
6602
 
6603
#.. Files
6604
#
285 dpurdie 6605
    foreach ( @elements )
227 dpurdie 6606
    {
6607
        my %package_entry;
6608
        if ( ! /^--(.*)/ )
6609
        {
6610
            $jar = $_;
6611
            my $src;
6612
            my $dest;
6613
 
6614
            if ( $JAR_FILES{$jar} )
6615
            {
6616
                $src = $JAR_FILES{$jar};
6617
                $dest = $jar;
6618
            }
6619
            else
6620
            {
6621
                $src = "\$(CLSDIR)/$jar\$(GBE_TYPE).jar";
6622
                $dest = "$jar\$(GBE_TYPE).jar";
6623
            }
6624
 
6625
 
6626
            Debug( "PackageJar( $dir/$dest, " .
6627
                "src: $src, dest: $dir, dist: $dist, type: $type )" );
6628
 
6629
            $package_entry{'src'} = $src;;
6630
            $package_entry{'dir'} = $dir;
6631
            $package_entry{'set'} = $dist;
6632
            $package_entry{'type'} = $type if ( $type );
6633
 
6634
            $PACKAGE_CLSS{ "$dir/$dest" } = {%package_entry};
6635
 
6636
        }
6637
    }
6638
}
6639
 
6640
#-------------------------------------------------------------------------------
6641
# Function        : PackageProgAddFiles         - Add files to a PackageProg
6642
#                   PackageLibAddFiles          - Add files to a PackageLib
6643
#                   PackageShlibAddFiles        - Add files to a PackageLib (shared lib)
6644
#                   PackageShlibAddLibFiles     - Add files to a PackageLib (shared lib)
6645
#                                                 Add static library files
6646
#
6647
# Description     : Add files to a Program package or installation
6648
#                   For use by Tool sets to allow additional files to be
6649
#                   packaged with a program.
6650
#
6651
#                   The files are only added if the named program is being
6652
#                   packaged and/or installed.
6653
#
6654
#
6655
# Inputs          : prog        - program identifier
6656
#                   file        - A file to be add
6657
#                   args        - Additional packageing arguments
6658
#
6659
# Returns         : Nothing
6660
#
6661
 
6662
sub PackageProgAddFiles
6663
{
6664
    Debug("PackageProgAddFiles");
6665
 
6666
    PackageAddFiles ( \%PACKAGE_PROGS, \%PACKAGE_PROGS, \%PROG_PKG, @_);
6667
    PackageAddFiles ( \%INSTALL_PROGS, \%INSTALL_PROGS, \%PROG_INS, @_);
6668
}
6669
 
6670
sub PackageLibAddFiles
6671
{
6672
    Debug("PackageLibAddFiles");
6673
 
6674
    PackageAddFiles ( \%PACKAGE_LIBS, \%PACKAGE_LIBS, \%LIB_PKG, @_ );
6675
    PackageAddFiles ( \%INSTALL_LIBS, \%INSTALL_LIBS, \%LIB_INS, @_ );
6676
}
6677
 
6678
sub PackageShlibAddFiles
6679
{
6680
    my ($prog, $file, @args) = @_;
6681
    Debug("PackageShlibAddFiles");
6682
 
6683
    PackageAddFiles ( \%INSTALL_SHLIBS, \%INSTALL_SHLIBS, \%SHLIB_INS, @_ );
6684
    PackageAddFiles ( \%PACKAGE_SHLIBS, \%PACKAGE_SHLIBS, \%SHLIB_PKG, @_ );
6685
 
6686
    #
6687
    #   These files become the target of the "make_install_shlib" operation unless:
6688
    #       Conditionally packaged files are not always created
6689
    #       RemoveOnly files are not always generated
6690
    #
6691
    my $no_add;
6692
    foreach ( @args )
6693
    {
6694
        if ( m/^defined=/ or m/^RemoveOnly=/ )
6695
        {
6696
            $no_add = 1;
6697
            last;
6698
        }
6699
    }
6700
 
6701
    push (@SHLIB_TARGETS, $file ) unless $no_add;
6702
}
6703
 
6704
sub PackageShlibAddLibFiles
6705
{
6706
    Debug("PackageShlibAddLibFiles");
6707
 
6708
    PackageAddFiles ( \%PACKAGE_SHLIBS, \%PACKAGE_LIBS, \%SHLIB_PKG, @_ , 'Class=lib');
6709
    PackageAddFiles ( \%INSTALL_SHLIBS, \%INSTALL_LIBS, \%SHLIB_INS, @_ , 'Class=lib');
6710
}
6711
 
6712
#-------------------------------------------------------------------------------
6713
# Function        : PackageAddFiles
6714
#
6715
# Description     : Internal function to add files to the data structures that
6716
#                   describe a package or installation
6717
#
6718
#                   Use this function to package or install additional files with
6719
#                   the Progs and Libs
6720
#
6721
#                   ie: Add a LIB file to be packaged with a Shared Library
6722
#                   ie: Add a MAP file to be packaged with a program
6723
#
6724
# Inputs          : ref_spkg  - Reference to the hash that contains the package data
6725
#                   ref_dpkg  - Reference to the target package/install hash
6726
#                               Normally the same as ref_dpkg, but does allow
289 dpurdie 6727
#                               a static library to be added to a dynamic library
227 dpurdie 6728
#                               package.
6729
#                   ref_list  - Reference to a hash that may contain package keys to process
6730
#                   prog      - Key for index to above
6731
#                   file      - A file to be added
6732
#                   args      - Additional packaging arguments
6733
#
6734
# Returns         :
6735
#
6736
sub PackageAddFiles
6737
{
6738
    my ($ref_spkg, $ref_dpkg, $ref_list, $prog, $file, @args ) = @_;
6739
 
6740
    #
6741
    #   Process entry
6742
    #   The files may need to be added to multiple packages
6743
    #
6744
    Debug("PackageAddFiles: $file");
6745
 
6746
    return unless ( $ref_list->{$prog} );
6747
 
6748
    #
6749
    #   Parse arguments and extract the "Class=xxx" argument. This may be used
6750
    #   to limit the extra files piggybacked with the base file
6751
    #   All files without a class will be treated as base files
6752
    #
6753
    my $class;
6754
    foreach ( @args )
6755
    {
6756
        next unless ( m~^Class=(.*)$~ );
6757
        $class = $1 unless ( $1 eq 'none' );
6758
    }
6759
    Debug("PackageAddFiles: Class: ", $class || 'Default=None');
6760
 
6761
    foreach my $entry_key ( @{$ref_list->{$prog}} )
6762
    {
6763
        Debug("PackageAddFiles: Entry found: $entry_key");
6764
 
6765
        #
6766
        #   Copy of the template entry
6767
        #
6768
        my %package_entry = %{$ref_spkg->{$entry_key}};
6769
        Error ("INTERNAL: Expected entry in PACKAGE_ hash not found: $entry_key" )
6770
            unless ( %package_entry );
6771
 
6772
        #
6773
        #   Do not add the file if the user has limited the extra files added
6774
        #   to the packaging list and the current file is not in the class list
6775
        #
6776
        if ( $class && $package_entry{'extras'} )
6777
        {
6778
            next unless ( $package_entry{'extras'}{$class} );
6779
        }
6780
 
6781
        #
6782
        #   Create new entries for the file
6783
        #
6784
        $package_entry{'src'} = $file;
6785
        foreach ( @args )
6786
        {
6787
            m~^(.*)=(.*)$~;
6788
            $package_entry{$1} = $2;
6789
        }
6790
 
6791
        #
6792
        #   Clean out useless fields
6793
        #   Must remove the placekeeper marker to allow the entry to be visible
6794
        #
6795
        delete $package_entry{'placekeeper'};
6796
        delete $package_entry{'version'};
6797
        delete $package_entry{'lib'};
261 dpurdie 6798
#       delete $package_entry{'extras'};                   # Keep these
227 dpurdie 6799
        delete $package_entry{'Class'};
6800
 
6801
        #
6802
        #   Add the entry
6803
        #
6804
        #   Under some conditions is it possible to attempt to add the same named
6805
        #   file. This will result in a circular dependancy in the makefile
6806
        #
6807
        #   The condition is when merged libaries with PDBs (WINCE+WIN32) are merged
261 dpurdie 6808
        #   and the source for the merge is the "local directory.
227 dpurdie 6809
        #
6810
        #
6811
        my $dst = $package_entry{'dir'} ;
6812
        ( my $dfile = $file) =~ s~.*/~~;
6813
        Debug( "    added $dst/$dfile = $file" );
6814
 
6815
        $ref_dpkg->{"$dst/$dfile"} = {%package_entry}
6816
            unless ( "$dst/$dfile" eq "$file" );
6817
    }
6818
}
6819
 
6820
#-------------------------------------------------------------------------------
6821
# Function        : PackageProgRemoveFiles
6822
#
6823
# Description     : Flag a Packaged program to be not packaged
6824
#                   This mechanism is used to remove a program from packageing
6825
#                   under conditions where the toolset has generated a different
6826
#                   program.
6827
#
6828
#                   The entry is flagged as a placeholder
6829
#
6830
# Inputs          : prog        - Program to process
6831
#
6832
# Returns         : Nothing
6833
#
6834
sub PackageProgRemoveFiles
6835
{
6836
    my ($prog) = @_;
6837
    Verbose ("PackageProgRemoveFiles: $prog" );
6838
    return unless (exists($PROG_PKG{$prog}));
6839
 
6840
    #
6841
    #   Must lookup the TAG to locate the  required entry
6842
    #
6843
    my $tag = $PROG_PKG{$prog};
6844
    foreach my $entry ( @$tag )
6845
    {
6846
        Verbose("Do not package: $entry");
6847
        if ( exists $PACKAGE_PROGS{$entry} )
6848
        {
6849
            $PACKAGE_PROGS{$entry}{placekeeper} = 'ProgRemoved';
6850
        }
6851
    }
6852
}
6853
 
6854
#-------------------------------------------------------------------------------
6855
# Function        : DPackageLibrary
6856
#
6857
# Description     : Collect information to allow the generation of a DPACKAGE
299 dpurdie 6858
#                   file. This directive allows the generation of "Library"
227 dpurdie 6859
#                   directives within the final DPACKAGE
6860
#
6861
#                   This directive does generate the DPACKAGE file.
6862
#
6863
# Inputs          : platform    - This does not need to be an active platform
6864
#                                 it is simply passed to the DPACKAGE builder
6865
#
6866
#                   using       - The "using" target
6867
#
6868
#                   ...         - Arguments for the Library directive
6869
#
6870
# Returns         :
6871
#
6872
sub DPackageLibrary
6873
{
6874
    JatsDPackage::DPackageAdd ( @_ );
299 dpurdie 6875
    $DPackageDirective = 1;
227 dpurdie 6876
}
6877
 
6878
#-------------------------------------------------------------------------------
6879
# Function        : SetProjectBase
6880
#
6881
# Description     : Allows the user to modify the build's concept of the Base
6882
#                   of the build. By default the base is the same directory as
6883
#                   the build.pl file, but in some contorted environments it
6884
#                   is a great deal simpler to specify a differnt base.
6885
#
6886
#                   The use may use the variable $ProjectBase as a path
6887
#                   specifier to locate files and directories
6888
#
6889
#                   Both absolute and relative paths are supported
6890
#                   If the initial value of $ProjectBase is relative then
6891
#                   it will be maintained as a relative path.
6892
#
6893
# Inputs          : elements        path to base
6894
#                                   These may be:
6895
#                                       --Up=xx
6896
#                                       name
6897
#
6898
# Returns         : Nothing
6899
#
6900
 
6901
#
6902
#   Allow the user to modify the project base variable
6903
#
6904
sub SetProjectBase
6905
{
6906
    my $rip = 0;
6907
    my $path = "";
6908
    my $is_relative;
6909
 
6910
    Debug("ProjectBase Initial: $ProjectBase, @_");
6911
 
6912
    #
6913
    #   Ensure that the ProjectBase is in a "nice" form
6914
    #   1) No /./ bits
6915
    #   2) No trailing /
6916
    #   3) Not equal to .
6917
    #   4) No training /.
6918
    #   5) No //
6919
    #
6920
    $ProjectBase =~ s~/\./~/~g;
6921
    $ProjectBase =~ s~/$~~g;
6922
    $ProjectBase =~ s~^\.$~~g;
6923
    $ProjectBase =~ s~/\.$~~g;
6924
    $ProjectBase =~ s~//$~/~g;
6925
 
6926
    #
6927
    #   ProjectBase may be absolute or relative
6928
    #   Determine this before we mess with it
6929
    #
6930
    $is_relative = ($ProjectBase !~ m~^/~);
6931
 
6932
    #
6933
    #   Process each argument
6934
    #
6935
    foreach ( @_ )
6936
    {
6937
        if ( /^--Up=([0-9]*)/ ) {
6938
            $rip = $1;
6939
        } elsif ( /^--/ ) {
6940
            Warning( "SetProjectBase - unknown option \"$_\" - ignored" );
6941
        } else {
6942
            $path = $_;
6943
        }
6944
    }
6945
 
6946
    #
6947
    #   Process the UP requests
6948
    #   If the tail directory is a ".." then up is done by adding another ".."
6949
    #   If the tail directory is not a "..", then up is done by removing it
6950
    #
6951
    #   If we go past the start of the path then simply add ".."
6952
    #
6953
    while ( $rip-- > 0 )
6954
    {
6955
        Debug2("ProjectBase: $ProjectBase, Up: $rip, IsRel: $is_relative");
6956
 
6957
        #
6958
        #   If ending in a /.. or is exactly equal to ..
6959
        #   Then its a dot-dot and the way to go UP is to append another ..
6960
        #
6961
        if ( $ProjectBase =~ m~(/\.\.$)|(^\.\.$)~ )
6962
        {
6963
            $ProjectBase .= '/..';
6964
        }
6965
        else
6966
        {
6967
            #
6968
            #   Not a dot-dot ending
6969
            #   Attempt to remove the last directory of the form
6970
            #       /xxxxx
6971
            #   Where the leading / is optional
6972
            #   Note: Must have at least one character in the dirname
6973
            #         This prevents leading / from matching - which is needed
6974
            #
6975
            unless ($ProjectBase =~ s~/?[^/]+$~~)
6976
            {
6977
                #
6978
                #   Removal failed
6979
                #   If a relative path then we can keep on going up,
6980
                #   otherwise we are dead.
6981
                #
6982
                Error ("ProjectBase outside project") unless ($is_relative);
6983
                $ProjectBase = '..';
6984
            }
6985
 
6986
            #
6987
            #   Ensure that the leading / in an absolute path is not deleted
6988
            #
6989
            $ProjectBase = '/'
6990
                unless ( $is_relative || $ProjectBase );
6991
        }
6992
    }
6993
 
6994
    #
6995
    #   Append the user path
6996
    #
6997
    $ProjectBase .= '/' . $path if ( $path );
6998
    $ProjectBase = '.' unless ( $ProjectBase );
6999
    Debug("ProjectBase set to : $ProjectBase");
7000
 
7001
    #
7002
    #   Once upon a time I tried to convert paths that contained spaces into
7003
    #   short (mangled) names. This was not sucessful because:
7004
    #       1) Clearcase dynamic views do not support name mangling
7005
    #       2) Samba file system does not appear to support name mangling
7006
    #
7007
    #   Spaces in paths are not good for MAKE
7008
    #   Now I simple generate a message
7009
    #
7010
    Warning( "ProjectBase contains a space: $ProjectBase")
7011
        if ( $ProjectBase =~ m/ / );
7012
 
7013
    #
7014
    #   Sanity check
7015
    #   Absolute paths can be checked easily
7016
    #   Checking of relative paths does not appear to work
7017
    #   When I tested it chdir, opendir and stat would limit themselves
7018
    #   and drop into the root directory ( under windows )
7019
    #
7020
    #   Solution: Check the path does not extend beyond the file tree
7021
    #
7022
    my $distance = 1;
7023
    my $tpath = $ProjectBase;
7024
 
7025
    if ( $is_relative && $tpath ne '.' )
7026
    {
7027
        #
7028
        #   Build up the complete pathname by merging it with the
7029
        #   current directory. Then clean it up.
7030
        #
7031
        $tpath = $::Cwd . '/' . $ProjectBase;
7032
 
7033
        #
7034
        #   Scan the list of diretories and count the distance from the root
7035
        #   This should not be greater than zero for sanity
7036
        #   Note: Get an empty elemement from the split due to
7037
        #         the leading / of the ABS path
7038
        #
7039
        $distance = 0;
7040
        foreach (  split ('/', $tpath) )
7041
        {
7042
            if ( m~\.\.~ )
7043
            {
7044
                $distance--;
7045
            }
7046
            else
7047
            {
7048
                $distance++;
7049
            }
7050
        }
7051
    }
7052
 
7053
    #
7054
    #   Warn if not a valid directory
7055
    #
7056
    Warning( "ProjectBase is not a directory: $ProjectBase")
7057
        if ( $distance <= 0 || !  -d $tpath  );
7058
 
7059
    #
7060
    #   $ProjectBase will always be a valid directory, but if its the top
7061
    #   directory (/) and it is added to a path we will get //path
7062
    #   This is not good, so // will be removed later in the AddIncDir and
7063
    #   AddSrcDir commands where $ProjectBase is really used.
7064
    #
7065
    #   Alternatively we could set $ProjectBase to an empty string, but then
7066
    #   this may be confused with an empty relative directory
7067
    #
7068
    Debug("ProjectBase Final  : $ProjectBase");
7069
}
7070
 
7071
#-------------------------------------------------------------------------------
7072
# Function        : DeployPackage
7073
#
7074
# Description     : Generate a deployed package
7075
#                   This is a gateway to a different packaging system
7076
#
7077
#                  DeployPackage and PackageXxxxx directives are mutually
7078
#                  exclusive. Only one person can play in the package area.
7079
#
7080
# Inputs          : Platform Specifier
7081
#                   Package Name    (Optional)
7082
#                   Options
7083
#                       --Name : Base name of the package. The default is taken
7084
#                                from the build.pl file
7085
#                       --Dir  : Package directory
7086
#                                The default is based on the package name
7087
#
7088
# Returns         :
7089
#
7090
sub DeployPackage
7091
{
7092
    my( $platforms, @elements ) = @_;
7093
    my $dir;
7094
    my $name;
7095
 
267 dpurdie 7096
    #
7097
    #   Flag that this build creates a deployable package, even if its not
7098
    #   active on this platform.
7099
    #
7100
    $DEPLOYPACKAGE = 1;
7101
 
7102
 
227 dpurdie 7103
    Debug2( "DeployPackage($platforms, @elements)" );
7104
    return if ( ! ActivePlatform($platforms) );
7105
 
7106
    #
7107
    #   Only allow one use of this directive
7108
    #
7109
    Error("DeployPackage can only be used once" ) if ( %DEPLOYPACKAGE );
267 dpurdie 7110
    $DEPLOYPACKAGE = 2;
227 dpurdie 7111
 
7112
    #
7113
    #   Ensure that the deployment file is available
7114
    #
7115
    my $command_file = $ScmDeploymentPatch ? "deploypatch.pl" : "deployfile.pl";
7116
    Error("DeployPackage: $command_file not found") unless (-f "./$command_file");
7117
    #
7118
    #   Collect arguments
7119
    #
7120
    foreach (@elements )
7121
    {
7122
        if ( m/^--Dir=(.*)/ ) {
7123
            Error ("DeployPackage: Package directory defined multiple times") if $dir;
7124
            $dir = $1;
7125
 
7126
        } elsif ( m/^--Name=(.*)/ ) {
7127
            Error ("DeployPackage: Package name defined multiple times") if $name;
7128
            $name = $1;
7129
 
7130
        } elsif ( m/^--/ ) {
7131
            Warning( "DeployPackage: Unknown option ignored: $_");
7132
 
7133
        } else {
7134
            Error ("DeployPackage: Package name defined multiple times") if $name;
7135
            $name = $_;
7136
 
7137
        }
7138
    }
7139
 
7140
    $name = $::ScmBuildPackage unless ( $name );
7141
 
7142
    #
7143
    #   Save the deployment data
7144
    #
7145
    $dir = lc($name) unless ( $dir );
7146
    $DEPLOYPACKAGE{'name'} = $name;
7147
    $DEPLOYPACKAGE{'dir'} = $dir;
7148
    $DEPLOYPACKAGE{'cmdfile'} = $command_file;
7149
 
7150
    #
7151
    #   Flag that toolset tests should be supressed
7152
    #   The Deploy world does not really use the full makefiles and if the
7153
    #   compilers are not installed will not be able to create deployment
7154
    #   packages
7155
    #
7156
    $ScmNoToolsTest = 1;
7157
}
7158
 
7159
 
7160
###############################################################################
7161
###############################################################################
7162
# Private function section.
7163
#       The following functions are used INTERNALLY by makelib.pl2.
7164
###############################################################################
7165
 
7166
###############################################################################
7167
#   A collection of functions to write to the MAKEFILE handle
7168
#
7169
#   MakeHeader          - Write a nice section header
7170
#   MakeNewLine         - Print a new line
7171
#   MakePrint           - Print a line ( without trailing \n)
7172
#   MakeQuote           - Escape \ and " character, then print a line
7173
#   MakePrintList       - Print an array
7174
#   MakeEntry           - Complex line printer
7175
#   MakePadded          - Padded line printer (internal)
7176
#   PadToPosn           - Calc space+tabs to tabstop (internal)
7177
#   MakeEntry3          - Complex Line Printer
7178
#   MakeDefEntry        - Print a definition line (Production + Debug support)
7179
#   MakeIfDefEntry      - Print ifdef entry
261 dpurdie 7180
#   MakeIfnDefEntry     - Print ifndef entry
7181
#   MakeIfZeroEntry     - Print ifeq entry
227 dpurdie 7182
#
7183
###############################################################################
7184
 
7185
sub MakeHeader
7186
{
7187
    my ($text, @rest) = @_;
7188
    my $length = length ($text);
7189
 
7190
    print MAKEFILE "\n";
7191
    print MAKEFILE "#--------- $text ", '-' x (80 - 12 - $length)  ,"\n";
7192
    print MAKEFILE "#    $_\n" foreach  ( @rest ) ;
7193
    print MAKEFILE "#\n";
7194
}
7195
 
7196
sub MakeNewLine         # Print a newline to the current 'Makefile'
7197
{
7198
    print MAKEFILE "\n";
7199
}
7200
 
7201
sub MakePrint           # Print to the current 'Makefile'
7202
{
7203
    print MAKEFILE @_
7204
        if ( defined $_[0] );
7205
}
7206
 
7207
sub MakeQuote           # Quote a makefile text line
7208
{
7209
    my( $line ) = @_;
7210
    $line =~ s/\\/\\\\/g;                       # quote all '\' characters
7211
    $line =~ s/"/\\"/g;                         # Then quote '"' characters
255 dpurdie 7212
    $line =~ s/=#/=\\#/g;                       # Then quote '=#' sequence
227 dpurdie 7213
    print MAKEFILE $line;
7214
}
7215
 
7216
sub MakePrintList
7217
{
7218
    print MAKEFILE $_ . "\n" foreach (@{$_[0]});
7219
}
7220
 
7221
 
7222
#-------------------------------------------------------------------------------
7223
# Function        : MakeEntry
7224
#
7225
# Description     : Build a entry based on the element list
7226
#                   Creates text of the form
7227
#                       $(BINDIR)/prog.exe: object1.obj \
7228
#                                           object2.obj
7229
#
7230
#
7231
# Inputs          : $prelim         - Preamble (one-off)
7232
#                   $postlim        - Postamble (one-off)
7233
#                   $prefix         - Pefix (to each element of array)
7234
#                   $postfix        - Postfix (to each element of array )
7235
#                   @elements       - Array of element to wrap
7236
#
7237
# Returns         :   1 Always
7238
#
7239
# Notes:
7240
#       The above description means that the following entry format is
7241
#       produced:
7242
#
7243
#           <preliminary><prefix><variant1><prefix><variant2>...<final>
7244
#
7245
#       With judicious use of newline and tab characters, a target
7246
#       and dependency list along with the command(s) to build the
7247
#       target can be constructed.
7248
#
7249
sub MakeEntry
7250
{
7251
    my( $prelim, $postlim, $prefix, $postfix, @elements ) = @_;
7252
 
7253
    MakePrint $prelim;
7254
    MakePrint "${prefix}${_}${postfix}" foreach ( @elements );
7255
    MakePrint $postlim if ($postlim);
7256
    return 1;
7257
}
7258
 
7259
#-------------------------------------------------------------------------------
7260
# Function        : MakePadded
7261
#
7262
# Description     : Generate aligned output of the form
7263
#                       Prefix_text           Aligned_text
7264
#                   where the aligned text is at a specified TAB boundary
7265
#
7266
# Inputs          : $align      - Tab stop (One tab = 8 chars)
7267
#                   $prefix     - Text to print before alignment occurs
7268
#                   @line       - Remainder of the line
7269
#
7270
sub MakePadded          # Print to the current 'Makefile', tab aligning
7271
{
7272
    my( $align, $prefix, @line ) = @_;
7273
 
7274
    my $strlen = length( $prefix );
7275
    my $pad = PadToPosn( $strlen, $align * 8 );
7276
 
7277
    print MAKEFILE $prefix . $pad;
7278
    print MAKEFILE @line;
7279
}
7280
 
7281
#-------------------------------------------------------------------------------
7282
# Function        : PadToPosn
7283
#
7284
# Description     : Given that we are at $startposn return a tab and space
7285
#                   string to place us at $endposn
7286
#
7287
sub PadToPosn
7288
{
7289
    my ($startposn, $endposn ) = @_;
7290
 
7291
 
7292
    #
7293
    #   Case where we are already too far into the line
7294
    #
7295
    return ( ' ' )if ( $endposn <= $startposn );
7296
 
7297
    my $tcount = 0;
7298
    my $scount = 0;
7299
 
7300
    while ( $startposn < $endposn )
7301
    {
7302
        $tcount ++;
7303
        $startposn = ($startposn >> 3) * 8 + 8;
7304
 
7305
        my $delta = $endposn - $startposn;
7306
        if ( $delta < 8 )
7307
        {
7308
            $scount = $delta;
7309
            last;
7310
        }
7311
 
7312
    }
7313
    return ( "\t" x $tcount .  ' ' x $scount );
7314
}
7315
 
7316
#-------------------------------------------------------------------------------
7317
# Function        : MakeEntry3
7318
#
7319
# Description     : Build a makefile entry based on the element list, tab aligned
7320
#                   Can creat text of the form:
7321
#                       TAG = NAME0 \       TAG : NAME0 \ 
7322
#                             NAME1               NAME1
7323
#
7324
#
7325
# Inputs          : $prelim             - Preliminary text
7326
#                   $presep             - Preliminary seperator
7327
#                   $elem_ref           - Either a single name or a reference to
7328
#                                         and array of names, or a hash.
7329
#
7330
# Returns         : Writes directly to the Makefile
7331
#
7332
sub MakeEntry3
7333
{
7334
    my( $prelim, $presep, $elem_ref ) = @_;
7335
 
7336
    #
7337
    #   The prelim may have some "\n" characters at the start
7338
    #   These simplify formatting, but mess up the nice formatting
7339
    #
7340
    if ($prelim =~ m~(^\n+)(.*)~ )
7341
    {
7342
        MakePrint $1;
7343
        $prelim = $2;
7344
    }
7345
 
7346
    #
7347
    #   Print the definition and the sep with nice padding
7348
    #
7349
    MakePadded ( 3, $prelim, $presep );
7350
    my $leadin = ' ';
7351
 
7352
    #
7353
    #   If a HASH reference then use a sorted list of keys from the hash.
7354
    #
7355
    if ( ref ($elem_ref) eq "HASH" )
7356
    {
7357
        my @hash_list;
7358
        @hash_list = sort keys ( %{$elem_ref} );
7359
        $elem_ref = \@hash_list;
7360
    }
7361
 
7362
    #
7363
    #   If the list is only one element long, then create a simple form
7364
    #   If the list is not an array ref, then treat it as a single element
7365
    #
7366
    if ( ref ($elem_ref) eq "ARRAY" )
7367
    {
7368
        my $line = 0;
7369
        foreach my $element ( @$elem_ref )
7370
        {
7371
            print MAKEFILE $leadin . $element;
7372
            $leadin = " \\\n" . PadToPosn(0,24 + length( $presep ) + 1 ) unless ($line++);
7373
        }
7374
    }
7375
    elsif ( defined $elem_ref )
7376
    {
7377
            print MAKEFILE $leadin . $elem_ref;
7378
    }
7379
    MakeNewLine();
7380
    return 1;
7381
}
7382
 
7383
#-------------------------------------------------------------------------------
7384
# Function        : MakeDefEntry
7385
#
7386
# Description     : Make a definition entry of the form
7387
#
7388
#                       TAG = NAME0 \
7389
#                             NAME1
7390
#
7391
#                   Support a list of definitions that will always be created
7392
#                   as well as a production and a debug list.
7393
#
7394
#                   Will always generate the "TAG = " string, even if the list
7395
#                   is empty.
7396
#
7397
#                   Will supress the TAG if there is no data if the FIRST opr starts with a '+'
7398
#
7399
# Inputs          : TAG         - Text tag to create
7400
#                   FIRST       - First assignement opr. = or +=
7401
#                   ALL_LIST    - A reference to a list of names to assign
7402
#                                 or a single name.
7403
#                   PROD_LIST   - Optional list to extend the definition with for a production build
7404
#                   DEBUG_LIST  - Optional list to extend the definition with for a debug build
7405
#
7406
# Returns         : Nothing
7407
#
7408
 
7409
sub MakeDefEntry
7410
{
7411
    my( $tag, $assign, $all, $prod, $debug ) = @_;
7412
 
7413
    #
7414
    #   Do not generate anything if the $opr is "+=" and there is no data
7415
    #   to output. ie: Supress empty TAG += statements
7416
    #
7417
    return if ( $assign =~ m/\+/ && ( ref($all) && ! defined $all->[0] ) );
7418
 
7419
    #
7420
    #   TAG for all entries
7421
    #
7422
    MakeEntry3( $tag, $assign, $all );
7423
 
7424
 
7425
    #
7426
    #   TAGs for PROD build
7427
    #   TAGs for DEBUG build
7428
    #
7429
    if ( defined $prod && defined $prod->[0] )
7430
    {
7431
        print MAKEFILE 'ifeq "$(DEBUG)" "0"' . "\n";
7432
        MakeEntry3( $tag, "+=", $prod );
267 dpurdie 7433
        print MAKEFILE 'endif' . "\n";
227 dpurdie 7434
    }
7435
 
7436
    if ( defined $debug && defined $debug->[0] )
7437
    {
7438
        print MAKEFILE 'ifeq "$(DEBUG)" "1"' . "\n";
7439
        MakeEntry3( $tag, "+=", $debug );
267 dpurdie 7440
        print MAKEFILE 'endif' . "\n";
227 dpurdie 7441
    }
7442
 
7443
}
7444
 
7445
sub MakeIfDefEntry
7446
{
7447
    my( $iftag, @rest ) = @_;
7448
 
7449
    print MAKEFILE "ifdef $iftag\n";
7450
    MakeDefEntry (@rest);
7451
    print MAKEFILE "endif\n\n";
7452
}
7453
 
7454
sub MakeIfnDefEntry
7455
{
7456
    my( $iftag, @rest ) = @_;
7457
 
7458
    print MAKEFILE "ifndef $iftag\n";
7459
    MakeDefEntry (@rest);
7460
    print MAKEFILE "endif\n\n";
7461
}
7462
 
261 dpurdie 7463
sub MakeIfZeroEntry
7464
{
7465
    my( $iftag, @rest ) = @_;
7466
 
7467
    print MAKEFILE "ifeq (\$($iftag),0)\n";
7468
    MakeDefEntry (@rest);
7469
    print MAKEFILE "endif\n\n";
7470
}
7471
 
227 dpurdie 7472
#-------------------------------------------------------------------------------
7473
# Function        : CreateNameList
7474
#
7475
# Description     : Create a list of names by adding a prefix and suffix to a
7476
#                   list of items. This is used to add a directory prefix and a
7477
#                   file suffix to a list of files.
7478
#
7479
# Inputs          : $prefix             ie: '$(OBJDIR)/'
7480
#                   $suffix             ie: '.obj'
7481
#                   $elem_ref           ie: A list of files ( passed be ref )
7482
#                                           If a Hash then its sorted keys is used
7483
#
7484
# Returns         : A ref to the resulting list
7485
#
7486
sub CreateNameList
7487
{
7488
    my( $prefix, $suffix, $elem_ref ) = @_;
7489
    my @result;
7490
 
7491
    if ( ref ($elem_ref) eq "HASH" )
7492
    {
7493
        my @hash_list;
7494
        @hash_list = sort keys ( %{$elem_ref} );
7495
        $elem_ref = \@hash_list;
7496
    }
7497
 
7498
    foreach  ( @$elem_ref )
7499
    {
7500
        push @result, $prefix . $_ . $suffix;
7501
    }
7502
    return \@result;
7503
}
7504
 
7505
#-------------------------------------------------------------------------------
7506
# Function        : ListGeneratedProjects
7507
#
7508
# Description     : Return a list of generated/nongenerated projects
7509
#                   Used in conjunction with CreateNameList
7510
#
7511
# Inputs          : $type       - TRUE : Generated
7512
#                                 FALSE: Not Generated
7513
#
7514
# Returns         : A reference to a list of projects
7515
#                   undef will be retuend if there are no projects
7516
#
7517
sub ListGeneratedProjects
7518
{
7519
    my ($type) = @_;
7520
    my @list;
7521
    foreach my $project ( @PROJECTS_ORDER )
7522
    {
7523
        if ( exists($PROJECTS{$project}->{'generated'}) xor $type )
7524
        {
7525
            push @list, $project;
7526
        }
7527
    }
7528
    return @list ? \@list : undef;
7529
}
7530
 
7531
#-------------------------------------------------------------------------------
7532
# Function        : ListCleanGenerated
7533
#
7534
# Description     : return a list of generated targets that have 'clean'
7535
#                   operations. This is used in conjunction with CreateNameList
7536
#
7537
# Inputs          : None
7538
#
7539
# Returns         : A list of project indexes, that can be cleaned
7540
#
7541
sub ListCleanGenerated
7542
{
7543
    my @list;
7544
    foreach my $i ( @GENERATE_FILES )
7545
    {
7546
        push @list, $i->{'index'}
7547
            if ( $i->{'clean'} );
7548
    }
7549
    return \@list;
7550
}
7551
 
251 dpurdie 7552
#-------------------------------------------------------------------------------
7553
# Function        : MakeResolve
7554
#
7555
# Description     : Internal Function
7556
#                   Locate a source file by examining a list of directories
7557
#
7558
#                   Don't use directly
7559
#                   Use MakeSrcResolve or MakeSrcResolveExtended
7560
#
7561
# Inputs          : $dirs           - Ref to an array of directories to scan
7562
#                   $source         - File to locate
7563
#
7564
# Returns         : Resolved path to the file
7565
#                   Will warn if multiple instances of the file are found
7566
#
227 dpurdie 7567
sub MakeResolve
7568
{
7569
    my( $dirs, $source ) = @_;
285 dpurdie 7570
    my( $first, $count );
227 dpurdie 7571
 
237 dpurdie 7572
    #
7573
    #   If the path contains a '$' then its assumed to be
7574
    #   a variable name in the path. Just assume that it exists
7575
    #
7576
    return $source if ( $source =~ m#\$# );
7577
 
7578
    #
7579
    #   If the path is absolute or contains a leading ., then don't search
7580
    #   Warn if it can't be found
7581
    #
7582
    if ( $source =~ m#^(/|\.)# )
7583
    {
7584
        Warning( "Unable to resolve '$source' path" ) unless -f $source;
7585
        return $source;
227 dpurdie 7586
    }
7587
 
237 dpurdie 7588
 
227 dpurdie 7589
#.. search local path first
7590
#
7591
    $count = 0;
7592
    $first = "";
7593
    $first = "$source"                          # was ./$source
7594
        if (-r "$source");
7595
 
7596
#.. search directory paths
7597
#
285 dpurdie 7598
    foreach my $dir (@$dirs)
227 dpurdie 7599
    {
285 dpurdie 7600
        my $temp = "$dir/$source";                 # was ./$dir/$source
227 dpurdie 7601
        Debug2( "MakeResolve: Looking in: $temp" );
7602
        if (-r "$temp")
7603
        {
7604
            if ($first eq "") {
7605
                $first = $temp;
7606
            } else {
7607
                Warning( "Duplicate '$source' image - '$temp'" );
7608
                $count++;
7609
            }
7610
        }
7611
        Debug3( "MakeResolve: $count, $temp" );
7612
    }
7613
 
7614
    if ($first eq "") {
7615
        $first = $source;
7616
        Warning( "Unable to resolve '$source' path" );
7617
    } else {
7618
        Warning( "          using '$first'" )
7619
            if ($count);
7620
    }
7621
    return $first;
7622
}
7623
 
251 dpurdie 7624
#-------------------------------------------------------------------------------
7625
# Function        : MakeSrcResolve
7626
#
7627
# Description     : Locate a source file by examining the list of source
7628
#                   directories. There are a few frills
7629
#
7630
#                   Look for a source file in
7631
#                       1) %::BUILD_KNOWNFILES
7632
#                       2) %SRCS
7633
#                       3) Dirs specified by the array @SRCSDIRS
7634
#
7635
# Inputs          : Name of a file to resolve
7636
#
7637
# Returns         : Resolved path.
283 dpurdie 7638
#                   Input file - if not found at all
251 dpurdie 7639
#
227 dpurdie 7640
sub MakeSrcResolve
7641
{
7642
    my ($name) = @_;
7643
    my $file;
7644
 
251 dpurdie 7645
    if ( exists ( $::BUILD_KNOWNFILES{$name} ) ) {
7646
        #
7647
        #   The Known Files list is relative to ScmRoot
7648
        #   This must be included in the full path
7649
        #
7650
        $file = $ScmRoot . '/' . $::BUILD_KNOWNFILES{$name};
7651
 
7652
    } elsif ( exists $SRCS{$name} ) {
7653
        $file = $SRCS{$name};
7654
 
7655
    } else {
7656
        $file = MakeResolve( \@SRCDIRS, @_ )
7657
    }
227 dpurdie 7658
    return $file;
7659
}
7660
 
7661
 
7662
# MakeSrcResolveExtended
7663
#   from_global = 0 : Search user specified directories
7664
#               = 1 : Search LinkPkgArchive list
7665
#
7666
our @PkgSrcDirList;
7667
sub MakeSrcResolveExtended
7668
{
7669
    my ( $from_global, $file ) = @_;
7670
 
7671
    #
7672
    #   Simple Case. Resolve source from known source directories
7673
    #
7674
    #
7675
    return MakeSrcResolve( $file )
7676
        unless ( $from_global );
7677
 
7678
    #
7679
    #   Not so simple Case
7680
    #   Resolve the source from the imported packages
7681
    #
7682
    #   Create a list of directores to search, but only the first time
311 dpurdie 7683
    #       - Interface directories - from BuildPkgArchive
227 dpurdie 7684
    #       - LnkPkgArchive directories
7685
    #         Using target,product,platform include directories
7686
    #
7687
    unless ( @PkgSrcDirList )
7688
    {
7689
        for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} })
7690
        {
311 dpurdie 7691
            next if ( $entry->{'TYPE'} eq 'build' ); # Ignore BuildPkgArchives
7692
 
227 dpurdie 7693
            for (@{$entry->{'PINCDIRS'}}, @{$entry->{'THXDIRS'}}, '' )
7694
            {
7695
                my $dir = $entry->{'ROOT'} . "/" . $_ ;
7696
                $dir =~ s~//~/~g;
7697
                $dir =~ s~/$~~;
311 dpurdie 7698
                push ( @PkgSrcDirList, $dir );
227 dpurdie 7699
            }
7700
        }
311 dpurdie 7701
    }
227 dpurdie 7702
 
7703
    return MakeResolve( \@PkgSrcDirList, $file );
7704
}
7705
 
7706
#-------------------------------------------------------------------------------
7707
# Function        : GetPackageRoot
7708
#
7709
# Description     : Determine the root directory for a given package
7710
#                   This routine is intended for non-standard JATS scripts that
7711
#                   access package contents directly
7712
#
7713
#                   Note: This routine does not attempt to handle multiple
7714
#                         instances of a package ( sysbasetypes ).
7715
#
7716
# Inputs          : $pname          - Name of the package
7717
#
7718
# Returns         :
7719
#
7720
sub GetPackageRoot
7721
{
7722
    my( $pname ) = @_;
7723
    Debug( "GetPackageRoot(@_)" );
7724
 
7725
    my $result = undef;
7726
    my $pkg = GetPackageEntry( $pname );
7727
    if ( $pkg )
7728
    {
7729
        $result = $pkg->{'ROOT'};
7730
        Debug( "GetPackageRoot: $result" );
7731
    }
7732
 
7733
    return $result;
7734
}
7735
 
7736
#-------------------------------------------------------------------------------
7737
# Function        : ActiveProject
7738
#
7739
# Description     : Determine if the specified project is currenly 'active'
7740
#
7741
# Inputs          : A list of projects. The projects may be comma seperated
7742
#
7743
# Returns         : TRUE    if the project is active
7744
#
7745
sub ActiveProject
7746
{
7747
    my ($project) = @_;
7748
    foreach (  split( '\s*,\s*', $project ) )
7749
    {
7750
        return 1
7751
            if ( $_ eq $::ScmBuildProject );
7752
    }
7753
    return 0;
7754
}
7755
 
7756
 
7757
#-------------------------------------------------------------------------------
7758
# Function        : ActivePlatform
7759
#
7760
# Description     : Determine if the specified platform is currently 'active'
7761
#                   This is used by all user directives in order to determine
7762
#                   if the directive should be ignored for the current platform
7763
#
7764
# Inputs          : $platform_spec      - A platform specifier
7765
#                                         This is a bit complex.
7766
#
241 dpurdie 7767
#                   Format of platform_spec. One or more of
7768
#                       PlatformName
7769
#                       AliasName
7770
#                       TargetName,--Target
7771
#                       --Project=ProjectName
7772
#                       --Defined=SomeValue
277 dpurdie 7773
#                       --MachType=SomeValue
227 dpurdie 7774
#
241 dpurdie 7775
#                   Each can be prefxied with a '!' to negate the test
7776
#
7777
#                   Valid options are:
271 dpurdie 7778
#                       --Target        - indicates that the platform is a 'target'
241 dpurdie 7779
#
7780
# Returns         : TRUE if the platform spec is satisfied
7781
#
227 dpurdie 7782
sub ActivePlatform
7783
{
7784
    my( $platform_spec ) = @_;
7785
    my( @platforms, $scmplatform, $platform );
7786
    my( %arguments, @args, $filter );
241 dpurdie 7787
    my @plist;
7788
    my ($match_count, $count_invert, $count_vert) = (0,0,0);
227 dpurdie 7789
 
241 dpurdie 7790
    #
7791
    #   Short circuit check
7792
    #   '*' is used so often that it pays to check it first
7793
    #
7794
    if ( $platform_spec eq '*' )
7795
    {
7796
        Debug3( " ActivePlatform(@_) = TRUE" );
7797
        return 1;
7798
    }
227 dpurdie 7799
 
241 dpurdie 7800
 
7801
    #
7802
    #   Platform specifier may be a comma seperated list
7803
    #   ie:  WIN32,MOS,XXX
7804
    #   Extract non-platform arguments
279 dpurdie 7805
    #   Process to yield a dummy platform of '0' or '1' - these will be seen later
241 dpurdie 7806
    #
7807
    foreach ( split( '\s*,\s*', $platform_spec ) )
7808
    {
7809
        if ( m~^(!?)--Project=(.+)~ ) {
7810
            my $result = ActiveProject( $2);
7811
            $result = $result ? 1 : 0;
7812
            push @plist, "$1$result";
7813
            next;
277 dpurdie 7814
 
7815
        } elsif ( m~^(!?)--Defined=(.+)~ ) {
241 dpurdie 7816
            my $result = 0;
7817
            no strict 'refs';
7818
            $result = 1 if ( defined( $$2 ) || defined( @$2 ) );
7819
            use strict 'refs';
7820
 
7821
            $result = $result ? 1 : 0;
7822
            push @plist, "$1$result";
7823
            next;
277 dpurdie 7824
 
7825
        } elsif ( m~^(!?)--MachType=(.+)~ ) {
7826
            my $result = ( uc($2) eq uc($::GBE_MACHTYPE) );
7827
            $result = $result ? 1 : 0;
7828
            push @plist, "$1$result";
7829
            next;
241 dpurdie 7830
        }
7831
 
7832
        #
7833
        #   Must be a platform argument
7834
        #   Add to a list
7835
        #
7836
        push @platforms, $_;
7837
    }
7838
 
7839
    #   Platform specified may be an Alias
7840
    #   Perform alias expansion
7841
    #
7842
    @platforms = ExpandPlatforms( @platforms );         # aliasing
227 dpurdie 7843
    Debug3( " ActivePlatform(@_)" );
7844
 
7845
#.. Arguments
241 dpurdie 7846
#   At this point we have a list of platforms and arguments
7847
#   Build up a hash of arguments for each platform being parsed
227 dpurdie 7848
#   Multiple arguments can follow a platform name
241 dpurdie 7849
#   Arguments apply to the preceeding platform name
227 dpurdie 7850
#
241 dpurdie 7851
    $platform = undef;
227 dpurdie 7852
    foreach ( @platforms )
7853
    {
241 dpurdie 7854
        if ( /^--Target/ ) {                     # Arguments
7855
            if ( $platform ) {
7856
                $arguments{$platform}{'Target'} = 1;
7857
            } else {
7858
                Warning ("No Platform preceedig platform option: $_");
7859
            }
7860
 
305 dpurdie 7861
        } elsif ( /^--Only(Prod)|(Debug)/ || /--board=/ ) {
273 dpurdie 7862
            # Known arguments
305 dpurdie 7863
            # Bit of a kludge. Must be a better way
273 dpurdie 7864
 
241 dpurdie 7865
        } elsif ( /^--/ ) {
7866
            Warning ("Unknown platform option: $_");
7867
 
227 dpurdie 7868
        } else {                                # Target
7869
            $platform = $_;
241 dpurdie 7870
            push @plist, $platform;
227 dpurdie 7871
        }
7872
    }
7873
 
241 dpurdie 7874
#.. Scan the expression
227 dpurdie 7875
#
7876
    $scmplatform = uc( $ScmPlatform );          # current platform
241 dpurdie 7877
    foreach ( @plist )
227 dpurdie 7878
    {
7879
        $platform = uc( Trim( $_ ) );           # trim white and convert case
7880
 
7881
        #
241 dpurdie 7882
        #   Determine filter comparison
7883
        #   Either a Platform or a Target
7884
        #
7885
        if ( $arguments{$platform}{'Target'} )
227 dpurdie 7886
        {
241 dpurdie 7887
            $filter = uc( $ScmTarget );
227 dpurdie 7888
        }
241 dpurdie 7889
        else
7890
        {
7891
            $filter = $scmplatform;             # filter specification
7892
        }
7893
 
227 dpurdie 7894
        Debug3( "   Platform=$platform, Filter=$filter" );
7895
 
7896
        #
7897
        #   Examine platform names
7898
        #   Allow negation of name (!), but all the names must be negated
7899
        #   as a mix does not make sense.
7900
        #   ie:     !P1,!P2,!P3     - All except P1,P2 or P3
7901
        #            P1,P2,P2       - Only P1,P2,P3
7902
        #
241 dpurdie 7903
        my $invert = 0;
7904
        if ( substr($platform, 0, 1) eq '!' )
7905
        {
7906
            $count_invert++;
7907
            $platform = substr($platform, 1);
227 dpurdie 7908
        }
7909
        else
241 dpurdie 7910
        {
7911
            $count_vert++;
7912
        }
227 dpurdie 7913
 
241 dpurdie 7914
        $match_count++ if ( $platform eq ''  ||
7915
                            $platform eq '*' ||
7916
                            $platform eq '1' ||
7917
                            $platform eq $filter );
227 dpurdie 7918
    }
7919
 
241 dpurdie 7920
    #
7921
    #   Sanity test
7922
    #   Force failure on bad sanity
7923
    #
7924
    if ( $count_vert && $count_invert )
7925
    {
7926
        Warning( "Platform expression makes no sense. Mixed use of '!' operator",
7927
                 "Expression: @_" );
7928
        return 0;
7929
    }
7930
 
7931
    #
7932
    #   Test for pass
7933
    #   If not using '!', then any match passes : P1 or P2 or P3
7934
    #   If are using '!', then any match is bad : !P1 and !P2 and !P3 == !(P1 or P2 or P3)
7935
    #
7936
    if ( ( $count_vert && $match_count ) || ( $count_invert && ( not $match_count) )   )
7937
    {
227 dpurdie 7938
        Debug3( " ActivePlatform(@_ == $ScmPlatform) = TRUE" );
7939
        return 1;
7940
    }
241 dpurdie 7941
 
227 dpurdie 7942
    Debug3( " ActivePlatform(@_ == $ScmPlatform) = FALSE" );
7943
    return 0;
7944
}
7945
 
7946
#-------------------------------------------------------------------------------
7947
# Function        : RegisterMakefileGenerate
7948
#
7949
# Description     : Register a function to be called at the start of the
7950
#                   makefile generation process
7951
#
7952
# Inputs          : $fname      - Name of the function
7953
#                   $args       - Function Arguments
7954
#
7955
# Returns         : Nothing
7956
#
7957
our @MF_Generators;
7958
sub RegisterMakefileGenerate
7959
{
7960
   my ($fref) = @_;
7961
   my $rtype = ref($fref) || 'not a reference';
7962
 
7963
   Error ("RegisterMakefileGenerate called incorrectly",
7964
          "First argument MUST be a code reference",
7965
          "It is a $rtype"
7966
          ) unless ( $rtype eq 'CODE' );
7967
 
7968
   #
7969
   #    Save the arguments by reference in an array
7970
   #    The array will be processed later
7971
   #
7972
   push @MF_Generators, \@_;
7973
}
7974
 
7975
#-------------------------------------------------------------------------------
271 dpurdie 7976
# Function        : RegisterSrcHook
7977
#
7978
# Description     : Register a function to be called when a source file is
7979
#                   declared
7980
#
7981
# Inputs          : $ext        - Extension of interest
7982
#                                 '*' will be used by all
7983
#                   $fname      - Name of the function
7984
#                   $args       - Function Arguments
7985
#
7986
# Returns         : Nothing
7987
#
7988
sub RegisterSrcHook
7989
{
7990
    my $ext = shift;
7991
    my ($fref) = @_;
7992
    my $rtype = ref($fref) || 'not a reference';
7993
 
7994
    Error ("RegisterSrcHook called incorrectly",
7995
           "Second argument MUST be a code reference",
7996
           "It is a $rtype"
7997
           ) unless ( $rtype eq 'CODE' );
7998
 
7999
    #
8000
    #    Save the arguments by reference in an array
8001
    #    The array will be processed later
8002
    #
8003
    push @{$MF_RegisterSrcHooks{$ext}}, \@_;
8004
}
8005
 
8006
 
8007
#-------------------------------------------------------------------------------
227 dpurdie 8008
# Function        : MakefileHeader
8009
#
8010
# Description:    : Generate a "standard" makefile header.
8011
#
8012
#..
8013
 
8014
sub MakefileHeader
8015
{
8016
    my ($file, $desc, $by, @trailing) = @_;
8017
    my ($diff);
8018
 
8019
    $diff = 0 if (($diff = ((80-5) - length($desc))) < 0);
8020
    $desc .= ' ' . ('-' x $diff);
8021
 
8022
    print $file <<EOF;
8023
# -*- mode: mak; -*-
8024
#-- $desc
8025
#
8026
#                   -- Please do not edit this file. --
8027
#
8028
#       To do so may result in a system failure, in additional to any
8029
#       changes made shall be overwritten.
8030
#
8031
# Created by $by
8032
#         on $::CurrentTime
8033
#
8034
EOF
8035
    #
8036
    #   Print out the trailer
8037
    #   This is an array. Place each entry on a new line
8038
    #
8039
    print $file $_ . "\n" for ( @trailing );
8040
}
8041
 
8042
###############################################################################
8043
# MakeFileGenerate:
8044
#       This subroutine does all of the actual make file generation based
8045
#       on information provided in the calls to the various public
8046
#       interface routines.
8047
#
8048
# Inputs:
8049
#
8050
# Returns:
8051
###############################################################################
8052
 
8053
my $MakefileGenerate_once = 0;
8054
sub MakefileGenerate
8055
{
8056
    my $Makefile = "$ScmPlatform.mk";
8057
    Debug( "MakefileGenerate: $Makefile" );
8058
 
8059
    #
8060
    #   Nasty things happen when we generate a makefile twice
8061
    #   Just warn the user and do nothing
8062
    #   If its in the common makefile.pl then just ignore it
8063
    #
8064
    if ( $ScmProcessingRootMake )
8065
    {
8066
        Warning ("MakefileGenerate directive is not allowed in common makefile.pl");
8067
        return;
8068
    }
8069
 
8070
    if ( $MakefileGenerate_once )
8071
    {
8072
        Warning ("MakefileGenerate should only be called once.",
8073
                 "Dir: $::Cwd");
8074
        return;
8075
    }
8076
    $MakefileGenerate_once = 1;
8077
 
8078
    #
8079
    #   Invoke all registered Makefile Generator functions
8080
    #   These allow clever directives to collect information to be
8081
    #   processed before the makefiles are created
8082
    #
8083
    while ( @MF_Generators )
8084
    {
8085
        Debug( "MakefileGenerate: Invoke RegisterMakefileGenerate function" );
8086
        my ($fname, @args) = @{shift @MF_Generators};
8087
        &$fname ( @args );
8088
    }
8089
 
8090
    #
8091
    #   Allow the toolset the opportunity to process all the collected data
8092
    #   before the makefile is created. This is optional
8093
    #
8094
    my( $if ) = MakeIf::Factory();              # build interface
8095
    $if->Preprocess();
8096
 
8097
    #
8098
    #   Auto package the 'descpkg' file
8099
    #   If this makefile packages any files, then it can also package the descpkg file
8100
    #   The descpkg will be piggybacked into all makefiles that do a package
8101
    #
8102
    if ( %PACKAGE_FILES || %PACKAGE_HDRS || %PACKAGE_CLSS || %PACKAGE_LIBS
8103
                        || %PACKAGE_SHLIBS || %PACKAGE_PROGS )
8104
    {
251 dpurdie 8105
        Src ('*', 'descpkg') unless ($SRCS{ descpkg });
8106
        PackageFile ('*', 'descpkg');
227 dpurdie 8107
    }
8108
 
8109
    #
8110
    #   Some toolsets NEED a relative root
261 dpurdie 8111
    #   Note: At the moment ScmRoot is relative anyway, thus this code
8112
    #         does nothing
227 dpurdie 8113
    #
8114
    my $gbe_root = $::ScmRoot;
8115
    if ( $::UseRelativeRoot )
8116
    {
8117
        $gbe_root =  RelPath( $::ScmRoot );
8118
    }
8119
 
8120
    #
8121
    #   Now start to create the makefile
8122
    #
285 dpurdie 8123
    open( MAKEFILE, '>', $Makefile ) || Error( "Cannot create $Makefile" );
227 dpurdie 8124
    ::MakefileHeader( *MAKEFILE,
8125
                      'Auto-generated Platform Dependent Makefile',
8126
                      "$ScmMakelib (version $ScmVersion)",
8127
                      "# Copyright (C) 1995-$::CurrentYear ERG Transit Systems, All rights reserved",
8128
                      '#',
8129
                      "# Located in $::Cwd",
8130
                      "# Platform $::ScmPlatform",
8131
                      '#' . ('-' x 79),
8132
                      );
8133
 
8134
    #
8135
    #   Ensure that some essential variables are set
8136
    #
8137
    print MAKEFILE <<EOF;
8138
#
8139
#   Validate essential environment variables
8140
#
8141
ifndef GBE_BIN
8142
    \$(error ERROR: GBE_BIN is not available)
8143
endif
8144
ifndef GBE_PERL
8145
    \$(error ERROR: GBE_PERL is not available)
8146
endif
8147
ifndef DEBUG
8148
    \$(error ERROR: DEBUG is not defined)
8149
endif
8150
EOF
8151
 
8152
 
8153
    print MAKEFILE <<EOF;
8154
 
8155
#
8156
#   Basic definitions
8157
#
261 dpurdie 8158
GBE_ROOT	:= $gbe_root
8159
GBE_ROOT_ABS	:= \$(abspath \$(GBE_ROOT))
227 dpurdie 8160
GBE_HOST	:= $::ScmHost
8161
GBE_HOSTMACH	:= $::GBE_MACHTYPE
8162
GBE_TARGET	:= $::ScmTarget
8163
GBE_MACHTYPE	:= $::ScmMachType
8164
GBE_PLATFORM	:= $::ScmPlatform
8165
GBE_PBASE	:= $::Pbase
8166
ifeq "\$(DEBUG)" "0"
8167
GBE_TYPE	:= P
8168
else
8169
GBE_TYPE	:= D
8170
endif
8171
EOF
8172
 
285 dpurdie 8173
MakePrint( "GBE_ARGS\t:= @ScmPlatformArgs\n" )
227 dpurdie 8174
    if ( scalar @ScmPlatformArgs );
8175
 
285 dpurdie 8176
MakePrint( "GBE_PRODUCT\t:= $ScmProduct\n" )
227 dpurdie 8177
    if ( $ScmProduct ne "" );
8178
 
285 dpurdie 8179
MakePrint( "GBE_OS_COMMON\t:= $::BUILDINFO{$ScmPlatform}{OS_COMMON}\n" )
227 dpurdie 8180
    if ( exists($::BUILDINFO{$ScmPlatform}{OS_COMMON}) );
8181
 
8182
 
8183
    print MAKEFILE <<EOF;
8184
 
8185
SHELL           := \$(GBE_BIN)/sh
8186
SHELLARGS       :=
8187
EXTENDED_LINE   := \$(GBE_BIN)/extend.lst
8188
export EXTENDED_LINE MAKE
8189
 
8190
MFLAGS		:= --no-print --warn -r
8191
BUILDNAME	:= $::ScmBuildName
8192
BUILDVER	:= $::ScmBuildVersionFull
261 dpurdie 8193
BUILDVERNUM	:= $::ScmBuildVersion
227 dpurdie 8194
BUILDPREVIOUSVER := $::ScmBuildPreviousVersion
8195
DEPLOYPATCH	:= $ScmDeploymentPatch
8196
GBE_NOTOOLSTEST := $ScmNoToolsTest
8197
 
8198
#
8199
#   Ensure PWD is correctly set
8200
#
8201
PWD             := \$(CURDIR)
8202
export PWD
8203
 
261 dpurdie 8204
#
8205
#   NOSCMDEPEND - Used to remove dependency checking of build files
8206
#                 Used internally by the build system
8207
#   NODEPEND    - Used to suppress generated dependency file checking
8208
#                 Mostly done in jmake.pl
8209
#   EXPERT      - Used to suppress dependency on this makefile
8210
#
8211
EOF
8212
 
285 dpurdie 8213
MakePrint( "NOSCMDEPEND\t?= " . ($ScmExpert ? '1' : '0' ) . "\n" );
8214
MakePrint( "EXPERT\t\t?= " . ($ScmExpert ? '1' : '0' ) . "\n" );
8215
MakePrint( "NODEPEND\t?= 0\n" );
261 dpurdie 8216
 
8217
print MAKEFILE <<EOF;
8218
 
8219
#
8220
#   SCM_MAKEFILE - The name of the file to depend upon
8221
#                  Supressed in EXPERT mode
8222
#
8223
ifneq (\$(EXPERT),0)
8224
SCM_MAKEFILE	:=
8225
NOSCMDEPEND	:= 1
8226
else
8227
SCM_MAKEFILE	:= $Makefile
8228
endif
8229
EOF
8230
 
267 dpurdie 8231
#
8232
#   Setup the base directory for the packaging process
8233
#   When building a deployable package the base directory is changed to match
8234
#   that used by the deployment world. This is done so that the descpkg file
8235
#   can be created in the correct location
8236
#
8237
my  $PKGDIR = "pkg/$::Pbase";
8238
    $PKGDIR = "build/deploy" if ( $DEPLOYPACKAGE );
8239
Verbose("Setting PKGDIR: $PKGDIR");
8240
 
261 dpurdie 8241
print MAKEFILE <<EOF;
8242
 
227 dpurdie 8243
#--------- Targets -------------------------------------------------------------
8244
 
8245
.PHONY: 	default all build install package unpackage uninstall \\
8246
		clean unbuild clobber deploy
8247
 
8248
default:	make_usage
8249
all:		install package deploy
8250
build:		make_init generate install_hdr depend make_lib \\
8251
		install_lib make_install_shlib make_prog install_class
8252
install:	build install_prog
8253
package:	package_files package_hdr package_lib package_shlib package_prog \\
8254
		package_class
8255
unpackage:	unpackage_class unpackage_prog unpackage_shlib \\
8256
		unpackage_lib unpackage_hdr unpackage_files
8257
uninstall:	uninstall_class uninstall_prog uninstall_shlib \\
8258
		uninstall_lib uninstall_hdr
8259
clean:		make_clean unmake_prog unmake_test unmake_lib unobj \\
261 dpurdie 8260
		undepend ungenerate rmlitter unmake_dir
227 dpurdie 8261
unbuild:	clean uninstall
8262
clobber:	unpackage unbuild
8263
deploy:		install run_deploy
8264
 
8265
#--------- Macros --------------------------------------------------------------
8266
 
8267
OBJDIR		= \$(GBE_PLATFORM)\$(GBE_TYPE).OBJ
8268
LIBDIR		= \$(GBE_PLATFORM).LIB
8269
BINDIR		= \$(GBE_PLATFORM)\$(GBE_TYPE).BIN
8270
CLSDIR		= classes\$(GBE_TYPE)
8271
 
267 dpurdie 8272
PKGDIR		= \$(GBE_ROOT)/$PKGDIR
227 dpurdie 8273
INCDIR_PKG	= \$(PKGDIR)/include
8274
LIBDIR_PKG	= \$(PKGDIR)/lib
8275
BINDIR_PKG	= \$(PKGDIR)/bin
8276
CLSDIR_PKG	= \$(PKGDIR)/classes
8277
 
8278
LOCALDIR	= \$(GBE_ROOT)/local
8279
INCDIR_LOCAL	= \$(LOCALDIR)/inc
8280
LIBDIR_LOCAL	= \$(LOCALDIR)/lib
8281
BINDIR_LOCAL	= \$(LOCALDIR)/bin
8282
CLSDIR_LOCAL	= \$(LOCALDIR)/classes
8283
BINDIR_LOCAL_PATH = \$(GBE_ROOT_ABS)/local/bin/\$(GBE_PLATFORM)\$(GBE_TYPE)
8284
 
8285
INTERFACEDIR	= \$(GBE_ROOT)/$ScmInterface
8286
INCDIR_INTERFACE= \$(INTERFACEDIR)/include
8287
LIBDIR_INTERFACE= \$(INTERFACEDIR)/lib
8288
BINDIR_INTERFACE= \$(INTERFACEDIR)/bin
8289
CLSDIR_INTERFACE= \$(INTERFACEDIR)/classes
8290
 
8291
.SUFFIXES:		# Delete the default suffixes
8292
 
8293
EOF
8294
 
8295
    MakePrintList( \@DEFINES );
8296
    MakeNewLine();
8297
 
8298
#-------------------------------------------------------------------------------
8299
#
8300
#
261 dpurdie 8301
    MakeHeader ("Defines, flags and file sets");
227 dpurdie 8302
 
8303
    # Flags
261 dpurdie 8304
    foreach my $opt ( keys %ScmCompilerOpts )
8305
    {
8306
        MakeDefEntry ( $opt, "=", $ScmCompilerOpts{$opt} );
8307
    }
227 dpurdie 8308
 
261 dpurdie 8309
    MakeDefEntry( "CFLAGS",         "=", \@CFLAGS, \@CFLAGS_PROD, \@CFLAGS_DEBUG );
8310
    MakeDefEntry( "CLINTFLAGS",     "=", \@CLINTFLAGS, \@CLINTFLAGS_PROD, \@CLINTFLAGS_DEBUG );
8311
    MakeDefEntry( "CDEPENDFLAGS",   "=", \@CFLAGS, \@CFLAGS_PROD, \@CFLAGS_DEBUG );
8312
    MakeDefEntry( "CXXFLAGS",       "=", \@CXXFLAGS, \@CXXFLAGS_PROD, \@CXXFLAGS_DEBUG );
8313
    MakeDefEntry( "CXXLINTFLAGS",   "=", \@CXXLINTFLAGS, \@CXXLINTFLAGS_PROD, \@CXXLINTFLAGS_DEBUG );
8314
    MakeDefEntry( "CXXDEPENDFLAG",  "=", \@CXXFLAGS, \@CXXFLAGS_PROD, \@CXXFLAGS_DEBUG );
267 dpurdie 8315
    MakeDefEntry( "ASFLAGS",        "=", \@ASFLAGS, \@ASFLAGS_PROD, \@ASFLAGS_DEBUG );
8316
    MakeDefEntry( "LDFLAGS",        "=", \@LDFLAGS, \@LDFLAGS_PROD, \@LDFLAGS_DEBUG );
227 dpurdie 8317
 
8318
 
8319
#-------------------------------------------------------------------------------
8320
#   
8321
#
261 dpurdie 8322
    MakeHeader ("Tool Search Path",
8323
                "Extend the PATH seen by all the tools to include",
8324
                "The tools/bin directories discovered in Packages" );
8325
    my $put_PATH;
8326
    my $put_LD_LIBRARY_PATH;
8327
    for my $path ( ToolExtensionPaths() )
8328
    {
8329
        MakePrint( "PATH := $path$::ScmPathSep\$(PATH)\n" );
8330
        $put_PATH = 1;
227 dpurdie 8331
 
261 dpurdie 8332
        if ( $::ScmHost eq "Unix" )
8333
        {
227 dpurdie 8334
        MakePrint( "LD_LIBRARY_PATH ?= \n" );
8335
        MakePrint( "LD_LIBRARY_PATH := $path$::ScmPathSep\$(LD_LIBRARY_PATH)\n" );
261 dpurdie 8336
            $put_LD_LIBRARY_PATH =1;
8337
        }
227 dpurdie 8338
    }
8339
 
261 dpurdie 8340
    #   Export the appropriate environment variables
8341
    #   Note: Windows has an issue with PATH and Path
8342
    #         Haven't got to the bottom of it yet, but it would appear that DLL
8343
    #         searching uses Path and other stuff uses PATH. Not too sure how we
8344
    #         end up with two (or more in the environment)
8345
    #
8346
    #
8347
    if ( $put_LD_LIBRARY_PATH )
8348
    {
227 dpurdie 8349
    MakePrint( "export LD_LIBRARY_PATH\n" );
261 dpurdie 8350
    }
227 dpurdie 8351
 
261 dpurdie 8352
    if ( $put_PATH )
8353
    {
227 dpurdie 8354
    MakePrint( "Path := \$(PATH)\n" );
8355
    MakePrint( "export PATH Path\n" );
261 dpurdie 8356
    }
227 dpurdie 8357
 
8358
#-------------------------------------------------------------------------------
8359
#   
8360
#
261 dpurdie 8361
    MakeHeader ("Perl Module Search Path",
8362
                "Extend the PERL5LIB seen by invocations of perl");
227 dpurdie 8363
 
261 dpurdie 8364
    my $perl_module_found;
8365
    for my $path ( ToolExtensionPaths() )
227 dpurdie 8366
    {
261 dpurdie 8367
        if (glob( "$path/*.pm"))
8368
        {
227 dpurdie 8369
        MakePrint( "PERL5LIB := $path$::ScmPathSep\$(PERL5LIB)\n" );
261 dpurdie 8370
            $perl_module_found = 1;
8371
        }
227 dpurdie 8372
    }
261 dpurdie 8373
    if ( $perl_module_found  )
8374
    {
227 dpurdie 8375
    MakePrint( "export PERL5LIB\n" );
261 dpurdie 8376
    }
227 dpurdie 8377
 
261 dpurdie 8378
#-------------------------------------------------------------------------------
8379
#   Internal Helper Functions
8380
#   Creating INCLUDE and LIBRARY paths
8381
#
8382
 
8383
# Assist in creating a list paths
8384
#   $pList  - Reference to an array to which $data will be added
8385
#   $pSeen  - Hash Ref to track tags that have been seen
8386
#   $data   - Data item to add, if tag is defined, but not seen
8387
#   $tag    - Resolved name for item
8388
#
227 dpurdie 8389
    sub PushPath
8390
    {
8391
        my ($pList, $pSeen, $data, $tag) = @_;
8392
        if ( $tag )
8393
        {
8394
            unless ( exists $pSeen->{$tag} )
8395
            {
8396
                $pSeen->{$tag} = 1;
8397
                push @{$pList}, $data;
8398
            }
8399
        }
8400
    }
8401
 
8402
    #
8403
    # Search paths for include files and libraries
8404
    # Currently symbolic paths are created, but there is very little need for this
8405
    #
8406
    sub MakePaths
8407
    {
8408
        my( $root ) = @_;
8409
        my @pathlist;
8410
        my %seen;
8411
 
8412
 
8413
        #   eg. SCA_WIN32   and SCA_WIN32       and SCA_SOLARIS
8414
        #       SCA             WIN32_i386          SPARC
8415
        #       WIN32           SCA                 SCA
8416
        #       .               WIN32               SOLARIS
8417
        #                       .                   .
8418
        #..
8419
        PushPath( \@pathlist, \%seen, "$root/\$(GBE_PLATFORM)",   $ScmPlatform );
8420
        PushPath( \@pathlist, \%seen, "$root/\$(GBE_PRODUCT)",    $ScmProduct );
8421
 
8422
        #
8423
        #   Insert extra path elements found in BUILDPLATFORM_PARTS
8424
        #   These will be present for BuildProduct (XXXX,-Uses=YYYY)
8425
        #   Note: Don't do for LOCAL paths, only INTERFACE
8426
        #
8427
        if ( $root =~ /INTERFACE/ ) {
8428
            my @parts = @{$::BUILDINFO{$ScmPlatform}{PARTS}};
8429
            foreach ( @parts ) {
8430
                PushPath( \@pathlist, \%seen, "$root/$_",   $_ );
8431
            }
8432
        }
8433
 
8434
        PushPath( \@pathlist, \%seen, "$root/\$(GBE_TARGET)",     $ScmTarget );
8435
 
8436
        push @pathlist, "$root";
8437
 
8438
        return \@pathlist;
8439
    }
8440
 
8441
#-------------------------------------------------------------------------------
8442
#   
8443
#
261 dpurdie 8444
    MakeHeader ("Include Search Paths",
8445
                "Local Include Paths" );
227 dpurdie 8446
 
8447
    # Include search path
8448
    #
8449
    #   user-local
8450
    #   local/
8451
    #           see above
8452
    #   interface/
8453
    #           see above
8454
    #   user-global
8455
    #
8456
 
261 dpurdie 8457
    MakeDefEntry ( "\nLINCDIRS",    "=", \@L_INCDIRS );     # .. Local
8458
    MakeDefEntry ( "LINCDIRS",      "+=", MakePaths( '$(INCDIR_LOCAL)' ));     # .. Sandbox interface
8459
    MakeDefEntry ( "LINCDIRS",      "+=", MakePaths( '$(INCDIR_INTERFACE)' )); # .. Sandbox interface
8460
    MakeDefEntry ( "LINCDIRS",      "+=", \@G_INCDIRS );    # .. Global
227 dpurdie 8461
 
261 dpurdie 8462
    MakeDefEntry   ( "INCDIRS",  "= ",  '$(LINCDIRS)' );
8463
    MakeIfDefEntry ( "PINCDIRS", "INCDIRS", "+=", '$(PINCDIRS)' );
8464
    MakeDefEntry   ( "LINCDIRS",    "+=", \@S_INCDIRS );    # .. System
227 dpurdie 8465
 
8466
    # Source search path
8467
 
261 dpurdie 8468
    MakeDefEntry( "\nNODEPDIRS",        "=", \@NODEPDIRS );
227 dpurdie 8469
 
261 dpurdie 8470
    MakeDefEntry( "\nSRCDIRS",          "=" , [ @L_SRCDIRS, @G_SRCDIRS ] );
8471
    MakeIfDefEntry ( "PINCDIRS", "SRCDIRS", "+= ", '$(PINCDIRS)' );
8472
    MakeDefEntry   ( "SRCDIRS",    "+=", \@S_INCDIRS );    # .. System
227 dpurdie 8473
 
8474
    # Library search path
8475
    #
8476
    #   user-local
8477
    #   local/
8478
    #           see above
8479
    #   interface/
8480
    #           see above
8481
    #   user-global
8482
 
261 dpurdie 8483
    MakeDefEntry( "\nLIBDIRS",  "=",  '$(LIBDIR)' );                    # User Local
8484
    MakeDefEntry( "LIBDIRS",    "+=", \@L_LIBDIRS );                    # Local
8485
    MakeDefEntry( "LIBDIRS",    "+=", MakePaths( '$(LIBDIR_LOCAL)' ));  # Sandbox/interface
8486
    MakeDefEntry( "LIBDIRS",    "+=", MakePaths( '$(LIBDIR_INTERFACE)' ));
8487
    MakeDefEntry( "LIBDIRS",    "+=", \@G_LIBDIRS );                    # Global
8488
    MakeIfDefEntry ( "PLIBDIRS", "LIBDIRS", "+= ", '$(PLIBDIRS)' );
8489
    MakeDefEntry( "LIBDIRS",    "+=", \@S_LIBDIRS );                    # System
227 dpurdie 8490
 
8491
#-------------------------------------------------------------------------------
8492
#
8493
#   Subdir creation and deletion
8494
#   Creation is done on the fly
8495
#   Deletion is done AFTER the toolset functions have been invoked to create the
8496
#   build artifacts so that the toolsets can create directories too
8497
 
8498
    MakeHeader ("Subdir creation");
8499
    CreateMkdirRules();
8500
    MkdirRule( "\$(OBJDIR)", 'OBJDIR' );                # Object build directory
8501
    MkdirRule( "\$(OBJDIR)/$_" ) foreach (@SHLIBS);     # Shared library build directory
8502
    MkdirRule( "\$(LIBDIR)", 'LIBDIR' );                # Library directory
8503
    MkdirRule( "\$(BINDIR)", 'BINDIR' );                # Binary directory
8504
 
261 dpurdie 8505
    #
8506
    #   Create a directory for library merge tool to work within
8507
    #
8508
    MkdirRule( "\$(MLIBDIR)", 'MLIBDIR', '--Path=$(GBE_PLATFORM).MRG', '--RemoveAll' ) if (@MLIBS);
8509
 
227 dpurdie 8510
#-------------------------------------------------------------------------------
8511
#   Generate rules and recipes to create all the toolset specific parts
8512
#   This is done fairly early to allow the toolsets to extend various
8513
#   definitions that may be used later in the makefile construction
8514
#
8515
    MakeHeader ("Construct Programs");
8516
 
8517
    foreach my $i ( @PROGS )
8518
    {
289 dpurdie 8519
        my $pProg = $PROGS->Get($i);
8520
        my $pArgs = $pProg->getItems('ARGS');
8521
        my $pObjs = $pProg->getItems('OBJS');
8522
        my $pLibs = $pProg->getItems('LIBS');
227 dpurdie 8523
 
289 dpurdie 8524
        #
8525
        #   Create a list of program object files
8526
        #
8527
        push @PROGOBJS, @$pObjs;
227 dpurdie 8528
 
8529
        MakePrint( "#---- (${i})\n\n" );
8530
        if ( $ScmToolsetProgDependancies )
8531
        {
261 dpurdie 8532
            #
8533
            #   Original style Prog Interface
271 dpurdie 8534
            #   Write some dependency information here and some in the toolset
8535
            #   Problems:
8536
            #       1) Errors in library dependency generation will be
8537
            #          reported after all the object files have been created
8538
            #          Thus the error message and the make-stop are seperated
8539
            #          by many,many lines of output. This makes it difficult
8540
            #          to see the error.
261 dpurdie 8541
            #
271 dpurdie 8542
            #       2) Lack of Flexability
8543
            #
293 dpurdie 8544
            MakeEntry( "\$(BINDIR)/$i$::exe: ", "", "\\\n\t\t", ".$::o ", @$pObjs );
227 dpurdie 8545
        }
8546
        else
8547
        {
261 dpurdie 8548
            #
8549
            #   New Style Prog Interface
8550
            #   The toolset does it all
8551
            #
8552
            #   Flag the progam packaging as a placeholder.
8553
            #   The toolset will replace/update it.
8554
            #
227 dpurdie 8555
            PackageProgRemoveFiles( $i );
8556
        }
8557
 
289 dpurdie 8558
        $if->LD    ( $i, $pArgs, $pObjs, $pLibs );
8559
        $if->LDLINT( $i, $pArgs, $pObjs, $pLibs );
227 dpurdie 8560
    }
8561
 
8562
#-------------------------------------------------------------------------------
8563
#   
8564
#
8565
    MakeHeader ("Construct Test Programs");
289 dpurdie 8566
    foreach my $i ( @TESTPROGS )
227 dpurdie 8567
    {
289 dpurdie 8568
        my $pProg = $TESTPROGS->Get($i);
8569
        my $pArgs = $pProg->getItems('ARGS');
8570
        my $pObjs = $pProg->getItems('OBJS');
8571
        my $pLibs = $pProg->getItems('LIBS');
227 dpurdie 8572
 
289 dpurdie 8573
        #
8574
        #   Create a list of program object files
8575
        #
8576
        push @TESTPROGOBJS, @$pObjs;
8577
 
227 dpurdie 8578
        MakePrint( "#---- (${i})\n\n" );
8579
        if ( $ScmToolsetProgDependancies )
8580
        {
293 dpurdie 8581
            MakeEntry( "\$(BINDIR)/$i$::exe: ", "", "\\\n\t\t", ".$::o ", @$pObjs );
227 dpurdie 8582
        }
8583
        else
8584
        {
8585
            PackageProgRemoveFiles( $i );
8586
        }
8587
 
289 dpurdie 8588
        $if->LD    ( $i, $pArgs, $pObjs, $pLibs );
8589
        $if->LDLINT( $i, $pArgs, $pObjs, $pLibs );
227 dpurdie 8590
    }
8591
 
8592
#-------------------------------------------------------------------------------
8593
#
8594
#
8595
    MakeHeader ("Transfer Scripts to BINDIR");
8596
    foreach my $i ( sort ( values %SCRIPTS ))
8597
    {
8598
        my $tname = "\$(BINDIR)/" . StripDir( $i );
8599
 
8600
 
8601
        MakePrint( "$i:\t\tmakefile.pl\n" .
261 dpurdie 8602
            "\t\$(XX_PRE)if [ ! -f \"$i\" ]; then echo Script [$i] not found; exit 2; fi\n\n" );
227 dpurdie 8603
 
8604
        #
8605
        #   Create a rule to copy the script into the BIN directory
8606
        #   Mark the script as executable - It can't hurt and its there
8607
        #   to be run as part of a test.
8608
        #
8609
        MakePrint "$tname:\t\$(GBE_BINDIR) $i\n" .
8610
                  "\t\$(XX_PRE)\$(cp) -f $i $tname\n" .
8611
                  "\t\$(XX_PRE)\$(chmod) -f +wx $tname\n\n"
8612
    }
8613
 
8614
#-------------------------------------------------------------------------------
8615
#   
8616
#
8617
    MakeHeader ("Construct Libraries");
8618
    foreach my $i ( @LIBS )
8619
    {
289 dpurdie 8620
        my $pLib  = $LIBS->Get($i);
8621
        my $pArgs = $pLib->getItems('ARGS');
8622
        my $pObjs = $pLib->getItems('OBJS');
227 dpurdie 8623
 
299 dpurdie 8624
        Error ("Library has no component objects: $i")
8625
            if ( scalar @$pObjs <= 0 );
8626
 
227 dpurdie 8627
        MakePrint "#---- (${i})\n\n";
289 dpurdie 8628
        $if->AR(     $i, $pArgs, $pObjs, $pLib);
8629
        $if->ARLINT( $i, $pArgs, $pObjs, $pLib );
227 dpurdie 8630
    }
8631
 
289 dpurdie 8632
#-------------------------------------------------------------------------------
8633
#   
8634
#
8635
    MakeHeader ("Construct Merged Libraries");
227 dpurdie 8636
    sub MlibEntry
8637
    {
289 dpurdie 8638
        my( $mlib, $plib, $pLibs ) = @_;
227 dpurdie 8639
        my @flib;
8640
 
289 dpurdie 8641
        MakePrint '$(LIBDIR)/' . GenLibName($mlib) . ":";
8642
        foreach my $lib ( @$pLibs )
227 dpurdie 8643
        {
289 dpurdie 8644
            #
8645
            #   Each library name may contains one embedded option which
8646
            #   specifies the source directory
8647
            #       libname[,--Option | BaseSubdir]
8648
            #
227 dpurdie 8649
            my ($slib, $sdir) = split( ',', $lib );
8650
 
8651
            #
283 dpurdie 8652
            #   By default the librares are pulled from LOCAL unless the
8653
            #   library is built in this directory, in which case it will
289 dpurdie 8654
            #   be used.
227 dpurdie 8655
            #
289 dpurdie 8656
            $sdir = ( $LIBS->Get($slib) ) ? '--Here' : '--Local'
8657
                unless ( $sdir );
227 dpurdie 8658
 
8659
            #
8660
            #   --Interface     - Pull library from the interface directory
8661
            #   --Local         - Pull library from the local directory
8662
            #   --SubDir=xxxx   - Pull library from specified subdirectory
283 dpurdie 8663
            #   --Here          - Pull from local directory if built locally
227 dpurdie 8664
            #   otherwise       - Pull library from specified subdirectory
8665
            #
8666
            if ($sdir eq '--Interface') {
8667
                $sdir = '$(LIBDIR_INTERFACE)/$(GBE_PLATFORM)';
8668
 
8669
            } elsif ( $sdir eq '--Local') {
8670
                $sdir = $PackageInfo{'Lib'}{'IBase'} .  # Base of Installed libs
8671
                        $PackageInfo{'Lib'}{'Dir'};     # Default subdir
8672
 
8673
            } elsif ( $sdir =~ m~^--SubDir=(.*)~ ) {
8674
                $sdir = $1 . '/$(LIBDIR)';
8675
 
283 dpurdie 8676
            } elsif ( $sdir eq '--Here') {
8677
                $sdir = '$(LIBDIR)';
8678
 
227 dpurdie 8679
            } else {
8680
                $sdir .= '/$(LIBDIR)';
8681
            }
8682
 
289 dpurdie 8683
            MakePrint " \\\n\t\t${sdir}/" . GenLibName($slib);
227 dpurdie 8684
            push @flib, "${sdir}/${slib}";
8685
        }
289 dpurdie 8686
        return \@flib;
227 dpurdie 8687
    }
8688
 
8689
    foreach my $i ( @MLIBS )
8690
    {
289 dpurdie 8691
        my $pLib  = $MLIBS->Get($i);
8692
        my $pArgs = $pLib->getItems('ARGS');
8693
        my $pLibs = $pLib->getItems('LIBS');
227 dpurdie 8694
 
261 dpurdie 8695
        MakePrint "#---- (${i})\n\n";
8696
 
227 dpurdie 8697
        unless ( defined &ToolsetARMerge )
8698
        {
8699
            Warning( "Merging of libraries not supported in this toolset yet" );
8700
            Warning( "MergeLibrary: \"$i\" will not be created" );
8701
        }
8702
        else
8703
        {
8704
            #
8705
            #   Create the dependency rule
8706
            #       Target library : source library list
8707
            #           Recipe - generated by the toolset
8708
            #
289 dpurdie 8709
            foreach ( @$pArgs )
227 dpurdie 8710
            {
8711
                Warning( "Ignoring unknown argument to MergeLibrary. $_" );
8712
            }
289 dpurdie 8713
            $pLibs = MlibEntry( $i, $pLib, $pLibs );
8714
            $if->ARMerge( $i, $pArgs, $pLibs, $pLib );
227 dpurdie 8715
        }
8716
    }
8717
 
289 dpurdie 8718
#-------------------------------------------------------------------------------
8719
#   
8720
#
8721
    MakeHeader ("Construct Shared Libraries");
227 dpurdie 8722
    foreach my $i ( @SHLIBS )
8723
    {
289 dpurdie 8724
        my $pShlib  = $SHLIBS->Get($i);
8725
        my $pArgs = $pShlib->getItems('ARGS');
8726
        my $pObjs = $pShlib->getItems('OBJS');
8727
        my $pLibs = $pShlib->getItems('LIBS');
8728
        my $version = $pShlib->{VERSION};
227 dpurdie 8729
 
289 dpurdie 8730
        $if->SHLD    ( $i, $pArgs, $pObjs, $pLibs, $version );
8731
        $if->SHLDLINT( $i, $pArgs, $pObjs, $pLibs, $version );
227 dpurdie 8732
    }
8733
 
8734
#-------------------------------------------------------------------------------
8735
#   Construct Objects
8736
#   For each object within OBJSOURCE construct the following:
8737
#
8738
#   $(OBJDIR)/object-name:     source-name [makefile]
8739
#       Toolset ...
8740
#
8741
#   
8742
#
8743
    MakeHeader ("Construct Objects");
8744
    foreach my $i ( sort keys %OBJSOURCE )
8745
    {
8746
        my( $src, $sname, $ext, $type, @args );
8747
 
8748
        $src  = $OBJSOURCE{ $i };
8749
        $sname = StripDir( $src );
8750
        $ext  = StripFile( $src );
8751
        $ext = lc($ext)
8752
            if ( $::ScmHost ne "Unix" );
8753
        $type = $ScmSourceTypes{ $ext }
8754
            unless (( $type = $SRC_TYPE{ $sname }) );
8755
 
8756
        #
8757
        #   Object source is an object file
8758
        #   No need the generate the object, just create makefile rule
261 dpurdie 8759
        #   [ddp] Not too sure how we get here
227 dpurdie 8760
        #
8761
        if ( $ext eq ".$::o" )
8762
        {
8763
            MakePrint "$src:";
261 dpurdie 8764
            MakePrint " \$(SCM_MAKEFILE)";
227 dpurdie 8765
            MakeNewLine();
8766
            next;
8767
        }
8768
 
8769
        #
8770
        #   Need to create object file
8771
        #
8772
        @args = split( /$;/, $SRC_ARGS{ StripDir( $sname ) } )
8773
            if $SRC_ARGS{ $sname };
8774
 
8775
        push( @args, "--Shared" )
8776
            if ( exists $SHOBJ_LIB{$i} );
8777
 
8778
        #
8779
        #   Convert relative paths to absolute paths if required by the
8780
        #   toolset. Some compilers need ABS paths to generate nice debug
8781
        #   information.
8782
        #
8783
        $src = AbsPath($src)
8784
            if ( $UseAbsObjects );
8785
 
8786
        #
8787
        #   Extract any user specified dependancies
261 dpurdie 8788
        #   These will be added to the dependency list
227 dpurdie 8789
        #
8790
        my @dlist;
8791
        @dlist = split( /$;/, $SRC_DEPEND{$sname} )
8792
            if ( exists $SRC_DEPEND{$sname} );
8793
 
261 dpurdie 8794
        #
8795
        #   Create the dependency part of the object rule
8796
        #   The source file MUST be the first dependent recipes
8797
        #   may assume that $< is the name source file
8798
        #
8799
        MakeEntry( "\$(OBJDIR)/$i.$::o: $src \$(SCM_MAKEFILE)", "", " \\\n\t", "", @dlist );
227 dpurdie 8800
 
8801
        if ( $type eq ".c" ) {
8802
            $if->CC(  $src, $i, \@args );
261 dpurdie 8803
 
227 dpurdie 8804
        } elsif ( $type eq ".cc" ) {
8805
            $if->CXX( $src, $i, \@args );
261 dpurdie 8806
 
227 dpurdie 8807
        } elsif ( $type eq ".asm" ) {
8808
            $if->AS( $src, $i, \@args );
261 dpurdie 8809
 
227 dpurdie 8810
        } else {
8811
            $if->EXT( $src, $i, \@args ) ||
8812
                Warning( "Don't know how to build '$ext' images' for $src, $i" );
8813
            MakeNewLine();
8814
        }
8815
    }
8816
 
8817
#-------------------------------------------------------------------------------
8818
#   Construct Projects
8819
#   Construct toolset specific projects
8820
#
8821
    MakeHeader ("Construct Projects");
8822
    while ( my($project, $entry) = each %PROJECTS)
8823
    {
8824
        $if->PROJECT( $entry );
8825
    }
8826
 
8827
#-------------------------------------------------------------------------------
8828
#   Automated tests
8829
#
8830
    MakeHeader ("Automated tests");
8831
 
8832
    my $idx = 0;
8833
    my @test_set = ("makefile.pl");
8834
    my @test_set_auto = ("makefile.pl");
8835
    my @copy_set = ();
8836
 
8837
    foreach my $pEntry ( @TESTS_TO_RUN )
8838
    {                                           # Foreach test
8839
        $idx++;
8840
        $pEntry->{'index'} = $idx;
8841
        $pEntry->{'test_name'} = "run_test_$idx";
8842
 
8843
        #
8844
        #   If the test is being run within a 'FrameWork' then the underlying
8845
        #   toolset must instantiate the frame work.
8846
        #
8847
        #   This may change. Perhaps frameworks shouldn't be a part of the
8848
        #   toolset. Perhaps they should be standalone. May change
8849
        #
8850
        if ( $pEntry->{framework} )
8851
        {
8852
            $if->TESTFRAMEWORK( $pEntry );
8853
        }
8854
 
8855
        #
8856
        #   Create a rule to run the test
8857
        #
8858
 
8859
        my $tdir_alias = $pEntry->{'testdir'};
8860
        my $tdir = '$(' . $tdir_alias . ')';
8861
 
8862
        my $test_name = $pEntry->{'test_name'};
8863
        push @test_set, $test_name;
8864
        push @test_set_auto, $test_name if ($pEntry->{'auto'} );
8865
 
8866
        my $tprog = $tdir . '/' . StripDir( $pEntry->{'prog'} );
8867
 
8868
        my $me = MakeEntry::New( *MAKEFILE, $test_name, '--Phony' );
8869
        $me->AddDependancy( "\$(GBE_$tdir_alias)" );
8870
        $me->AddDependancy( "\$(INTERFACEDIR)/set_$::ScmPlatform.sh" );
8871
        $me->AddDependancy( $tprog ) if $pEntry->{'copyprog'};
8872
        $me->AddDependancy( @{ $pEntry->{'copyin' } } );
8873
        $me->AddDependancy( map { $tdir . '/' . StripDir($_) } @{ $pEntry->{'copyonce' } } );
8874
        $me->AddDependancy( @{ $pEntry->{'preq'} } );
8875
        $me->RecipePrefix ('$(XX_PRE)');
8876
        $me->RecipeComment( "------ Running test [$idx] ..." );
8877
 
8878
        #
8879
        #   Extend the PATH seen by the script to include the local/bin directory
8880
        #   Allows programs and tests that have been created elsewhere in the component
8881
        #   to be accessed within the script.
8882
        #
8883
        $me->AddShellRecipe ( ". \$(INTERFACEDIR)/set_$::ScmPlatform.sh" );
8884
 
8885
        #
8886
        #   Copy in the files that we need
8887
        #
8888
        foreach my $file ( @{$pEntry->{'copyin'}} )
8889
        {
8890
            my $dst = $tdir . '/' . StripDir( $file );
8891
            UniquePush( \@COPYIN, $dst );
8892
            UniquePush( \@copy_set, $file );
8893
            $me->AddShellRecipe ( "\$(cp) -f $file $dst" );
8894
            $me->AddShellRecipe ( "\$(chmod) -f +wx $dst" );
8895
        }
8896
 
8897
        #
8898
        #   Insert and FrameWork Recipe bits
8899
        #
8900
        $me->AddShellRecipe ( @{$pEntry->{'ShellRecipe'}} );
8901
 
8902
        $me->AddShellRecipe ( "cd $tdir" );
8903
        $me->AddShellRecipe ( ["GBE_TYPE=\$(GBE_TYPE)",
8904
                               "GBE_HOST=\$(GBE_HOST)",
8905
                               "GBE_ROOT=\$(GBE_ROOT_ABS)",
8906
                    		   "PATH=.\\$::ScmPathSep\$(BINDIR_LOCAL_PATH)\\$::ScmPathSep\$\$PATH",
8907
                               $pEntry->{'command'},
8908
                               @{$pEntry->{'args'}},
8909
                               ] );
8910
        $me->Print();
8911
 
8912
 
8913
        #
8914
        #   Create entries to handle the copy-once files
8915
        #
8916
        foreach my $file ( @{ $pEntry->{'copyonce' } } )
8917
        {
8918
            my $tname = $tdir . '/' . StripDir($file);
8919
            my $me = MakeEntry::New( *MAKEFILE, $tname  );
8920
            $me->AddDependancy( $file );
8921
            $me->AddRecipe ( "\$(call CopyFile,CopyIn,$tname,$file,$tdir,)"  );
8922
            $me->Print();
8923
 
8924
            UniquePush( \@COPYIN, $tname );
8925
            UniquePush( \@copy_set, $file );
8926
 
8927
        }
8928
    }
8929
 
8930
    #
8931
    #   Generate a target that specifies the tests to be run
8932
    #   Each test is provided with a dummy name
8933
    #
8934
    push @test_set, @TESTPROJECT_TO_ARUN;
8935
    push @test_set, @TESTPROJECT_TO_URUN;
8936
    MakeEntry3("\nrun_tests", ":", \@test_set )
8937
        if (@test_set);
8938
 
8939
    push @test_set_auto, @TESTPROJECT_TO_ARUN;
8940
    MakeEntry3("\nrun_unit_tests", ":", \@test_set_auto )
8941
        if (@test_set_auto);
8942
 
8943
    #
8944
    #   Generate sanity test for each copyin script
8945
    #   Simply to provide a nice error message for generated scripts
8946
    #   that do not exist at run-time
8947
    #
8948
    test_copy_in:
8949
    foreach my $i ( @copy_set )
8950
    {
8951
        next if ( $SCRIPTS{$i} );
8952
        foreach (  @SHLIB_TARGETS )
8953
        {
8954
            next test_copy_in if ( $i eq $_ );
8955
        }
8956
        MakePrint( "\n$i:\t\tmakefile.pl\n" .
8957
            "\t\@if [ ! -f \"$i\" ]; then echo ERROR: CopyIn Script [$i] not found; exit 2; fi\n" );
8958
    }
8959
 
261 dpurdie 8960
#-------------------------------------------------------------------------------
8961
#   Deploy rules
8962
#
8963
MakeHeader ("Deploy Rules");
227 dpurdie 8964
 
261 dpurdie 8965
print MAKEFILE <<EOF;
8966
.PHONY:		run_deploy
8967
EOF
227 dpurdie 8968
 
261 dpurdie 8969
#
8970
#   Build up the deployfile.pl command line from the available pieces
8971
#
8972
my $command_file = "";
8973
my @command_line;
8974
 
8975
if ( %DEPLOYPACKAGE )
8976
{
8977
    $command_file = $DEPLOYPACKAGE{'cmdfile'};
8978
 
8979
    push @command_line, "\$(XX_PRE)\$(GBE_PERL) -w $command_file";
8980
    push @command_line, "-r \"\$(GBE_ROOT)\"";
8981
    push @command_line, "-n \"$DEPLOYPACKAGE{'name'}\"";
8982
    push @command_line, "-d \"$DEPLOYPACKAGE{'dir'}\"";
8983
    push @command_line, "-v \"\$(BUILDVER)\"";
8984
    push @command_line, "-t \"\$(GBE_TYPE)\"";
8985
    push @command_line, "-o \"\$(BUILDPREVIOUSVER)\"";
8986
    push @command_line, "-m \"\$(GBE_PLATFORM)\"";
8987
    push @command_line, "-g \"\$(GBE_TARGET)\"";
8988
    push @command_line, "-k \"\$(GBE_PRODUCT)\""        if ( $ScmProduct );
8989
    push @command_line, "-p \"\$(DEPLOYPATCH)\""        if ( $ScmDeploymentPatch );
8990
 
8991
}
8992
 
8993
MakeEntry( "run_deploy:\t$command_file\n", "\n", "\t\t", " \\\n", @command_line );
8994
 
227 dpurdie 8995
#-------------------------------------------------------------------------------
261 dpurdie 8996
#   Custom Rules
8997
#
8998
    MakeHeader ("Custom Rules");
8999
    MakePrintList ( \@RULES );
9000
 
9001
#-------------------------------------------------------------------------------
9002
#   Generated Files
9003
#
9004
    MakeHeader ("Generated Files");
9005
    MakePrint ("\n.PHONY: phony_generate\n\n" );
9006
 
9007
    foreach my $i ( @GENERATE_FILES )
9008
    {
9009
        my $gen_tag = $i->{'index'};
9010
 
9011
        #
263 dpurdie 9012
        #   If predelete is enabled, then create a list of files to delete
9013
        #
9014
        if ( $i->{'predelete'}  )
9015
        {
9016
            MakeDefEntry( "generate_gen_$gen_tag", "=",  $i->{'gen'} );
9017
            MakePrint("\n")
9018
        }
9019
 
9020
 
9021
        #
261 dpurdie 9022
        #   Generate the basic generate rule and recipe
9023
        #   together with the prerequisites
9024
        #
9025
        MakeEntry ( "", ":", "", " ", @{$i->{'gen'}} );
9026
 
9027
        unless ( $i->{'clean'} && $i->{'shell'} )
9028
        {
9029
            MakeEntry ( "", "", " \\\n\t\t", "", @{$i->{'preq'}} );
9030
            MakeEntry ( "", "", " \\\n\t\t", "", "phony_generate" ) if $i->{'preq_sus'};
9031
            MakeEntry ( "", "", " \\\n\t\t", "", "\$(SCM_MAKEFILE)" );
9032
 
9033
            MakePrint ("\n\t" . "\@\$(echo) [$i->{'text'}] generating.." );
263 dpurdie 9034
            if ( $i->{'predelete'}  )
9035
            {
9036
                MakePrint ("\n\t" . "\$(XX_PRE)\$(call RmFiles,generate_gen_$gen_tag)" );
9037
            }
261 dpurdie 9038
            MakePrint ("\n\t" . "\$(XX_PRE)\$(call generate_$gen_tag,)" );
9039
        }
9040
 
9041
        #
9042
        #   Generate 'clean' rules and recipes
9043
        #
9044
        if ( $i->{'clean'} )
9045
        {
9046
            MakePrint ("\n\nPHONY: clean_generate_$gen_tag" );
9047
            MakePrint ("\nclean_generate_$gen_tag:" );
9048
            MakePrint ("\n\t" . "\@\$(call generate_$gen_tag,$i->{'clean'})" );
9049
        }
9050
 
9051
        #
9052
        #   Define a function to contain the body of the generation call
9053
        #   The first argument will be a 'clean' argument
9054
        #
9055
        MakePrint ("\n\ndefine generate_$gen_tag" );
9056
        if ( $i->{'shell'} )
9057
        {
9058
            MakeEntry ("\n\t(" , "\\\n\t)\n", " \\\n\t", ";" , @{$i->{'toolargs'}} );
9059
        }
9060
        else
9061
        {
9062
            MakeEntry ("\n\t" . $i->{'tool'} . ' $1', "\n", " \\\n\t\t", "" , @{$i->{'toolargs'}} );
9063
        }
9064
        MakePrint ("endef\n\n" );
9065
    }
9066
 
9067
#-------------------------------------------------------------------------------
9068
#   Toolset Post Processing
9069
#   Allow the toolset to perform any post processing, before we finally write
9070
#   out any definitions.
9071
#
9072
#   We will not interprete any more user directives, but new stuff may get added
9073
#
9074
#
9075
MakeHeader ("Toolset Post Processing");
9076
$if->Postprocess();
9077
 
9078
################################################################################
9079
#   All interactions with the toolset are now complete
9080
#   All lists are now complete
9081
#
9082
#   Can now create internal definitions
9083
#   
9084
################################################################################
9085
 
9086
    #
9087
    #   Would be nice if this would work
9088
    #   Unfortunatelty we still need $if for the CCDEPENDS and CTAGS work
9089
    #   These must be defined AFTER the definitions
9090
    #
9091
    #   Ideally we should construct our makefile in sections
9092
    #   and then we can order the sections when we write them out
9093
    #
9094
#$if = 0;                            # Ensure the MakeIf class is not called
9095
                                     # If this file is modified
9096
 
9097
#-------------------------------------------------------------------------------
227 dpurdie 9098
#   Sources
9099
#
9100
MakeHeader  ( "Sources");
9101
MakeDefEntry( "CSRCS",      "=",  \@CSRCS );
9102
MakeDefEntry( "CXXSRCS",    "=",  \@CXXSRCS );
9103
MakeDefEntry( "ASSRCS",     "=",  \@ASSRCS );
9104
 
9105
#-------------------------------------------------------------------------------
9106
#   Generated, Installed and Packaged components
9107
#
9108
MakeHeader  ("Generated, Installed and Packaged components");
9109
MakeDefEntry( "INITS",           "=",  \@INITS )   if ( @INITS );
9110
MakeDefEntry( "GENERATED",       "=",  \@GENERATED ) if ( @GENERATED );
9111
MakeDefEntry( "GENERATED_NOTSRC","=",  \@GENERATED_NOTSRC ) if ( @GENERATED_NOTSRC );
9112
MakeDefEntry( "GENERATEDCLEAN",  "=",  CreateNameList( 'clean_generate_', '', ListCleanGenerated() ));
9113
MakeDefEntry( "INSTALL_HDRS",    "=",  \%INSTALL_HDRS ) if ( %INSTALL_HDRS );
9114
MakeDefEntry( "INSTALL_CLSS",    "=",  \%INSTALL_CLSS ) if ( %INSTALL_CLSS );
9115
MakeDefEntry( "OBJS",            "=", CreateNameList( '$(OBJDIR)/', ".$::o", \@OBJS) );
9116
MakeDefEntry( "SHOBJS",          "=", CreateNameList( '$(OBJDIR)/', ".$::o", \%SHOBJ_LIB ));
289 dpurdie 9117
MakeDefEntry( "PROGOBJS",        "=", CreateNameList( '', ".$::o", \@PROGOBJS ));
9118
MakeDefEntry( "TESTPROGOBJS",    "=", CreateNameList( '', ".$::o", \@TESTPROGOBJS ));
9119
MakeDefEntry( "LIBS",            "=", $LIBS->AllTargets() ) if ($::a);
9120
MakeDefEntry( "MLIBS",           "=", $MLIBS->AllTargets() ) if ($::a);
227 dpurdie 9121
MakeDefEntry( "SHNAMES",         "=", \@SHLIBS );
9122
MakeDefEntry( "SHDIRS",          "=", CreateNameList( '$(OBJDIR)/', "", \@SHLIBS ));
9123
MakeDefEntry( "SHLIBS",          "=", \@SHLIB_TARGETS );
9124
MakeDefEntry( "SCRIPTS",         "=", CreateNameList( '$(BINDIR)/', "", \%SCRIPTS ));
9125
MakeDefEntry( "COPYIN",          "=", \@COPYIN );
289 dpurdie 9126
MakeDefEntry( "PROGS",           "=", $PROGS->AllTargets() );
227 dpurdie 9127
MakeDefEntry( "PROGS_EXTRA",     "=", \@PROGS_EXTRA );
289 dpurdie 9128
MakeDefEntry( "TESTPROGS",       "=", $TESTPROGS->AllTargets());
227 dpurdie 9129
MakeDefEntry( "LINTLIBS",        "=", CreateNameList( 'lib_', '_lint', \@LINTLIBS ));
9130
MakeDefEntry( "LINTSHLIBS",      "=", CreateNameList( 'shlib_', '_lint', \@LINTSHLIBS ));
9131
MakeDefEntry( "LINTPROGS",       "=", CreateNameList( 'prog_', '_lint', \@PROGS ));
289 dpurdie 9132
MakeDefEntry( "LINTPROGS",      "+=", CreateNameList( 'prog_', '_lint', \@TESTPROGS ));
227 dpurdie 9133
MakeDefEntry( "PROJECTS",        "=", CreateNameList( 'Project_', '', ListGeneratedProjects(1) ));
9134
MakeDefEntry( "PROJECTSGEN",     "=", CreateNameList( 'Project_', '', ListGeneratedProjects(0) ));
9135
MakeDefEntry( "PROJECTSCLEAN",   "=", CreateNameList( 'ProjectClean_', '', \%PROJECTS ));
9136
 
261 dpurdie 9137
MakeHeader ("Toolset components");
9138
MakeDefEntry( "USERGENERATED",        "=", \@USERGENERATED )    if ( @USERGENERATED );
9139
MakeDefEntry( "TOOLSETGENERATED",     "=", \@TOOLSETGENERATED ) if ( @TOOLSETGENERATED );
9140
MakeDefEntry( "TOOLSETOBJS",          "=", \@TOOLSETOBJS )      if ( @TOOLSETOBJS );
9141
MakeDefEntry( "TOOLSETLIBS",          "=", \@TOOLSETLIBS )      if ( @TOOLSETLIBS );
9142
MakeDefEntry( "TOOLSETPROGS",         "=", \@TOOLSETPROGS )     if ( @TOOLSETPROGS );
9143
MakeDefEntry( "TOOLSETDIRS",          "=", \@TOOLSETDIRS )      if ( @TOOLSETDIRS );
9144
MakeDefEntry( "TOOLSETDIRTREES",      "=", \@TOOLSETDIRTREES )  if ( @TOOLSETDIRTREES );
227 dpurdie 9145
 
9146
#--------- Determine compiler flag groups to use ----------------------------
9147
#
9148
#   Allows the compiler options to be controlled for both the debug and
9149
#   the production builds. Allows control over
9150
#       1) Optimisations
9151
#       2) Debug Information
9152
#
9153
MakeHeader ("Determine compiler flag groups to use");
9154
 
9155
print MAKEFILE <<EOF;
9156
 
9157
ifneq "\$(DEBUG)" "1"
9158
USE_OPTIMISE	:= \$(PROD_USE_OPTIMISE)
9159
USE_DEBUGINFO	:= \$(PROD_USE_DEBUGINFO)
9160
else
9161
USE_OPTIMISE	:= \$(DEBUG_USE_OPTIMISE)
9162
USE_DEBUGINFO	:= \$(DEBUG_USE_DEBUGINFO)
9163
endif
9164
 
9165
EOF
9166
 
261 dpurdie 9167
#-------------------------------------------------------------------------------
9168
#   Source browsing tools
9169
#
9170
MakeHeader ("Source browsing tools");
9171
    print MAKEFILE <<EOF;
9172
.PHONY:			ctags
9173
ctags:
9174
EOF
9175
    $if->CTAGS()
9176
        if (@CSRCS || @CXXSRCS);
227 dpurdie 9177
 
261 dpurdie 9178
#-------------------------------------------------------------------------------
9179
#   Depend
9180
#   If we are build C or C++ source files then create rules and recipes
9181
#   to invoke a dependency generator.
227 dpurdie 9182
#
261 dpurdie 9183
#   NODEPEND is used to disable, at make-time, the dependency generation
9184
#   and inclusion process.
9185
#
9186
#
9187
MakeHeader ("Depend");
9188
if ($::o && (@CSRCS || @CXXSRCS))
9189
{
9190
    $ScmDependTags = 1;
9191
    print MAKEFILE <<EOF;
9192
depend:			\$(OBJDIR)/depend
9193
 
9194
\$(OBJDIR)/depend:	\$(SCM_MAKEFILE) \$(GBE_OBJDIR)
9195
\$(OBJDIR)/depend:	\$(CSRCS) \$(CXXSRCS)
9196
ifeq (\$(NODEPEND),0)
9197
	\@echo [\$@] Doing a make depend..
9198
	-\$(XX_PRE)\$(rm) -f \$(OBJDIR)/depend
9199
EOF
9200
    $if->CCDepend( "\$(OBJDIR)/depend", "\$(CSRCS)" )
9201
        if ( @CSRCS );
9202
    $if->CXXDepend( "\$(OBJDIR)/depend", "\$(CXXSRCS)" )
9203
        if ( @CXXSRCS );
9204
    MakePrint
9205
        "\t-\@\$(touch) -f \$(OBJDIR)/depend\n";
9206
    print MAKEFILE <<EOF;
9207
else
9208
	\@echo [\$@] Skipping make depend..
9209
	-\$(XX_PRE)\$(rm) -f \$(OBJDIR)/depend
9210
endif
9211
EOF
9212
}
9213
else
9214
{
9215
    print MAKEFILE <<EOF;
9216
depend:
9217
EOF
9218
}
9219
 
9220
#
9221
#   Rule to unmake the depend file
9222
#
9223
    print MAKEFILE <<EOF;
9224
 
9225
undepend:
9226
	-\$(XX_PRE)\$(rm) -f \$(OBJDIR)/depend
9227
EOF
9228
 
9229
#--------- IFLAG Documentation -------------------------------------------------
9230
#
9231
#   IFLAG - iteration flag. This is setting by the calling process
9232
#                           and is a function of the phase being processed
227 dpurdie 9233
#       0   No external dependencies.
9234
#       1   Source dependency list.
261 dpurdie 9235
#       2   Shared library dependency list
9236
#       3   Application dependency list
227 dpurdie 9237
#
9238
#
261 dpurdie 9239
#--------- Dependencies --------------------------------------------------------
9240
#   Include the 'depend' file if required
9241
#
9242
    MakeHeader ("Dependency Inclusion");
9243
    print MAKEFILE <<EOF;
9244
ifeq (\$(NODEPEND),0)
9245
 ifdef IFLAG
9246
  ifneq "\$(IFLAG)" "0"
9247
-include	\$(OBJDIR)/depend
9248
  endif
227 dpurdie 9249
 endif
9250
endif
9251
 
9252
EOF
9253
 
9254
#-------------------------------------------------------------------------------
9255
#   Standard rules
9256
#
9257
MakeHeader ("Standard rules");
9258
 
9259
    print MAKEFILE <<EOF;
9260
.PHONY:		make_usage
9261
make_usage:
9262
	\@echo -e \\
9263
	" make [SHOWENV=1] [LEAVETMP=1] [OPTIONS=[opt][,...]] {DEBUG=0|1} target(s)\\n"\\
9264
	"\\n"\\
9265
	"Build one or more of the following targets for the platform\\n"\\
9266
	"$ScmPlatform, recursively checking each configured sub directories.\\n"\\
9267
	"\\n"\\
9268
	"Valid targets include:\\n"\\
9269
	"  all:             build, install and package\\n"\\
9270
	"  build:           build everything\\n"\\
9271
	"  debug:           build all things for debug\\n"\\
9272
	"  prod:            build all things for production\\n"\\
9273
	"  install:         install of public usage\\n"\\
9274
	"  depend:          construct the dependencies\\n"\\
9275
	"  lint:            lints C and C++ source\\n"\\
9276
	"  package:         build all packages\\n"\\
9277
	"  package-{set}:   build specific package\\n"\\
9278
	"  unpackage:       remove all packages\\n"\\
9279
	"  run_tests:       Run the tests specified in the makefile\\n"\\
9280
	"  run_unit_tests:  Run the automatic unit tests specified in the makefile\\n"\\
9281
	"  deploy:          Run the deployment scripts\\n"\\
9282
	"  rmlitter:        remove litter (core, bak, tmp, err and cmd files)\\n"\\
9283
	"  clean:           delete generate, obj, libraries and programs\\n"\\
9284
	"  unbuild:         delete everything which can be remade\\n"\\
9285
	"  clobber:         unbuilds and deletes packages\\n"\\
9286
EOF
9287
 
9288
    print MAKEFILE <<EOF;
9289
	"\\n"
9290
 
9291
make_clean:
9292
	-\@echo "Removing generated files (objects, libraries, binaries etc)";
9293
 
9294
#
9295
#   Under windows/cygwin, there is a problem with the rm being used
9296
#   The expansion of wildcards will terminate the command if:
9297
#       1) No files exist to expand  : Solution : touch a file of that type
9298
#       2) A directory is involved   : Solution : cd to directory
9299
#
9300
#   Cannot use make's wildcard function as this only operates in the current directory
9301
#
9302
.PHONY:		rmlitter
9303
rmlitter:
315 dpurdie 9304
	-\$(AA_PRE)( echo "Removing litter";\\
227 dpurdie 9305
		\$(touch) _delete.bak _delete.tmp _delete.err ;\\
9306
		\$(rm) -f core *.bak *.tmp *.err ;\\
293 dpurdie 9307
		for subdir in \$(SHDIRS) '' ; do \\
9308
			if [ -d "\$\$subdir" ] ; then \\
227 dpurdie 9309
				( cd \$\$subdir ;\\
9310
				\$(touch) _delete.err _delete.cmd ;\\
289 dpurdie 9311
				\$(rm) -r * ; );\\
9312
			fi ;\\
9313
		done;\\
293 dpurdie 9314
		for subdir in \$(OBJDIR) '' ; do \\
9315
			if [ -d "\$\$subdir" ] ; then \\
289 dpurdie 9316
				( cd \$\$subdir ;\\
9317
				\$(touch) _delete.err _delete.cmd ;\\
227 dpurdie 9318
				\$(rm) -r *.err *.cmd ; );\\
9319
			fi ;\\
9320
		done;\\
9321
	)
9322
 
261 dpurdie 9323
.PHONY:		lint_init
9324
lint_init:
9325
 
227 dpurdie 9326
EOF
9327
 
261 dpurdie 9328
#
9329
#   Dependencies for 'make_init'
9330
#
9331
#
9332
my @initdep;
9333
push @initdep, '$(INITS)' if ( @INITS );
227 dpurdie 9334
 
261 dpurdie 9335
#
9336
#   Dependencies for 'make_dir'
9337
#
9338
my @mkdirdep;
289 dpurdie 9339
push @mkdirdep, '$(GBE_OBJDIR)' if ( @CSRCS || @CXXSRCS || @OBJS || @PROGOBJS || @TESTPROGOBJS );
261 dpurdie 9340
push @mkdirdep, '$(SHDIRS)'     if ( %SHOBJ_LIB || @SHLIBS);
9341
push @mkdirdep, '$(GBE_LIBDIR)' if ( @LIBS || @MLIBS || @SHLIBS || %INSTALL_LIBS || %PACKAGE_LIBS );
289 dpurdie 9342
push @mkdirdep, '$(GBE_BINDIR)' if ( @SHLIBS || %SCRIPTS || @PROGS || @TESTPROGS || %INSTALL_PROGS || %PACKAGE_PROGS );
227 dpurdie 9343
 
261 dpurdie 9344
#
9345
#   Actions for for 'unobj'
9346
#
9347
my @unobjact;
9348
push @unobjact, RmFilesCmd( 'OBJS' )            if ( @OBJS );
9349
push @unobjact, RmFilesCmd( 'SHOBJS' )          if ( %SHOBJ_LIB );
9350
push @unobjact, RmFilesCmd( 'PROGOBJS' )        if ( @PROGOBJS );
289 dpurdie 9351
push @unobjact, RmFilesCmd( 'TESTPROGOBJS' )    if ( @TESTPROGOBJS );
261 dpurdie 9352
push @unobjact, RmFilesCmd( 'TOOLSETOBJS' )     if ( @TOOLSETOBJS );
227 dpurdie 9353
 
261 dpurdie 9354
#
9355
#   Dependencies for 'make_lib'
9356
#
9357
my @libdep;
9358
push @libdep, '$(GBE_OBJDIR)', '$(GBE_LIBDIR)', '$(LIBS)' if ( @LIBS );
227 dpurdie 9359
 
261 dpurdie 9360
#
9361
#   Dependencies for 'lint_lib'
9362
#
9363
my @liblintdep;
9364
push @liblintdep, 'lint_init', '$(GBE_OBJDIR)', '$(GBE_LIBDIR)', '$(LINTLIBS)' if ( @LIBS );
227 dpurdie 9365
 
261 dpurdie 9366
#
9367
#   Dependencies for 'make_mlib'
9368
#
9369
my @mlibdep;
9370
push @mlibdep, '$(GBE_OBJDIR)', '$(GBE_LIBDIR)', '$(GBE_MLIBDIR)', '$(MLIBS)' if ( @MLIBS );
227 dpurdie 9371
 
261 dpurdie 9372
#
9373
#   Dependencies for 'make_install_shlib' (tag)
9374
#
9375
my @shlibdep;
9376
push @shlibdep, '$(SHDIRS)', '$(SHLIBS)' if ( @SHLIBS );
227 dpurdie 9377
 
261 dpurdie 9378
#
9379
#   Dependencies for 'lint_shlib'
9380
#
9381
my @shliblintdep;
9382
push @shliblintdep, 'lint_init', '$(GBE_LIBDIR)', '$(LINTSHLIBS)' if ( @SHLIBS );
227 dpurdie 9383
 
261 dpurdie 9384
#
9385
#   Actions for 'unmake_lib'
9386
#
9387
my @unlibact;
9388
push @unlibact, RmFilesCmd( 'SHLIBS' )      if ( @SHLIBS );
9389
push @unlibact, RmFilesCmd( 'MLIBS' )       if ( @MLIBS );
9390
push @unlibact, RmFilesCmd( 'LIBS' )        if ( @LIBS );
9391
push @unlibact, RmFilesCmd( 'TOOLSETLIBS' ) if ( @TOOLSETLIBS );
227 dpurdie 9392
 
261 dpurdie 9393
#
9394
#   Actions for 'unmake_mlib'
9395
#
9396
my @unmlibact;
9397
push @unmlibact, RmFilesCmd( 'MLIBS' ) if ( @MLIBS );
227 dpurdie 9398
 
261 dpurdie 9399
#
9400
#   Dependencies for 'make_script'
9401
#
9402
my @scriptdep;
9403
push @scriptdep, '$(GBE_BINDIR)', '$(SCRIPTS)' if ( %SCRIPTS );
227 dpurdie 9404
 
261 dpurdie 9405
#
9406
#   Actions for 'unmake_script'
9407
#
9408
my @unscriptact;
9409
push @unscriptact , RmFilesCmd( 'SCRIPTS' ) if ( %SCRIPTS );
9410
push @unscriptact , RmFilesCmd( 'COPYIN' )  if ( @COPYIN );
227 dpurdie 9411
 
261 dpurdie 9412
#
9413
#   Dependencies for 'make_prog'
9414
#
9415
my @progdep;
9416
push @progdep, '$(GBE_OBJDIR)', '$(GBE_BINDIR)', '$(PROGS)' if ( @PROGS );
9417
push @progdep, '$(PROGS_EXTRA)' if (@PROGS_EXTRA);
227 dpurdie 9418
 
261 dpurdie 9419
#
9420
#   Dependencies for 'make_prog' created for 'projects'
9421
#
9422
my @projectdep;
9423
push @projectdep, '$(PROJECTS)' if (ListGeneratedProjects(1) );
227 dpurdie 9424
 
261 dpurdie 9425
#
9426
#   Dependencies for 'generate' created for 'projects'
9427
#
9428
my @projectgendep;
9429
push @projectgendep, '$(PROJECTSGEN)' if (ListGeneratedProjects(0) );
227 dpurdie 9430
 
261 dpurdie 9431
#
9432
#   Dependencies for 'unmake_prog' created for 'projects'
9433
#
9434
my @projectcleandep;
9435
push @projectcleandep, '$(PROJECTSCLEAN)' if (%PROJECTS);
227 dpurdie 9436
 
261 dpurdie 9437
#
9438
#   Dependencies for 'lint_prog'
9439
#
9440
my @proglintdep;
289 dpurdie 9441
push @proglintdep, 'lint_init', '$(GBE_OBJDIR)', '$(GBE_BINDIR)', '$(LINTPROGS)' if ( @PROGS || @TESTPROGS );
227 dpurdie 9442
 
261 dpurdie 9443
#
9444
#   Actions for 'unmake_prog'
9445
#
9446
my @unprogact;
9447
push @unprogact, RmFilesCmd( 'PROGS' )        if ( @PROGS );
9448
push @unprogact, RmFilesCmd( 'TOOLSETPROGS' ) if ( @TOOLSETPROGS );
227 dpurdie 9449
 
261 dpurdie 9450
#
9451
#   Dependencies for 'lint_prog'
9452
#
9453
my @testprogdep;
289 dpurdie 9454
push @testprogdep, '$(GBE_OBJDIR)', '$(GBE_BINDIR)', '$(TESTPROGS)' if ( @TESTPROGS );
227 dpurdie 9455
 
9456
#
261 dpurdie 9457
#   Dependencies for 'run_tests' and friends
9458
#
9459
my @untestprogact;
289 dpurdie 9460
push @untestprogact ,RmFilesCmd( 'TESTPROGS' ) if ( @TESTPROGS );
227 dpurdie 9461
 
261 dpurdie 9462
#
9463
#   Dependencies for 'generated'
9464
#
9465
my @generatedep;
9466
push @generatedep, '$(GENERATED)' if ( @GENERATED );
9467
 
9468
#
9469
#   Actions for 'ungenerate'
9470
#
9471
my @ungenact;
9472
push @ungenact, RmFilesCmd( 'GENERATED' ) if ( @GENERATED );
9473
push @ungenact, RmFilesCmd( 'GENERATED_NOTSRC' ) if ( @GENERATED_NOTSRC );
9474
push @ungenact, RmFilesCmd( 'TOOLSETGENERATED' ) if ( @TOOLSETGENERATED );
9475
push @ungenact, RmFilesCmd( 'USERGENERATED' ) if ( @USERGENERATED );
9476
 
9477
#
9478
#   Dependencies for 'ungenerate'
9479
#
9480
my @ungeneratedep;
9481
push @ungeneratedep, '$(GENERATEDCLEAN)';
9482
 
227 dpurdie 9483
#-------------------------------------------------------------------------------
261 dpurdie 9484
# Function        : PrintPhonyRule
227 dpurdie 9485
#
261 dpurdie 9486
# Description     : Helper function to print some internal phony makefile targets
9487
#                   These are used to hold the basic makefile together
9488
#
9489
# Inputs          : $target         - Name of the phony target
9490
#                   $prereq         - Prerequisites
9491
#                                     Leading spaces removed
9492
#                   $recipe         - Optional Reference to an array of recipes
9493
#                                     Will be printed one per line
9494
#
9495
#
9496
sub PrintPhonyRule
227 dpurdie 9497
{
261 dpurdie 9498
    my ($target, $prereq, $recipe) = @_;
9499
    $prereq =~ s/^\s+//;
227 dpurdie 9500
 
261 dpurdie 9501
    MakePadded( 2, '.PHONY:', $target, "\n");
9502
    MakePadded( 2,"$target:", $prereq, "\n");
9503
    MakePrint ("\t\t" . $_ . "\n") foreach ( @{$recipe} );
9504
    MakePrint ("\n");
227 dpurdie 9505
}
9506
 
261 dpurdie 9507
#   make_init - Test toolset presence and sanity
9508
#   Will only be called ONCE for each platform in a recursive build
9509
#   Should be used to ensure that the required toolset is present
9510
#
9511
PrintPhonyRule ('make_init',       "@initdep" );
227 dpurdie 9512
 
261 dpurdie 9513
#   make_dir    - Create required subdirectories
9514
#   Will be invoked as a part of most targets that create files
9515
#   Will be invoked by the calling wrappers
9516
#   Should not be invoked when cleaning
9517
#
9518
PrintPhonyRule ('make_dir',       "@mkdirdep" );
9519
 
9520
 
9521
PrintPhonyRule ('generate',       "@generatedep @projectgendep" );
9522
PrintPhonyRule ('ungenerate',     "@ungeneratedep",  \@ungenact);
9523
PrintPhonyRule ('unobj',          "",  \@unobjact);
9524
PrintPhonyRule ('make_lib',       "@libdep" );
9525
PrintPhonyRule ('lint_lib',       "@liblintdep" );
9526
PrintPhonyRule ('make_mlib',      "@mlibdep" );
9527
PrintPhonyRule ('lint_shlib',     "@shliblintdep" );
9528
PrintPhonyRule ('unmake_lib',     "", \@unlibact );
9529
PrintPhonyRule ('unmake_mlib',    "", \@unmlibact );
9530
PrintPhonyRule ('make_script',    "@scriptdep" );
9531
PrintPhonyRule ('unmake_script',  "", \@unscriptact );
9532
PrintPhonyRule ('make_prog',      "@scriptdep @progdep @projectdep" );
9533
PrintPhonyRule ('lint_prog',      "@proglintdep" );
9534
PrintPhonyRule ('run_tests',      "@scriptdep @testprogdep" );
9535
PrintPhonyRule ('run_unit_tests', "@scriptdep @testprogdep" );
9536
PrintPhonyRule ('unmake_prog',    "unmake_script @projectcleandep", \@unprogact );
9537
PrintPhonyRule ('make_test',      "@scriptdep @testprogdep" );
9538
PrintPhonyRule ('unmake_test',    "unmake_script", \@untestprogact );
9539
 
227 dpurdie 9540
#-------------------------------------------------------------------------------
9541
#   Package and Installation Summary
9542
#
9543
    MakeHeader ("Package and Installation Summary");
9544
    sub InstallTarget
9545
    {
9546
        my( $target, $hashp, $prereq, $fprereq ) = @_;
9547
        my( $element );
9548
 
9549
        MakePrint "$target:";
9550
        MakePrint "\t$fprereq" if ($fprereq);
9551
 
9552
        foreach my $element ( sort keys %{$hashp} )
9553
        {
9554
            #
9555
            #   Skip placekeepers
9556
            #
9557
            next if ( $hashp->{$element}{'placekeeper'} );
9558
 
9559
            #
9560
            #   Prepend any prerequisites (once)
9561
            #
9562
            if ( $prereq )
9563
            {
9564
                MakePrint " \\\n\t${prereq}";
9565
                $prereq = 0;
9566
            }
9567
 
9568
            MakePrint " \\\n\t${element}";
9569
        }
9570
        MakePrint "\n\n";
9571
    }
9572
 
9573
InstallTarget( "install_hdr",       \%INSTALL_HDRS );
9574
InstallTarget( "install_lib",       \%INSTALL_LIBS,  'make_mlib' );
261 dpurdie 9575
InstallTarget( "make_install_shlib",\%INSTALL_SHLIBS, '', "@shlibdep" );
227 dpurdie 9576
InstallTarget( "install_prog",      \%INSTALL_PROGS, 'make_script' );
9577
InstallTarget( "install_class",     \%INSTALL_CLSS );
9578
 
9579
InstallTarget( "package_files",     \%PACKAGE_FILES );
9580
InstallTarget( "package_hdr",       \%PACKAGE_HDRS );
9581
InstallTarget( "package_lib",       \%PACKAGE_LIBS );
9582
InstallTarget( "package_shlib",     \%PACKAGE_SHLIBS );
9583
InstallTarget( "package_prog",      \%PACKAGE_PROGS, 'make_script' );
9584
InstallTarget( "package_class",     \%PACKAGE_CLSS );
9585
 
9586
#-------------------------------------------------------------------------------
9587
#   Installations
9588
 
9589
MakeHeader ("Installations");
9590
PackageRule ( \&InstallCmd, \%INSTALL_HDRS  );
9591
PackageRule ( \&InstallCmd, \%INSTALL_CLSS  );
9592
PackageRule ( \&InstallCmd, \%INSTALL_LIBS  );
9593
PackageRule ( \&InstallCmd, \%INSTALL_SHLIBS  );
9594
PackageRule ( \&InstallCmd, \%INSTALL_PROGS  );
9595
 
9596
 
9597
#-------------------------------------------------------------------------------
9598
#   Packaging
9599
#
9600
MakeHeader ("Packaging");
9601
PackageRule ( \&PackageCmd, \%PACKAGE_FILES );
9602
PackageRule ( \&PackageCmd, \%PACKAGE_HDRS );
9603
PackageRule ( \&PackageCmd, \%PACKAGE_CLSS );
9604
PackageRule ( \&PackageCmd, \%PACKAGE_LIBS );
9605
PackageRule ( \&PackageCmd, \%PACKAGE_SHLIBS );
9606
PackageRule ( \&PackageCmd, \%PACKAGE_PROGS );
9607
 
9608
#-------------------------------------------------------------------------------
9609
#   Uninstall/unpackaging
9610
#
9611
MakeHeader ("Uninstall/unpackaging");
9612
 
9613
UnpackageRule( "uninstall_hdr",         \&UninstallCmd, \%INSTALL_HDRS );
9614
UnpackageRule( "uninstall_lib",         \&UninstallCmd, \%INSTALL_LIBS );
9615
UnpackageRule( "uninstall_shlib",       \&UninstallCmd, \%INSTALL_SHLIBS );
9616
UnpackageRule( "uninstall_prog",        \&UninstallCmd, \%INSTALL_PROGS );
9617
UnpackageRule( "uninstall_class",       \&UninstallCmd, \%INSTALL_CLSS );
9618
 
9619
UnpackageRule( "unpackage_files",       \&UnpackageCmd, \%PACKAGE_FILES );
9620
UnpackageRule( "unpackage_hdr",         \&UnpackageCmd, \%PACKAGE_HDRS );
9621
UnpackageRule( "unpackage_lib",         \&UnpackageCmd, \%PACKAGE_LIBS );
9622
UnpackageRule( "unpackage_shlib",       \&UnpackageCmd, \%PACKAGE_SHLIBS );
9623
UnpackageRule( "unpackage_prog",        \&UnpackageCmd, \%PACKAGE_PROGS );
9624
UnpackageRule( "unpackage_class",       \&UnpackageCmd, \%PACKAGE_CLSS );
9625
 
261 dpurdie 9626
#-------------------------------------------------------------------------------
267 dpurdie 9627
#   Distribution Sets
261 dpurdie 9628
#
267 dpurdie 9629
MakeHeader ("Distribution Sets");
9630
PackageSetRules();
9631
 
9632
#-------------------------------------------------------------------------------
9633
#
261 dpurdie 9634
#   Subdir deletion
9635
#   This is done AFTER the toolset functions have been invoked to create the
9636
#   build artifacts so that the toolsets can create directories too
9637
#
9638
#   Note: Toolset directories are deleted first
9639
#   Note: User Directories are deleted in the reverse order of creation
9640
#
9641
    MakeHeader ("Subdir deletion");
285 dpurdie 9642
    MakePrint( ".PHONY:\t\tunmake_dir\n" );
261 dpurdie 9643
    MakePrint( "unmake_dir:\n" );
9644
    MakePrint( "\t-\$(AA_PRE)echo Removing directories;" );
9645
    MakePrint( " \\\n\t\$(rmdir) \$(TOOLSETDIRS);" )            if ( @TOOLSETDIRS );
9646
    MakePrint( " \\\n\t\$(rm) -rf \$(TOOLSETDIRTREES);" )       if ( @TOOLSETDIRTREES );
9647
    RmdirRules();
9648
    MakeNewLine();
227 dpurdie 9649
 
261 dpurdie 9650
#--------- Toolset Rules -------------------------------------------------------
9651
    MakeHeader ("Toolset Rules");
9652
    MakePrintList ( \@TOOLSETRULES );
9653
 
227 dpurdie 9654
#-------------------------------------------------------------------------------
9655
#   Makefile targets
9656
#
261 dpurdie 9657
MakeHeader ("Makefile targets",
9658
            "These targets are not used by JATS",
9659
            "They can only used when the makefile is used directly",
9660
            "This is not the intended use of this makefile",
9661
           );
227 dpurdie 9662
 
9663
#
9664
#   Examine %INC and extract included files within JATS
9665
#   These will be added to the list of dependent files
9666
#
9667
foreach  (  values %INC)
9668
{
9669
    next if ( m/Makefile.*\.cfg$/ );    # Skip my config
9670
    if ( ( m/^\./)          ||
9671
         ( m/^$::GBE_CORE/) ||
9672
         ( m/^$::GBE_BIN/)  ||
9673
         ( m/^$::GBE_PERL/) ||
9674
         ( m/^$::GBE_TOOLS/) )
9675
    {
9676
        UniquePush (\@ScmDepends, $_ )
9677
    }
9678
}
9679
 
9680
MakeDefEntry    ( "GBE_DEPENDS", "=" );
261 dpurdie 9681
MakeIfZeroEntry ( "NOSCMDEPEND", "GBE_DEPENDS", "+=", \@ScmDepends );
227 dpurdie 9682
 
9683
    print MAKEFILE <<EOF;
9684
 
9685
\$(GBE_PLATFORM).mk:	\$(GBE_DEPENDS)
9686
	\@echo One or more JATS source or internal files have changed, "rebuild" required
261 dpurdie 9687
	\@for i in \$? ; do echo "      Changed: \$\$i"; done
227 dpurdie 9688
	\@exit 10
9689
 
9690
EOF
9691
 
261 dpurdie 9692
#--------- Maketags ------------------------------------------------------------
227 dpurdie 9693
 
9694
    Maketag( "make_init",           @INITS );
261 dpurdie 9695
    Maketag( "make_dir",            @mkdirdep );
9696
    Maketag( "generate",            @generatedep || @projectgendep || @USERGENERATED || ($ScmToolsetGenerate != 0) );
227 dpurdie 9697
    Maketag( "depend",              $ScmDependTags != 0 );
261 dpurdie 9698
    Maketag( "make_lib",            @libdep );
9699
    Maketag( "make_mlib",           @mlibdep );
9700
    Maketag( "make_install_shlib",  %INSTALL_SHLIBS || @shlibdep);
9701
    Maketag( "make_script",         @scriptdep );
9702
    Maketag( "make_prog",           @progdep || @projectdep );
9703
    Maketag( "make_test",           @testprogdep );
263 dpurdie 9704
    Maketag( "run_tests",           @TESTS_TO_RUN || @TESTPROJECT_TO_URUN || $TESTS_TO_RUN);
227 dpurdie 9705
    Maketag( "run_unit_tests",      $TESTS_TO_AUTORUN || @TESTPROJECT_TO_ARUN);
9706
    Maketag( "install_hdr",         %INSTALL_HDRS );
9707
    Maketag( "install_class",       %INSTALL_CLSS );
9708
    Maketag( "install_lib",         %INSTALL_LIBS );
9709
    Maketag( "install_prog",        %INSTALL_PROGS );
9710
    Maketag( "deploy",              %DEPLOYPACKAGE );
9711
    Maketag( "package",             %PACKAGE_FILES || %PACKAGE_HDRS || %PACKAGE_CLSS ||
9712
                                    %PACKAGE_LIBS || %PACKAGE_SHLIBS || %PACKAGE_PROGS );
9713
 
261 dpurdie 9714
    #
9715
    #   Display tags in the MAKEFILE
9716
    #   Not used here - just for show
9717
    #
9718
    MakeHeader ("Maketags");
9719
    foreach my $tag ( sort keys %MakeTags )
9720
    {
9721
        MakePadded( 2, "#   $tag:", defined ($MakeTags{$tag}) ? 1 : 0, "\n");
9722
    }
9723
 
227 dpurdie 9724
#-------------------------------------------------------------------------------
9725
#   End of Makefile
9726
#
9727
    MakeHeader ("End of Makefile");
9728
    close( MAKEFILE );
9729
 
9730
#
9731
#   Save all platform information
9732
#   Done after the makefile is written as toolsets can extend the data
9733
#
9734
    WriteParsedConfig();
9735
 
9736
#
9737
#   Write out any accumulated DPACKAGE data
9738
#
9739
    JatsDPackage::DPackageSave();
9740
 
9741
    return 0;
9742
}
9743
 
9744
#-------------------------------------------------------------------------------
9745
# Function        : Maketag
9746
#
9747
# Description     : Create Makefile tags to speed up recursive makes
9748
#
9749
# Inputs          : tag_name
9750
#                   dep
9751
#
9752
# Returns         : 
9753
#
9754
sub Maketag
9755
{
9756
    my( $tag, $dep ) = @_;
9757
    $MakeTags{$tag} = 1 if ( defined($dep) && $dep );
9758
}
9759
 
9760
#-------------------------------------------------------------------------------
9761
#   Function to create and delete directories within the build system
9762
#
9763
#    To stop make regenerating directory dependent targets each time the
9764
#    directory content is modified, rule should only be dependent on a internally
9765
#    created alias file 'gbedir', which represents the time a dir was created not
9766
#    last modified.
9767
#
9768
#    Must use tags like GBE_BINDIR, GBE_LIBDIR and GBE_OBJDIR to ensure that the
9769
#    directories are created correctly.
9770
#
9771
my %MkdirRuleData;
9772
my @MkdirRuleOrder;
9773
my $MkdirRulePrinting = 0;
9774
my $MkdirRuleGbeFile = ( $::ScmHost eq "Unix" ) ? ".gbedir" : "_gbedir";
9775
 
9776
#-------------------------------------------------------------------------------
9777
# Function        : MkdirRule
9778
#
9779
# Description     : Create Rules and Recipes to create a directory at make-time
9780
#                   Mark the information for such that the directories will
9781
#                   be deleted in a 'clean'
9782
#
9783
#                   Can be called before we start writing the makefile
9784
#                   Such entries will be retained and dumped at a known time
9785
#
9786
# Inputs          : $subdir     - Symbolic name of the subdir $(OBJDIR)
9787
#                   $alias      - Optional script alias for the dir 'OBJDIR' --> GBE_OBJDIR
9788
#                   Options:
9789
#                       --Path=path     Optional value of $subdir '$(GBE_PLATFORM)$(GBE_TYPE).OBJ'
9790
#                       --RemoveAll     Remove all files on clean
9791
#
9792
# Returns         : Nothing
9793
#
9794
 
9795
sub MkdirRule
9796
{
9797
    my( $subdir, $alias, @opts ) = @_;
9798
 
9799
    #
9800
    #   Create data entry once
9801
    #
9802
    $alias =~ s~^GBE_~~ if $alias;
9803
    unless ( $MkdirRuleData{$subdir}  )
9804
    {
9805
        my %data;
9806
 
9807
        #
9808
        #   Parse options
9809
        #
9810
        foreach ( @opts )
9811
        {
9812
            if ( /^--Path=(.+)/ ) {
9813
                $data{path} = $1;
9814
            } elsif ( /^--RemoveAll/ ) {
9815
                $data{remove_all} = 1;
9816
            } else {
9817
                Error ("MkdirRule: Unknown option: $_");
9818
            }
9819
        }
9820
        $data{alias} = $alias if ( $alias );
9821
 
9822
        $MkdirRuleData{$subdir} = \%data;
9823
        push @MkdirRuleOrder, $subdir;
9824
    }
9825
 
9826
    #
9827
    #   Save or print
9828
    #
9829
    return unless ( $MkdirRulePrinting );
9830
 
9831
    #
9832
    #   Create a definition of the physical directory
9833
    #
9834
    my $path = $MkdirRuleData{$subdir}{path};
261 dpurdie 9835
    MakePadded (2, $alias, ":= $path\n") if ( $path && $alias );
227 dpurdie 9836
 
9837
    #   Create an alias to be used within rules
9838
    #   The defined aliase will be prefixed with 'GBE_'
9839
    #
261 dpurdie 9840
    MakePadded (2, "GBE_$alias", ":= $subdir/$MkdirRuleGbeFile\n") if ( $alias );
227 dpurdie 9841
 
9842
    #
9843
    #   Create a recipe to create the directory
9844
    #   This is not as simple as it sounds
9845
    #   The touch is required.
9846
    #       Had 'timestamp' issues on solaris'. The 'echo' did not appear
9847
    #       to be enough. Perhaps the output was not flushed
9848
    #
261 dpurdie 9849
    MakePadded (2, "$subdir", ": $subdir/$MkdirRuleGbeFile\n");
227 dpurdie 9850
    MakePrint
9851
        "$subdir/$MkdirRuleGbeFile:\n".
9852
        "\t\$(XX_PRE)if [ ! -d $subdir ]; then \$(mkdir) -p $subdir; fi; \\\n".
9853
        "\t\$(echo) '# DO NOT REMOVE.' > \$@; \\\n".
9854
        "\t\$(touch) \$@\n\n";
9855
}
9856
 
9857
#-------------------------------------------------------------------------------
9858
# Function        : RmdirRules
9859
#
9860
# Description     : Create the body of a recipe to delete the directoeis that
9861
#                   have been created.
9862
#
9863
#                   The rule header will have been written to the makefile
9864
#
9865
# Inputs          : Uses $MkdirRuleData
9866
#
9867
# Returns         : Nothing.
9868
#                   Prints to the makefile
9869
#
9870
sub RmdirRules
9871
{
9872
    #
9873
    #   Determine the list of directories to delete
9874
    #   Sort such that subdirs are deleted files
9875
    #
9876
    foreach my $subdir ( reverse sort keys %MkdirRuleData )
9877
    {
9878
        MakePrint "\\\n";                       # join to previous line
261 dpurdie 9879
        MakePrint "\tif [ -d $subdir ]; then \\\n";
9880
        unless ( $MkdirRuleData{$subdir}{remove_all} )
9881
        {
9882
            MakePrint "\t\t\$(rm) -f $subdir/$MkdirRuleGbeFile; \\\n";
9883
            MakePrint "\t\t\$(rmdir) $subdir; \\\n";
9884
        }
9885
        else
9886
        {
9887
            MakePrint "\t\t\$(rm) -rf $subdir; \\\n";
9888
        }
227 dpurdie 9889
        MakePrint "\tfi;";
9890
    }
9891
}
9892
 
9893
#-------------------------------------------------------------------------------
9894
# Function        : CreateMkdirRules
9895
#
9896
# Description     : Create Rules to make dirs at runtime
9897
#                   This function is called to instantiate those entries
9898
#                   That have been requested before the makefile has has
9899
#                   started to be created.
9900
#
9901
#                   Once this function has been called all new MkdirRule calls
9902
#                   will result in the recipes being created in-line.
9903
#
9904
# Inputs          : Nothing
9905
#
9906
# Returns         : Even Less
9907
#
9908
#
9909
sub CreateMkdirRules
9910
{
9911
    $MkdirRulePrinting = 1;
9912
    foreach my $subdir ( @MkdirRuleOrder )
9913
    {
9914
        my $data = $MkdirRuleData{$subdir};
9915
        MkdirRule($subdir, $data->{alias}, $data->{path} );
9916
    }
9917
}
9918
 
9919
#-------------------------------------------------------------------------------
9920
# Function        : PackageRule
9921
#
9922
# Description     : Generate rules and recipes to "install" and "package" files
9923
#
9924
# Inputs          : codecmd     - A code reference to the actual installer routine
9925
#                   hashp       - A reference to a INSTALL or PACKAGE hash
9926
#
299 dpurdie 9927
#                   hashp is a reference to a hash
227 dpurdie 9928
#                       The key is the full path of the install target
9929
#                       The value is (another) hash that describes the install options
9930
#
9931
#                   Valid keys are:
9932
#                       src                 - Path of the source file [Mandatory]
9933
#                       dir                 - Target directory [Mandatory]
9934
#
9935
#                       defined             - Copy the file only if value is defined
9936
#                       exe                 - Mark the file as executable
9937
#                       Mode                - File modes. Default is -w
9938
#                       placekeeper         - Marks SHARED library placekeepers
9939
#                       set                 - Distribution sets
9940
#                       type                - Copy the file in DEBUG or PROD mode
9941
#                                             Valid values are "D" or "P"         
9942
#                       version             - Shared library version information
9943
#                       RemoveOnly          - Do not install the file. Entries are
9944
#                                             created to allow the removal of the file
9945
#
9946
# Returns         :
9947
#
9948
sub PackageRule
9949
{
9950
    my ($codecmd, $hashp) = @_;
9951
 
9952
    foreach my $dest ( keys %{$hashp} )
9953
    {
9954
 
9955
        my $entry = $hashp->{$dest};
9956
 
9957
        #
9958
        #   Skip placekeepers
9959
        #
9960
        next if ( $entry->{'placekeeper'} );
9961
 
9962
        #
9963
        #   Some entries are not installed via this mechanism, but can be removed
9964
        #   if they exist. Mark these as PHONY to keep targets happy
9965
        #
9966
        if ( $entry->{'RemoveOnly'} )
9967
        {
9968
            MakePrint ".PHONY:\t$dest\n";
9969
            MakePrint "$dest:\n\n";
9970
            next;
9971
        }
9972
 
9973
        my $fname = $entry->{'src'};
9974
        my $fmode = $entry->{'Mode'};
9975
        $fmode .= "+x" if ( $entry->{'exe'}  );
9976
 
9977
        #
9978
        #   User conditionional
9979
        #   Mark both the source and the target as PHONY if the condition is not met
9980
        #   This will ensure that the target need not be built.
9981
        #
9982
        my $udef = $entry->{'defined'};
9983
        if ( $udef )
9984
        {
9985
            MakePrint "ifndef $udef \n";
9986
            MakePrint ".PHONY:\t\t$dest\n";
9987
            MakePrint ".PHONY:\t\t$fname\n";
9988
            MakePrint "$dest:\n";
9989
            MakePrint "else\n"
9990
        }
9991
 
9992
        #
9993
        #   Conditional installation for DEBUG/PRODUCTION
9994
        #
9995
        my $type = $entry->{'type'};
9996
        if ( $type )
9997
        {
9998
            if ( $type eq "D" ) {
9999
                MakePrint 'ifeq "$(DEBUG)" "0"'."\n";
10000
            } elsif ( $type eq "P" ) {
10001
                MakePrint 'ifneq "$(DEBUG)" "0"'."\n";
10002
            } else {
10003
                Error("INTERNAL: Unexpected packaging type: $type");
10004
            }
10005
            MakePrint ".PHONY:\t\t$dest\n";
10006
            MakePrint "$dest:\n";
10007
            MakePrint "else\n"
10008
        }
10009
 
10010
        #
10011
        #   The body of the copy
10012
        #
10013
        MakePadded( 4, "$dest:" );
10014
        MakePrint "\t$fname\n";
10015
        MakePrint $codecmd->( $dest, $fname, $entry->{'dir'}, $fmode );
10016
        MakeNewLine();
10017
 
10018
 
10019
        #
10020
        #   Unwind conditionals
10021
        #
10022
        MakePrint "endif\n" if ( $type );
10023
        MakePrint "endif\n" if ( $udef );
10024
 
10025
        #
10026
        #   Distribution sets
10027
        #
10028
        my $dist = $entry->{'set'};
10029
        if ( $dist )
10030
        {
267 dpurdie 10031
            foreach my $set ( split( ',', $dist ) )
10032
            {
10033
                push @{$PACKAGE_SETS{$set}{LIST}}, $dest;
227 dpurdie 10034
            }
10035
            MakeNewLine();
10036
        }
10037
    }
10038
}
10039
 
10040
#-------------------------------------------------------------------------------
267 dpurdie 10041
# Function        : PackageSetRules
10042
#
10043
# Description     : Generate the packageset rules
10044
#                   These appear to be a now-defuct feature
10045
#
10046
#                   By default all packaged files are a part of package_setALL
10047
#
10048
# Inputs          : None
10049
#                   Takes data from %PACKAGE_SET
10050
#
10051
# Returns         : Nothing
10052
#
10053
sub PackageSetRules
10054
{
10055
    foreach my $set ( sort keys %PACKAGE_SETS )
10056
    {
10057
        my $me = MakeEntry::New( *MAKEFILE, "package_set$set", '--Phony' );
10058
        $me->AddDependancy( @{$PACKAGE_SETS{$set}{LIST}} );
10059
        $me->Print();
10060
    }
10061
}
10062
 
10063
#-------------------------------------------------------------------------------
227 dpurdie 10064
# Function        : UnPackageRule
10065
#
10066
# Description     : Generate rules and recipes to "uninstall" and "unpackage" files
10067
#
10068
# Inputs          : target      - Name of the target
10069
#                   codecmd     - A code reference to the actual installer routine
10070
#                   hashp       - A reference to a INSTALL or PACKAGE hash
10071
#
10072
# Returns         :
10073
#
10074
sub UnpackageRule
10075
{
10076
    my ($target, $codecmd, $hashp) = @_;
10077
 
10078
    MakePrint ".PHONY:\t\t"."$target\n";
10079
    MakePrint "$target:\t";
10080
 
10081
    foreach my $dest ( sort keys %{$hashp} )
10082
    {
10083
 
10084
        my $entry = $hashp->{$dest};
10085
 
10086
        #
10087
        #   Skip placekeepers
10088
        #
10089
        next if ( $entry->{'placekeeper'} );
10090
 
10091
        MakePrint "\n" . $codecmd->($dest);
10092
    }
10093
    MakePrint "\n\n";
10094
}
10095
 
10096
 
10097
#
10098
#   Internal macro interface, see RULE.STD for definitions:
10099
#
10100
sub RmFilesCmd
10101
{
10102
    my ( $list ) = @_;
261 dpurdie 10103
    return "\$(call RmFiles,$list)";
227 dpurdie 10104
}
10105
 
10106
sub InstallCmd
10107
{
10108
    my( $dest, $file, $path, $fmode ) = @_;
10109
 
10110
    $path =~ s~/$~~;                        # remove trailing "/"
10111
    $fmode = "-w"                           # default, read-only
10112
        if ( !defined( $fmode ) || $fmode eq "" );
10113
 
10114
    return "\t\$(call InstallFile,$dest,$file,$path,$fmode)";
10115
}
10116
 
10117
sub UninstallCmd
10118
{
10119
    my( $file ) = @_;
10120
 
10121
    return "\t\$(call UninstallFile,$file)";
10122
}
10123
 
10124
sub PackageCmd
10125
{
10126
    my( $dest, $file, $path, $fmode ) = @_;
10127
 
10128
    $path =~ s~/$~~;                        # remove trailing "/"
10129
    $fmode = "-w"                           # default, read-only
10130
        if ( !defined( $fmode ) || $fmode eq "" );
10131
 
10132
    return "\t\$(call PackageFile,$dest,$file,$path,$fmode)";
10133
}
10134
 
10135
sub UnpackageCmd
10136
{
10137
    my( $file ) = @_;
10138
    return "\t\$(call UnpackageFile,$file)";
10139
}
10140
 
10141
1;
10142