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