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