Subversion Repositories DevTools

Rev

Rev 7266 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5708 dpurdie 1
##############################################################################
6177 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). 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;
6133 dpurdie 110
use ToolsetFiles;
227 dpurdie 111
 
112
 
113
our $ScmVersion             = "2.34";
114
our $ScmGlobal              = 0;
115
our $ScmExpert              = 0;
116
our $ScmInterface           = "interface";      # default 'interface'
117
our $ScmPackage             = 1;                # package active by default.
118
our $ScmProcessingRootMake  = 0;                # Processing root makefile.pl
119
our $ScmPlatformSeen        = 0;                # Platform directive has been seen
6133 dpurdie 120
my  $ScmNotGeneric          = 1;                # Not a generic build
227 dpurdie 121
 
122
our $ScmToolsetVersion      = "";               # version of toolset
123
our $ScmToolsetGenerate     = 1;                # generate active by default.
124
our $ScmToolsetProgDependancies = 1;            # 1: Write program dependancies
125
                                                # 0: Don't write progdeps. Prog is Phony
289 dpurdie 126
our $ScmToolsetSingleType   = 0;                # Toolset does not support Debug and Production
227 dpurdie 127
our $ScmToolsetProgSource   = ();               # Toolset Program Source
339 dpurdie 128
our $ScmToolsetSoName       = 0;                # 1: Shared library supports SoName
363 dpurdie 129
our $ScmToolsetNillLibSrc   = 0;                # 1: Librarys created without source specified
5411 dpurdie 130
our %ScmToolsetProperties   = ();               # Toolset specific features and limitations
7018 dpurdie 131
                                                # Known values: UnitTests, AutoUnitTests, LdFlagSpace
6415 dpurdie 132
our %ScmGlobalOptions       = ();               # Hash of Global(platform) options. Access via functions
133
our %ScmRecipeTags          = ();               # Hash of exposed recipe names
363 dpurdie 134
 
227 dpurdie 135
our $ScmRoot                = "";
136
our $ScmMakelib             = "";
137
our $ScmPlatform            = "";
138
our $ScmMachType            = "";
139
our $ScmSrcDir              = "";
140
our @ScmPlatformDirs        = ();
141
our @ScmPlatformArgs        = ();
289 dpurdie 142
our $ScmBuildType           = 0;                # 0, P, D. 0 == P and D
227 dpurdie 143
our $ScmProduct             = "";
144
our $ScmTarget              = "";
145
our $ScmTargetHost          = "";
146
our $ScmToolset             = "";
147
our @ScmToolsetArgs         = ();
148
our @ScmDepends             = ();
149
our %ScmSourceTypes         = ();
150
our $ScmDeploymentPatch     = "";
151
our $ProjectBase            = "";               # Base of the user's project
152
our $ScmNoToolsTest         = "";               # Supress compiler tests
153
our $ScmDependTags          = 0;                # Create dependancy scanning tag
4781 dpurdie 154
our $ScmMakeUid;                                # Unique makefile id (number 1 .. )
227 dpurdie 155
 
156
our @CFLAGS                 = ();
157
our @CFLAGS_DEBUG           = ();
158
our @CFLAGS_PROD            = ();
159
our @CLINTFLAGS             = ();
160
our @CLINTFLAGS_DEBUG       = ();
161
our @CLINTFLAGS_PROD        = ();
162
our @CXXFLAGS               = ();
163
our @CXXFLAGS_DEBUG         = ();
164
our @CXXFLAGS_PROD          = ();
165
our @CXXLINTFLAGS           = ();
166
our @CXXLINTFLAGS_DEBUG     = ();
167
our @CXXLINTFLAGS_PROD      = ();
168
our @ASFLAGS                = ();
267 dpurdie 169
our @ASFLAGS_DEBUG          = ();
170
our @ASFLAGS_PROD           = ();
227 dpurdie 171
our @LDFLAGS                = ();
267 dpurdie 172
our @LDFLAGS_DEBUG          = ();
173
our @LDFLAGS_PROD           = ();
227 dpurdie 174
 
175
our @INCDIRS                = ();
176
our @NODEPDIRS              = ();
177
our @S_INCDIRS              = ();
178
our @G_INCDIRS              = ();
179
our @L_INCDIRS              = ();
180
our @SRCDIRS                = ();
181
our @S_SRCDIRS              = ();
182
our @G_SRCDIRS              = ();
183
our @L_SRCDIRS              = ();
184
our @LIBDIRS                = ();
185
our @S_LIBDIRS              = ();
186
our @G_LIBDIRS              = ();
187
our @L_LIBDIRS              = ();
188
 
189
our %SRCS                   = ();
190
our %SRC_ARGS               = ();
191
our %SRC_TYPE               = ();
192
our %SRC_DEPEND             = ();
193
our %SCRIPTS                = ();
194
our @COPYIN                 = ();
195
our @INITS                  = ();
196
our @DEFINES                = ();
197
our @OBJS                   = ();
198
our %SHOBJ_LIB              = ();
199
our @PROGOBJS               = ();
289 dpurdie 200
our @TESTPROGOBJS           = ();
227 dpurdie 201
our %OBJSOURCE              = ();
202
our @CHDRS                  = ();
203
our @CSRCS                  = ();
204
our @CXXSRCS                = ();
205
our @ASHDRS                 = ();
206
our @ASSRCS                 = ();
207
our @GENERATED              = ();
208
our @GENERATED_NOTSRC       = ();
209
our @RULES                  = ();
210
our @TOOLSETRULES           = ();
211
our @TOOLSETDIRS            = ();
212
our @TOOLSETDIRTREES        = ();
213
our @TOOLSETGENERATED       = ();
214
our @USERGENERATED          = ();
215
our @TOOLSETOBJS            = ();
216
our @TOOLSETLIBS            = ();
217
our @TOOLSETPROGS           = ();
218
our %INSTALL_HDRS           = ();
219
our %INSTALL_CLSS           = ();
6898 dpurdie 220
our @CLOBBERFILES           = ();
221
our @CLOBBERDIRS            = ();
227 dpurdie 222
 
4778 dpurdie 223
our @TOOLSET_UTF_PRE        = ();       # Toolsets can extend rules run before all unit tests
224
our @TOOLSET_UTF_POST       = ();       # Toolsets can extend rules run after all unit tests
225
our @TOOLSET_UTF_COLLATE    = ();       # Toolsets can extend rules run to collate unit tests results
226
 
227 dpurdie 227
our @LIBS                   = ();
289 dpurdie 228
our $LIBS                   = ();
227 dpurdie 229
our %LIB_PKG                = ();
230
our %LIB_INS                = ();
231
our %INSTALL_LIBS           = ();
232
 
233
our @MLIBS                  = ();
289 dpurdie 234
our $MLIBS                  = ();
227 dpurdie 235
 
236
our @SHLIBS                 = ();
289 dpurdie 237
our $SHLIBS                 = ();
227 dpurdie 238
our @SHLIB_TARGETS          = ();
239
our %SHLIB_PKG              = ();
240
our %SHLIB_INS              = ();
241
our %INSTALL_SHLIBS         = ();
6387 dpurdie 242
our @INSTALL_DIRS           = ();
227 dpurdie 243
 
289 dpurdie 244
our $TESTPROGS              = ();
245
our @TESTPROGS              = ();
227 dpurdie 246
 
289 dpurdie 247
our $PROGS                  = ();           # Simplify tracking of progs
227 dpurdie 248
our @PROGS                  = ();
289 dpurdie 249
our @PROGS_EXTRA            = ();           # Look at doing better !!
227 dpurdie 250
our %PROG_PKG               = ();
251
our %PROG_INS               = ();
252
our %INSTALL_PROGS          = ();
253
 
254
our %PACKAGE_DIST           = ();
255
our %PACKAGE_SETS           = ();
256
our %PACKAGE_HDRS           = ();
257
our %PACKAGE_LIBS           = ();
258
our %PACKAGE_CLSS           = ();
259
our %PACKAGE_SHLIBS         = ();
260
our %PACKAGE_PROGS          = ();
261
our %PACKAGE_FILES          = ();
6387 dpurdie 262
our @PACKAGE_DIRS           = ();
227 dpurdie 263
 
264
our @LINTLIBS               = ();
265
our @LINTSHLIBS             = ();
266
 
4501 dpurdie 267
our @TESTS_TO_RUN           = ();                           # Info from 'RunTest' directives
227 dpurdie 268
 
4996 dpurdie 269
our @TESTPROJECT_TO_URUN    = ();                           # List of Unit Tests and Projects names (Auto and Non Auto in order defined in makefile)
270
our @TESTPROJECT_TO_ARUN    = ();                           # List of Auto Tests and Projects names in order defined in makefile
4501 dpurdie 271
my  $TESTS_TO_AUTORUN       = undef;                        # Flag - Auto Test found
272
my  $TESTS_TO_RUN           = undef;                        # Flag - Unit Test found
273
 
227 dpurdie 274
#our $CurrentTime           = "";
275
#our $CurrentDate           = "";
276
#our $Cwd                   = "";
277
 
278
our @GENERATE_FILES         = ();
279
our %DEPLOYPACKAGE          = ();
267 dpurdie 280
our $DEPLOYPACKAGE          = 0;
261 dpurdie 281
our %MakeTags;
227 dpurdie 282
 
283
#
284
#   Some toolset options that affect the generation of the makefile
285
#
286
our $UseAbsObjects          = 0;                # Default is relative paths to objects
287
our $UseRelativeRoot        = 0;                # Default is absolute paths to build root
299 dpurdie 288
our $DPackageDirective      = 0;
227 dpurdie 289
 
271 dpurdie 290
#
291
#   Arrays of hook functions
292
#
293
our %MF_RegisterSrcHooks;                       # Hook source file discovery
294
 
227 dpurdie 295
###############################################################################
296
#
297
#   Packaging and Installation Information
298
#   Held in a structure as its used in a few places
299
#   Items
300
#       PBase   - Package Base directory. Used for user overrides
301
#       IBase   - Local Install Base directory
302
#       Dir     - Default directory suffix for components. Added to Pbase and IBase
303
#
304
#
305
our %PackageInfo = (
306
    'File' => { 'PBase' => '$(PKGDIR)'       ,'IBase' => '$(LOCALDIR)'       , 'Dir' => '' },
307
    'Hdr'  => { 'PBase' => '$(INCDIR_PKG)'   ,'IBase' => '$(INCDIR_LOCAL)'   , 'Dir' => ''},
308
    'Lib'  => { 'PBase' => '$(LIBDIR_PKG)'   ,'IBase' => '$(LIBDIR_LOCAL)'   , 'Dir' => '/$(GBE_PLATFORM)'},
309
    'Prog' => { 'PBase' => '$(BINDIR_PKG)'   ,'IBase' => '$(BINDIR_LOCAL)'   , 'Dir' => '/$(GBE_PLATFORM)$(GBE_TYPE)'},
310
    'Jar'  => { 'PBase' => '$(CLSDIR_PKG)'   ,'IBase' => '$(CLSDIR_LOCAL)'   , 'Dir' => ''},
241 dpurdie 311
    'Tool' => { 'PBase' => '$(PKGDIR)'       ,'IBase' => '$(LOCALDIR)'       , 'Dir' => '/tools/bin/$(GBE_HOSTMACH)'},
227 dpurdie 312
    );
313
 
4778 dpurdie 314
###############################################################################
315
#
316
#   An array of reserved names
317
#   Used to attempt to prevent developers from naming toolset targets with names reserved
318
#   within the build system
319
our @reservedMakeTargets = qw (
320
    preprocess_tests postprocess_tests collate_test_results
321
);
322
 
227 dpurdie 323
MakeLib2Init();                                 # Runtime initialisation
324
 
325
sub MakeLib2Init
326
{
327
#.. Test environment
328
#
329
    EnvImport( "GBE_CORE" );
330
    EnvImport( "GBE_BIN" );
331
    EnvImport( "GBE_PERL" );
332
    EnvImport( "GBE_TOOLS" );
333
    EnvImport( "GBE_CONFIG" );
334
    EnvImport( "GBE_MACHTYPE" );
335
 
336
#.. Common stuff
337
#
338
    require "$::GBE_TOOLS/common.pl";           # Common stuff
339
    push( @ScmDepends, "$::GBE_TOOLS/common.pl" );
340
 
341
    CommonInit( "makelib2" );
342
    Debug( "version:   $ScmVersion" );
343
 
344
#.. Cache arguments
345
#
346
    CommandLine();
347
 
348
#.. Build defaults
349
#
350
    $ScmSourceTypes{ ".h" }     = ".h";
351
    $ScmSourceTypes{ ".hpp" }   = ".h";
352
    $ScmSourceTypes{ ".c" }     = ".c";
353
    $ScmSourceTypes{ ".C" }     = ".c";
354
    $ScmSourceTypes{ ".cpp" }   = ".cc";
355
    $ScmSourceTypes{ ".cc" }    = ".cc";
356
    $ScmSourceTypes{ ".asm" }   = ".asm";
357
    $ScmSourceTypes{ ".x" }     = "--Ignore";
358
    $ScmSourceTypes{ ".ini" }   = "--Ignore";
359
    $ScmSourceTypes{ ".sh" }    = "--Ignore";
360
    $ScmSourceTypes{ ".pl" }    = "--Ignore";
361
    $ScmSourceTypes{ ".awk" }   = "--Ignore";
362
 
363
#.. Get the stuff from the build configuration file
364
#
365
    ConfigLoad();
4781 dpurdie 366
    $ScmMakeUid = GetMakfilefileUid();
367
    Debug("ScmMakeUid: $ScmMakeUid");
227 dpurdie 368
 
369 dpurdie 369
    if ( (%::ScmBuildPlatforms) )        # Interface/build.cfg
227 dpurdie 370
    {
371
        AddPlatformArg( split( /$;/, $::ScmBuildPlatforms{ $ScmPlatform } ));
372
    }
373
 
369 dpurdie 374
    if ( (%::ScmBuildIncludes) )         # Interface/build.cfg
227 dpurdie 375
    {
376
        my( @includes ) = split( ',', $::ScmBuildIncludes{ $ScmPlatform } );
377
        my( $global ) = $ScmGlobal;
378
 
379
        $ScmGlobal = 1;                         # Follow defs are "global's" ...
380
        foreach my $elem ( @includes )
381
        {
382
            AddIncDir( "*", $elem ) if ($elem);
383
        }
384
        $ScmGlobal = $global;                   # Restore global status ...
385
    }
386
 
369 dpurdie 387
    if ( (%::ScmBuildLibraries) )        # Interface/build.cfg
227 dpurdie 388
    {
389
        my( @libraries ) = split( ',', $::ScmBuildLibraries{ $ScmPlatform } );
390
        my( $global ) = $ScmGlobal;
391
 
392
        $ScmGlobal = 1;                         # Follow defs are "global's" ...
393
        foreach my $elem ( @libraries )
394
        {
395
            AddLibDir( "*", $elem ) if ($elem);
396
        }
397
        $ScmGlobal = $global;                   # Restore global status ...
398
    }
399
 
400
#.. Determine the value of $ScmMachType
401
#   In the makefile GBE_MACHTYPE will be set to $ScmMachType.
402
#
403
#   There is an compatibility issue here.
404
#   A lot of (legacy) package.pl files use GBE_MACHTYPE to specify platform
405
#   specfic directories and names. This is not to be encouraged.
406
#
407
#   Allow for a platformm specific override
408
#
409
    if ( exists( $::BUILDINFO{$ScmPlatform}{'SCMMACHTYPE'} ))
410
    {
411
        $ScmMachType = $::BUILDINFO{$ScmPlatform}{'SCMMACHTYPE'};
412
        Verbose("Override ScmMachType: $ScmMachType");
413
    }
414
    else
415
    {
416
        $ScmMachType = $ScmPlatform;
417
    }
418
 
419
 
420
#.. Get the stuff from the Package definition file
421
#   A convention is that package.pl provide a package name via $Pbase
422
#   This may be different to the BUILDNAME. Generate a default $Pbase
423
#   to allow the package.pl to use the package name part of the buildname
424
#
425
    $::Pbase = $::ScmBuildPackage;
426
    if ( -f "$ScmRoot/package.pl" )
427
    {
428
        Warning ("package.pl file used. Use is being deprecated");
429
 
430
        my( $global ) = $ScmGlobal;             # Follow defs are "global's" ...
431
        $ScmGlobal = 1;
432
        require "$ScmRoot/package.pl";
433
        $ScmGlobal = $global;                   # Restore global status ...
434
 
435
        if ( defined ($::ScmBuildPackage) && defined ($::Pbase) )
436
        {
437
            #   Special case.
438
            #   $Pbase is set to ".". Set $Pbase to the Build Name to force
439
            #   construction of a well formatted package.
440
            #
441
            $::Pbase = $::ScmBuildPackage
442
                if ( $::Pbase eq "." );
443
 
444
            #
445
            #   Error if Pbase has changed
446
            #
447
            Error ("Pbase is not the same as the BuildName (Check package.pl)",
448
                   "Pbase    : $::Pbase",
449
                   "BuildName: $::ScmBuildPackage")
450
                if ( $::Pbase ne $::ScmBuildPackage );
451
        }
452
    }
289 dpurdie 453
 
454
    #
455
    #   Create objects to keep track of Libraies and Programs
456
    #
457
    $LIBS       = MakeObject::NewType( 'Library',       \@LIBS,     '$(LIBDIR)/', \&GenLibName);
458
    $MLIBS      = MakeObject::NewType( 'MergedLibrary', \@MLIBS,    '$(LIBDIR)/', \&GenLibName);
459
    $SHLIBS     = MakeObject::NewType( 'SharedLibrary', \@SHLIBS,   '$(LIBDIR)/', \&GenLibName);
460
    $PROGS      = MakeObject::NewType( 'Program',       \@PROGS,    '$(BINDIR)/', \&GenProgName);
461
    $TESTPROGS  = MakeObject::NewType( 'TestProgram',   \@TESTPROGS,'$(BINDIR)/', \&GenProgName);
227 dpurdie 462
}
463
 
261 dpurdie 464
#-------------------------------------------------------------------------------
289 dpurdie 465
# Function        : GenLibName
466
#
467
# Description     : Helper function to generate a (static) library name
468
#                   Used by MakeObject::NewType
469
#
470
#                   If the toolset doesn't support Debug and Prod, then
471
#                   The library name will not have the suffix
472
#
473
# Inputs          : arg0        - Base name of the library
343 dpurdie 474
#                   arg1        - Mode: 1 == Plain. No P or D
289 dpurdie 475
#
476
# Returns         : Name of the library as used in the makefiles
477
#                   Does not include base directory
478
#
479
sub GenLibName
480
{
343 dpurdie 481
    if ( $ScmToolsetSingleType || $_[1] ) {
289 dpurdie 482
        return "$_[0].$::a"
483
    } else {
484
        return "$_[0]\$(GBE_TYPE).$::a"
485
    }
486
}
487
 
488
#-------------------------------------------------------------------------------
489
# Function        : GenProgName
490
#
491
# Description     : Helper function to generate a program name
492
#                   Used by MakeObject::NewType
493
#
494
# Inputs          : arg0        - Base name of the library
495
#
496
# Returns         : Name of the program as used in the makefiles
497
#                   Does not include base directory
498
#
499
sub GenProgName
500
{
501
    return "$_[0]$::exe"
502
}
503
 
504
 
505
#-------------------------------------------------------------------------------
261 dpurdie 506
# Function        : CommandLine
507
#
508
# Description     : Process the command line.
509
#                   Arguments describes below
510
#
511
# Arguments       : ARG0        - Root of the project
512
#                   ARG1        - Path to this script
513
#                   ARG2        - Target Platform
514
#
515
#                   Options follow
516
#                       --interface=name    - Name of interface dir
517
#                       --arg=xxx           - Platform argument
518
#
519
#                   Otherwise display a usage message
520
#
521
# Returns         : Nothing
522
#
227 dpurdie 523
sub CommandLine
524
{
261 dpurdie 525
    Verbose ("Command Line: @ARGV");
227 dpurdie 526
 
261 dpurdie 527
    #
528
    #   Extract options first
529
    #
530
    my $opt_help = 0;
531
    my $result = GetOptions (
532
                "help+"         => \$opt_help,
533
                "interface=s"   => \$::ScmInterface,
534
                "arg=s"         => sub{ AddPlatformArg( "--$_[1]") }
535
                );
536
    Usage() if ( $opt_help || !$result );
537
 
538
    #
539
    # Need 3 Arguments
540
    #
227 dpurdie 541
    $ScmRoot     = ${ARGV[0]};
261 dpurdie 542
    $ScmRoot     = RelPath( $ScmRoot );
227 dpurdie 543
    $ProjectBase = $ScmRoot;
544
 
545
    $ScmMakelib  = ${ARGV[1]};
546
    $ScmPlatform = ${ARGV[2]};
547
    $ScmTarget   = $ScmPlatform;
548
 
549
    Message ("[$ScmPlatform] Generate Makefile");
550
    Debug( "root\t=$ScmRoot" );
551
    Debug( "makelib\t=$ScmMakelib" );
552
    Debug( "platform\t=$ScmPlatform" );
553
}
554
 
555
#   Usage ---
556
#       Command line usage help.
557
#..
558
 
559
sub Usage
560
{
261 dpurdie 561
    Error ( "Usage: perl makefile.pl2 <ROOTDIR> <makelib.pl2> <PLATFORM> [options ...]",
562
            "Valid options:",
563
            "    --interface=name  Set interface directory",
564
            "    --arg=text        Specify platform argument",
565
            );
227 dpurdie 566
}
567
 
568
 
569
#-------------------------------------------------------------------------------
570
# Function        : SubDir
571
#
572
# Description     : Include a sub-makefile
573
#                   When called when processing by this script this directive
574
#                   does nothing. The processing will be done by makelib.pl
575
#
576
#                   This directive MUST occur before the Platform directive
577
#
578
# Inputs          : None that are used
579
#
580
# Returns         : Nothing
581
#
582
 
583
sub SubDir
584
{
585
    Error ("SubDir directive not allowed after the Platform directive")
586
        if ( $ScmPlatformSeen );
587
}
588
 
589
 
590
###############################################################################
591
#   Platform support
592
###############################################################################
593
 
594
sub Platform
595
{
596
    my( $global, $file );
597
 
598
    Debug( "Platform( $ScmPlatform, @ScmPlatformArgs )" );
599
 
600
#.. Sanity test
601
#
602
    Error ("Platform directive is not allowed in common makefile.pl")
603
        if ( $ScmProcessingRootMake );
604
 
605
    Error ("Only one Platform directive is allowed")
606
        if ( $ScmPlatformSeen );
607
    $ScmPlatformSeen = 1;
608
 
609
#.. Arguments
610
#
611
    $ScmTargetHost = $::ScmHost;                # default
612
 
613
#.. Common configuration
614
#
615
    $global = $ScmGlobal;                       # Follow defs are "global's" ...
616
    $ScmGlobal = 1;
617
 
618
#.. Common rules (ScmHost specific)
619
#
620
    push( @ScmDepends, "$ScmMakelib" );         # parent
621
 
622
    $file = Require( "$::GBE_CONFIG", "Rules", "Common rules " );
623
    push( @ScmDepends, "$file" );
624
 
625
#.. Platform (defines ScmToolset)
626
#
369 dpurdie 627
    if ( ( %::ScmBuildProducts ) &&      # interface/build.cfg
4551 dpurdie 628
           $::ScmBuildProducts{ $ScmPlatform } )
227 dpurdie 629
    {
630
        my( @args ) = split( ',', $::ScmBuildProducts{ $ScmPlatform } );
631
 
632
        $ScmProduct = $args[0];
633
        $ScmTarget = $args[1];
634
 
635
        Debug( " mapping to product $ScmProduct" );
636
 
637
                                                # Platform/target specific
638
        MakeIf::PackageDirs( \@ScmPlatformDirs, $ScmPlatform, $ScmTarget );
639
        push @ScmPlatformDirs, "$::GBE_CONFIG"; # .. plus default
640
 
641
        @ScmPlatformArgs = ( "--product=$ScmProduct", @ScmPlatformArgs );
642
        $file = Require( "PLATFORM", $ScmTarget,
643
                    "Platform definition ", @ScmPlatformDirs );
644
    }
645
    else                                        # standard
646
    {
647
        Debug( " native platform" );
648
 
649
                                                # Platform specific
650
        MakeIf::PackageDirs( \@ScmPlatformDirs, $ScmPlatform );
651
        push @ScmPlatformDirs, "$::GBE_CONFIG"; # .. plus default
652
 
6133 dpurdie 653
        #   Map all GENERIC builds onto the one platform definition
4551 dpurdie 654
        my $platformDefs = $ScmPlatform;
6133 dpurdie 655
        if ($::BUILDINFO{$ScmPlatform}{IS_GENERIC})
656
        {
657
            $ScmNotGeneric = 0;
658
            $platformDefs = 'GENERIC' ;
659
        }
4551 dpurdie 660
 
661
        $file = Require( "PLATFORM", $platformDefs,
227 dpurdie 662
                    "Platform definition ", @ScmPlatformDirs );
663
    }
664
    push( @ScmDepends, "$file" );
665
 
666
    Error( "Toolset undefined for platform $ScmPlatform ...")
667
        unless( $ScmToolset );
668
 
669
#.. Toolset
670
#
671
    $file = Require( "$::GBE_CONFIG/TOOLSET", $ScmToolset, "Toolset definition " );
672
    push( @ScmDepends, "$file" );
673
 
674
#.. Package definitions
675
#
367 dpurdie 676
#   Global DPACKAGE definitions, which may pull in $ScmTarget specific definitions.
227 dpurdie 677
#
678
 
679
    MakeIf::PackageLoad( $ScmPlatform );        # DPACKAGE's (if any)
680
 
681
 
682
#.. Package extensions
683
#   Import, into the current package, files of the form gbe/DIRECTIVES
684
#   These allow the JATS directives to be extended by the contents of a package
685
#   without the need to update the core JATS release.
686
#
687
#   Intended use: Associate a directive with a tool script, such that the
688
#   new directive simplifies the use of the tool script.
689
#
690
#
691
#   First: Extend the Perl Search Space to include the toolset extensions
692
#          Although the directives are in gbe/DIRECTIVES/*.pm, they may need
693
#          to reference other packages that are not.
694
#
311 dpurdie 695
#           Look in the 'interface' and 'link' packages
696
#           The 'build' packages are duplicated into the 'interface'
697
#
227 dpurdie 698
    for my $path ( ToolExtensionPaths() )
699
    {
700
        UniquePush (\@INC, $path)
701
            if (glob( "$path/*.pm") || glob( "$path/*/*.pm"));
702
    }
703
 
704
    for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} })
705
    {
311 dpurdie 706
        next if ( $entry->{'TYPE'} eq 'build' );
227 dpurdie 707
        my $cfgdir = $entry->{'CFGDIR'};
708
        next unless ( $cfgdir );
709
        my $base_dir = $entry->{'ROOT'} . $cfgdir . '/DIRECTIVES';
710
        next unless ( -d $base_dir );
711
        foreach my $file  ( glob ("$base_dir/*.pm") )
712
        {
713
            push( @ScmDepends, "$file" );
714
            require $file;
715
        }
716
    }
717
 
718
    #
271 dpurdie 719
    #   Include local toolset extensions
720
    #   These are rooted in the build directory and are not to be confused with
721
    #   extensions that may be packaged
6387 dpurdie 722
    #   Simplify life - add the directory to the BUILDTOOLSPATH
271 dpurdie 723
    #
724
    my $local_base_dir = "$ScmRoot/gbe/DIRECTIVES";
725
    if ( -d $local_base_dir )
726
    {
6387 dpurdie 727
        unshift @::BUILDTOOLSPATH, AbsPath($local_base_dir); 
271 dpurdie 728
        foreach my $file  ( glob ("$local_base_dir/*.pm") )
729
        {
730
            push( @ScmDepends, "$file" );
731
            require $file;
732
        }
733
    }
734
 
735
    #
227 dpurdie 736
    #   All makefile.pl's will include a makefile.pl found in the build
737
    #   root directory ( The same directory as build.pl ). This makefile.pl
738
    #   is a little bit different - It should not "require "$ARGV[1]", nor
739
    #   should it use a Platform directive.
740
    #
741
    #   Note: This makefile is processed AFTER the toolset has been initialised
742
    #         so that toolset extensions are available to the directives
743
    #
744
    $file = "$ScmRoot/makefile.pl";
745
    if ( -e $file ) {
746
        $ScmProcessingRootMake = 1;
747
        require "$file";
748
        $ScmProcessingRootMake = 0;
749
        push( @ScmDepends, "$file" );
750
    }
751
 
752
    #
289 dpurdie 753
    #   Sanity Test for platforms that do not support both debug and production
754
    #   builds at the same time. This information is flagged by the toolset
755
    #   which we have now loaded.
756
    #
757
    if ( $ScmToolsetSingleType  )
758
    {
759
        unless ( $ScmBuildType )
760
        {
761
            Error ("The toolset used by the \"$ScmPlatform\" platform does not support",
762
                   "both Production and Debug Builds" );
763
        }
764
    }
765
 
766
    #
227 dpurdie 767
    #   Restore global status ...
768
    #
769
    $ScmGlobal = $global;
770
}
771
 
772
 
773
sub PlatformRequire
774
{
775
    my( $script, @arguments ) = @_;
776
    my( $file );
777
 
778
    Debug( "PlatformRequire($script, @arguments)" );
779
 
780
    push( @ScmPlatformArgs, @arguments );       # additional arguments
781
 
782
    $file = Require( "PLATFORM", $script,
783
                "PlatformRequire ", @ScmPlatformDirs );
784
 
785
    push( @ScmDepends, "$file" );
786
}
787
 
788
 
789
sub PlatformInclude
790
{
791
    my( $script, @arguments ) = @_;
792
    my( $file );
793
 
794
    Debug( "PlatformInclude( @_ )" );
795
 
796
    $file = Require2( \@arguments, "PLATFORM", $script,
797
                "PlatformInclude ", @ScmPlatformDirs );
798
 
799
    push( @ScmDepends, "$file" );
800
}
801
 
802
 
803
sub PlatformDefine
804
{
805
    Debug2( "PlatformDefine(@_)" );
806
 
807
    Define( @_ );
808
}
809
 
810
 
811
sub PlatformDefines
812
{
813
    my( $script ) = @_;
814
    my( $line );
815
 
816
    Debug2( "PlatformDefine(@_)" );
817
 
818
    $script = Exists( "PLATFORM", $script,      # locate image
819
                "PlatformDefines", @ScmPlatformDirs );
820
 
271 dpurdie 821
    push( @DEFINES, "# PlatformDefines from: $script" );
285 dpurdie 822
    open( my $fh, '<', $script ) || Error( "Opening $script" );
823
    while (<$fh>) {
227 dpurdie 824
        $_ =~ s/\s*(\n|$)//;                    # kill trailing whitespace & nl
825
        push( @DEFINES, $_ );
826
    }
827
    push( @ScmDepends, "$script" );             # makefile dependencies
285 dpurdie 828
    close( $fh );
227 dpurdie 829
}
830
 
831
 
832
sub PlatformEntry
833
{
834
    my( $prelim, $postlim, $prefix, $postfix, @elements ) = @_;
835
 
285 dpurdie 836
    my $str = "$prelim";
837
    foreach my $element ( @elements )
227 dpurdie 838
    {
839
        $str .= "${prefix}${element}${postfix}";
840
    }
841
    $str .= "$postlim";
842
    PlatformDefine( $str );
843
}
844
 
845
 
846
#
847
#   Add arguments to the ScmPlatformArgs, but remove "Global" arguments
848
#       --OnlyDebug
849
#       --OnlyProduction
343 dpurdie 850
#       --NoToolSet
227 dpurdie 851
#
289 dpurdie 852
#   Capture OnlyDebug and OnlyProd information
853
#   Will be sanitized by caller.
854
#
227 dpurdie 855
sub AddPlatformArg
856
{
857
    Debug("AddPlatformArg: @_" );
289 dpurdie 858
    foreach  ( @_ )
859
    {
860
        if ( m~^--OnlyDebug~ ) {
861
            $ScmBuildType = 'D';
862
        } elsif ( m~--OnlyProd~ ) {
863
            $ScmBuildType = 'P';
343 dpurdie 864
        } elsif ( m~--NoToolSet~ ) {
865
            $ScmNoToolsTest = 1;
289 dpurdie 866
        } else {
343 dpurdie 867
            UniquePush( \@::ScmPlatformArgs, $_ );
289 dpurdie 868
        }
869
    }
227 dpurdie 870
 
871
    Debug("AddPlatformArg: Result: @::ScmPlatformArgs" );
872
    1;
873
}
874
 
875
###############################################################################
876
# Toolset support
877
#
878
#   Toolset( 'platform [, ... ]', name, [arg, ... ] )
879
#       Specify the toolset for a platform
880
#
881
#   ToolDefine( )
882
#   ToolDefines( )
883
#       Specifies toolset defines for insertion into the target makefile.
884
#
885
#   ToolsetDir
886
#       Define toolset created directory(s) for removal during
887
#       'clean' operations.
888
#
889
#   ToolsetGenerate
890
#       Define toolset created file(s) for removal during
891
#       'clean' operations.
892
#
893
#   ToolsetObj
894
#       Define toolset created object(s) for removal during
895
#       'clean' operations.
896
#
897
#   ToolsetLib
898
#       Define toolset created library(s) for removal during
899
#       'clean' operations.
900
#
901
#   ToolsetProg
902
#       Define toolset created prog(s) for removal during
903
#       'clean' operations.
904
#
905
#   ToolsetRule( )
906
#   ToolsetRules( )
907
#       Specifies toolset rules for insertion into the target makefile.
908
#
909
##############################################################################
910
 
911
sub Toolset
912
{
913
    my( $platforms, $toolset, @arguments ) = @_;
914
 
915
    Debug2( "Toolset(@_)" );
916
 
4309 dpurdie 917
    return 1 if ( ! ActivePlatform($platforms) );
227 dpurdie 918
 
919
    $ScmToolset = $toolset;
920
    @ScmToolsetArgs = @arguments;
4309 dpurdie 921
    return 1;
227 dpurdie 922
}
923
 
924
 
925
sub ToolsetRequire
926
{
927
    my( $script, @arguments ) = @_;
928
    my( $file );
929
 
930
    Debug2( "ToolsetRequire(@_)" );
931
 
932
    @ScmToolsetArgs = @arguments;
933
    $file = Require( "",
934
                     $script,
935
                     "ToolsetRequire",
936
                     "$::GBE_CONFIG/TOOLSET", @::BUILDTOOLSPATH );
937
    push( @ScmDepends, "$file" );
938
}
939
 
940
 
941
sub ToolsetDefine
942
{
943
    Debug2( "ToolsetDefine(@_)" );
944
 
945
    Define( @_ );
946
}
947
 
948
 
949
sub ToolsetDefines
950
{
951
    Debug2( "ToolsetDefines(@_)" );
952
 
261 dpurdie 953
    Defines( "$::GBE_CONFIG/TOOLSET", @_ );
227 dpurdie 954
}
955
 
956
 
957
sub ToolsetDir
958
{
959
    Debug2( "ToolsetDir(@_)" );
960
 
261 dpurdie 961
    UniquePush ( \@TOOLSETDIRS, @_ );
227 dpurdie 962
}
963
 
964
 
965
sub ToolsetDirTree
966
{
967
    Debug2( "ToolsetDirTree(@_)" );
968
 
261 dpurdie 969
    UniquePush ( \@TOOLSETDIRTREES, @_);
227 dpurdie 970
}
971
 
972
 
973
sub ToolsetGenerate
974
{
975
    Debug2( "ToolsetGenerate(@_)" );
976
 
977
    UniquePush( \@TOOLSETGENERATED, @_ );
978
}
979
 
6898 dpurdie 980
sub ToolsetClobberFile
981
{
982
    Debug( "ToolsetClobberFile(@_)" );
983
    UniquePush( \@CLOBBERFILES, @_ );
984
}
227 dpurdie 985
 
6898 dpurdie 986
sub ToolsetClobberDir
987
{
988
    Debug( "ToolsetClobberDir(@_)" );
989
    UniquePush( \@CLOBBERDIRS, @_ );
990
}
991
 
227 dpurdie 992
sub ToolsetObj
993
{
994
    Debug2( "ToolsetObj(@_)" );
995
 
261 dpurdie 996
    foreach my $obj ( @_ )
227 dpurdie 997
    {
261 dpurdie 998
        UniquePush( \@TOOLSETOBJS, "$obj.$::o"  );
227 dpurdie 999
    }
1000
}
1001
 
1002
 
1003
sub ToolsetLib
1004
{
1005
    Debug2( "ToolsetLib(@_)" );
1006
 
261 dpurdie 1007
    foreach my $lib ( @_ )
227 dpurdie 1008
    {
289 dpurdie 1009
        UniquePush( \@TOOLSETLIBS, GenLibName( $lib ) );
227 dpurdie 1010
    }
1011
}
1012
 
1013
 
1014
sub ToolsetProg
1015
{
1016
    Debug2( "ToolsetProg(@_)" );
1017
 
261 dpurdie 1018
    foreach my $prog ( @_ )
227 dpurdie 1019
    {
289 dpurdie 1020
        UniquePush( \@TOOLSETPROGS, GenProgName( $prog ) );
227 dpurdie 1021
    }
1022
}
1023
 
1024
 
1025
sub ToolsetRule
1026
{
1027
    Debug2( "ToolsetRule(@_)" );
1028
 
1029
    push( @TOOLSETRULES, @_ );
1030
}
1031
 
1032
 
1033
sub ToolsetRules
1034
{
1035
    my( $script ) = @_;
1036
    my( $line );
1037
 
1038
    Debug2( "ToolsetRules(@_)" );
1039
 
1040
    $script = Exists( "$::GBE_CONFIG/TOOLSET", $script, "ToolsetRules" );
271 dpurdie 1041
    push( @TOOLSETRULES, "# ToolsetRules from: $script" );
285 dpurdie 1042
    open( my $fh, '<', $script ) || Error( "Opening $script" );
1043
    while (<$fh>) {
227 dpurdie 1044
        $_ =~ s/\s*(\n|$)//;                    # kill trailing whitespace & newline
1045
        push( @TOOLSETRULES, $_ );
1046
    }
1047
    push( @ScmDepends, "$script" );             # makefile dependencies
285 dpurdie 1048
    close( $fh );
227 dpurdie 1049
}
1050
 
4778 dpurdie 1051
#-------------------------------------------------------------------------------
4902 dpurdie 1052
# Function        : SetGlobalOption  
1053
#
1054
# Description     : Set a global toolset option
1055
#                   The global options are intended to allow platform-specific
1056
#                   operation of various tools and utilities. The scope is wider than 
1057
#                   just the underlying tooolset 
1058
#
1059
# Inputs          : $name           - Name of the option
1060
#                   $value          - Value to save            
1061
#
1062
# Returns         : Nothing
1063
#
1064
 
1065
sub SetGlobalOption
1066
{
1067
    my ($name, $value) = @_;
4928 dpurdie 1068
    Debug( "SetGlobalOption.", $name, $value );
4902 dpurdie 1069
    $ScmGlobalOptions{$name} = $value;
1070
}
1071
 
1072
#-------------------------------------------------------------------------------
1073
# Function        : GetGlobalOption   
1074
#
1075
# Description     : Get a global toolset option
1076
#
1077
# Inputs          : $name           - Name of the option to fetch
1078
#                   $default        - Default value to return, if the option
1079
#                                     is not present.
1080
#
1081
# Returns         : The value of the option, or the default value
1082
#
1083
 
1084
sub GetGlobalOption 
1085
{
1086
    my ($name, $default) = @_;
1087
    if (exists $ScmGlobalOptions{$name})
1088
    {
1089
        $default = $ScmGlobalOptions{$name};
1090
    }
4928 dpurdie 1091
    Debug( "GetGlobalOption .", $name, $default  );
4902 dpurdie 1092
    return $default;
1093
}
1094
 
1095
 
1096
#-------------------------------------------------------------------------------
4778 dpurdie 1097
# Function        : ToolsetAddUnitTestPreProcess
1098
#                   ToolsetAddUnitTestPostProcess
1099
#                   ToolsetAddUnitTestCollateProcess
1100
#
1101
# Description     : Functions to allow toolsets to add recipes to be run before
1102
#                   and after Unit Tests are run.    
1103
#
1104
# Inputs          : $target         - Name of the recipe to be run 
1105
#
1106
# Returns         : Nothing
1107
#
1108
sub ToolsetAddUnitTestPreProcess
1109
{
1110
    _ToolsetAddUnitTest(\@TOOLSET_UTF_PRE, @_ );
1111
}
227 dpurdie 1112
 
4778 dpurdie 1113
sub ToolsetAddUnitTestPostProcess
1114
{
1115
    _ToolsetAddUnitTest(\@TOOLSET_UTF_POST, @_ );
1116
}
1117
 
1118
sub ToolsetAddUnitTestCollateProcess
1119
{
1120
    _ToolsetAddUnitTest(\@TOOLSET_UTF_COLLATE, @_ );
1121
}
1122
 
1123
#-------------------------------------------------------------------------------
1124
# Function        : _ToolsetAddUnitTest  
1125
#
1126
# Description     : Internal helper function used by ToolsetAddUnitTest*
1127
#
1128
# Inputs          : $aref           - Ref to an array of names to extend
1129
#                   $target         - Name of recipe to run 
1130
#
1131
# Returns         : Nothing
1132
#
1133
sub _ToolsetAddUnitTest
1134
{
1135
    my ($aref, $target ) = @_;
1136
 
1137
    #   Determine name of parent function
1138
    my $fname = (caller(1))[3];
1139
    $fname =~ s~.*::~~;
1140
    Debug2( "$fname ($target)" );
1141
 
1142
    #
1143
    #   Ensure user is not using a reserved target
1144
    #
1145
    if (grep {$_ eq $target} @reservedMakeTargets) {
1146
        Error("Internal: $fname uses reserved make taget: $target");
1147
    }
1148
 
1149
    push @$aref, $target;
1150
 
1151
}
1152
 
227 dpurdie 1153
###############################################################################
1154
# User interface:
1155
#
1156
#   AddFlags( 'platform [, ... ]', 'flags' [, 'flag' ... ] )
1157
#       This subroutine takes the C and C++ compiler flags
1158
#       specified adding them to a global list for later
1159
#       inclusion in the built makefile.
1160
#
1161
#   AddCFlags( 'platform [, ... ]', 'flags' [, 'flag' ... ] )
1162
#       This subroutine takes the C compiler flags
1163
#       specified adding them to a global list for later
1164
#       inclusion in the built makefile.
1165
#
1166
#   AddCXXFlags( 'platform [, ... ]', 'flags' [, 'flag' ... ] )
1167
#       This subroutine takes the C++ compiler flags
1168
#       specified adding them to a global list for later
1169
#       inclusion in the built makefile.
1170
#
1171
#   AddLintFlags( 'platform [, ... ]', 'flags' [, ... ] )
1172
#       This subroutine takes the Lint flags specified
1173
#       adding them to a global list for later inclusion
1174
#       in the built makefile.
1175
#
1176
#   AddASFlags( 'platform [, ... ]', 'flags' [, ... ] )
1177
#       This subroutine takes the Assemler flags specified
1178
#       adding them to a global list for later inclusion
1179
#       in the built makefile.
1180
#
1181
#   AddLDFlags( 'platform [, ... ]', 'flags' [, ... ] )
1182
#       This subroutine takes the Linker flags specified
1183
#       adding them to a global list for later inclusion
1184
#       in the built makefile.
1185
#
1186
#   AddDir
1187
#       This subroutine takes the directories specified adding
1188
#       them to a global include and source directory list for
1189
#       later inclusion in the built makefile.
1190
#
1191
#   AddIncDir( 'platform [, ... ]', 'dir' [, ... ] )
1192
#       This subroutine takes the include file directories
1193
#       specified adding them to a global list for later
1194
#       inclusion in the built makefile.
1195
#
1196
#   AddSrcDir( 'platform [, ... ]', 'dir' [, ... ] )
1197
#       This subroutine takes the source file directories
1198
#       specified adding them to a global list used to resolve
1199
#       Src() definitions.
1200
#
1201
#   AddLibDir( 'platform [, ... ]', 'dir' [, ... ] )
1202
#       This subroutine takes the library directories
1203
#       specified adding them to a global list for later
1204
#       inclusion in the built makefile.
1205
#
1206
#   AddSourceType( 'ext', '.c|.cc|.asm' )
1207
#       This subroutine takes the extension(s) specified by the
1208
#       programmer and adds them to a global list for later
1209
#       inclusion in the built makefile.  This list contains
1210
#       the extensions to be recognised as 'C', 'C++' or
1211
#       assembler file types.
1212
#
1213
#   AddSourceFile( 'platform [, ... ]', 'file' [, ... ] )
1214
#       This subroutine takes the non-standard source file(s)
1215
#       and adds them add it to either C, C++ or assembler
1216
#       sources and the object list.
1217
#
1218
#   Init( 'platform [, ... ]', 'rule' )
1219
#       Initialisation rule
1220
#
1221
#   Generate( 'platform [, ... ]', 'file' [, ... ] )
1222
#       This subroutine is used to add the list of given
1223
#       source files to the generate sources list, and if
1224
#       the generated source is of type C, C++ or assember
1225
#       also adds it to either C, C++ or assembler sources and
1226
#       the object lists.
1227
#
1228
#       --c             Treat as a C source file.
1229
#       --cpp           Treat as a C++ source file.
1230
#       --asm           Treat as a assembler source file.
1231
#
1232
#   Rule( 'platform [, ... ]', definition )
1233
#       This subroutine is used to add the non-standard make
1234
#       rules required to build the system.  eg. any rules
1235
#       necessary to produce a .cc & .h file from a .x file.
1236
#
1237
#   Src( 'platform [, ... ]', 'file' [, ... ], [ 'arg' [, ...]] )
1238
#       This subroutine is used to add the list of given source
1239
#       files to the sources list, and if the source is of type
1240
#       C, C++ or assember also adds it to either C, C++ or
1241
#       assembler sources and the object lists.  The optional
1242
#       list of arguments is assigned to all source files.
1243
#
1244
#       --c             Treat as a C source file.
1245
#       --cpp           Treat as a C++ source file.
1246
#       --asm           Treat as a assembler source file.
1247
#       --Shared        Shared, produces position-independent
1248
#                       code (on targets where required).
1249
#
1250
#   Lib( 'platform [, ... ]', 'name', 'obj' [, ... ] [, '-arg' [, ... ]] )
1251
#       This subroutine takes a library definition list and adds
1252
#       the  entries to the 3 libraries definition lists. 'name'
1253
#       of the library to be created.  List of the object files
1254
#       'obj' that make up this library.  List of special
1255
#       arguments 'arg' to pass to the librarian.
1256
#
1257
#   MergeLibrary( 'platform [, ... ]', 'name', 'lib' [, ... ] )
1258
#       This subroutine takes a library merge list and adds
1259
#       the  entries to the 2 merge libraries definition lists. 'name'
1260
#       of the library to be created.  List of the libraries to be merged
1261
#
1262
#   LocalScript( 'platform [, ... ]', name, ['1'] )
1263
#   Script( 'platform [, ... ]', name, ['1'] )
1264
#       This subroutine takes a list that defines the name of
1265
#       the script to be placed in the platform 'bin' directory,
1266
#       and an optional second element that defines whether the
1267
#       script should be made executable or not.
1268
#
1269
#   Prog( 'platform [, ... ]', 'name', ['obj', ... ],
1270
#               ['-llib', ... ], ['options'] )
1271
#       This subroutine takes a list that defines which program
1272
#       (binary) is to be made, what libraries and object it is
1273
#       made from, and any special commands required to perform
1274
#       the program creation.
1275
#
1276
#       @PROGS          Updated list of programs to create
1277
#
1278
#   TestProg( 'platform [, ... ]', 'name', ['obj', ... ],
1279
#               ['-llib', ... ], ['options'] )
1280
#       This subroutine takes a list that defines which test program
1281
#       (binary) is to be made, what libraries and object it is
1282
#       made from, and any special commands required to perform
1283
#       the program creation.
1284
#
1285
#       @TESTPROGS      Updated list of programs to create
1286
#
1287
#   InstallHdr( 'platform [, ... ]', 'file' [, ...], ['-arg'] )
1288
#       This subroutine takes the given list of files and adds them
1289
#       to the install header files list.  Files in this list will be
1290
#       installed into the 'local header directory' area for public
1291
#       consumption.  This is generally API files for other modules
1292
#       to use.
1293
#
1294
#       --Strip         Strip directory from source
6276 dpurdie 1295
#       --Strip=n       Strip part of directory from source
227 dpurdie 1296
#       --Full          Install using full path
1297
#       --Subdir=subdir Install within the specified sub-directory
1298
#       --Prefix=subdir   "       "     "      "      "     "
1299
#
1300
#   InstallLib( 'platform [, ... ]', 'file', ['subdir'] )
1301
#       This subroutine takes the given list of files and adds them
1302
#       to the install libraries files list.  Files in this list will
1303
#       be installed into the 'local library directory' area for
1304
#       public consumption.
1305
#
1306
#   InstallProg( 'platform [, ... ]', 'file', ['subdir'] ) )
1307
#       This subroutine takes a list that defines the executable file
1308
#       that is to be installed.  The file in this list will be
1309
#       installed into the 'local executable directory' specified for
1310
#       public consumption.
1311
#
1312
###############################################################################
1313
 
1314
 
1315
sub Include                                     # User include
1316
{
1317
    my( $path, $name ) = @_;
1318
    my( $file );
1319
 
1320
    $file = Require( $path, $name, "Include" );
1321
    push( @ScmDepends, "$file" );
1322
}
1323
 
1324
sub ForceCCompile
1325
{
1326
    CompileOptions( $_[0], 'compile_as_c' );            # Backward compatability
1327
}
1328
 
1329
#-------------------------------------------------------------------------------
1330
#   Create a data structure to define the global compiler options
1331
#    The hash is keyed by compiler option
1332
#    The value contains another hash.
1333
#       The key is a makefile variable to set ( or remove )
1334
#       The value is the value to assign to the makefile variable
1335
#       If the value is 'undef' then the variable will be deleted
1336
#
1337
#   Keys of the form key=value are also supported
1338
#
1339
#   If the value is a CODE reference, then routine will be called with the key
1340
#   and value as arguments. The return value will be utilised.
1341
#
1342
our %ScmCompilerOptions =
1343
    (
1344
        'strict_ansi'           => { 'USE_STRICT_ANSI'    => '1' },
1345
        'no_strict_ansi'        => { 'USE_STRICT_ANSI'    => '' },      # Default
1346
 
1347
        'profile'               => { 'USE_PROFILE'        => '1' },
1348
        'no_profile'            => { 'USE_PROFILE'        => '' },       # Default
1349
 
1350
 
1351
        'prod_no_optimise'      => { 'PROD_USE_OPTIMISE'   => '' },
1352
        'prod_no_debuginfo'     => { 'PROD_USE_DEBUGINFO'  => '' },     # Default
1353
        'prod_optimise'         => { 'PROD_USE_OPTIMISE'   => '1' },    # Default
1354
        'prod_debuginfo'        => { 'PROD_USE_DEBUGINFO'  => '1' },
1355
 
1356
        'debug_no_optimise'     => { 'DEBUG_USE_OPTIMISE'  => '' },     # Default
1357
        'debug_no_debuginfo'    => { 'DEBUG_USE_DEBUGINFO' => '' },
1358
        'debug_optimise'        => { 'DEBUG_USE_OPTIMISE'  => '1' },
1359
        'debug_debuginfo'       => { 'DEBUG_USE_DEBUGINFO' => '1' },    # Default
1360
 
1361
        'compile_as_cpp'        => { 'FORCE_CC_COMPILE'    => '1',
1362
                                     'FORCE_C_COMPILE'     => undef },
1363
        'compile_as_c'          => { 'FORCE_C_COMPILE'     => '1',
1364
                                     'FORCE_CC_COMPILE'    => undef },
267 dpurdie 1365
 
1366
        'no_define_source_file' => { 'DISABLE__SOURCE__' => '1' },
4928 dpurdie 1367
        'define_source_file'    => { 'DISABLE__SOURCE__' => undef },        # Default
267 dpurdie 1368
 
4928 dpurdie 1369
        'warnings_as_errors'    => { 'WARNINGS_AS_ERRORS'        => '1' },
1370
        'no_warnings_as_errors' => { 'WARNINGS_AS_ERRORS'        => undef },       # Default
1371
 
227 dpurdie 1372
    );
1373
 
1374
#
1375
#   The toolset can extend the options by setting the following hash
1376
#
1377
our %ScmToolsetCompilerOptions = ();
1378
 
1379
#
1380
#   Define default compiler options
1381
#   These are makefile variables that will be assigned
1382
#
1383
our %ScmCompilerOpts =
1384
    (
1385
        'USE_STRICT_ANSI'       => '',
1386
        'USE_PROFILE'           => '',
1387
        'PROD_USE_DEBUGINFO'    => '',
1388
        'PROD_USE_OPTIMISE'     => '1',
1389
        'DEBUG_USE_OPTIMISE'    => '',
1390
        'DEBUG_USE_DEBUGINFO'   => '1',
1391
    );
1392
 
1393
 
1394
sub CompileOptions
1395
{
1396
    my( $platforms, @elements ) = @_;
1397
    return if ( ! ActivePlatform($platforms) );
1398
 
1399
    for (@elements)
1400
    {
1401
        my $oref;
1402
 
1403
        #
1404
        #   The toolset option may be a text string or a definition
1405
        #       Name        - A text string
1406
        #       Name=Value  - A value
1407
        #
1408
        my $value;
1409
        my $key = $_;
1410
        if ( $key =~ m~(.*=)(.*)~ )
1411
        {
1412
            $key = $1;
1413
            $value = $2 || '';
1414
        }
247 dpurdie 1415
        $key = lc( $key );
227 dpurdie 1416
 
1417
        #
1418
        #   Examine the global flags
1419
        #   Then the toolset extensions
1420
        #   Then just drop it
1421
        #
1422
        unless ( $oref = ($ScmCompilerOptions{$key} || $ScmToolsetCompilerOptions{$key}) )
1423
        {
1424
            Warning ("Compile Option ignored: $_");
1425
            next;
1426
        }
1427
 
1428
        #
1429
        #   Parse the definition and adjust makefile variables as required
1430
        #   Set the value of a make variable or remove the definition
1431
        #
1432
        #   If the user value is a code reference, then call the code
1433
        #   and use the returned value as the value.
1434
        #
1435
        while ( (my($ukey, $uvalue)) = each %{$oref} )
1436
        {
1437
            if ( defined( $uvalue) )
1438
            {
1439
                if ( ref($uvalue) eq "CODE" )
1440
                {
255 dpurdie 1441
                    $uvalue = &$uvalue( $key, $value, $ukey);
227 dpurdie 1442
                    unless ( defined $uvalue )
1443
                    {
1444
                        Warning ("Compile Option ignored: $_");
1445
                        next;
1446
                    }
1447
                }
247 dpurdie 1448
                elsif ( defined $value )
1449
                {
1450
                    $uvalue = $value;
1451
                }
227 dpurdie 1452
 
1453
                $ScmCompilerOpts{$ukey} = $uvalue;
1454
            }
1455
            else
1456
            {
1457
                delete $ScmCompilerOpts{$ukey};
1458
            }
1459
        }
1460
    }
1461
}
1462
 
1463
#-------------------------------------------------------------------------------
1464
# Function        : AddFlags
1465
#                   AddCFlags
1466
#                   AddCXXFlags
1467
#                   AddASFlags
1468
#                   AddLDFlags
1469
#                   AddLintFlags
1470
#
1471
# Description     : Add target specfic flags to the C compiler
1472
#                   This SHOULD only be used to add Defines to the compiler
1473
#                   but it can be absued.
1474
#
1475
# Inputs          : $platform       - Platforms for which the directive is active
1476
#                   ...             - list of flags to add
1477
#
1478
#                   Embedded options include:
1479
#                       --Debug     - Following options are added to the debug build
1480
#                       --Prod      - Following options are added to the production build
1481
#
1482
# Returns         : Nothing
1483
#
1484
 
1485
sub AddFlags
1486
{
1487
    my( $platforms, @elements ) = @_;
1488
 
1489
    AddCFlags( $platforms, @elements );
1490
    AddCXXFlags( $platforms, @elements );
1491
}
1492
 
1493
sub AddCFlags
1494
{
1495
    my( $platforms, @elements ) = @_;
1496
 
1497
    Debug2( "AddCFlags($platforms, @elements)" );
1498
    return if ( ! ActivePlatform($platforms) );
1499
 
1500
    WarnIfNastyFlag( @elements );
1501
    __AddFlags( "CFLAGS", \@elements,
1502
                \@CFLAGS, \@CLINTFLAGS,
1503
                \@CFLAGS_DEBUG, \@CLINTFLAGS_DEBUG,
1504
                \@CFLAGS_PROD,  \@CLINTFLAGS_PROD );
1505
}
1506
 
1507
sub AddCXXFlags
1508
{
1509
    my( $platforms, @elements ) = @_;
1510
 
1511
    Debug2( "AddCXXFlags($platforms, @elements)" );
1512
    return if ( ! ActivePlatform($platforms) );
1513
 
1514
    WarnIfNastyFlag( @elements );
1515
    __AddFlags( "CXXFLAGS", \@elements,
1516
               \@CXXFLAGS, \@CXXLINTFLAGS,
1517
               \@CXXFLAGS_DEBUG, \@CXXLINTFLAGS_DEBUG,
1518
               \@CXXFLAGS_PROD,  \@CXXLINTFLAGS_PROD );
1519
}
1520
 
1521
sub AddASFlags
1522
{
1523
    my( $platforms, @elements ) = @_;
1524
 
1525
    Debug2( "AddASFlags($platforms, @elements)" );
1526
 
1527
    return if ( ! ActivePlatform($platforms) );
1528
 
267 dpurdie 1529
    __AddFlags( "ASFLAGS", \@elements,
1530
                \@ASFLAGS, undef,
1531
                \@ASFLAGS_DEBUG, undef,
1532
                \@ASFLAGS_PROD, undef );
227 dpurdie 1533
}
1534
 
1535
sub AddLDFlags
1536
{
1537
    my( $platforms, @elements ) = @_;
1538
 
1539
    Debug2( "AddLDFlags($platforms, @elements)" );
1540
 
1541
    return if ( ! ActivePlatform($platforms) );
1542
 
1543
    foreach  ( @elements )
1544
    {
267 dpurdie 1545
        next if ( m~^--(Debug|Prod)~ );
227 dpurdie 1546
        Warning("Use of linker flag discouraged (will be used): $_");
7018 dpurdie 1547
        if ( $ScmToolsetProperties{'LdFlagSpace'} ) {
1548
            $_ =~ s/\s/\$(spacealt)/g;
1549
        }
227 dpurdie 1550
    }
7010 dpurdie 1551
 
1552
 
1553
 
267 dpurdie 1554
    __AddFlags( "LDFLAGS", \@elements,
1555
                \@LDFLAGS, undef,
1556
                \@LDFLAGS_DEBUG, undef,
1557
                \@LDFLAGS_PROD, undef );
227 dpurdie 1558
 
1559
}
1560
 
1561
sub AddLintFlags
1562
{
1563
    my( $platforms, @elements ) = @_;
1564
 
1565
    return if ( ! ActivePlatform($platforms) );
1566
 
1567
    Debug2( "AddLintFlags($platforms, @elements)" );
1568
 
1569
    __AddFlags( "LINTFLAG", \@elements,
1570
                \@CLINTFLAGS, \@CXXLINTFLAGS,
1571
                \@CLINTFLAGS_DEBUG, \@CXXLINTFLAGS_DEBUG,
1572
                \@CLINTFLAGS_PROD, \@CXXLINTFLAGS_PROD  );
1573
}
1574
 
1575
 
1576
#-------------------------------------------------------------------------------
1577
# Function        : __AddFlags
1578
#
1579
# Description     : Generic flag adding to lists routine
1580
#                   Internal use only
1581
#
1582
#                   Supports --Debug and --Prod options
1583
#                   if the appropriate list is present.
1584
#
1585
# Inputs          : Lots
1586
#                   References to compiler and lint flags for
1587
#                   common, debug and product builds.
1588
#
1589
#                   Not all the lists are needed.
1590
#
1591
# Returns         : Nothing
1592
#
1593
sub __AddFlags
1594
{
1595
    my ($textname, $eref,
1596
                   $f_all,      $flint_all,
1597
                   $f_debug,    $flint_debug,
1598
                   $f_prod,     $flint_prod ) = @_;
1599
 
1600
    #
1601
    #   Start added flags to the ALL lists
1602
    #
1603
    my $list = $f_all;
1604
    my $lintlist = $flint_all;
1605
    my $nowarn = 0;
1606
 
1607
    #
1608
    #   Process flags up front
1609
    #
1610
    $nowarn = 1 if ( grep (/^--NoWarn$/, @$eref) );
1611
 
1612
    #
1613
    #   Process all the user arguments
1614
    #
1615
    ADD:
1616
    foreach my $element ( @$eref )
1617
    {
1618
        #
1619
        #   Skip flags
1620
        #
1621
        if ( $element eq '--NoWarn' )
1622
        {
1623
            next;
1624
        }
1625
 
1626
        #
1627
        #   Detect --Debug and --Prod options and swap
1628
        #   lists accordingly.
1629
        #
1630
        if ( $element eq '--Debug' )
1631
        {
1632
            Error ("--Debug not supported for $textname") unless ( $f_debug );
1633
            $list = $f_debug;
1634
            $lintlist = $flint_debug;
1635
            next;
1636
        }
1637
 
1638
        if ( $element eq '--Prod' )
1639
        {
1640
            Error ("--Prod not supported for $textname") unless ( $f_prod );
1641
            $list = $f_prod;
1642
            $lintlist = $flint_prod;
1643
            next;
1644
        }
1645
 
1646
        #
1647
        #   Scan all the lists for a possible duplicates
1648
        #
1649
        foreach my $temp ( @$f_all, @$f_debug, @$f_prod ) {
1650
            if ($temp eq $element) {
1651
                Warning( "Duplicate $textname ignored '$element'") unless $nowarn;
1652
                next ADD;
1653
            }
1654
        }
1655
 
1656
        #
1657
        #   Add the flag to the compiler and lint lists
1658
        #
1659
        push( @$list, $element ) if $list;
1660
        push( @$lintlist, $element ) if $lintlist;
1661
    }
1662
}
1663
 
1664
sub WarnIfNastyFlag
1665
{
1666
    foreach  ( @_ )
1667
    {
1668
        Warning("Use of compiler flags discouraged (will be used): $_")
1669
            unless ( m/^-[DU]/ || m/^--Debug/ || m/^--Prod/ || /^--NoWarn/ );
1670
    }
1671
}
1672
 
1673
 
1674
sub AddDir
1675
{
1676
    AddIncDir( @_);
1677
    AddSrcDir( @_ );
1678
}
1679
 
1680
 
1681
sub AddIncDir
1682
{
1683
    _AddDir( 'AddIncDir', 'INCDIR', \@INCDIRS, \@S_INCDIRS, \@G_INCDIRS, \@L_INCDIRS, @_ );
1684
}                                                           
1685
 
1686
sub AddSrcDir                                               
1687
{                                                           
1688
    _AddDir( 'AddSrcDir', 'SRCDIR', \@SRCDIRS, \@S_SRCDIRS, \@G_SRCDIRS, \@L_SRCDIRS, @_ );
1689
}                                                           
1690
 
1691
sub AddLibDir                                               
1692
{                                                           
1693
    _AddDir( 'AddLibDir', 'LIBDIR', \@LIBDIRS, \@S_LIBDIRS, \@G_LIBDIRS, \@L_LIBDIRS, @_ );
1694
}
1695
 
1696
#-------------------------------------------------------------------------------
1697
# Function        : _AddDir
1698
#
1699
# Description     : Internal routine to add a directory to list of directories
1700
#                   Common code to simplify implementation of other directives
1701
#
1702
# Inputs          : $name           - Name of function
1703
#                   $udir           - User name of dir list
1704
#                   $dirref         - Reference to directory array
1705
#                   $s_dirref       - Reference to system directory array
1706
#                   $g_dirref       - Reference to global directory array
1707
#                   $l_dirref       - Reference to local directory array
1708
#                   @args           - User arguments
1709
#                                       - platforms
1710
#                                       - Directories and --Options
1711
#
1712
sub _AddDir
1713
{
1714
    my( $name, $udir, $dirref, $s_dirref, $g_dirref, $l_dirref, $platforms, @elements ) = @_;
1715
 
1716
    Debug ( "$name($platforms, @elements)" );
1717
    Error ( "$name: Insufficient arguments") unless ( @elements );
1718
    return if ( ! ActivePlatform($platforms) );
1719
 
1720
    #
1721
    #   Cleanup user parameters
1722
    #
1723
    foreach ( @elements )
1724
    {
1725
        s/^\s+//;                               # Remove leading space
1726
        s/\s+$//;                               # Remove trailing spaces
1727
        s~/$~~;                                 # Remove trailing /
1728
        s~//~/~g;                               # Remove multiple /
1729
    }
1730
 
1731
#.. Collect arguments
1732
    my $tlist_ref = $ScmGlobal ? $g_dirref : $l_dirref; # "current" scope ....
1733
    my $nowarn = 0;
1734
    my $nodepend = 0;
1735
    my @dirs;
1736
 
1737
    foreach ( @elements )
1738
    {
1739
        if ( ! /^--/ ) {                        # Collect directories
1740
            push @dirs, $_;
1741
 
1742
        } elsif (/^--Local$/) {                 # "local" scope ....
1743
            $tlist_ref = $l_dirref;
1744
 
1745
        } elsif (/^--Global$/) {                # "global" scope ...
1746
            $tlist_ref = $g_dirref;
1747
 
1748
        } elsif (/^--System$/) {                # "system" scope ...
1749
            $tlist_ref = $s_dirref;
1750
 
1751
        } elsif (/^--NoDepend$/) {              # Split from dependency list
1752
            if ( $udir eq 'INCDIR' ) {          # AddIncDir only
1753
                $nodepend = 1;
1754
            }
1755
 
1756
        } elsif (/^--NoWarn$/) {                # Disable warnings
1757
            $nowarn = 1;
1758
 
1759
        } elsif (/^--(.*)/) {
1760
            Message( "$name: unknown option $_ -- ignored\n" );
1761
 
1762
        }
1763
    }
1764
 
1765
    Error ( "$name: No directory specified: ($platforms, @elements)" )
1766
        unless ( @dirs );
1767
 
1768
 
1769
#.. Push source path(s)
1770
    foreach ( @dirs )
1771
    {
1772
        #
1773
        #   Add to complete list of directories
1774
        #   Warn on duplicates
1775
        #
1776
        unless ( UniquePush( $dirref, $_) )
1777
        {
1778
            Warning( "Duplicate $udir ignored '$_'" )
1779
                unless ( $nowarn );
1780
            next;
1781
        }
1782
 
1783
        #
1784
        #   Check that the directory actually exists
1785
        #   If the path contains a $(XXXXX) then it can't be checked
1786
        #
1787
        if ( index( $_, '$' ) == -1 )
1788
        {
1789
            Warning( "$name. Directory not found: $_",
1790
                     "Current directory         : $::Cwd",
2450 dpurdie 1791
                     "Cannot resolved Directory : " . AbsPath($_, $::Cwd, 1),
227 dpurdie 1792
                       )
1793
                unless ( $nowarn || -d $_ );
1794
        }
1795
 
1796
        #
1797
        #   Add to suitable list
1798
        #
1799
        push @{$tlist_ref}, $_;
6133 dpurdie 1800
        ToolsetFiles::AddDir($_, 'Include');
227 dpurdie 1801
 
1802
        #
1803
        #   Add to the no dependancy list (ie generated depend file)
1804
        #   Only used by AddIncDir, accepted by AddSrcDir
1805
        #
1806
        push( @NODEPDIRS, $_ )
1807
            if ($nodepend);
1808
    }
1809
}
1810
 
6177 dpurdie 1811
#-------------------------------------------------------------------------------
1812
# Function        : ExtendIncDir 
1813
#
1814
# Description     : Allow the directory search paths to be extended into sub
1815
#                   directories.
1816
#                   
1817
#                   Limit use, but ...
1818
#
1819
# Inputs          : $platform       - Active platforms
1820
#                   ...             - Path extensions
1821
#
1822
# Returns         : 
1823
#
1824
my  %ExtendIncDirSeen;
1825
sub ExtendIncDir
1826
{
1827
    my( $platforms, @paths ) = @_;
1828
    Debug2( "ExtendIncDir($platforms, @paths)" );
1829
    return if ( ! ActivePlatform($platforms) );
1830
    Error ('ExtendIncDir. No extensions listed') unless @paths;
1831
    #
1832
    #   Ensure the user only extends the paths once.
1833
    #   Could silently discard excess - better to force the user to get it right
1834
    #
1835
    foreach my $path ( @paths) {
1836
        ReportError ('ExtendIncDir. Multiple defintions for: ' . $path) if exists $ExtendIncDirSeen{$path}; 
1837
        $ExtendIncDirSeen{$path} = 0;
1838
    }
1839
    ErrorDoExit();
227 dpurdie 1840
 
6177 dpurdie 1841
    #
1842
    #   Zip though all the packages and extend the search paths
1843
    #   Also gets those in the interface directory
1844
    #
1845
    for my $package (@{$::ScmBuildPkgRules{$ScmPlatform} })
1846
    {
1847
        #DebugDumpData("package", $package);
1848
        foreach my $path ( @paths)
1849
        {
1850
            if ( $package->{PINCDIRS})
1851
            {
1852
                my @output;
1853
                foreach my $pdir ( @{$package->{PINCDIRS}})
1854
                {
1855
                    my $tdir = catdir ($pdir, $path);
1856
                    my $adir = catdir ($package->{ROOT}, $tdir);
1857
                    if ( -d $adir) {
1858
                        Verbose("Extending $package->{DNAME} $package->{VERSION}: $tdir");
1859
                        push @output, $tdir;
1860
                        $ExtendIncDirSeen{$path}++;
1861
                    }
1862
                    push @output, $pdir;
1863
                }
1864
              @{$package->{PINCDIRS}} = @output;
1865
            }
1866
        }
1867
    }
1868
 
1869
    #
1870
    #   Report extensions that have not been used
1871
    #
1872
    foreach my $path ( @paths) {
1873
        ReportError ('ExtendIncDir. Search path not extendable: ' . $path) unless $ExtendIncDirSeen{$path}; 
1874
    }
1875
 
1876
    ErrorDoExit();
1877
}
1878
 
1879
 
227 dpurdie 1880
sub AddProg
1881
{
1882
    my( $platforms, @progs ) = @_;
1883
 
1884
    Debug2( "AddProg($platforms, @progs)" );
1885
 
1886
    return if ( ! ActivePlatform($platforms) );
1887
 
285 dpurdie 1888
    foreach my $prog (@progs)
227 dpurdie 1889
    {
289 dpurdie 1890
        my $pProg = $PROGS->Get($prog);
227 dpurdie 1891
        Warning( "Duplicate prog ignored '$prog'" )
289 dpurdie 1892
            if ( $pProg );
1893
        $pProg = $PROGS->NewAdd($prog)
227 dpurdie 1894
    }
1895
}
1896
 
1897
 
1898
sub AddSourceType
1899
{
1900
    my( $ext, $type ) = @_;
1901
 
1902
    Debug2( "AddSourceType(@_)" );
1903
 
1904
    #
1905
    #   Default Source Type (C)
1906
    #
1907
    $type = ".c" unless ( $type );
1908
 
1909
    Error ("Source type '$ext' not allowed")
1910
        if ( $ext !~ /^\.\w+$/ );
1911
 
1912
    $type = lc($type)
1913
        if ( $::ScmHost ne "Unix" );
1914
    $ScmSourceTypes{ $ext } = $type;
1915
}
1916
 
1917
 
1918
sub AddSourceFile
1919
{
1920
    my( $platforms, @elements ) = @_;
1921
 
1922
    Debug2( "AddSourceFile($platforms, @elements)" );
1923
    return if ( ! ActivePlatform($platforms) );
1924
 
285 dpurdie 1925
    foreach my $path ( @elements )
227 dpurdie 1926
    {
1927
        __AddSourceFile( 1, $path );
1928
    }
1929
}
1930
 
1931
 
1932
#-------------------------------------------------------------------------------
1933
# Function        : __AddSourceFile
1934
#
1935
# Description     : Internal function
1936
#                   Add a source file to internal lists
1937
#
1938
#                   Assumes that the current platform is ACTIVE
1939
#
1940
# Inputs          : push    0: Don't push onto OBJS (non-shared objfiles)
1941
#                   path    Filename.extension
1942
#                   obj     object file name (optional)
1943
#                   type    Type of file. "" -> auto detect
1944
#
1945
# Returns         : True        - File is a 'known' source file
1946
#                   False       - File is not a 'known' source file
1947
#
1948
sub __AddSourceFile
1949
{
1950
    my( $push, $path, $obj, $type ) = @_;
271 dpurdie 1951
    my( $filename, $ext, $srcfile, $is_obj, $ext_type, $result );
227 dpurdie 1952
 
271 dpurdie 1953
    $filename = StripDir($path);                # file name
227 dpurdie 1954
 
1955
    $ext  = StripFile($path);                   # extension
1956
    $ext = lc($ext)
1957
        if ( $::ScmHost ne "Unix" );
1958
 
271 dpurdie 1959
    if (! ($srcfile = $SRCS{$filename})) {
227 dpurdie 1960
        $srcfile = $path;                       # generated
1961
    }
1962
 
271 dpurdie 1963
    $obj  = StripExt( $filename )               # Base name of object file
227 dpurdie 1964
        if ( ! defined($obj) || $obj eq "" );
1965
 
1966
    $type = ""                                  # optional type
1967
        if ( ! defined( $type ) );
1968
 
1969
    #
1970
    #   Push file onto a suitable source file list
1971
    #
1972
    $result = 0;
1973
    $ext_type = "";                             # map extension
1974
    $ext_type = $ScmSourceTypes{ $ext }
1975
        if ( exists( $ScmSourceTypes{ $ext } ) );
1976
    $result = 1 if ( $ext_type );
1977
 
1978
    if ( $type eq "" && defined $::ScmToolsetProgSource{$ext} )
1979
    {
1980
        Debug( "SourceFile: $path is ToolsetProgSource   -> $srcfile" );
1981
        push( @CSRCS, $srcfile );
1982
        $result = 1;
1983
    }
1984
    elsif ( ($type eq "" && $ext_type eq ".h") || ($type eq ".h") )
1985
    {
1986
        Debug( "SourceFile: $path is .h   -> $srcfile" );
1987
        push( @CHDRS, $srcfile );
1988
    }
1989
    elsif ( ($type eq "" && $ext_type eq ".inc") || ($type eq ".inc") )
1990
    {
1991
        Debug( "SourceFile: $path is .inc -> $srcfile" );
1992
        push( @ASHDRS, $srcfile );
1993
    }
1994
    elsif ( ($type eq "" && $ext_type eq ".c") || ($type eq ".c") )
1995
    {
1996
        Debug( "SourceFile: $path is .c   -> $srcfile=$obj" );
1997
        push( @CSRCS, $srcfile );
1998
        $is_obj = 1;
1999
    }
2000
    elsif ( ($type eq "" && $ext_type eq ".cc") || ($type eq ".cc") )
2001
    {
2002
        Debug( "SourceFile: $path is .cc  -> $srcfile=$obj" );
2003
        push( @CXXSRCS, $srcfile );
2004
        $is_obj = 1;
2005
    }
2006
    elsif ( ($type eq "" && $ext_type eq ".asm") || ($type eq ".asm") )
2007
    {
2008
        Debug( "SourceFile: $path is .asm -> $srcfile=$obj" );
2009
        push( @ASSRCS, $srcfile );
2010
        $is_obj = 1;
2011
    }
2012
    elsif ( $ext_type eq "--Ignore" )
2013
    {   # ignored ...
2014
        #   .x      "rpcgen" source files
2015
        #   .ini    Configuration
2016
        #   .sh     Shell script
2017
    }
2018
    else
2019
    {
2020
        Debug( "SourceFile: $path is unknown file type" );
2021
 
2022
        #
2023
        #   Insert source files with unknown extensions onto lists
2024
        #   of there own type
2025
        #
2026
        if ( $ext )
2027
        {
2028
            (my $varname = uc ( $ext . 'SRCS')) =~ s~\.~~g;
2029
            no strict 'refs';
2030
            push @$varname, $srcfile;
2031
            use strict 'refs';
2032
        }
2033
    }
2034
 
2035
    #
271 dpurdie 2036
    #   See if there is a hook function for this type of source file
2037
    #   Invoke user function to perform additional processing on the file
2038
    #
2039
    if ( %MF_RegisterSrcHooks )
2040
    {
2041
        my @listeners;
2042
        push @listeners, @{$MF_RegisterSrcHooks{$ext}} if ( exists $MF_RegisterSrcHooks{$ext} );
2043
        push @listeners, @{$MF_RegisterSrcHooks{'*'}}  if ( exists $MF_RegisterSrcHooks{'*'} );
2044
        while ( @listeners )
2045
        {
2046
            Debug( "RegisterSrcHook: Invoke SrcHook function" );
2047
            my ($fname, @args) = @{shift @listeners};
2048
            &$fname ( $srcfile ,$filename, $obj, $ext ,@args );
2049
        }
2050
    }
2051
 
2052
    #
227 dpurdie 2053
    #   Object files are saved in
2054
    #       OBJSOURCE   - Generate a recipe to create the object
2055
    #       OBJS        - A list of ALL non-shared object files
2056
    #
6133 dpurdie 2057
    if ( $is_obj && $::o && $ScmNotGeneric )
227 dpurdie 2058
    {
2059
        $OBJSOURCE{ "$obj" } = $srcfile;
2060
        push( @OBJS, $obj )
2061
            if ($push);
2062
    }
2063
 
2064
    #
2065
    #   Indicate to the user that the file is a 'known' source file
2066
    #   This implies that the file is required early in the build process
2067
    #   and may need to be generated early.
2068
    #
2069
    return $result;
2070
}
2071
 
2072
#-------------------------------------------------------------------------------
2073
# Function        : SetValue
2074
#
2075
# Description     : Defines a variable that can be used within the makefile.pl
2076
#                   Use sparingly
2077
#                   An attempt to formalise a mechanism that is used anyway, but
2078
#                   with correct platform detection
2079
#
2080
# Inputs          : $platform       - Platform selector
2081
#                   $name           - Name to set
2082
#                   $value          - Value to set
2083
#                   options         - Options
2084
#                                       --NoWarn
2085
#                                       --Project=xxxx[,xxxx]+
2086
#                                       --
2087
#
2088
sub SetValue
2089
{
2090
    my( $platforms, @elements ) = @_;
2091
    my $name;
2092
    my $value;
2093
    my $nowarn;
2094
    my $nomoreswicthes = 0;
2095
 
2096
    Debug2( "SetValue($platforms, @elements)" );
2097
 
2098
    return if ( ! ActivePlatform($platforms) );
2099
 
2100
    #
2101
    #   Process elements extracting values and options
2102
    #
2103
    foreach ( @elements )
2104
    {
2105
        if ( m/^--$/ ) {
2106
            $nomoreswicthes = ! $nomoreswicthes;
2107
            next;
2108
        }
2109
 
2110
        if ( m/^--/ && ! $nomoreswicthes )
2111
        {
2112
 
2113
            if ( m/^--NoWarn/ ) {
2114
                $nowarn = 1;
2115
 
2116
            } elsif ( m/^--Project=(.*)/ ) {
2117
                return unless ( ActiveProject( $1) );
2118
 
2119
            } else {
2120
                Error ("SetValue: Unknown option: $_");
2121
 
2122
            }
2123
 
2124
        } elsif ( ! defined $name ) {
2125
            $name = $_;
2126
 
2127
        } elsif ( ! defined $value ) {
2128
            $value = $_;
2129
 
2130
        } else {
2131
            Error ("SetValue: $name. Too many parameters" );
2132
 
2133
        }
2134
    }
2135
 
2136
    #
2137
    #   Warn if the named variable already exists
2138
    #   It may be a JATS internal or it may be a user.
2139
    #
2140
    unless ( $nowarn )
2141
    {
2142
        no strict 'refs';
2143
        Warning("SetValue: $name. Redefined") if defined ( $$name );
2144
        use strict 'refs';
2145
    }
2146
 
2147
    #
2148
    #   Set the value
2149
    #
2150
    no strict 'refs';
2151
    $$name = $value;
2152
    use strict 'refs';
2153
}
2154
 
2155
#-------------------------------------------------------------------------------
2156
# Function        : SetList
2157
#
2158
# Description     : Defines a list variable that can be used within the makefile.pl
2159
#                   Use sparingly
2160
#                   An attempt to formalise a mechanism that is used anyway, but
2161
#                   with correct platform detection
2162
#
2163
# Inputs          : $platform       - Platform selector
2164
#                   $name           - Name to set
2165
#                   $value,...      - Values to set
2166
#                   options         - Options
2167
#                                       --NoWarn
2168
#                                       --Project=xxxx[,xxxx]+
2169
#                                       --Unique
2170
#                                       --Clear
2171
#                                       --Append
2172
#                                       --
2173
#
2174
my %SetList_names;
2175
sub SetList
2176
{
2177
    my( $platforms, @elements ) = @_;
2178
    my $name;
2179
    my @value;
2180
    my $nowarn;
2181
    my $unique;
2182
    my $clear;
2183
    my $nomoreswicthes = 0;
2184
 
2185
    Debug2( "SetList($platforms, @elements)" );
2186
 
2187
    return if ( ! ActivePlatform($platforms) );
2188
 
2189
    #
2190
    #   Process elements extracting values and options
2191
    #
2192
    foreach ( @elements )
2193
    {
2194
        if ( m/^--$/ ) {
2195
            $nomoreswicthes = ! $nomoreswicthes;
2196
            next;
2197
        }
2198
 
2199
        if ( m/^--/ && ! $nomoreswicthes )
2200
        {
2201
            if ( m/^--NoWarn/ ) {
2202
                $nowarn = 1;
2203
 
2204
            } elsif ( m/^--Project=(.*)/ ) {
2205
                return unless ( ActiveProject( $1) );
2206
 
2207
            } elsif ( m/^--Unique/ ) {
2208
                $unique = 1;
2209
 
2210
            } elsif ( m/^--Clear/ ) {
2211
                $clear = 1;
2212
 
2213
            } elsif ( m/^--Append/ ) {
2214
                $clear = 0;
2215
 
2216
            } else {
2217
                Error ("SetList: Unknown option: $_");
2218
            }
2219
        } elsif ( ! defined $name ) {
2220
            $name = $_;
2221
 
2222
        } else {
2223
            push @value, $_;
2224
 
2225
        }
2226
    }
2227
 
2228
    Error ("SetList: No name specified") unless ( $name );
2229
 
2230
    #
2231
    #   Warn if the named variable already exists
2232
    #   It may be a JATS internal or it may be a user.
2233
    #
2234
    #   Only do this iff the name is not known to this function
2235
    #   Keep a list a names that have been set.
2236
    #
2237
    if ( ! $SetList_names{$name} && ! $nowarn )
2238
    {
2239
        no strict 'refs';
4455 dpurdie 2240
        Warning("SetList: $name. Defined outside the ScanList/SetList directive","May clash with Jats internals") if ( @$name );
227 dpurdie 2241
        use strict 'refs';
2242
    }
2243
    $SetList_names{$name} = 1;
2244
 
2245
    #
2246
    #   Clear list
2247
    #
2248
    if ( $clear )
2249
    {
2250
        no strict 'refs';
2251
        @$name = ();
2252
        use strict 'refs';
2253
    }
2254
 
2255
    #
2256
    #   Set the value
2257
    #
2258
    no strict 'refs';
2259
    if ( $unique ) {
2260
        UniquePush( \@$name, @value);
2261
    } else {
2262
        push @$name, @value;
2263
    }
2264
    use strict 'refs';
2265
}
2266
 
2267
#-------------------------------------------------------------------------------
2268
# Function        : ScanList
2269
#
2270
# Description     : Create a list by scanning for files in a directory
2271
#                   The files may be in a local directory or within a package
2272
#                   Care must be taken when using a package as the results
2273
#                   may differ bewteen BuildPkgArchive and LinkPkgArchive
2274
#
2275
#                   Interworks with SetList
2276
#
2277
# Inputs          : $platform       - Platform selector
2278
#                   $name           - Name to set
2279
#                   $value,...      - Values to set
2280
#                   options         - Options
2281
#                                       --NoWarn
2282
#                                       --Project=xxxx[,xxxx]+
2283
#                                       --Unique
2284
#                                       --Clear
2285
#                                       --Append
2286
#
2287
#                                       --Package=xxxx[,ext]
2288
#                                       --Dir=xxx
2289
#
2290
#                                       --Subdir=yyy
2291
#                                       --DirListOnly
2292
#                                       --FileListOnly
335 dpurdie 2293
#                                       --Recurse (default)
227 dpurdie 2294
#                                       --NoRecurse
335 dpurdie 2295
#                                       --FullPath (default)
2296
#                                       --NoFullPath
227 dpurdie 2297
#
2298
#                                       --FilterIn=xxx
2299
#                                       --FilterInRe=xxx
2300
#                                       --FilterOut=xxx
2301
#                                       --FilterOutRe=xxx
2302
#
2303
# Returns         :
2304
#
2305
sub ScanList
2306
{
2307
    my( $platforms, @elements ) = @_;
2308
    my $name;
2309
    my $package;
2310
    my $dir;
2311
    my $subdir;
2312
    my @set_args;
2313
    my $search = JatsLocateFiles->new('Recurse','FullPath' );
2314
 
2315
    Debug2( "ScanList($platforms, @elements)" );
2316
 
2317
    return if ( ! ActivePlatform($platforms) );
2318
 
2319
    #
2320
    #   Process elements extracting values and options
2321
    #
2322
    foreach ( @elements )
2323
    {
2324
        if ( m/^--Unique|--Clear|--Append|--NoWarn/ ) {
2325
            push @set_args, $_;
2326
 
2327
        } elsif ( m/^--Project=(.*)/ ) {
2328
            return unless ( ActiveProject( $1) );
2329
 
2330
        } elsif ( m/^--Package=(.*)/ ) {
2331
            $package = $1;
2332
 
2333
        } elsif ( m/^--Dir=(.*)/ ) {
2334
            $dir = $1;
2335
 
2336
        } elsif ( m/^--Subdir=(.*)/ ) {
2337
            $subdir = $1;
2338
 
2339
        } elsif ( $search->option( $_ ) ) {
2340
            Verbose ("Search Option: $_" );
2341
 
2342
        } elsif ( m/^--/ ) {
2343
            Error ("ScanList: Unknown option: $_");
2344
 
2345
        } elsif ( ! defined $name ) {
2346
            $name = $_;
2347
 
2348
        } else {
2349
                Error ("ScanList $name: Unknown option: $_");
2350
 
2351
        }
2352
    }
2353
 
2354
    Error ("ScanList: No variable name specified") unless ( $name );
2355
    Error ("ScanList: Must Specify --Dir or --Package") unless ( $dir || $package );
2356
    Error ("ScanList: --Dir and --Package are mutually exclusive") if ( $dir && $package );
2357
 
2358
    #
2359
    #   Locate the base of the scan
2360
    #   This may be either a package name or a local directory
2361
    #
2362
    #   Its no use allowing the user to use OBJ/LIB/BIN directories as the
2363
    #   directories MUST exist at build time. Don't really want the user doing
2364
    #   that level of poking out of a package
2365
    #
2366
    if ( $package )
2367
    {
2368
        $dir = GetPackageBase( "ScanList", $package );
2369
        Error ("ScanList: Package not found: $package") unless ( $dir );
2370
    }
2371
    else
2372
    {
2373
        Error ("ScanList: Root directory not found: $dir") unless ( -d $dir );
2374
    }
2375
    if ( $subdir )
2376
    {
2377
        $dir .= "/" . $subdir;
2378
        Error ("ScanList: Sub directory not found: $subdir") unless ( -d $dir );
2379
    }
2380
 
2381
    #
2382
    #   Use SetList to do the rest of the work
2383
    #
2384
    SetList( $platforms, $name, @set_args, '--', $search->search($dir) );
2385
}
2386
 
2387
 
2388
sub Init
2389
{
2390
    push( @INITS, @_ );
2391
}
2392
 
2393
#-------------------------------------------------------------------------------
2394
# Function        : Generate
2395
#
2396
# Description     : Legacy Function - don't use unless you have too.
2397
#                   Flags files that are to be generated during the
2398
#                   early 'generate' make phase. Will also add named files
2399
#                   to various internal lists
2400
#
2401
#                   Intended to be used in conjunction with the 'Rule' directive
2402
#                   to flag header and source files that need to be created early
2403
#                   in the build process.
2404
#
2405
# Inputs          : See GenerateSrcFile
2406
#
2407
# Returns         : 
2408
#
2409
sub Generate
2410
{
2411
    my( $platforms, @elements ) = @_;
2412
 
2413
    Debug2( "Generate($platforms, @elements)" );
2414
 
2415
    return if ( ! ActivePlatform($platforms) );
2416
    Message("Generate directive used. Consider replacing with GenerateFiles");
2417
 
2418
    #
2419
    #   Use Non-warning version to do the hard work
2420
    #
2421
    GenerateSrcFile( 1, @elements );
2422
}
2423
 
2424
#-------------------------------------------------------------------------------
2425
# Function        : Generated
2426
#
2427
# Description     : Legacy Function - don't use unless you have too.
2428
#                   Flags files that are generated by misc Rules
2429
#
2430
#                   Intended to be used in conjunction with the 'Rule' directive
2431
#                   to mark files that have been generated, so that they can be
2432
#                   cleaned up.
2433
#
2434
#                   Note the difference to the 'Generate' directive which will
2435
#                   ensure that the Rule will be run in the 'generate' phase,
2436
#                   this directive doesn't.
2437
#
2438
# Inputs          : Files with internal Makefile Paths and codes
2439
#                   Eg: Generated( '*', "\$(LIBDIR)/libcsf\$(GBE_TYPE).\${a}" );
2440
#                   See why its YUK!
2441
#
2442
# Returns         : 
2443
#
2444
sub Generated
2445
{
2446
    my( $platforms, @elements ) = @_;
2447
    my( @args );
2448
 
2449
    return if ( ! ActivePlatform($platforms) );
2450
    Debug2( "Generated($platforms, @elements)" );
2451
 
2452
    #.. Collect arguments
2453
    #
2454
    foreach ( @elements )
2455
    {
2456
        if ( /^-(.*)/ )
2457
        {
2458
            Debug( "Gen: arg $_" );
2459
            push ( @args, $_);
2460
        }
2461
    }
2462
 
2463
    #.. Push source file(s)
2464
    #
2465
    foreach ( @elements )
2466
    {
2467
        if ( ! /^-(.*)/ )
2468
        {
2469
            Debug( "Generated: $_ (@args)" );
2470
            push (@USERGENERATED, $_);
2471
 
2472
            #
2473
            #   Add the file to the list of known source files
2474
            #   This will allow them to be packaged
2475
            #
2476
            GenerateSrcFile (0, $_ );
2477
        }
2478
    }
2479
}
2480
 
2481
 
2482
#-------------------------------------------------------------------------------
2483
# Function        : GenerateSrcFile
2484
#
2485
# Description     : Internal Function (No $platform)
2486
#                   Determine how to handle a 'Generated' file
2487
#
2488
#
2489
# Inputs          : $generated          - 0: Don't add to GENERATED List
2490
#                                         1: Add to GENERATED List
2491
#                                         2: Add to GENERATED List, if a source file
2492
#                   FileName(s)         - Name of one or more files to process
2493
#                                         All files are processed in the same way
2494
#                                         These file may contain Makefile prefixes
2495
#                                         ie: $(OBJDIR)/file.obj
2496
#                   Options:
2497
#                       --c             - Hint: Its a "C" file
2498
#                       --cpp           - Hint: Its a C++ file
2499
#                       --asm           - Hint: Its an ASM file
2500
#                       -*              - Save as argument attached to the file
2501
#
303 dpurdie 2502
# Returns         : Number of 'source' file
227 dpurdie 2503
#
2504
sub GenerateSrcFile                             # Internal Function - no $platform
2505
{
2506
    my( $generated, @elements ) = @_;
2507
    my( $type, @args );
303 dpurdie 2508
    my $result = 0;
227 dpurdie 2509
 
2510
    Debug2( "GenerateSrcFile($generated,@elements)" );
2511
 
2512
    #.. Collect arguments
2513
    #
2514
    $type = "";
2515
    foreach ( @elements )
2516
    {
2517
        if ( /^--c$/ ) {
2518
            Debug( "Gen: --c" );
2519
            $type = ".c";
2520
 
2521
        } elsif ( /^--cpp$/ ) {
2522
            Debug( "Gen: --cpp" );
2523
            $type = ".cc";
2524
 
2525
        } elsif ( /^--asm$/ ) {
2526
            Debug( "Gen: --asm" );
2527
            $type = ".asm";
2528
 
2529
        } elsif ( /^-(.*)/ ) {
2530
            Debug( "Src: arg $_" );
2531
            push @args, $_;
2532
        }
2533
    }
2534
 
2535
    #.. Process source file(s)
2536
    #
2537
    #   Determine if file is already a known SRCS file - skip if already known
2538
    #   Update SRCS data
2539
    #   Update SRC_TYPE data
2540
    #   Update SRC_ARGS data
2541
    #   Add the file to a suitable source file list ie: @CHDRS,...
2542
    #   Flag as a GENERATED file - These will be processed during the 'generate' phase
2543
    #
2544
    foreach my $source ( @elements )
2545
    {
2546
        next if ( $source =~ /^-(.*)/ );                # Not a source file
2547
 
2548
        my $basename = StripDir( $source );
2549
        Debug( "Generate: $source=$basename (@args)" );
2550
 
2551
        if ($SRCS{ $basename }) {
2552
            Warning( "Duplicate src ignored '$source'" );
2553
            next;
2554
        }
2555
        $SRCS{ $basename } = $source;
2556
 
2557
        HashJoin( \%SRC_ARGS, $;, $basename, @args )
2558
            if (@args);
2559
 
2560
        $SRC_TYPE{ $basename } = $type
2561
            if ($type);
2562
 
2563
        #
5867 dpurdie 2564
        #   Add the file to any source file lists that may like to know
227 dpurdie 2565
        #   about this file.
2566
        #
2567
        #   If the file was a known source file, then it may need to be generated
2568
        #   very early in the build process.
2569
        #
2570
        my $src_file_type = __AddSourceFile( 1, $basename );
285 dpurdie 2571
        if ($generated == 1 || ($src_file_type && $generated > 1) )
227 dpurdie 2572
        {
2573
            push(@GENERATED, $source);
303 dpurdie 2574
            $result++;
227 dpurdie 2575
        }
2576
        else
2577
        {
2578
            push(@GENERATED_NOTSRC, $source);
2579
        }
2580
    }
303 dpurdie 2581
 
2582
    return $result;
227 dpurdie 2583
}
2584
 
2585
#-------------------------------------------------------------------------------
2586
# Function        : GenerateFiles
2587
#
2588
# Description     : Generate files in a controlled manner using a specified
2589
#                   tool to perform the task
2590
#
2591
# Inputs          : $1      - platform specifier '*' (comma delemitered)
2592
#                   $2      - Tool Name
2593
#                   $3...   - Command line argument to generate files with embedded information
2594
#                           - or options. Multiple command line arguments will be joind with
2595
#                             a single space
2596
#
2597
#                   The generated files will be placed in the OBJ directory for
2598
#                   the current target platform. This allows different files to
2599
#                   be generated for each platform, without collision.
2600
#
2601
#                   The full name of the generated files will be added to the list of
2602
#                   source files. Thus the user does not need to know the
2603
#                   full name of the file - it will be tracked by JATS.
2604
#
2605
#                   If a generated file is a header file, then the OBJ directory
2606
#                   will be added as AddIncDir() so that the header files can be
2607
#                   extracted
2608
#
2609
#                   If a generated file is a "C"/"C++" source file, then it will
2610
#                   compiled and the object file made available
2611
#
2612
#                   The tool name may be:
2613
#                       --Tool=name  or "name"
2614
#                               Look in the tool paths in Packages
2615
#                               Look in the JATS tool directory for named script
2616
#                               Look in the JATS bin directory for the named exe
2617
#                               Look in the users path ( and generate a warning )
2618
#                               Give up and hope magic happens later
2619
#                       --Script=name
2620
#                               Resolve the name using known Src paths
2621
#                               The script may be generated and need not exist
2622
#                               at the time the makefile is created.
2623
#                       --Shell
2624
#                               The command line argument is a shell script that
2625
#                               will be passed to a simple shell.
263 dpurdie 2626
#                       --Prog=name
2627
#                               Resolve to a program generated within this makefile
227 dpurdie 2628
#
2629
#
2630
#                   The command line argument contains keywords to allow
2631
#                   information to be extracted from the line. Keywords are:
2632
#
2633
#                       --Generated(xxx)        - xxx is a generated file
2634
#                                                 It will be placed in the OBJDIR
2635
#                       --GeneratedCommon(xxx)  - xxx is a generated file
2636
#                                                 File will be placed in the local directory
2637
#                                                 and will be shared by by all platforms
2638
#                       --GeneratedObject(xxx)  - xxx is a generated object file
2639
#                                                 It will be placed in the OBJDIR and will
2640
#                                                 have a suitable object suffix appended
2641
#                       --GeneratedProg(xxx)    - xxx is a generated program file
2642
#                                                 It will be placed in the BINDIR
2643
#                       --Prerequisite(xxx)     - xxx is a prerequisite file
2644
#                                                 The full name of the file will be located
2645
#                                                 and used within the command. The file will
2646
#                                                 be added to the list of recipe prerequisites
2647
#                       --GeneratedDirectory(xxx)
2648
#                       --GeneratedCommonDirectory(xxx)
2649
#                       --GeneratedObjectDirectory(xxx)
2650
#                       --GeneratedProgDirectory(xxx)
6177 dpurdie 2651
#                                               - xxx is a generated file
2652
#                                                 The containing directory will be placed on the command line
227 dpurdie 2653
#                       --PackageBase(xxx)      - xxx is a package. The keyword will be replaced
2654
#                                                 with the pathname to the package. If the package
2655
#                                                 has been copied in the the interface directory
2656
#                                                 then the interface directory will be used.
2657
#                       --PackageInfo(xxx,--opt)- xxx is a package. The keyword will be replaced
2658
#                                                 with the information requested.
2659
#                                                 Options are:
2660
#                                                   --path
2661
#                                                   --version
2662
#                                                   --fullversion
2663
#                                                   --project
2664
#
2665
#                       Where "xxx" may be of the form:
2666
#                           name,option[,option]
2667
#
2668
#                       Flag options are:
2669
#                           --file             - The file part of the full name
2670
#                           --dir              - The directory part of the full name
2671
#                           --abspath          - Abs path
2672
#                           --absdrive         - Abs path with drive letter
2673
#
2674
#                       --Var(Name,opt)         - Name is the name of a recognised varable
2675
#                                                 Refer to ExpandGenVar function for details
2676
#                                                 of Name and available options
2677
#                                                 The expanded text will be replaced with an
2678
#                                                 suitable makefile variables that will be
2679
#                                                 replaced at run-time.
6504 dpurdie 2680
#                                                 
2681
#                       --Tool(Name,opt)        - Name is the name of a 'tool' found withnin a package
2682
#                                                 The argument is replaced with the full path of the
2683
#                                                 tool. opt may be
2684
#                                                   --dir
2685
#                                                   --file
2686
#                                                   --abspath
2687
#                                                   --absdrive
227 dpurdie 2688
#
2689
#                   The keyword will be replaced with the resolved name. This may be a file,
2690
#                   a directory or other text.
2691
#
2692
#                   Options do not alter command line text. They do affect the way the command is
2693
#                   processed.
2694
#                   Options include:
2695
#                       --Prereq=name           - The name of a file to add as a prerequisite
2696
#                                                 The file does not form part of the command line
2697
#                       --Created=name          - The name of a file to treat as a generated file
2698
#                       --CreatedCommon=name      The file does not form part of the command line 
2699
#                       --CreatedObject=name
2700
#                       --CreatedProg=name
2701
#
2702
#                       --NoVarTag              - Modifes --Var operation to suppress tags
2703
#                       --NoWarn                - Don't warn if no prerequistes found
2704
#                       --NoGenerate            - Don't warn if no generated files are found
2705
#                                                 Will create a dummy rule name and the recipe will
2706
#                                                 always be executed during the 'GenerateFiles' phase
2707
#                       --UnknownPreq           - Prerequisites are not fully known.
2708
#                                                 Rebuild the target whenever it is required.
2709
#                       --AutoGenerate          - Examine the generated file to determine when the
2710
#                                                 tools is to be run.
261 dpurdie 2711
#                                                 Must be before any options that declare
2712
#                                                 creation of files.
227 dpurdie 2713
#                       --Text=<text>           - Display text for command
2714
#
263 dpurdie 2715
#                       --Clean[=arg]           - Call script with arg[-clean] for cleaning.
2716
#                       --PreDelete             - Delete generated files before running the command
6415 dpurdie 2717
#                       --RecipeTag=Name        - Name the recipe
2718
#                                                 Allows recipe to be called by Name and clean_Name
6898 dpurdie 2719
#                                                 
2720
#                       --UtfFormat=name        - Flags the program as a 'test' to be run in the Test Phase
6906 dpurdie 2721
#                                                 Intended to support things like Gradle that run tests in there own world
6898 dpurdie 2722
#                                                 Enables support for (Must occur first)
2723
#                           --AutoUtf           - Non interactive unit test
2724
#                           --NoAutoUtf         - Interactive unit Test
2725
#                           --UtfArg=nnn        - Argument passed into the UTF formatter
2726
#                           --UtfDir=path       - SUbdir in which the Unit Tests will be run    
2727
#                       
227 dpurdie 2728
#
2729
#               Eg: GenerateFiles ( '*', "--Tool=mod_if.pl",
2730
#                                        "-src --Prerequisite(udh_module.cfg)",
2731
#                                        "-direct -hdr --Generated(udp.h) -quiet" );
2732
#
2733
my $NoGenIndex = 0;
6415 dpurdie 2734
my %recipeTags;
227 dpurdie 2735
sub GenerateFiles
2736
{
6415 dpurdie 2737
    #
2738
    #   Remove undfined arguments
2739
    #   Simplifies programatic construction of argument lists
2740
    #
2741
    my ( $platforms, $tool, @args) = grep defined, @_;
227 dpurdie 2742
 
2743
    return if ( ! ActivePlatform($platforms) );
2744
 
6504 dpurdie 2745
    Debug( "GenerateFiles:($platforms, $tool, @args)" );
227 dpurdie 2746
 
2747
    my @preq_files;
2748
    my $preq_unknown;
2749
    my @gen_files;
2750
    my $shell_script;
2751
    my $shell_cmds;
2752
    my @tool_args;
2753
    my $no_warn;
2754
    my $clean_tag;
2755
    my $text;
2756
    my $gtype = 1;
303 dpurdie 2757
    my @has_source;
227 dpurdie 2758
    my @var_opts;
261 dpurdie 2759
    my @genreq_seen;
263 dpurdie 2760
    my $predelete;
6415 dpurdie 2761
    my $recipeTag;
6898 dpurdie 2762
    my $utfAuto;
2763
    my $utfFormat;
2764
    my $utfDir;
2765
    my @utfArgs;
2766
    my $isaUtf;
2767
    my $noGenerate;
227 dpurdie 2768
 
2769
    #
2770
    #   Process the first argument - this describes the program that will be used
2771
    #   to generate the files. It may be:
2772
    #       --Tool          - A Jats Tool or Plugin
2773
    #       --Script        - A shell script file
2774
    #       --Shell         - Raw shell commands
2775
    #       --Prog          - A program created within the Makefile
2776
    #
2777
    #
2778
    if ( $tool =~ /^--Tool=(.*)/ || $tool =~ /^([^-].*)/)
2779
    {
2780
        $tool = $1;
2781
        my $tool_no_prereq = 0;
2782
 
2783
        #
2784
        #   Process the Tool name and determine the location of the tool
2785
        #   Support --Tool=name and "name"
2786
        #   Locate the tool one of the many well known locations
2787
        #       1) Tool paths from Package Archives
2788
        #       2) JATS tool and binaries
2789
        #       3) User PATH (!YUK)
2790
        #
2791
 
2792
        #
2793
        #   Create a list of known extensions to scan
2794
        #   Basically present so that we can use .exe files without the .exe name
2795
        #
2796
        my @extension_list;
2797
        push @extension_list, '.exe' if ( $::ScmHost ne "Unix" );
2798
        push @extension_list, '.pl', '.sh', '.ksh', '';
2799
        TOOL_SEARCH:
2800
        {
2801
            #
2802
            #   Locate tool with package
2803
            #
2804
            if ( my $fname = ToolExtensionProgram( $tool, @extension_list ))
2805
            {
2806
                $tool = $fname;
2807
                last TOOL_SEARCH;
2808
            }
2809
 
2810
            #
2811
            #   Search the JATS tools and Bin directory
2812
            #   Retain the symbolic name of the JATS directory
2813
            #
2814
            for my $ext ( @extension_list )
2815
            {
2816
                foreach my $jdir ( qw( / /DEPLOY/ /LOCAL/ ) )
2817
                {
2818
                    if ( -f "$::GBE_TOOLS$jdir$tool$ext" )
2819
                    {
2820
                        $tool = "\$(GBE_TOOLS)$jdir$tool$ext";
2821
                        last TOOL_SEARCH;
2822
                    }
2823
                }
2824
 
2825
                if ( -f "$::GBE_BIN/$tool$ext" )
2826
                {
2827
                    $tool = "\$(GBE_BIN)/$tool$ext";
2828
                    last TOOL_SEARCH;
2829
                }
2830
            }
2831
 
2832
            #
2833
            #   Has the user provided an absolute PATH
2834
            #   This is not good, but for testing we can use it
2835
            #
2836
            if ( $tool =~ m~^/~ || $tool =~ m~^.:~ )
2837
            {
2838
                Warning("Absolute path program specified. Uncontrolled tool: $tool");
2839
                for my $ext ( @extension_list )
2840
                {
2841
                    if ( -f "$tool$ext" )
2842
                    {
2843
                        $tool = "$tool$ext";
2844
                        last TOOL_SEARCH;
2845
                    }
2846
                }
2847
            }
2848
 
2849
            #
2850
            #   May have a relative path to a local tool
2851
            #
2852
            if ( -f $tool )
2853
            {
2854
                UniquePush (\@preq_files, $tool);
2855
                last TOOL_SEARCH;
2856
            }
2857
 
2858
            #
2859
            #   Search the users PATH
2860
            #   Generate a warning if the program is found. These programs are
2861
            #   not nice as they are not really controlled.
2862
            #
2863
            for my $dir (split( $::ScmPathSep, $ENV{'PATH'} ) )
2864
            {
2865
                for my $ext ( @extension_list )
2866
                {
2867
                    if ( -f "$dir/$tool$ext" )
2868
                    {
2869
                        Warning("External program found in the user's PATH. Uncontrolled tool: $tool");
2870
                        $tool = "$dir/$tool$ext";
2871
 
2872
                        #
2873
                        #   Do not make the program a pre-requisite if we are running
2874
                        #   under Windows. This avoids two problems:
2875
                        #       1) May have spaces in pathname
2876
                        #       2) May have driver letter in pathname
2877
                        #
2878
                        $tool_no_prereq = 1 if ( $::ScmHost eq "WIN" );
2879
                        last TOOL_SEARCH;
2880
                    }
2881
                }
2882
            }
2883
 
2884
            #
2885
            #   Specified progrom not found
2886
            #   Generate a warning and use the raw name
2887
            #
2888
            Warning("Tool not found: $tool");
2889
            $tool_no_prereq = 1;
2890
        }
2891
        UniquePush (\@preq_files, $tool) unless ($tool_no_prereq);
2892
 
2893
    } elsif ( $tool =~ /^--Script=(.*)/ ) {
2894
 
2895
        #
2896
        #   Locate the script in a known source directory and make
2897
        #   the script a prerequisite of the target files, since the
2898
        #   script may be generated.
2899
        #
2900
        $tool = MakeSrcResolve ( $1 );
2901
        UniquePush (\@preq_files, $tool);
2902
 
2903
    } elsif ( $tool =~ /^--Shell$/ ) {
2904
        #
2905
        #   The user has provided a shell script within the command body
2906
        #   This will be executed directly by a shell
2907
        #   directores will need to use a "/" separator
2908
        #
2909
        $tool = "InternalShell";
2910
        $shell_script = 1;
2911
        $shell_cmds = 1;
2912
 
2913
 
2914
    } elsif ( $tool =~ /^--Prog=(.*)$/ ) {
2915
        #
2916
        #   Using a program that has been created within this script
2917
        #
2918
        my $prog = $1;
289 dpurdie 2919
        if ( my $pProg = $PROGS->Get($prog) )
227 dpurdie 2920
        {
289 dpurdie 2921
            $tool = $pProg->getPath()
227 dpurdie 2922
                unless ( $tool = $SRCS{$prog} );
2923
        UniquePush (\@preq_files, $tool);
2924
        }
2925
        else
2926
        {
2927
            Error ("Unknown program: $prog");
2928
        }
2929
 
2930
    } else {
2931
 
2932
        #
2933
        #   Currently generate a warning and then use the raw tool name
2934
        #
2935
        Error ("Unknown TOOL syntax: $tool");
2936
    }
2937
 
2938
    #
2939
    #   May need to quote the path
2940
    #   If the toolpath contains spaces then ugliness can occur - so quote the program
2941
    #
2942
    $tool = '"' . $tool . '"'
2943
        if ( (! $shell_script ) && $tool =~ m~\s~ );
2944
 
2945
    #
2946
    #   Determine special startup for various programs
2947
    #       Perl  - use known implemenatation
2948
    #       Shell - use known implemenatation
2949
    #       Otherwise - simply run it
2950
    #
2951
    #   Windows: Shell and Perl don't need '\' in paths
2952
    #
2953
    if ( $tool =~ /\.pl$/ )
2954
    {
2955
        $tool = "\$(GBE_PERL) $tool";
2956
        $shell_script = 1;
2957
    }
2958
    elsif ( $tool =~ /\.k?sh$/ )
2959
    {
2960
        $tool = "\$(GBE_BIN)/sh $tool";
2961
        $shell_script = 1;
2962
    }
2963
    Debug( "GenerateFiles: Tool: $tool" );
2964
 
2965
 
2966
    #
2967
    #   Process the remaining arguments
2968
    #   These will be command line arguments or options/flags
2969
    #   Command line arguments are concatenated together
2970
    #
2971
    for my $arg (@args)
2972
    {
263 dpurdie 2973
        if ( $arg =~ /^--PreDelete$/ )
2974
        {
2975
            #
2976
            #   Delete generated files before running the generation process
2977
            #   Some programs refuse to overwrite existing files
2978
            #
2979
            $predelete = 1;
2980
            next;
6898 dpurdie 2981
 
2982
        } elsif ( $arg =~ /^--NoVarTag$/ ) {
227 dpurdie 2983
            #
2984
            #   Modify the operation of --Var to supress the tags
6387 dpurdie 2985
            #   Should be used early as will only affect following --Var usage
227 dpurdie 2986
            #
2987
            push @var_opts, "--notag";
2988
            next;
2989
 
6898 dpurdie 2990
        } elsif ( $arg =~ /^--NoWarn$/ ) {
227 dpurdie 2991
            #
2992
            #   Supress warnings - No prequisites found
2993
            #   This is acceptable, but normally a tool should take an input
2994
            #   and create some output from it.
2995
            #
2996
            $no_warn = 1;
2997
            next;
2998
 
6898 dpurdie 2999
        } elsif ( $arg =~ /^--NoGenerate$/ ) {
227 dpurdie 3000
            #
3001
            #   Tool does generate a definable output
6898 dpurdie 3002
            #       Should only be used internally
227 dpurdie 3003
            #
6898 dpurdie 3004
            $noGenerate = 1;
227 dpurdie 3005
            next;
3006
 
6898 dpurdie 3007
        } elsif ( $arg =~ /^--UnknownPreq/ ) {
227 dpurdie 3008
            #
3009
            #   Indicate that the prequisites are not known, or too complex to
3010
            #   describe. ie: All files in a directory. May be used by packaging
3011
            #   tools.
3012
            #   The recipe will be run EVERY time we want to use the target.
3013
            #
3014
            $preq_unknown = 1;
3015
            $no_warn = 1;
3016
            next;
3017
 
6898 dpurdie 3018
        } elsif ( $arg =~ /^--AutoGenerate/ ) {
227 dpurdie 3019
            #
3020
            #   Determine when to run the tool based on the types of files that
3021
            #   are generated. Existance of a source file will force the tool
3022
            #   to be run during the 'generate' phase, othewise the tool will be run
3023
            #   when the generated components are required.
3024
            #
3025
            $gtype = 2;
261 dpurdie 3026
            Warning ("AutoGenerate MUST occur before options that declare generation of files",
3027
                     "Have seen:", @genreq_seen)
3028
                if (@genreq_seen);
227 dpurdie 3029
            next;
6898 dpurdie 3030
 
3031
        } elsif ( $arg =~ /^--Prereq=(.*)/ ) {
227 dpurdie 3032
            #
3033
            #   Specify a prerequisite file, that is not a part of the command line
3034
            #   Simply add the files to the list of preq files
3035
            #
3036
            my $fn = LocatePreReq ($1);
3037
            UniquePush ( \@preq_files, $fn );
3038
            Debug( "GenerateFiles: ExtraPrereq: $fn" );
3039
            next;
3040
 
6898 dpurdie 3041
        } elsif ( $arg =~ /^--Created(.*)=(.*)/ ) {
227 dpurdie 3042
            #
3043
            #   Specify a generated file, that is not a part of the command line
3044
            #   Add the files to the list of generated files
3045
            #
3046
            my $type = $1;
3047
            my $fn = $2;
3048
 
343 dpurdie 3049
            #
3050
            #   Append object suffix to CreatedObject
3051
            #
227 dpurdie 3052
            $fn .= '.' . $::o
3053
                if ( $type =~ m/Object/ );
3054
 
343 dpurdie 3055
            #
3056
            #   If the files is 'created' in a subdir, then add the dir
3057
            #   as a prerequisite.
3058
            #
3059
            if ( $type =~ m/Prog/ ) {
3060
                $fn = "\$(BINDIR)/$fn";
3061
                UniquePush (\@preq_files, '$(GBE_BINDIR)');
3062
 
3063
            } elsif ( $type !~ m/Common/ ) {
3064
                $fn = "\$(OBJDIR)/$fn";
3065
                UniquePush (\@preq_files, '$(GBE_OBJDIR)');
3066
            }
227 dpurdie 3067
 
3068
            #
3069
            #   Examine the file and see if it needs to be compiled
3070
            #   Add to the list of source files
3071
            #
261 dpurdie 3072
            push @genreq_seen, $arg;
303 dpurdie 3073
            if ( UniquePush (\@gen_files, $fn) )
3074
            {
3075
                if ( GenerateSrcFile ( $gtype, $fn  ) && $gtype == 2 )
3076
                {
3077
                    push @has_source, $fn;
3078
                }
3079
            }
227 dpurdie 3080
            Debug( "GenerateFiles: ExtraCreated: $fn" );
3081
            next;
3082
 
6898 dpurdie 3083
        } elsif ( $arg =~ /^--Clean($|=(.*))/ ) {
227 dpurdie 3084
            #
3085
            #   Detect Clean option
3086
            #
3087
            $clean_tag = $2 ? $2 : '-clean';
3088
 
3089
            #
3090
            #   Shell command with a --Clean will only
3091
            #   be run during a clean phase. They should not have any prereq
3092
            #   and should not generate any files, so simplify the interface.
3093
            #
3094
            push @args, '--NoWarn', '--NoGenerate'
3095
                if ( $shell_cmds );
3096
            next;
3097
 
6898 dpurdie 3098
        } elsif ( $arg =~ /^--Text=(.*)/ ) {
227 dpurdie 3099
            #
3100
            #   Display this text when executing commands
3101
            #
3102
            $text = $1;
3103
            next;
3104
 
6898 dpurdie 3105
        } elsif ( $arg =~ /^--RecipeTag=(.*)/ ) {
6415 dpurdie 3106
            #
3107
            #   Tag the generated Recipe
3108
            #   Only use the last tag - allow users to overwrite system tags
3109
            #
3110
            $recipeTag = $1;
3111
            Error ("Duplicate RecipeTag - $recipeTag") if ($recipeTags{$recipeTag}++ > 1);
3112
            next;
6898 dpurdie 3113
 
3114
        } elsif ( $arg =~ m/^--AutoUtf$/i) {
3115
            $utfAuto = 1;
3116
            $isaUtf = 1;
3117
            next;
3118
 
3119
        } elsif ( $arg =~ m/^--NoAutoUtf$/i ) {
3120
            $utfAuto = 0;
3121
            $isaUtf = 1;
3122
            next;
3123
 
3124
        } elsif ( $arg =~ m/^--UtfFormat=(.*)/i) {
3125
            $utfFormat = $1;
3126
            $isaUtf = 1;
3127
            next;
3128
 
3129
        } elsif ( $arg =~ m/^--UtfDir=(.*)/i) {
3130
            $utfDir = $1;
3131
            $isaUtf = 1;
3132
            next;
3133
 
3134
        } elsif ( $arg =~ m/^--UtfArg=(.*)/i) {
3135
            push @utfArgs, $1;
3136
            $isaUtf = 1;
3137
            next;
6415 dpurdie 3138
        }
3139
 
6898 dpurdie 3140
 
227 dpurdie 3141
        #   Not an option. Must be an argument to the tool/program
3142
        #   Process the tool arguments and extract file information
3143
        #   Extract all fields of the form:
3144
        #           --xxxxx(yyyyyy[,zzzzz])
3145
        #           --xxxxx{yyyyyyy}
3146
        #           --xxxxx[yyyyyyy] to allow embedded brackets
3147
        #
3148
        while ( $arg =~ m/--(\w+)               # --CommandWord         $1
3149
                                (               # Just for grouping
3150
                                \((.*?)\)   |   # Stuff like (yyyyy)    $3
3151
                                {(.*?)}     |   # or    like {yyyyy}    $4
3152
                                \[(.*?)\]       # or    like [yyyyy]    $5
3153
                                )/x )           # Allow comments and whitespace
3154
        {
3155
            my $cmd = $1;                       # The command
3156
            my $ufn = $3 || $4 || $5;           # User filename + options
3157
            my $mb = $-[0];                     # Match begin offset
3158
            my $me = $+[0];                     # Match end
3159
            my $flags = '';                     # Optional flags ( --dir or --file )
3160
            my $raw_arg = $ufn;                 # Raw arguments
6387 dpurdie 3161
            my $all = substr( $arg, $mb, $me - $mb ); # All of match. Avoid use of $&
343 dpurdie 3162
            my $is_path = 1;
285 dpurdie 3163
 
227 dpurdie 3164
 
3165
            Error ("GenerateFiles. Empty element not allowed: $all")
3166
                unless ( defined($ufn) );
3167
 
3168
            $ufn =~ s/\s+$//;
3169
            $ufn =~ s/^\s+//;
3170
            $ufn =~ s~//~/~g;                   # Remove multiple /
3171
            if ( $ufn =~ m/(.*?),(.*)/ )        # Extract out any flags
3172
            {
3173
                $ufn = $1;
3174
                $flags = $2;
3175
            }
3176
 
3177
            my $fn = $ufn ;                     # Replacement filename
343 dpurdie 3178
            my $fnp = '';                       # Prefix to $fn
227 dpurdie 3179
            Error ("GenerateFiles. Empty element not allowed: $all" )
3180
                if ( length ($ufn) <= 0 );
3181
 
3182
            #
3183
            #   Process found user command
3184
            #
3185
            if ( $cmd =~ /^Generated/ )
3186
            {
3187
                my $use_dir = "";
343 dpurdie 3188
 
227 dpurdie 3189
                #
3190
                #   Generated filename
3191
                #       Determine the target directory
3192
                #       Determine the full name of the file.
3193
                #       Flag the file as generated
3194
                #
3195
                if ( $cmd =~ /Prog/ )
3196
                {
3197
                    #
3198
                    #   Generated Prog are generated in the BIN directory
3199
                    #   Ensure the directory exists by using its symbolic name
3200
                    #   as a prerequisite.
3201
                    #
343 dpurdie 3202
                    $use_dir = '$(BINDIR)';
3203
                    UniquePush (\@preq_files, '$(GBE_BINDIR)');
227 dpurdie 3204
                }
3205
                elsif ( $cmd !~ /Common/ )
3206
                {
3207
                    #
3208
                    #   Files that are not Common are generated in the
3209
                    #   object directory. This directory must exist, so it
3210
                    #   symbolic name GBE_OBJDIR is made a prerequisite too.
3211
                    #
3212
                    #   If the file is a header file, then add the directory
3213
                    #   to the include search path too.
3214
                    #
343 dpurdie 3215
                    $use_dir = '$(OBJDIR)';
3216
                    UniquePush (\@preq_files, '$(GBE_OBJDIR)');
3217
                    AddIncDir( $platforms , '$(OBJDIR)', '--NoWarn' )
227 dpurdie 3218
                        if ( $ScmSourceTypes{ StripFile($fn) } && $ScmSourceTypes{ StripFile($fn) } eq ".h" );
3219
                }
3220
 
3221
 
3222
                #
3223
                #   Append a toolset specfic object file name suffix
3224
                #   for Object files only
3225
                #
3226
                $fn .= ".$::o"
3227
                    if ( $cmd =~ /Object/ );
3228
 
3229
                #
3230
                #   Merge directory and filename parts
3231
                #
3232
                $fn = $use_dir . ( $use_dir ? "/" : ""  ) . $fn;
3233
 
3234
                #
3235
                #   Save for later user
3236
                #   Flag the file as a generated file
3237
                #
261 dpurdie 3238
                push @genreq_seen, $cmd;
303 dpurdie 3239
                if ( UniquePush (\@gen_files, $fn) )
3240
                {
5878 dpurdie 3241
                    if ($SRCS{ StripDir( $fn ) })
303 dpurdie 3242
                    {
5878 dpurdie 3243
                        abtWarning(1,"GenerateFiles. Generated File also a Src file: $fn");
303 dpurdie 3244
                    }
5878 dpurdie 3245
                    elsif ( GenerateSrcFile ( $gtype, $fn  ) )
3246
                    {
3247
                        push ( @has_source, $fn ) if ($gtype == 2);
3248
                    }
303 dpurdie 3249
                }
227 dpurdie 3250
 
3251
                #
3252
                #   Use the directory or the full name
3253
                #   If using the directory then ensure that we have a name
3254
                #   even if its "."
3255
                #
3256
                $fn = ($use_dir) ? "$use_dir" : "."
3257
                    if ( $cmd =~ /Directory/ );
3258
 
3259
                Debug( "GenerateFiles: Generate: $fn" );
3260
 
3261
            }
3262
            elsif ( $cmd =~ /^Prereq/ )
3263
            {
3264
                #
3265
                #   Prerequisite filename
3266
                #       Resolve the full name of the file. It may be known
3267
                #       as a source file (possibly generated) or it may be
3268
                #       located in a known source directory
3269
                #
3270
                $fn = LocatePreReq ($ufn);
3271
                UniquePush (\@preq_files, $fn);
3272
 
3273
                Debug( "GenerateFiles: Prereq: $fn" );
3274
 
3275
            }
3276
            elsif ( $cmd =~ /^PackageBase/ )
3277
            {
3278
                $fn = GetPackageBase( "GenerateFiles", $raw_arg );
3279
                UniquePush (\@preq_files, $fn);
3280
            }
3281
            elsif ( $cmd =~ /^PackageInfo/ )
3282
            {
3283
                $fn = GetPackageInfo( "GenerateFiles", $raw_arg );
3284
            }
3285
            elsif ( $cmd =~ /^Var/ )
3286
            {
6504 dpurdie 3287
                # --Var(...)
343 dpurdie 3288
                ($fnp, $fn, $is_path) = ExpandGenVar( "GenerateFiles", $raw_arg, @var_opts );
227 dpurdie 3289
                $flags = '';
343 dpurdie 3290
                if ( $raw_arg eq 'ObjDir' ) {
3291
                    UniquePush (\@preq_files, '$(GBE_OBJDIR)');
3292
                } elsif ( $raw_arg eq 'BinDir' ) {
3293
                    UniquePush (\@preq_files, '$(GBE_BINDIR)');
3294
                } elsif ( $raw_arg eq 'LibDir' ) {
3295
                    UniquePush (\@preq_files, '$(GBE_LIBDIR)');
3296
                }
227 dpurdie 3297
            }
6504 dpurdie 3298
            elsif ( $cmd =~ /^Tool/ ) {
3299
                # --Tool(toolName)
3300
                ($fn, $is_path) = ExpandTool( "GenerateFiles", $raw_arg );
3301
            }
227 dpurdie 3302
            else
3303
            {
3304
                Warning ("GenerateFiles: Unknown replacement command: $cmd");
3305
                $fn = $ufn;
3306
            }
3307
 
3308
            #
3309
            #   Process path modification flags
3310
            #
3311
            $fn = ProcessPathName( $fn, $flags );
3312
 
3313
            #
3314
            #   Minor kludge under windows. Ensure directores have a "\" sep
3315
            #   Unless the user has specified a straight shell command
3316
            #
5986 dpurdie 3317
            $fn = "\$(subst /,\$(dirsep),$fn)"
343 dpurdie 3318
                if ( $is_path && $::ScmHost eq "WIN" && ! defined($shell_script) );
227 dpurdie 3319
 
3320
            #
343 dpurdie 3321
            #   Prepend any $fn Prefix
3322
            #   This will be a tag and is not subject to path processing
3323
            #
3324
            $fn = $fnp . $fn;
3325
 
3326
            #
227 dpurdie 3327
            #   Replace the found string with the real name of the file
3328
            #   Note: 4 argument version of substr is not always available
3329
            #         so we must do it the hard way
3330
            #               substr( $arg, $mb, $me - $mb, $fn);
3331
            #
3332
            $arg = substr( $arg, 0, $mb ) . $fn . substr( $arg, $me );
3333
 
3334
            Debug2( "GenerateFiles: subs: $all -> $fn" );
3335
        }
3336
 
3337
        #
3338
        #   Save the tool arguments in an array
3339
        #
3340
        push @tool_args, $arg;
3341
    }
3342
 
3343
    #
5867 dpurdie 3344
    #   Sanity test. Ensure that some file have been marked as generated
227 dpurdie 3345
    #                Warn if no prerequisites found
3346
    #
303 dpurdie 3347
    Warning( "GenerateFiles. --AutoGenerate option has no effect",
3348
             "The following files are 'source' files",  @has_source ) if ( @has_source );
6898 dpurdie 3349
    Warning( "No Prerequisite files found in $tool",@tool_args) unless ( $isaUtf || $no_warn || $#preq_files >= 0 );
227 dpurdie 3350
 
6423 dpurdie 3351
    #
6906 dpurdie 3352
    #   These would be nice tests - but break too much
3353
    #   
3354
    #    ReportError("Mixed use of --NoGenerate and generated files") if (@gen_files && $noGenerate);
3355
    #    ReportError  ( "No generated files found in $tool",@tool_args) unless ($isaUtf || $noGenerate || $#gen_files > 0);
3356
 
3357
    #
6898 dpurdie 3358
    #   Sanity test. If a UTF then we shouldn't generate files
3359
    #   
3360
    if ($isaUtf ) {
3361
        ReportError('In UTF mode generated files are not supported:', @gen_files) if @gen_files;
3362
    }
3363
 
3364
    #   Invocation does not generate and files
3365
    #       Need to create a dummy name for the rule
3366
    #       Use a base name and a number
3367
    #       
3368
    if ($noGenerate)
3369
    {
3370
        my $dummy_target = 'generate_files_' . $NoGenIndex;
3371
        UniquePush (\@gen_files, $dummy_target );
3372
        UniquePush (\@GENERATED, $dummy_target) unless $isaUtf;
3373
    }
3374
 
3375
    ErrorDoExit();
3376
 
3377
    #
6423 dpurdie 3378
    #   Determine the text to display while generating files
3379
    #   Will be either user-text or the first target file (default)
3380
    #   Suffix with RecipeTag, if provided
3381
    #   
3382
    my $txtSuffix = '';
3383
    $txtSuffix = "($recipeTag)" if defined $recipeTag;
3384
    $text = $gen_files[0] unless defined $text;
3385
    $text .= $txtSuffix;
227 dpurdie 3386
 
3387
    #
3388
    #   Save information
3389
    #   Will be used to create makefile statements later
3390
    #
3391
    my %gen_data;
3392
 
3393
    $gen_data{'index'}      = $NoGenIndex++;
6415 dpurdie 3394
    $gen_data{'recipeTag'}  = $recipeTag if defined $recipeTag;
227 dpurdie 3395
    $gen_data{'shell'}      = $shell_cmds;
3396
    $gen_data{'gen'}        = \@gen_files;
3397
    $gen_data{'preq'}       = \@preq_files;
3398
    $gen_data{'tool'}       = $tool;
3399
    $gen_data{'toolargs'}   = \@tool_args;
3400
    $gen_data{'clean'}      = $clean_tag;
6423 dpurdie 3401
    $gen_data{'text'}       = $text;
227 dpurdie 3402
    $gen_data{'preq_sus'}   = 1 if ( $preq_unknown );
263 dpurdie 3403
    $gen_data{'predelete'}  = 1 if ( $predelete );
227 dpurdie 3404
 
6898 dpurdie 3405
    if ($isaUtf)
3406
    {
3407
        $gen_data{'isautf'}     = 1;
3408
        $gen_data{'utfauto'}    = $utfAuto if ( $utfAuto );
3409
        $gen_data{'utfformat'}  = $utfFormat if ( $utfFormat );
3410
        $gen_data{'utfdir'}     = $utfDir if ( $utfDir );
3411
        $gen_data{'utfargs'}    = \@utfArgs;
3412
 
3413
        $TESTS_TO_RUN = 1;
3414
        $TESTS_TO_AUTORUN = 1 if ( $utfAuto );
3415
    }
3416
 
227 dpurdie 3417
    push(@GENERATE_FILES, \%gen_data);
6387 dpurdie 3418
#DebugDumpData("GenerateFiles", \%gen_data);
227 dpurdie 3419
    Debug2( "GenerateFiles: cmd: $tool @tool_args" );
3420
}
3421
 
3422
#-------------------------------------------------------------------------------
3423
# Function        : MakePerlModule
3424
#
3425
# Description     : Build Perl Module(s) using the Perl Build System
3426
#                   This is a thin wrapper around a specialised script
3427
#
3428
#                   The user can do the same job with correct use of
3429
#                   a GenerateFiles, but this is a lot tidier.
3430
#
3431
# Inputs          : $1      - platform specifier '*' (comma delemitered)
3432
#                   $*      - Paths to Perl Modules[,command options]
3433
#                             Options to the BuildPerl script
3434
#
3435
# Returns         :
3436
#
3437
sub MakePerlModule
3438
{
3439
    my ( $platforms, @args) = @_;
3440
 
3441
    return if ( ! ActivePlatform($platforms) );
3442
 
3443
    Debug2( "MakePerlModule:($platforms, @args)" );
3444
    my @opts;
3445
 
3446
    #
3447
    #   Extract options from paths to Perl Packages
3448
    #   Package names do not start with a '-'
3449
    #
3450
    foreach my $arg ( @args )
3451
    {
3452
        if ( $arg =~ /^-/ ) {
3453
            push @opts, $arg;
3454
 
3455
        } else {
3456
            #
3457
            #   Perl Package Directory Name
3458
            #   This may also contain embedded command to the Make command
3459
            #   These will be seperated with a comma
3460
            #       ie: module,-options=fred
3461
            #
3462
            my ($name,$options) = split( ',', $arg );
3463
            push @opts, "-PerlPackage=$arg";
3464
            push @opts, "--Prereq=$name/Makefile.PL";
3465
        }
3466
    }
3467
 
3468
    #
3469
    #   Invoke GenerateFiles with a bunch of additional arguments
3470
    #
3471
    GenerateFiles ($platforms, "--Tool=jats_buildperl.pl",
3472
                          '--Var(MachType)',                        # Build Machine type
3473
                          '--Var(PackageDir)',                      # Package dir
3474
                          '--NoGenerate',                           # Don't know the output
3475
                          '--Text=Make Perl Module',                # Pretty print
3476
                          '--NoWarn',
3477
                          '--Clean=-clean_build',                   # Jats clean support
3478
                          '--NoVarTag',                             # No more Tags
3479
                          @opts,
3480
                          );
3481
}
3482
 
3483
#-------------------------------------------------------------------------------
3484
# Function        : MakeLinuxDriver
3485
#
3486
# Description     : Build a Linux Device Driver using the Linux Device Driver
3487
#                   Build System
3488
#                   This is a thin wrapper around a specialised script
3489
#
3490
#                   The user can do the same job with correct use of
3491
#                   a GenerateFiles, but this is a lot tidier.
3492
#
3493
# Inputs          : $1      - platform specifier '*' (comma delemitered)
3494
#                   $2      - name of the driver. No extension
3495
#                   $*      - Driver sources
3496
#                             Options to the script
3497
#
3498
# Returns         :
3499
#
3500
sub MakeLinuxDriver
3501
{
3502
    my ( $platforms, $driver_name, @args) = @_;
3503
 
3504
    return if ( ! ActivePlatform($platforms) );
3505
 
285 dpurdie 3506
    Error ("No driver name specified") unless ( $driver_name );
227 dpurdie 3507
    Debug2( "MakeLinuxDriver:($platforms, $driver_name ,@args)" );
3508
    my @srcs;
3509
    my @opts;
3510
 
3511
    #
3512
    #   Extract options from source files
3513
    #   Package names do not start with a '-'
3514
    #
3515
    foreach my $arg ( @args )
3516
    {
3517
         if ( $arg =~ /^--Define=(.)/ ) {
3518
            push @opts, $arg;
5672 dpurdie 3519
 
3520
         } elsif ( $arg =~ /^--ExternalModule=(.)/ ) {
3521
               push @opts, $arg;
227 dpurdie 3522
 
3523
         } elsif ( $arg =~ /^-/ ) {
3524
            push @opts, $arg;
3525
            Warning ("MakeLinuxDriver: Unknown option: $arg. Passed to script");
3526
 
3527
        } else {
3528
            push @srcs, $arg;
3529
            push @opts, "--Prereq=$arg";
3530
        }
3531
    }
3532
 
3533
    #
3534
    #   Cleanup the drive name
3535
    #
3536
    $driver_name =~ s~\.ko$~~;
3537
 
3538
    #
3539
    #   Remove the specified sources from the list of object files
3540
    #   that will be build. This will ensure that some internal rules are
3541
    #   not generated.
3542
    #
3543
    foreach ( @srcs )
3544
    {
3545
        my $file = StripExt(StripDir( $_ ));
3546
        delete $OBJSOURCE{ $file };
3547
        @OBJS = grep(!/^$file$/, @OBJS);
3548
    }
3549
 
3550
    #
3551
    #   Invoke GenerateFiles with a bunch of additional arguments
3552
    #   At runtime the include directories will be added as
3553
    #   absolute paths
3554
    #
3555
    GenerateFiles ($platforms, "--Tool=jats_buildlinux.pl",
3556
                    "-Output=--GeneratedProg($driver_name.ko)",
3557
                    "-Driver=$driver_name",
3558
                    "-GccPath=\$(GCC_CC)",
3559
                    "-Arch=\$(HOST_CPU)",
3560
                    "-LeaveTmp=\$(LEAVETMP)",
3561
                    "-Verbose=\$(CC_PRE)",
3562
                    "-Type=\$(GBE_TYPE)",
3563
                    "-Platform=\$(GBE_PLATFORM)",
5672 dpurdie 3564
                    "--Var(LocalBinDir)",
227 dpurdie 3565
                    '$(patsubst %,-Incdir=%,$(INCDIRS))',
5672 dpurdie 3566
                    '--Clean',
227 dpurdie 3567
                    @opts,
3568
                    @srcs
3569
                    );
3570
}
3571
 
3572
#-------------------------------------------------------------------------------
3573
# Function        : GetPackageBase
3574
#
3575
# Description     : Helper routine
3576
#                   Given a package name, determine the base address of the
3577
#                   package
3578
#
3579
# Inputs          : $dname         - Directive name     (Reporting)
3580
#                   $name          - Required package
3581
#                                    Allows two forms:
3582
#                                       package_name
3583
#                                       package_name,ext
3584
#
3585
# Returns         : Path to the directory in which the files are installed
3586
#                   This may be the interface directory
3587
#
3588
sub GetPackageBase
3589
{
3590
    my ($dname, $fname) = @_;
3591
    my $pkg;
3592
    my ($name, $ext) = split(',', $fname);
3593
 
3594
    $pkg = GetPackageEntry( $name, $ext );
3595
    Error ("$dname: Package not found: $fname") unless ( $pkg );
3596
 
3597
    #
3598
    #   If a BuildPkgArchive then use the interface directory
3599
    #
3600
    return ( $pkg->{'TYPE'} eq 'link' ) ? $pkg->{'ROOT'} : '$(INTERFACEDIR)';
3601
}
3602
 
3603
#-------------------------------------------------------------------------------
3604
# Function        : GetPackageInfo
3605
#
3606
# Description     : Helper routine
3607
#                   Given a package name, return some information about the package
3608
#                   Only one information item is allowed with each call
3609
#
3610
# Inputs          : $dname         - Directive name     (Reporting)
3611
#                   $name          - Required package
3612
#                                    Allows two forms:
3613
#                                       package_name
3614
#                                       package_name,ext
3615
#                                    Selector
3616
#                                       --path
3617
#                                       --version
3618
#                                       --fullversion
3619
#                                       --project
3620
#
3621
# Returns         : Package information
3622
my %GetPackageInfo = qw(path ROOT
3623
                        version DVERSION
3624
                        fullversion VERSION
3625
                        project DPROJ);
3626
sub GetPackageInfo
3627
{
3628
    my ($dname, $args) = @_;
3629
    my $pkg;
3630
    my $name;
3631
    my $ext;
3632
    my $info;
3633
 
363 dpurdie 3634
    #
3635
    #   Split up the arguments
3636
    #       Options start with '--'
3637
    #   First non-option is the package name
3638
    #   2nd non-option is the packag extension
3639
    #
3640
    #   Only one option allowed
3641
    #       Convert it into a known package info item
3642
    #
3643
    #
227 dpurdie 3644
    foreach ( split(',', $args) )
3645
    {
3646
        if ( m/^--(.*)/ ) {
3647
            Error( "$dname: Too many info requests: $args") if ( $info );
3648
            $info = $GetPackageInfo{$1};
3649
            Error( "$dname: Unknown info type: $_") unless ($info);
363 dpurdie 3650
 
227 dpurdie 3651
        } elsif ( $ext ) {
3652
            Error("$dname: Too many names: $args");
363 dpurdie 3653
 
227 dpurdie 3654
        } elsif ( $name ) {
3655
            $ext = $_;
363 dpurdie 3656
 
227 dpurdie 3657
        } else {
3658
            $name = $_;
3659
        }
3660
    }
3661
 
3662
    $pkg = GetPackageEntry( $name, $ext );
3663
    Error ("$dname: Package not found: $args") unless ( $pkg );
3664
 
3665
    #
3666
    #   If a BuildPkgArchive then use the interface directory
363 dpurdie 3667
    #   Default data item - path to the package
227 dpurdie 3668
    #
363 dpurdie 3669
    $info = 'ROOT' unless ( $info );
3670
    if ( $info eq 'ROOT' &&  $pkg->{'TYPE'} ne 'link' )
227 dpurdie 3671
    {
3672
        return ( '$(INTERFACEDIR)');
3673
    }
363 dpurdie 3674
 
227 dpurdie 3675
    return ( $pkg->{$info} );
3676
}
3677
 
3678
#-------------------------------------------------------------------------------
3679
# Function        : GetPackageEntry
3680
#
3681
# Description     : Return the package class pointer given a package name
3682
#
3683
# Inputs          : $name          - Required package
3684
#                   $ext           - Option package extension
3685
#
3686
# Returns         : Class pointer
3687
#
3688
sub GetPackageEntry
3689
{
3690
    my ($name, $ext) = @_;
3691
    $ext = '' unless ( $ext );
3692
 
3693
    for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} })
3694
    {
3695
        next unless ( $entry->{'NAME'} eq $name );
3696
        next if ( $ext && $entry->{'DPROJ'} ne $ext );
3697
        return $entry;
3698
    }
285 dpurdie 3699
    return;
227 dpurdie 3700
}
3701
 
3702
#-------------------------------------------------------------------------------
3703
# Function        : ExpandGenVar
3704
#
3705
# Description     : Expand a known variable for the Generate Files option
3706
#
3707
# Inputs          : $dname         - Directive name     (Reporting)
3708
#                   $arg           - Raw argument
3709
#                                    This of the form of
3710
#                                       Tag[,--option]+
3711
#                                    Tags are specified in %ExpandGenVarConvert
3712
#
3713
#                                   Options are:
3714
#                                       --tag
3715
#                                       --notag
3716
#                                       --tag=<SomeTag>
3717
#                                       --absdrive
3718
#                                       --abspath
285 dpurdie 3719
#                                       --default=text
343 dpurdie 3720
#                                       --allownone
227 dpurdie 3721
#                                   Not all options are avalaible on all variables
3722
#                   @opts           - Options
3723
#                                       --notag     - Default is --notag
3724
#
343 dpurdie 3725
# Returns         : Tag             - Any tag component of the expansion
3726
#                   Path/Value      - Path/Value of the component
3727
#                   is_path         - Above is a path
3728
#                   is_abs          - Path is absolute
227 dpurdie 3729
#
3730
 
3731
#
3732
#   Create a Hash to simplify the process of converting Var names
343 dpurdie 3733
#   into makefile variables. There are two data items, separated by a comma.
3734
#       The first is the runtime expansion value
3735
#       The second describes the first:
3736
#           NotPresent  - Expansion is not a path
3737
#           '-'         - Expansion is a path and is relative to CWD
3738
#           '+'         - Expansion is a path and is absolute
227 dpurdie 3739
#
3740
my %ExpandGenVarConvert = (
3741
    'BuildName'         => '$(GBE_PBASE)',
3742
    'BuildVersion'      => '$(BUILDVER)',
3743
    'BuildVersionNum'   => '$(BUILDVERNUM)',
3744
 
3745
    'PackageDir'        => '$(PKGDIR),+',
3746
    'PackagePkgDir'     => '$(PKGDIR)/pkg/pkg.$(GBE_PLATFORM),+',
3747
    'PackageIncDir'     => '$(INCDIR_PKG),+',
6133 dpurdie 3748
    'PackageIncPlatDir' => '$(INCDIR_PKG)/$(GBE_PLATFORM),+',
227 dpurdie 3749
    'PackageLibDir'     => '$(LIBDIR_PKG)/$(GBE_PLATFORM),+',
3750
    'PackageBinDir'     => '$(BINDIR_PKG)/$(GBE_PLATFORM)$(GBE_TYPE),+',
3751
 
3752
    'PackageToolDir'    => '$(PKGDIR)/tools,+',
3753
    'PackageToolBin'    => '$(PKGDIR)/tools/bin/$(GBE_HOSTMACH),+',
3754
    'PackageToolScript' => '$(PKGDIR)/tools/scripts,+',
3755
 
3756
    'LibDir'            => '$(LIBDIR),+',
3757
    'BinDir'            => '$(BINDIR),+',
3758
    'ObjDir'            => '$(OBJDIR),+',
3759
 
3760
    'InterfaceDir'      => '$(INTERFACEDIR),+',
3761
    'InterfaceIncDir'   => '$(INCDIR_INTERFACE),+',
3762
    'InterfaceLibDir'   => '$(LIBDIR_INTERFACE)/$(GBE_PLATFORM),+',
3763
    'InterfaceBinDir'   => '$(BINDIR_INTERFACE)/$(GBE_PLATFORM)$(GBE_TYPE),+',
3764
 
3765
    'LocalDir'          => '$(LOCALDIR),+',
3766
    'LocalIncDir'       => '$(INCDIR_LOCAL),+',
3767
    'LocalLibDir'       => '$(LIBDIR_LOCAL)/$(GBE_PLATFORM),+',
3768
    'LocalBinDir'       => '$(BINDIR_LOCAL)/$(GBE_PLATFORM)$(GBE_TYPE),+',
3769
 
3770
    'Platform'          => '$(GBE_PLATFORM)',
3771
    'Product'           => '$(GBE_PRODUCT)',
3772
    'Target'            => '$(GBE_TARGET)',
3773
 
3774
    'Type'              => '$(GBE_TYPE)',
3775
    'Arch'              => '$(HOST_CPU)',
3776
    'Architecture'      => '$(HOST_CPU)',
3777
    'MachType'          => '$(GBE_HOSTMACH)',
3778
    'BuildRoot'         => '$(GBE_ROOT),+',
3779
 
3780
 
3781
    'Verbose'           => '$(CC_PRE)',
3782
    'LeaveTmp'          => '$(LEAVETMP)',
329 dpurdie 3783
    'Cwd'               => '$(CURDIR),-',
227 dpurdie 3784
 
6133 dpurdie 3785
    # Generated when used
227 dpurdie 3786
    'CompilerPath'      => '$(SCM_COMPILERPATH)',
3967 dpurdie 3787
    'PkgArch'           => '$(PACKAGE_ARCH)',
6133 dpurdie 3788
 
3789
    'Native'            => '0',
3790
    'Toolset'           => '0',
3791
 
227 dpurdie 3792
    );
3793
 
3794
sub ExpandGenVar
3795
{
3796
    my ($dname, $args, @uopts) = @_;
3797
    my $expansion;
3798
    my $prefix='';
3799
    my ($tag, @opts) = split('\s*,\s*', $args);
3800
    my $no_prefix;
285 dpurdie 3801
    my $default_value;
3802
    my $allow_none;
329 dpurdie 3803
    my $is_abs = 0;
227 dpurdie 3804
 
285 dpurdie 3805
    #
3806
    #   Parse options lists
3807
    #       Options provided by the caller
3808
    #       Options embedded in the argument
227 dpurdie 3809
    foreach ( @uopts )
3810
    {
3811
        if ( m/^--notag$/ ) {
3812
            $no_prefix = 1;
3813
        } else{
3814
            Error ("$dname: Unknown option: $_")
3815
        }
3816
    }
3817
 
285 dpurdie 3818
    foreach ( @opts )
3819
    {
3820
        if ( m/^--default=(.+)/i ) {
3821
            $default_value = $1;
3822
        } elsif ( m/^--allownone$/i ) {
3823
            $allow_none = 1;
3824
        }
3825
    }
3826
 
227 dpurdie 3827
    #
3828
    #   Perform run-time update on the %ExpandGenVarConvert
3829
    #   Most of it can be initialised at startup - but not all of it.
3830
    #
3831
    $ExpandGenVarConvert{CompilerPath} = undef unless $::ScmToolsetCompilerPath;
3832
    $ExpandGenVarConvert{Product}      = '$(GBE_PLATFORM)' unless $ScmProduct;
3833
 
6133 dpurdie 3834
    $ExpandGenVarConvert{Native}      = '1'  if isAnAlias ('NATIVE');
3835
    $ExpandGenVarConvert{Toolset}     = '1'  if isAnAlias ('TOOLSET');
3836
 
3837
 
227 dpurdie 3838
    #
3839
    #   Look up a hash of conversions
3840
    #   Could allow for a code ref, but not needed yet
3841
    #
3842
    Error ("$dname: Unknown expansion --Var($tag)")
3843
        unless ( exists $ExpandGenVarConvert{$tag} );
3844
 
285 dpurdie 3845
    #
3846
    #   Handle undefined expansions
3847
    #   Only 'CompilerPath', but it can be a pain in user land
3848
    #
3849
    $expansion = $ExpandGenVarConvert{$tag};
3850
    unless ( defined $expansion  )
3851
    {
6798 dpurdie 3852
        return '','',0,0 if ( $allow_none );
285 dpurdie 3853
        $expansion = $default_value;
3854
        Error ("$dname: Expansion --Var($tag) not be supported by toolset: $ScmToolset")
3855
            unless ( $expansion );
3856
    }
227 dpurdie 3857
 
285 dpurdie 3858
 
227 dpurdie 3859
    ($expansion,my $is_path) = split (',', $expansion );
329 dpurdie 3860
    $is_abs = 1
3861
        if ($is_path && $is_path eq '-' );
227 dpurdie 3862
 
3863
    #
3864
    #   Process options
3865
    #   Assume that a tag will be provided
3866
    #
3867
    $prefix =  $no_prefix ? '' : "-$tag=";
3868
    foreach my $opt ( @opts )
3869
    {
3870
        if ( $opt =~ /^--tag=(.*)/i ) {
3871
            $prefix = "$1=";
3872
 
3873
        } elsif ( $opt =~ m/^--tag$/i ) {
3874
            $prefix = "-$tag=";
3875
 
3876
        } elsif ( $opt =~ m/^--notag/i ) {
3877
            $prefix = '';
3878
 
329 dpurdie 3879
        } elsif ( $is_path && !$is_abs && $opt =~ /--abspath|--absdrive/i ) {
227 dpurdie 3880
            $expansion = '$(CURDIR)/' . $expansion;
329 dpurdie 3881
            $is_abs = 1;
227 dpurdie 3882
 
285 dpurdie 3883
        } elsif ( $opt =~ m/^--default=(.+)/i ) {
3884
            # Already processed
3885
        } elsif ( $opt =~ m/^--allownone$/i ) {
3886
            # Already processed
227 dpurdie 3887
        } else {
3888
            Error ("$dname: Unsupported option($opt) for --Var(@_)");
3889
        }
3890
    }
3891
 
3892
    Debug ("ExpandGenVar: args $args --> $prefix$expansion");
343 dpurdie 3893
    return $prefix , $expansion, $is_path ? 1 : 0, $is_abs;
227 dpurdie 3894
 
3895
}
3896
 
3897
#-------------------------------------------------------------------------------
6504 dpurdie 3898
# Function        : ExpandTool
3899
#
3900
# Description     : Locate a 'tool' and provide the complete path
3901
#
3902
# Inputs          : $dname         - Directive name     (Reporting)
3903
#                   $arg           - Name of the tool to locate (no extension) with 
3904
#                                    embedded options. Options are:
3905
#                                       --dir
3906
#                                       --file
3907
#                                       --abspath
3908
#                                       --absdrive
3909
#
3910
#                                    
3911
# Returns         : Path/Value      - Path/Value of the component
3912
#                   is_path         - Above is a path
3913
#                   is_abs          - Path is absolute
3914
#
3915
 
3916
sub ExpandTool
3917
{
3918
    my ($dname, $args) = @_;
3919
    my ($toolName, @opts) = split('\s*,\s*', $args);
3920
    my $is_abs = 1;
3921
    my $is_path = 1;
3922
 
3923
    #
3924
    #   Locate the tool in one of the dependent packages
3925
    #
3926
    my @extension_list; 
3927
    push @extension_list, '.exe' if ( $::ScmHost ne "Unix" );
3928
    my $toolFullPath =  ToolExtensionProgram( $toolName, @extension_list );
3929
    if ($toolFullPath) {
3930
        $toolName = $toolFullPath;
3931
    } else {
3932
            Warning("$dname. Tool not found: $toolName", "Searched:", ToolExtensionPaths());
3933
    }
3934
 
3935
    #
3936
    #   Process options
3937
    #
3938
    foreach my $opt ( @opts )
3939
    {
3940
        if ( $opt =~ m/^--dir/i ) {
3941
            $toolName = StripFileExt($toolName);
3942
 
3943
        } elsif ( $opt =~ m/^--file/i ) {
3944
            $toolName = StripDir($toolName);
3945
            $is_abs = 0;
3946
            $is_path = 0;
3947
 
3948
        } elsif ( $opt =~ m/^--abspath/i ) {
3949
            $toolName = AbsPath($toolName);
3950
 
3951
        } elsif ( $opt =~ m/^--absdrive/i ) {
3952
            $toolName = FullPath($toolName);
3953
 
3954
        } else {
3955
            Error ("$dname: Unsupported option($opt) for --Tool(@_)");
3956
        }
3957
    }
3958
 
3959
    Debug ("ExpandTool: $args --> $toolName");
3960
    return $toolName, $is_path ? 1 : 0, $is_abs;
3961
}
3962
 
3963
#-------------------------------------------------------------------------------
6133 dpurdie 3964
# Function        : isAnAlias 
3965
#
3966
# Description     : Internal Helper
3967
#                   Determine if this platform is an alias for ...
3968
#
3969
# Inputs          :  $target    - Test against this target
3970
#
3971
# Returns         :  True - Is an alais for $target.
3972
#
3973
sub isAnAlias
3974
{
3975
    my ($target) = @_;
3976
    if (exists ($::BUILDINFO{$ScmPlatform}{'USERALIAS'}) )
3977
    {
3978
        if ( grep /^$target$/, @{$::BUILDINFO{$ScmPlatform}{'USERALIAS'}} )
3979
        {
3980
                return 1;    
3981
        }
3982
 
3983
    }
3984
    if (exists ($::BUILDINFO{$ScmPlatform}{'ALIAS'}) )
3985
    {
3986
        if ( $target eq $::BUILDINFO{$ScmPlatform}{'ALIAS'} )
3987
        {
3988
                return 1;    
3989
        }
3990
    }
3991
 
3992
    return 0;
3993
}
3994
 
3995
#-------------------------------------------------------------------------------
227 dpurdie 3996
# Function        : ProcessPathName
3997
#
3998
# Description     : Massage a pathname according to a set of flags
3999
#
4000
# Inputs          : $fn         - Patchname to massage
4001
#                   $flags      - Flags in a string
4002
#                                   --dir       - only the directory part ( or a "." )
4003
#                                   --file      - only the file part
4004
#                                   --abspath   - Absolute path
4005
#                                   --absdrive  - Absolute path with drive letter(WIN)
4006
#
4007
# Returns         : Massaged pathname
4008
#
4009
sub ProcessPathName
4010
{
4011
    my ( $fn, $flags ) = @_;
4012
    #
4013
    #   Process flags
4014
    #       --dir           - only the directory part ( or a "." )
4015
    #       --file          - only the file part
4016
    #       --abspath       - Absolute path
4017
    #       --absdrive      - Absolute path with drive letter(WIN)
4018
    #
4019
    if ( $flags =~ /--dir/ )
4020
    {
4021
        $fn = '.'
4022
            unless ( $fn =~ s~/[^/]*$~~);
4023
    }
4024
 
4025
    if ( $flags =~ /--file/ )
4026
    {
4027
        $fn =~ s~.*/~~;
4028
    }
4029
 
4030
    if ( $flags =~ /--abspath/ )
4031
    {
4032
        $fn = AbsPath( $fn );
4033
    }
4034
    elsif ( $flags =~ /--absdrive/ )
4035
    {
4036
        $fn = AbsPath( $fn );
4037
        if ( $::ScmHost eq "WIN" )
4038
        {
4039
            $fn = $::CwdDrive . '/' . $fn
4040
                unless ( $fn =~ m~^\w:/~  );
4041
            $fn =~ s~//~/~g;
4042
        }
4043
    }
4044
 
4045
  return $fn;
4046
}
4047
 
4048
#-------------------------------------------------------------------------------
4049
# Function        : LocatePreReq
4050
#
4051
# Description     : Locate a file known to JATS
4052
#                   There are many places to search
4053
#                       1) Src files - specified with a Src directive
4054
#                       2) Scripts - specified with a script directive
4055
#                       3) Search - Files in the specified search path
4056
#                       4) Programs specified with a 'Prog' directive
4057
#
4058
#                   Should also look in other locations (Libs, SharedLibs)
4059
#                   Not done yet. May be issues of a name clash if a program
4060
#                   and a library have the same name.
4061
#
4062
# Inputs          : Name to locate
4063
#
4064
# Returns         : Full pathname of file
4065
#
4066
sub LocatePreReq
4067
{
4068
    my ( $name ) = @_;
4069
    Debug ("LocatePreReq:Looking for $name");
4070
    #
4071
    #   Try a Src file first
4072
    #
4073
    if ( exists $SRCS{ $name } )
4074
    {
4075
        return $SRCS{ $name };
4076
    }
4077
 
4078
    #
4079
    #   Try a script
4080
    #
4081
    if ( exists $SCRIPTS{ $name } )
4082
    {
4083
        return $SCRIPTS{ $name };
4084
    }
4085
 
4086
    #
4087
    #   Try a PROG
4088
    #
289 dpurdie 4089
    if ( my $pProg = $PROGS->Get($name) )
227 dpurdie 4090
    {
289 dpurdie 4091
        return $pProg->getPath();
227 dpurdie 4092
    }
4093
 
4094
    #
4095
    #   Try searching for the file
4096
    #   Uses Data from AddSrcDir
4097
    #
4098
    #   Done: last because it generates warning messages
4099
    #
4100
    return MakeSrcResolve( $name );
4101
}
4102
 
4103
#-------------------------------------------------------------------------------
4104
# Function        : ToolExtensionPaths
4105
#
4106
# Description     : Return a list of toolset extension directories
4107
#                   The data will have been discovered by the build process
4108
#                   and will have been saved for the makefile creation phase
4109
#
4110
# Inputs          : None
4111
#
4112
# Returns         : Return an ordered unique list
4113
#
4114
sub ToolExtensionPaths
4115
{
4116
    Debug( "ToolExtensionPaths:", @::BUILDTOOLSPATH );
4117
    return @::BUILDTOOLSPATH;
4118
}
4119
 
4120
#-------------------------------------------------------------------------------
4121
# Function        : ToolExtensionProgram
4122
#
4123
# Description     : Determine if the named program exists within the PATH
4124
#                   that also includes the toolset extension
4125
#
4126
# Inputs          : program             - Name of program
4127
#                   elist               - An array of possible program extensions
4128
#
6504 dpurdie 4129
# Returns         : Full path the to program or an empty element (not undef)
227 dpurdie 4130
#
4131
sub ToolExtensionProgram
4132
{
4133
    my ($program, @elist ) = @_;
4134
 
4135
    #
4136
    #   If elist is empty then insert a defined entry
4137
    #
4138
    push @elist, '' unless ( @elist );
4139
 
4140
    #
4141
    #   Scan all toolset directories
4142
    #   for the program
4143
    #
4144
    for my $dir ( ToolExtensionPaths() )
4145
    {
4146
        for my $ext ( @elist )
4147
        {
4148
            my $tool = "$dir/$program$ext";
4324 dpurdie 4149
            Debug( "ToolsetExtensionProgram: Look for: $tool" );
227 dpurdie 4150
 
4151
            return $tool if ( -f $tool );
4152
        }
4153
    }
4154
}
4155
 
4156
sub Define
4157
{
4158
    Debug2( "Define(@_)" );
4159
 
4160
    push( @DEFINES, @_ );
4161
}
4162
 
4163
 
4164
sub Defines
4165
{
4166
    my( $path, $script ) = @_;
4167
    my( $line );
4168
 
4169
    Debug2( "Defines($path, $script)" );
4170
 
4171
    $script = Exists( $path, $script, "Defines" );
271 dpurdie 4172
    push( @DEFINES, "# Defines from: $script" );
285 dpurdie 4173
    open( my $fh, '<', $script ) || Error( "Opening $script" );
4174
    while (<$fh>) {
227 dpurdie 4175
        $_ =~ s/\s*(\n|$)//;                    # kill trailing whitespace & nl
4176
        push( @DEFINES, $_ );
4177
    }
4178
    push( @ScmDepends, "$script" );             # makefile dependencies
285 dpurdie 4179
    close( $fh );
227 dpurdie 4180
}
271 dpurdie 4181
#-------------------------------------------------------------------------------
4182
# Function        : Rule
4183
#
4184
# Description     : Add a Rule and Recipe to the generated makefile
4185
#                   This is not encouraged as it has been misused to create
4186
#                   unreadable and unmaintainable makefiles.
4187
#
4188
#                   Rules will be added to the makefile after the rules and
4189
#                   recipes created by JATS directives
4190
#
4191
# Inputs          : $platform               - Platform predicate
4192
#                   @rule                   - Array of rules to add
4193
#
4194
# Returns         : 
4195
#
227 dpurdie 4196
sub Rule
4197
{
4198
    my( $platforms, @rule ) = @_;
4199
 
4200
    return if ( ! ActivePlatform($platforms) );
4201
 
4202
    push( @RULES, @rule );
4203
    Message("Rule directive used. Consider replacing with GenerateFiles");
4204
}
4205
 
271 dpurdie 4206
#-------------------------------------------------------------------------------
4207
# Function        : Rules
4208
#
4209
# Description     : Add a file of Rules and Recipes to the generated makefile
4210
#                   Used internally ONLY as there is no platform predicate
4211
#                   Similar to 'Rule()'
4212
#
4213
# Inputs          : $path                   - path to script
4214
#                   $script                 - File fo Rules
4215
#
4216
# Returns         : 
4217
#
227 dpurdie 4218
sub Rules
4219
{
4220
    my( $path, $script ) = @_;
4221
    my( $line );
4222
 
4223
    $script = Exists( $path, $script, "Rules" );
271 dpurdie 4224
    push( @RULES, "# Rules from: $script" );
285 dpurdie 4225
    open( my $fh, '<', $script ) || Error( "Opening $script" );
4226
    while (<$fh>) {
227 dpurdie 4227
        $_ =~ s/\s*(\n|$)//;                    # kill trailing whitespace & nl
4228
        push( @RULES, $_ );
4229
    }
4230
    push( @ScmDepends, "$script" );             # makefile dependencies
285 dpurdie 4231
    close( $fh );
227 dpurdie 4232
}
4233
 
271 dpurdie 4234
#-------------------------------------------------------------------------------
4235
# Function        : AddRule
4236
#
4237
# Description     : Inernal function
4238
#                   Add a line to the Rules area
4239
#
4240
# Inputs          : @elements                   - Array of lines to add
4241
#
4242
# Returns         : Nothing
4243
#
4244
sub AddRule
4245
{
4246
    push( @RULES, @_ );
4247
}
227 dpurdie 4248
 
271 dpurdie 4249
#-------------------------------------------------------------------------------
4250
# Function        : Src
4251
#
4252
# Description     : This directive is used to identify files to JATS
4253
#                   Once a file has been identified as a 'Source' file, then it
4254
#                   can be used by name, without the need to locate the file again.
4255
#                   This implies that filenames must be unique.
4256
#                   The directories cannot be used to make files of the same name
4257
#                   unqiue - this is not the JATS way
4258
#
4259
#                   Source files will be classified as one of:
4260
#                       c, c++, header, assembler or other
4261
#
4262
#
4263
# Inputs          : $platform               - Active Platform Predicate
4264
#                   @elements               - A list of files and options
4265
#
4266
#                   Valid options are:
4267
#                       --c                 - Specifies the type of file
4268
#                       --cpp
4269
#                       --h, --headers
4270
#                       --asm
4271
#                       --FromPackage       - Search packages for the file
4272
#                       --List=xxx          - Append file to a named list
4273
#                       --Depends=xxx       - Manually name a dependency
6387 dpurdie 4274
#                       --IgnoreDuplicates  - Ignore duplicates (mostly internal use)
271 dpurdie 4275
#
4276
#                   Options are processed before file elements
4277
#                   Thus options apply to all files in the list
4278
#
4279
# Returns         : Nothing
4280
#
227 dpurdie 4281
sub Src
4282
{
4283
    my( $platforms, @elements ) = @_;
6387 dpurdie 4284
    my( $type, @args, $source, $basename, $from_package, @lists, $ignoreDups );
227 dpurdie 4285
    my( @depends, @srcs );
4286
 
4287
    $platforms = '' unless ( $platforms );
4288
    Debug2( "Src($platforms, @elements)" );
4289
 
4290
    #
4291
    #   Ensure that there is a file within the list
4292
    #
4293
    Warning( "Src directive does not specify any files: Src($platforms, @elements)" )
4294
        unless (grep( /^[^-]/, @elements ) );
4295
 
4296
    return if ( ! ActivePlatform($platforms) );
4297
 
4298
    #
4299
    #   Remove spaces from both ends of the arguments.
4300
    #   It is easier to remove spaces now than to detect them later
4301
    #
4302
    foreach ( @elements )
4303
    {
4304
        s/^\s+//;
4305
        s/\s+$//;
4306
        s~//~/~g;                               # Remove multiple /
4307
    }
4308
 
4309
    #.. Collect arguments
4310
    #
4311
    $type = "";
4312
    foreach ( @elements )
4313
    {
4314
        if ( /^--c$/ )
4315
        {
4316
            Debug( "Src: --c" );
4317
            $type = ".c";
4318
        }
4319
        elsif ( /^--cpp$/ )
4320
        {
4321
            Debug( "Src: --cpp" );
4322
            $type = ".cc";
4323
        }
4324
        elsif ( /^--h$/ || /^--header$/ )
4325
        {
4326
            Debug( "Src: --h" );
4327
            $type = ".h";
4328
        }
4329
        elsif ( /^--asm$/ )
4330
        {
4331
            Debug( "Src: --asm" );
4332
            $type = ".asm";
4333
        }
6387 dpurdie 4334
        elsif ( /^--IgnoreDup/ )
4335
        {
4336
            $ignoreDups = 1;
4337
        }
227 dpurdie 4338
        elsif ( /^--FromPackage$/ )
4339
        {
4340
            $from_package = 1;
4341
        }
4342
        elsif ( /^--List=(.*)/ )
4343
        {
4344
            my $list_name = $1;
4345
            Error( "Bad list name: $list_name" )
4346
                unless ( $list_name =~ m/^[A-Za-z]\w+/ );
4347
            push @lists, $list_name;
4348
        }
4349
        elsif ( /^--Depends=(.*)/ )
4350
        {
4351
            foreach ( split( ',', $1) )
4352
            {
4353
                my $full = MakeSrcResolveExtended( $from_package, $_ );
4354
                push @depends, $full;
4355
            }
4356
        }
4357
        elsif ( /^-(.*)/ )
4358
        {
4359
            Debug( "Src: arg $_" );
4360
            push @args, $_;
4361
        }
4362
        else
4363
        {
4364
            push @srcs, $_;
4365
            Warning ("Src files contains a '\\' character: $_" ) if (m~\\~);
4366
        }
4367
    }
4368
 
4369
    #.. Push source file(s)
4370
    foreach ( @srcs )
4371
    {
4372
        if ( ! /^-(.*)/ )
4373
        {
4374
            $source = MakeSrcResolveExtended( $from_package, $_ );
4375
            $basename = StripDir( $source );
4376
            Debug( "Src: $_ -> $source=$basename (@args),(@depends)" );
4377
 
4378
            if ( $SRCS{ $basename } ) {
6387 dpurdie 4379
                Warning( "Duplicate src ignored '$source'") unless $ignoreDups;
227 dpurdie 4380
                next;
4381
            }
4382
            $SRCS{ $basename } = $source;
4383
 
4384
            HashJoin( \%SRC_ARGS, $;, $basename, @args )
4385
                if (@args);
4386
 
4387
            HashJoin( \%SRC_DEPEND, $;, $basename, @depends )
4388
                if ( @depends );
4389
 
4390
            $SRC_TYPE{ $basename } = $type
4391
                if ($type);
4392
 
4393
 
4394
            foreach (@lists) {
4395
                my $lname_short = "LIST_$_";
4396
                my $lname_full = "LIST_FULL_$_";
4397
 
4398
                no strict 'refs';
4399
 
4400
                push @$lname_short,$basename;
4401
                push @$lname_full ,$source;
4402
 
4403
                use strict 'refs';
4404
            }
4405
 
4406
            __AddSourceFile( 1, $source, "", $type );
4407
        }
4408
    }
4409
}
4410
 
6387 dpurdie 4411
#-------------------------------------------------------------------------------
4412
# Function        : AddToSrc 
4413
#
4414
# Description     : Internal function
4415
#                   Used by plugins and tools
4416
#                   
4417
#                   Will test if specified file is known to JATS, before
4418
#                   adding to the the list of known (Src) files 
4419
#
4420
# Inputs          : $platform
4421
#                   $file           - Only one file
4422
#                   @srcOpts        - Same as Src
4423
#
4424
# Returns         : True if any file can be found
4425
#                   Returns full path to the file    
4426
#
4427
sub AddToSrc
4428
{
4429
    my( $platforms, $file, @args ) = @_;
4430
    Debug2( "AddToSrc($platforms, $file, @args)" );
227 dpurdie 4431
 
6387 dpurdie 4432
    #
4433
    #   Process files
4434
    #
4435
    my $basename = StripDir( $file );
4436
    unless (exists $SRCS{$file} || exists  $SRCS{$basename} ) {
4437
        Src ('*', $file, @args);
4438
    }
4439
 
4440
    return $SRCS{$basename};
4441
}
4442
 
4443
 
227 dpurdie 4444
###############################################################################
4445
#  sub LibNameSplit
4446
#      Just a little help to deal with major/minor stuff for shared libs -
4447
#      given the name of the library as the argument, split out major and minor
4448
#      parts and return the basename, i.e name without major and minor and
4449
#      the pair of major and minor.
4450
###############################################################################
4451
 
4452
sub LibNameSplit
4453
{
4454
    my ( @bits ) = split('\.', $_[0]);
4455
    my ( $major, $minor );
4456
 
4457
    if ($#bits >= 1) {
4458
        $major = $bits[0]; $minor = $bits[1];
4459
    } elsif ($#bits >= 0) {
4460
        $major = $bits[0]; $minor = 0;
4461
    } else {
4462
        $major = 1; $minor = 0;
4463
    }
4464
    Debug( "LibName: $@_[0] ($major.$minor)" );
4465
    return ($major, $minor);
4466
}
4467
 
4468
#-------------------------------------------------------------------------------
4469
# Function        : Lib
4470
#
4471
# Description     : Generate a static library
4472
#
4473
# Inputs          : Platform specifier
4474
#                   Name of the library
4475
#                   Arguemnts ...
4476
#
4477
# Returns         :
4478
#
4479
sub Lib
4480
{
4481
    my( $platforms, $lib, @args ) = @_;
4482
    return if ( ! ActivePlatform($platforms) );
4483
 
4484
    Error ("Lib: Library name not defined") unless ( $lib );
4485
 
4486
    #
4487
    #   May be a shared library or a static library - for historic reasons
4488
    #   If the user has specified a --Shared then its a shared library
4489
    #
4490
    return SharedLib( @_ )
4491
        if ( grep (/^--Shared/, @args) );
4492
 
4493
    #
4494
    #   Does this toolset support libraries
4495
    #
4496
    Error ("Libraries are not supported") unless ( defined $::a );
4497
 
4498
    #.. Fully qualify library path for addition to library list.
4499
    $lib = "lib$lib"
4500
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4501
    Debug( "Lib: $lib" );
4502
 
4503
    #
289 dpurdie 4504
    #   Create a new object to describe the library
227 dpurdie 4505
    #   Ensure that only one such lib exists
289 dpurdie 4506
    #   Add the library to the list of static libraries
227 dpurdie 4507
    #
4508
    Error( "Library of the same name already defined: $lib" )
289 dpurdie 4509
        if ( $LIBS->Get($lib) );
4510
    $LIBS->NewAdd($lib);
227 dpurdie 4511
 
4512
    #
4513
    #   Process arguments
4514
    #
4515
    push( @LINTLIBS, $lib );
4516
    _LibArgs( $lib, @args );
4517
}
4518
 
4519
 
4520
#-------------------------------------------------------------------------------
4521
# Function        : SharedLib
4522
#
4523
# Description     : Generate a shared library
4524
#
4525
# Inputs          : Platform specifier
4526
#                   Name of the library
4527
#                   Arguemnts ...
4528
#
4529
# Returns         :
4530
#
4531
sub SharedLib
4532
{
4533
    my( $platforms, $lib, @args ) = @_;
4534
 
4535
    return if ( ! ActivePlatform($platforms) );
4536
 
4537
    Error ("SharedLib: Library name not defined") unless ( $lib );
4538
    Error ("Shared Libraries are not supported") unless ( defined $::so );
4539
 
4540
#.. Fully qualify library path for addition to library list.
4541
    $lib = "lib$lib"
4542
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4543
    Debug( "ShLib: $lib" );
4544
 
4545
    #
4546
    #   Ensure that only one such lib exists
4547
    #
289 dpurdie 4548
    Error( "Library of the same name already defined: $lib" )
4549
        if ( $SHLIBS->Get($lib) );
4550
    $SHLIBS->NewAdd($lib);
293 dpurdie 4551
 
227 dpurdie 4552
    #
4553
    #   If the user has not specified a --Shared parameter then provide one
4554
    #
4555
    push @args, "--Shared=Current"
4556
        unless ( grep (/^--Shared/, @args) );
4557
 
4558
    #
4559
    #   Process arguments
4560
    #
4561
    push( @LINTSHLIBS, $lib );
4562
    _SharedLibArgs( $lib, @args );
4563
}
4564
 
4565
 
4566
#-------------------------------------------------------------------------------
4567
# Function        : LibArgs
4568
#
4569
# Description     : Add arguments to an existing library directive
4570
#
4571
# Inputs          : Platform specifier
4572
#                   Name of the library
4573
#                   Arguemnts ...
4574
#
4575
# Returns         :
4576
#
4577
sub LibArgs
4578
{
4579
    my( $platforms, $lib, @args ) = @_;
4580
    return if ( ! ActivePlatform($platforms) );
4581
 
4582
#.. Fully qualify library path for addition to library list.
4583
    $lib = "lib$lib"
4584
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4585
    Debug( "LibArgs: $lib" );
4586
 
4587
    #
4588
    #   Process the arguments
4589
    #
4590
    _LibArgs( $lib, @args );
4591
}
4592
 
4593
 
4594
#-------------------------------------------------------------------------------
4595
# Function        : _LibArgs
4596
#
4597
# Description     : Process static library arguments
4598
#                   Internal use only
4599
#
4600
# Inputs          : Name of the library
4601
#                   Arguments to process
4602
#
4603
sub _LibArgs
4604
{
4605
    my( $lib, @elements) = @_;
4606
    my $obj;
4607
 
4608
    #
289 dpurdie 4609
    #   Ensure that only one such lib exists
4610
    #
4611
    my $libp = $LIBS->Get($lib);
4612
    Error("Library name not defined: $lib")
4613
        unless ( $libp );
4614
 
4615
    #
227 dpurdie 4616
    #   Process each element
4617
    #
4618
    foreach (@elements)
4619
    {
371 dpurdie 4620
        if ( /^\s+/ )
4621
        {
4622
            Error ("Argument cannot start with a space: '$_'");
4623
        }
227 dpurdie 4624
        if ( /^--Shared/ )
4625
        {
4626
            Error( "--Shared not valid for a static library" );
4627
        }
4628
 
4629
        if ( /^-l(.*)/ || /^--l(.*)/ || /^-L(.*)/ || /^--L(.*)/ )
4630
        {
4631
        #.. Target library specified - add to library list.
4632
        #
4633
            Warning( "$_ within non shared library specification" );
4634
            next;
4635
        }
4636
 
4637
        if ( /^--if(.*)/ )
4638
        {
4639
            Warning( "$_ within non shared library specification" );
4640
            next;
4641
        }
4642
 
4643
        if ( /^--(.*)/ )
4644
        {
4645
            Debug( "LibArgs: arg $_" );
4646
 
4647
            #.. Argument specified - add to argument list
4648
            #
289 dpurdie 4649
            $libp->addItem('ARGS', $_);
4650
 
227 dpurdie 4651
            next;
4652
        }
4653
 
369 dpurdie 4654
        if ( %::ScmToolsetProgSource )
227 dpurdie 4655
        {
4656
            #
4657
            #   Toolset provides support for some file types
4658
            #   to be passed directly to the librarian builder
4659
            #
4660
            my $ext  = StripFile($_);
4661
            if ( exists ($::ScmToolsetProgSource{$ext}) )
4662
            {
4663
                my $full_path = MakeSrcResolve ( $_ );
4664
                my $flag = $::ScmToolsetProgSource{$ext};
4665
                Debug( "LibArgs: src $_" );
289 dpurdie 4666
                $libp->addItem('ARGS', "$flag$full_path" );
227 dpurdie 4667
                next;
4668
            }
4669
        }
4670
 
4671
        if ( $::o )
4672
        {
4673
        #.. Object specified - add to object list.
4674
        #
4675
            $obj = _LibObject( "", $_ );
4676
 
4677
        #.. Add to object list.
4678
        #   Note:   Object path must be explicit as several
4679
        #           toolsets add additional objects.
4680
        #
289 dpurdie 4681
            $libp->addItem('OBJS', "\$(OBJDIR)/$obj" );
227 dpurdie 4682
            next;
4683
        }
4684
 
4685
        #
4686
        #   Don't know how to handle this type of argument
4687
        #
4688
        Error ("LibArgs: Don't know how to handle: $_" );
4689
    }
4690
}
4691
 
4692
 
4693
#-------------------------------------------------------------------------------
4694
# Function        : SharedLibArgs
4695
#
4696
# Description     : Add arguments to an existing shared library directive
4697
#
4698
# Inputs          : Platform specifier
4699
#                   Name of the library
4700
#                   Arguemnts ...
4701
#
4702
# Returns         :
4703
#
4704
sub SharedLibArgs
4705
{
4706
    my( $platforms, $lib, @args ) = @_;
4707
    return if ( ! ActivePlatform($platforms) );
4708
 
4709
#.. Fully qualify library path for addition to library list.
4710
    $lib = "lib$lib"
4711
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4712
    Debug( "ShLibArgs: $lib" );
4713
 
4714
    _SharedLibArgs( $lib, @args );
4715
}
4716
 
4717
 
4718
#-------------------------------------------------------------------------------
4719
# Function        : _SharedLibArgs
4720
#
4721
# Description     : Process shared library arguments
4722
#                   Internal use only
4723
#
4724
# Inputs          : Name of the library
4725
#                   Arguments to process
4726
#
4727
sub _SharedLibArgs
4728
{
4729
    my ( $lib, @elements) = @_;
4730
 
289 dpurdie 4731
    my $libp = $SHLIBS->Get($lib);
4732
    Error("Library name not defined: $lib")
4733
        unless ( $libp );
4734
 
227 dpurdie 4735
    #
289 dpurdie 4736
    #.. Collect --Shared arguments
339 dpurdie 4737
    #   Need to process this one first so that we have a version number
227 dpurdie 4738
    #
4739
    foreach (@elements)
4740
    {
371 dpurdie 4741
        if ( /^\s+/ )
4742
        {
4743
            Error ("Argument cannot start with a space: '$_'");
4744
        }
289 dpurdie 4745
        next unless ( /^--Shared/ );
4746
 
4747
        my $shared;
227 dpurdie 4748
        if ( /^--Shared$/ )
4749
        {
4750
        #.. Shared library, default library version 1.0
4751
        #
4752
            $shared = "1.0";
4753
        }
4754
        elsif ( /^--Shared=Current$/ )
4755
        {
4756
        #.. Shared library, using 'current' build version
4757
        #
4758
            $shared = $::ScmBuildVersion;
289 dpurdie 4759
            $shared = "1.0" if ($shared eq "");
227 dpurdie 4760
        }
4761
        elsif ( /^--Shared=(.*)/ )
4762
        {
4763
        #.. Shared library, specific version
4764
        #
4765
            my($M, $m) = LibNameSplit($1);
289 dpurdie 4766
            $shared = "$M.$m";
4767
        }
227 dpurdie 4768
 
289 dpurdie 4769
        #
4770
        #   Update the shared Names
4771
        #
4772
        if ( defined $shared )
4773
        {
227 dpurdie 4774
            Warning( "multiple --Shared arguments" )
339 dpurdie 4775
                if (exists $libp->{ VERSION });
227 dpurdie 4776
            Debug( "ShLibArgs: shared $_ ($shared)" );
289 dpurdie 4777
            $libp->{ VERSION } = $shared;
227 dpurdie 4778
        }
289 dpurdie 4779
        else
4780
        {
4781
            Error ("ShLibArgs: --Shared argument not understood");
4782
        }
227 dpurdie 4783
    }
4784
 
4785
 
4786
#.. Parse all of the object and argument entries.
4787
#
4788
    foreach (@elements)
4789
    {
289 dpurdie 4790
        next if ( /^--Shared(.*)/ );
227 dpurdie 4791
 
4792
        if ( /^[-]{1,2}([lL])(.*)/ )
4793
        {
4794
        #.. Target library specified - add to library list.
339 dpurdie 4795
        #   Support --L and -L and --l and -l
227 dpurdie 4796
        #
4797
            Debug( "ShLibArgs: lib  -$1$2" );
289 dpurdie 4798
            $libp->addItem('LIBS', "-$1$2" );
227 dpurdie 4799
            next;
4800
        }
4801
 
4802
        if ( /^--if(.*)/ )
4803
        {
4804
        #.. Library conditional - add to library list.
4805
        #
4806
            Debug( "ShLibArgs: cond $_" );
289 dpurdie 4807
            $libp->addItem('LIBS', $_);
227 dpurdie 4808
            next;
4809
        }
4810
 
339 dpurdie 4811
        if ( /^--SoName=(.*)/i )
4812
        {
4813
        #.. Specify the SoName of the library
4814
        #   Not supported by all toolsets
4815
        #
4816
            my $soMode = $1;
4817
            if ( !$ScmToolsetSoName )
4818
            {
4819
                Warning ("Toolset does not support --SoName. Option ignored");
4820
                next;
4821
            }
4822
 
4823
            Error ("SharedLib: $lib. Multiple --SoName arguments not allowed")
4824
                if ( $libp->{ SONAME } );
4825
 
4826
            my ($major, $minor, $patch, $build, $raw_patch) = SplitVersion($::ScmBuildVersionFull);
4827
            my $soname = '.';
4828
            if ( $soMode =~ m/Major/i ) {
4829
                $soname .= $major;
4830
            } elsif ( $soMode =~ m/^Minor/i ) {
4831
                $soname .= "$major.$minor";
4832
            } elsif ( $soMode =~ m/^Patch/i ) {
4833
                $soname .= "$major.$minor.$patch";
4834
            } elsif ( $soMode =~ m/^Build/i ) {
4835
                $soname .= "$major.$minor.$patch.$build";
4836
            } elsif ( $soMode =~ m/^Full/i ) {
4837
                $soname .= $libp->{ VERSION };
4838
            } elsif ( $soMode =~ m/^None/i ) {
4839
                $soname = '';
4840
            } elsif ( $soMode =~ m/^[0-9.]+$/ ) {
4841
                $soname .= $soMode;
4842
            } else {
4843
                Error ("Unknown --SoName mode: $soMode");
4844
            }
4845
            $libp->addItem('ARGS', '--SoNameSuffix=' . $soname);
4846
            $libp->{ SONAME } = 1;
4847
            next;
4848
        }
4849
 
227 dpurdie 4850
        if ( /^-(.*)/ )
4851
        {                           
4852
        #.. Argument specified - add to argument list
4853
        #
4854
            Debug( "ShLibArgs: arg  $_" );
289 dpurdie 4855
            $libp->addItem('ARGS', $_);
227 dpurdie 4856
            next;
4857
        }
4858
 
369 dpurdie 4859
        if ( %::ScmToolsetProgSource )
227 dpurdie 4860
        {
4861
            #
4862
            #   Toolset provides support for some file types
4863
            #   to be passed directly to the program builder
4864
            #
4865
            my $ext  = StripFile($_);
4866
            if ( exists ($::ScmToolsetProgSource{$ext}) )
4867
            {
4868
                my $full_path = MakeSrcResolve ( $_ );
4869
                my $flag = $::ScmToolsetProgSource{$ext};
4870
                Debug( "ShLibArgs: src $_" );
289 dpurdie 4871
                $libp->addItem('ARGS', "$flag$full_path");
227 dpurdie 4872
                next;
4873
            }
4874
        }
4875
 
4876
        if ( $::o )
4877
        {
4878
        #.. Object specified - add to object list.
4879
        #
4880
            my ($obj) = _LibObject( $lib, $_ );
4881
 
4882
        #.. Add to object list.
4883
        #   Note:   Object path must be explicit as several
4884
        #           toolsets add additional objects.
4885
        #
4886
            $SHOBJ_LIB{ $obj } = $lib;
289 dpurdie 4887
            $libp->addItem('OBJS', "\$(OBJDIR)/$obj");
227 dpurdie 4888
            next;
4889
        }
4890
 
4891
        #
4892
        #   Don't know how to handle this type of argument
4893
        #
4894
        Error ("SharedLib: Don't know how to handle: $_" );
4895
    }
4896
}
4897
 
4898
 
4899
#-------------------------------------------------------------------------------
4900
# Function        : _LibObject
4901
#
4902
# Description     : Process library object file
4903
#                   Common processing routine for static and shared library
4904
#                   Internal use only
4905
#
4906
# Inputs          : shared  - Name of the shared library is shared, if defined
4907
#                   fname   - Name of file
4908
#
4909
# Returns         : Name of the object file
4910
#
4911
sub _LibObject
4912
{
4913
    my ($shared, $fname) = @_;
4914
    my ($file, $ext, $obj, $srcfile, $delete_obj);
4915
 
4916
    #.. Object specified - add to object list.
4917
    #
4424 dpurdie 4918
    #   Want to handle several cases
4919
    #       Normal - User has provided the name of an object file (without the obj suffix)
4920
    #       Other  - User has provided the name of a source file
4921
    #                Need to perform implicit source file processing
4922
    #
4923
    #   The hard part is detecting the difference
4924
    #   Just can't use the existence of a '.' 
4925
    #
4926
    if ($OBJSOURCE{$fname}) {
4927
        $file = $fname;                             # Already know about this file
4928
        $ext = '';                                  # Don't need to split it
4929
    } else {
4930
        $file = StripDirExt($fname);                # file name, without extension or Dir
4931
        $ext  = StripFile($fname);                  # extension
4932
    }
227 dpurdie 4933
 
4934
    if ($shared) {
4935
        $obj = "$shared/$file";                 # library specific subdir
4936
    } else {
4937
        $obj = "$file";
4938
    }
4939
 
4940
    Debug( "LibObjs: obj [$shared]$fname ($file$ext)" );
4941
 
4942
    #.. Unqualified object name
4943
    #
4424 dpurdie 4944
    if ( $ext eq '' ) {
227 dpurdie 4945
        #
4946
        #   Object file not covered by a "Src" statement
4947
        #   Assume that it will be created
4948
        #
4424 dpurdie 4949
        unless ( $srcfile = $OBJSOURCE{$file} )
227 dpurdie 4950
        {
4951
            #
4424 dpurdie 4952
            #   If the object is "generated" then it will be in the
227 dpurdie 4953
            #   SRCS list
4954
            #
4955
            unless ( $srcfile = $SRCS{"$file.$::o"} )
4956
            {
4957
                Warning( "No source for object '$fname' ($file)" );
4958
            }
4959
        }
4960
        $delete_obj = 1;
4961
    }
4962
 
4963
    #.. Qualified object name (ie has extension)
4964
    #       Strip extension and resolve ...
4965
    #       Assume that the named file can be built into an object file
4966
    #
4967
    else
4968
    {
4969
        #.. Resolve
4970
        #
4971
        if ( !($srcfile = $OBJSOURCE{ "$file" }) )
4972
        {
4973
            $srcfile = MakeSrcResolve( $fname );
4974
            $SRCS{ $fname } = $srcfile;
4975
            __AddSourceFile( 0, $fname, $obj );
4976
            $delete_obj = 1;
4977
        }
4978
    }
4979
 
4980
    #.. Delete generated object file
4981
    #   Ensure that the object file is added to the delete list
4982
    #   Add it to the ToolsetObj deletion list as the main OBJ deleltion
4983
    #   list will aready have been processed
4984
    #
4985
    ToolsetObj( "\$(OBJDIR)/$obj" )
4986
        if ( $delete_obj );
4987
 
4988
 
4989
    #.. Shared library objects,
4990
    #       Must explicitly relate source and object, as shared libraries
4991
    #       objects are built within a library specific subdirs.
4992
    #
4993
    $OBJSOURCE{ $obj } = $srcfile
371 dpurdie 4994
        if ( $shared && defined $srcfile );
227 dpurdie 4995
 
4996
    return $obj;
4997
}
4998
 
4999
 
5000
# MergeLibrary
5001
#   Merge a list of libraries into one library
5002
#
5003
sub MergeLibrary
5004
{
5005
    my( $platforms, $lib, @elements ) = @_;
5006
 
5007
    return if ( ! ActivePlatform($platforms) );
5008
 
5009
 
5010
#.. Fully qualify library path for addition to library list.
5011
    $lib = "lib$lib"
5012
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
5013
    Debug( "MergeLibrary: $lib" );
5014
 
289 dpurdie 5015
    #
5016
    #   Create a new object to describe the library
5017
    #   Ensure that only one such lib exists
5018
    #   Add the library to the list of static libraries
5019
    #
5020
    Error( "Merged Library of the same name already defined: $lib" )
5021
        if ( $MLIBS->Get($lib) );
5022
    my $libp = $MLIBS->NewAdd($lib);
5023
 
227 dpurdie 5024
#.. Parse all of the object and argument entries.
5025
#
5026
    foreach (@elements)
5027
    {
5028
        if ( /^--(.*)/ )
5029
        {
289 dpurdie 5030
            $libp->addItem('ARGS', $_);
227 dpurdie 5031
        }
5032
        else
5033
        {
5034
            my ($llib);
5035
 
5036
            #
5037
            #   Collect the source libraries
5038
            #   These must have been installed and will be in a known area
5039
            #   Create full names for the libaries
5040
            #
5041
            if ( $ScmTargetHost eq "Unix" ) {
5042
                $llib = "lib$_";                # Prefix "lib" ....
5043
                $lib =~ s/^liblib/lib/;         # @LIBS already has lib added
5044
            } else {
5045
                $llib = $_;
5046
            }
5047
 
5048
            Debug( "MergeLibrary: merge $llib" );
289 dpurdie 5049
            $libp->addItem('LIBS', $llib);
227 dpurdie 5050
        }
5051
    }
5052
}
5053
 
5054
#-------------------------------------------------------------------------------
5055
# Function        : Script
5056
#
5057
# Description     : Locate a script for test purposes
5058
#
5059
# Inputs          : $platforms      - Platform selector
5060
#                   $script         - A single script name
5061
#                   $execute        - Flag to indicate that the script is to
5062
#                                     marked as executable when used in a TestProg
5063
#                                     This flag is NOT used as the script will
5064
#                                     be forced executable
5065
#
5066
# Returns         : Nothing
5067
#
5068
sub Script
5069
{
5070
    my( $platforms, $script, $execute ) = @_;
5071
 
5072
    Debug2( "Script(@_)" );
5073
 
5074
    return if ( ! ActivePlatform($platforms) );
5075
 
5076
    #
5077
    #   Locate the script as a source file
5078
    #
5079
    my $file = MakeSrcResolve ( $script );
5080
    $script = StripDir( $file );
5081
    $SCRIPTS{ $script } = $file;
5082
}
5083
 
5084
#-------------------------------------------------------------------------------
5085
# Function        : RunTest
5086
#
5087
# Description     : Define a test to be run with the 'run_tests' and 'run_unit_tests'
5088
#
5089
# Inputs          : $platform       - Enabled for these platforms
5090
#                   $prog           - Program to run
5091
#                                     This SHOULD return a non-zero exit status
5092
#                                     on error. The program may be a 'TestProg'
5093
#                                     or a 'Script'.
5094
#                   @elements       - Options and test arguments
5095
#                                     Options are:
4778 dpurdie 5096
#                                       --Auto              - Non interactive unit test
5097
#                                       --Unit              - Same and --Auto
5098
#                                       --UtfFormat=nnn     - Specifies Automated Unit Test, 
5099
#                                                             results post processed with formatter
4781 dpurdie 5100
#                                       --UtfArg=nnn        - Argument passed into the UTF formatter    
5101
#                                       --Name=nnn          - Test Name.
5695 dpurdie 5102
#                                       --CopyIn=file       - A file to be copied into the test directory.
5103
#                                       --MaxTime=fff.ff[smhd] - Max Test Time. Default 30m
227 dpurdie 5104
#
5105
#                                     Non Options are passed to the test program.
5106
#                                     --PackageBase(xxx)    - Base of package
5107
#                                     --PackageInfo(xxx)    - Package information
5108
#                                     --File(xxx)           - Resolved name of file
5109
#                                     --Var(xxx)            - Expanded variable
5110
#                                     --Local(xxx)          - File within the local directory
5111
#
4778 dpurdie 5112
#                                     Toolset Framework support (ie NUNIT in csharp.pl)
5113
#                                       --FrameWork=name    - Name of framework
5114
#                                       --xxxx              - Args passed to framework constructor
5115
#
227 dpurdie 5116
# Returns         : Nothing
5117
#
4781 dpurdie 5118
my %RunTestNames;                       # Unique Name Tests
227 dpurdie 5119
sub RunTest
5120
{
5121
    my( $platforms, $prog, @elements ) = @_;
5122
    my $command = './';                 # program prefix / command
5123
    my $winprog = 1;                    # 1: Convert / -> \ (WIN32 only)
5124
    my $framework;
5125
    my @framework_opts;
5126
    my @copy = ();
5127
    my $auto;
4778 dpurdie 5128
    my $utfFormat;
4781 dpurdie 5129
    my @utfArgs;
5130
    my $utfName;
5695 dpurdie 5131
    my $maxTime;
227 dpurdie 5132
 
5133
    return if ( ! ActivePlatform($platforms) );
5134
 
5135
    #
5136
    #   Scan @elements and extract useful information
5137
    #   Need to process twice as some args will modify the
5138
    #   processing done later
5139
    #
5140
    my @args;
5141
    foreach ( @elements )
5142
    {
5143
        if ( m/^--FrameWork=(.+)/ ) {
5144
            $framework = $1;
5145
 
5146
        } elsif ( m/^--Auto/ || m/^--Unit/) {
5147
            $auto = 1;
5148
 
4781 dpurdie 5149
        } elsif ( m/^--Name=(.*)/) {
5150
            $utfName = $1;
5151
 
5152
            Error("Duplicate Test Name: $utfName")
5153
                if (exists $RunTestNames{$utfName} );
5154
            $RunTestNames{$utfName} = 1;
5155
 
4778 dpurdie 5156
        } elsif ( m/^--UtfFormat=(.*)/) {
5157
            $utfFormat = $1;
5158
 
4781 dpurdie 5159
        } elsif ( m/^--UtfArg=(.*)/) {
5160
            push @utfArgs, $1;
5161
 
5695 dpurdie 5162
        } elsif ( m/^--MaxTime=(.*)/) {
5163
            $maxTime = $1;
5164
            unless ($maxTime =~ m~^[0-9]*\.?[0-9]+[smhd]?$~) {
5165
                Error("MaxTime invalid: $maxTime");
5166
            }
5167
 
227 dpurdie 5168
        } elsif ( m/^--CopyIn=(.*)/ ) {
5169
            push @copy, MakeSrcResolve ( $1 );
5170
 
5171
        } elsif ( $framework && m/^--\w+=(.+)/ ) {
5172
            push @framework_opts, $_;
5173
 
5174
        } else {
5175
            push @args, $_;
5176
        }
5177
    }
5178
    @elements = @args;
5179
    @args = ();
5180
 
5181
    #
5182
    #   Determine the source of the test prog
4612 dpurdie 5183
    #   If using a plug-in framework, then we don't know
227 dpurdie 5184
    #   If not, then may be a script or a TESTPROGS
5185
    #
5186
 
5187
    unless ( $framework )
5188
    {
289 dpurdie 5189
        if ( $TESTPROGS->Get($prog) || $PROGS->Get($prog)  ) {
227 dpurdie 5190
            #
5191
            #   Append a suitable EXE suffix
5192
            #
289 dpurdie 5193
            $prog = GenProgName( $prog );
227 dpurdie 5194
 
5195
        } elsif ( exists $SCRIPTS{$prog} ) {
5196
            #
5197
            #   Script names are raw
5198
            #   Perl script are invoked directly
5199
            #
5200
            $command = "\$(GBE_PERL) -w "
5201
                if ( $prog =~ /\.pl$/ );
5202
 
5203
            #
5204
            #   Pass / to shells
5205
            #
5206
            $winprog = 0
5207
                unless ( $prog =~ m~\.bat$~ )
5208
 
5209
        } else {
5210
            Warning("RunTest program not known: $prog",
261 dpurdie 5211
                  "It is not a TestProg, Prog or a Script",
5212
                  "The test may fail" );
227 dpurdie 5213
        }
5214
    }
5215
 
5216
    #
5217
    #   Extract and process options
5218
    #
5219
    my @uargs = ();
5220
    my @preq_files;
5221
 
5222
    foreach my $arg (@elements) {
5223
        #
5224
        #   Process the tool arguments and extract file information
5225
        #   Extract all fields of the form:
5226
        #           --xxxxx(yyyyyy[,zzzzz])
5227
        #           --xxxxx{yyyyyyy}
5228
        #           --xxxxx[yyyyyyy] to allow embedded brackets
5229
        #
5230
        while ( $arg =~ m/--(\w+)               # --CommandWord         $1
5231
                                (               # Just for grouping
5232
                                \((.*?)\)   |   # Stuff like (yyyyy)    $3
5233
                                {(.*?)}     |   # or    like {yyyyy}    $4
5234
                                \[(.*?)\]       # or    like [yyyyy]    $5
5235
                                )/x )           # Allow comments and whitespace
5236
        {
5237
            my $cmd = $1;                       # The command
5238
            my $ufn = $3 || $4 || $5;           # User filename + options
5239
            my $mb = $-[0];                     # Match begin offset
5240
            my $me = $+[0];                     # Match end
5241
            my $flags = '';                     # Optional flags ( --dir or --file )
5242
            my $raw_arg = $ufn;                 # Raw arguments
6387 dpurdie 5243
            my $all = substr( $arg, $mb, $me - $mb ); # All of match. Avoid use of $&
329 dpurdie 5244
            my $is_abs;
5245
            my $is_path = 1;
227 dpurdie 5246
 
5247
            Error ("RunTest. Empty element not allowed: $all")
5248
                unless ( defined($ufn) );
5249
 
5250
            $ufn =~ s/\s+$//;
5251
            $ufn =~ s~//~/~g;                   # Remove multiple /
5252
            if ( $ufn =~ m/(.*?),(.*)/ )        # Extract out any flags
5253
            {
5254
                $ufn = $1;
5255
                $flags = $2;
5256
            }
5257
 
5258
            my $fn = $ufn ;                     # Replacement filename
343 dpurdie 5259
            my $fnp = '';                       # Prefix to $fn
227 dpurdie 5260
            Error ("RunTest. Empty element not allowed: $all" )
5261
                if ( length ($ufn) <= 0 );
5262
 
5263
            #
5264
            #   Process found user command
5265
            #
5266
            if ( $cmd =~ /^File/ )
5267
            {
5268
                #
5269
                #   Prerequisite filename
5270
                #       Resolve the full name of the file. It may be known
5271
                #       as a source file (possibly generated) or it may be
5272
                #       located in a known source directory
5273
                #
5274
                $fn = MakeSrcResolve ( $ufn );
5275
                UniquePush (\@preq_files, $fn);
5276
 
5277
                Debug( "RunTest: Prereq: $fn" );
5278
 
5279
            }
5280
            elsif ( $cmd =~ /^PackageBase/ )
5281
            {
5282
                $fn = GetPackageBase( "RunTest", $raw_arg );
5283
                UniquePush (\@preq_files, $fn);
5284
            }
5285
            elsif ( $cmd =~ /^PackageInfo/ )
5286
            {
5287
                $fn = GetPackageInfo( "RunTest", $raw_arg );
5288
            }
5289
            elsif ( $cmd =~ /^Var/ )
5290
            {
343 dpurdie 5291
                ($fnp, $fn, $is_path, $is_abs) = ExpandGenVar( "RunTest", $raw_arg );
227 dpurdie 5292
                $flags = '';
5293
            }
6504 dpurdie 5294
            elsif ( $cmd =~ /^Tool/ )
5295
            {
5296
                ($fn, $is_path, $is_abs) = ExpandTool( "RunTest", $raw_arg );
5297
                $flags = '';
5298
            }
227 dpurdie 5299
            elsif ( $cmd =~ /^Local/ )
5300
            {
5301
                $fn = '$(LOCALDIR)/' . $ufn ;
5302
                UniquePush (\@preq_files, $fn);
5303
            }
6387 dpurdie 5304
            elsif ( $cmd =~ /^Dir/ )
5305
            {
5306
                # Item is a directory.
5307
                # Must be massaged so that it will be correct within the context
5308
                # Modified path is simply added to the command line
5309
                # 
5310
                $fn = $ufn;
5311
                unless (-d $fn) {
5312
                    if (-f $fn) {
5313
                        Warning ("Not a directory. Its a file: $arg") ;
5314
                    } else {
5315
                        Warning ("Directory not found: $arg");
5316
                    }
5317
                }
5318
            }
227 dpurdie 5319
            else
5320
            {
5321
                Warning ("RunTest: Unknown replacement command: $cmd");
5322
                $fn = $ufn;
5323
            }
5324
 
5325
            #
5326
            #   Process path modification flags
5327
            #       --dir           - only the directory part ( or a "." )
5328
            #       --file          - only the file part
5329
            #       --abspath       - Absolute path
5330
            #       --absdrive      - Absolute path with drive letter(WIN)
5331
            #
5332
            $fn = ProcessPathName( $fn, $flags );
5333
 
5334
            #
5335
            #   The program is going to be executed within a subdirectory
5336
            #   so add one more level of indirection to the path, but only if
5337
            #   the path is relative
5338
            #
329 dpurdie 5339
            if ( $is_path && ! $is_abs )
227 dpurdie 5340
            {
329 dpurdie 5341
                unless ( $fn =~ m~^/|^\w:/~  )
5342
                {
5343
                    $fn = '../' . $fn
5344
                        unless( $fn =~ s~=~=../~ );
5345
                    $fn =~ s~/.$~~;
5346
                }
227 dpurdie 5347
            }
5348
 
5349
            #
5350
            #   Minor kludge under windows. Ensure directores have a "\" sep
5351
            #   Unless the user has specified a straight shell command
5352
            #
5986 dpurdie 5353
            $fn = "\$(subst /,\$(dirsep),$fn)"
227 dpurdie 5354
                if ( $::ScmHost eq "WIN" && $winprog );
5355
 
5356
            #
343 dpurdie 5357
            #   Prepend any $fn Prefix
5358
            #   This will be a tag and is not subject to path processing
5359
            #
5360
            $fn = $fnp . $fn;
5361
 
5362
            #
227 dpurdie 5363
            #   Replace the found string with the real name of the file
5364
            #   Note: 4 argument version of substr is not always available
5365
            #         so we must do it the hard way
5366
            #               substr( $arg, $mb, $me - $mb, $fn);
5367
            #
5368
            $arg = substr( $arg, 0, $mb ) . $fn . substr( $arg, $me );
5369
 
5370
            Debug2( "RunTest: subs: $all -> $fn" );
5371
        }
5372
        push(@uargs, "'$arg'");
5373
    }
5374
 
5375
    #
5376
    #   Create the test entry
5377
    #   This is a structure that will be placed in an array
5378
    #   The array preserves order and uniqness
5379
    #
5380
    my %test_entry;
5381
    $test_entry{'framework'}= $framework if ( $framework );
5382
    $test_entry{'framework_opts'}= \@framework_opts if ( $framework );
5383
    $test_entry{'command'}  = $command . $prog unless ( $framework);
5384
 
5385
    $test_entry{'prog'}     = $prog;
5386
    $test_entry{'copyprog'} = 1;
5387
    $test_entry{'args'}     = \@uargs;
5388
    $test_entry{'auto'}     = $auto if ( $auto );
4778 dpurdie 5389
    $test_entry{'utfformat'}= $utfFormat if ( $utfFormat );
4781 dpurdie 5390
    $test_entry{'utfargs'}  = \@utfArgs;
5391
    $test_entry{'utfname'}  = $utfName;
5695 dpurdie 5392
    $test_entry{'maxtime'}  = $maxTime if ($maxTime);
227 dpurdie 5393
    $test_entry{'copyin'}   = \@copy;
5394
    $test_entry{'copyonce'} = ();
5395
    $test_entry{'preq'}     = \@preq_files;
5396
    $test_entry{'testdir'}  = 'BINDIR';
5397
 
5398
    push ( @TESTS_TO_RUN, \%test_entry );
5399
 
5400
    #
5401
    #   Flag Auto Run processing required
5402
    #
4501 dpurdie 5403
    $TESTS_TO_RUN = 1;
227 dpurdie 5404
    $TESTS_TO_AUTORUN = 1 if ( $auto );
5405
}
5406
 
5407
 
5408
sub TestProg
5409
{
5410
    my( $platforms, $prog, @elements ) = @_;
5411
 
5412
    Debug2( "TestProg($platforms, $prog, @elements)" );
5413
 
5414
    return if ( ! ActivePlatform($platforms) );
5415
 
5416
    Error ("TestProg: Program name not defined") unless ( $prog );
5417
    Error ("Programs are not supported") unless ( defined $::exe );
5418
 
289 dpurdie 5419
    #
5420
    #   Create a new Prog object, or retrieve any existing one
5421
    #
5422
    my $pProg = $TESTPROGS->Get($prog);
5423
    $pProg = $TESTPROGS->NewAdd($prog)
5424
        unless ( $pProg );
227 dpurdie 5425
 
5426
#.. Parse all of the object, library and argument entries
5427
    Debug( "TestProg: $prog" );
5428
    foreach (@elements)
5429
    {
5430
        if ( /^[-]{1,2}([lL])(.*)/ )
5431
        {
5432
        #.. Target Library specified - add to library list.
5433
        #  
5434
            Debug( "TestProg: lib  -$1$2" );
289 dpurdie 5435
            $pProg->addItem('LIBS', "-$1$2");
227 dpurdie 5436
            next;
5437
        }
5438
 
5439
        if ( /^--if(.*)/ )
5440
        {
5441
        #.. Library conditional - add to library list.
5442
        #
5443
            Debug( "TestProg: cond $_" );
289 dpurdie 5444
            $pProg->addItem('LIBS', $_);
227 dpurdie 5445
            next;
5446
        }
5447
 
5448
        if ( /^-(.*)/ )
5449
        {
5450
        #.. Argument specified - add to argument list
5451
        #
5452
            Debug( "TestProg: arg $_" );
289 dpurdie 5453
            $pProg->addItem('ARGS', $_);
227 dpurdie 5454
            next;
5455
        }
5456
 
369 dpurdie 5457
        if ( %::ScmToolsetProgSource )
227 dpurdie 5458
        {
5459
            #
5460
            #   Toolset provides support for some file types
5461
            #   to be passed directly to the program builder
5462
            #
5463
            my $ext  = StripFile($_);
5464
            if ( exists ($::ScmToolsetProgSource{$ext}) )
5465
            {
5466
                my $full_path = MakeSrcResolve ( $_ );
5467
                my $flag = $::ScmToolsetProgSource{$ext};
5468
                Debug( "TestProg: src $_" );
289 dpurdie 5469
                $pProg->addItem('ARGS', "$flag$full_path");
227 dpurdie 5470
                next;
5471
            }
5472
        }
5473
 
5474
        if ( $::o )
5475
        {
5476
        #.. Object specified - add to object list.
5477
        #
5478
            my $obj = _LibObject( "", $_ );
5479
 
5480
        #.. Add to program object list.
289 dpurdie 5481
            $pProg->addItem('OBJS', "\$(OBJDIR)/$obj");
227 dpurdie 5482
            next;
5483
        }
5484
 
5485
        #
5486
        #   Don't know how to handle this type of argument
5487
        #
5488
        Error ("TestProg: Don't know how to handle: $_" );
5489
    }
5490
}
5491
 
5492
 
5493
sub Prog
5494
{
5495
    my( $platforms, $prog, @elements ) = @_;
5496
 
5497
    Debug2( "Prog($platforms, $prog, @elements)" );
5498
 
5499
    return if ( ! ActivePlatform($platforms) );
5500
 
5501
    Error ("Prog: Program name not defined") unless ( $prog );
5502
    Error ("Programs are not supported") unless ( defined $::exe );
5503
 
289 dpurdie 5504
    #
5505
    #   Create a new Prog object, or retrieve any existing one
5506
    #
5507
    my $pProg = $PROGS->Get($prog);
5508
    $pProg = $PROGS->NewAdd($prog)
5509
        unless ( $pProg );
227 dpurdie 5510
 
5511
#.. Parse all of the object, library and argument entries
5512
    Debug( "Prog: $prog" );
5513
    foreach (@elements)
5514
    {
5515
        if ( /^[-]{1,2}([lL])(.*)/ )
5516
        {
5517
        #.. Target Library specified - add to library list.
5518
        #  
5519
            Debug( "Prog: lib  -$1$2" );
289 dpurdie 5520
            $pProg->addItem('LIBS', "-$1$2");
227 dpurdie 5521
            next;
5522
        }
5523
 
5524
        if ( /^--if(.*)/ )
5525
        {
5526
        #.. Library conditional - add to library list.
5527
        #
5528
            Debug( "Prog: cond $_" );
289 dpurdie 5529
            $pProg->addItem('LIBS', $_);
227 dpurdie 5530
            next;
5531
        }
5532
 
5533
        if ( /^-(.*)/ )
5534
        {
5535
        #.. Argument specified - add to argument list
5536
        #
5537
            Debug( "Prog: arg $_" );
289 dpurdie 5538
            $pProg->addItem('ARGS', $_);
227 dpurdie 5539
            next;
5540
        }
5541
 
369 dpurdie 5542
        if ( %::ScmToolsetProgSource )
227 dpurdie 5543
        {
5544
            #
5545
            #   Toolset provides support for some file types
5546
            #   to be passed directly to the program builder
5547
            #
5548
            my $ext  = StripFile($_);
5549
            if ( exists ($::ScmToolsetProgSource{$ext}) )
5550
            {
5551
                my $full_path = MakeSrcResolve ( $_ );
5552
                my $flag = $::ScmToolsetProgSource{$ext};
5553
                Debug( "Prog: src $_" );
289 dpurdie 5554
                $pProg->addItem('ARGS', "$flag$full_path");
227 dpurdie 5555
                next;
5556
            }
5557
        }
5558
 
5559
        if ( $::o )
5560
        {
5561
        #.. Object specified - add to object list.
5562
        #
5563
            my $obj = _LibObject( "", $_ );
5564
 
5565
        #.. Add to program object list.
289 dpurdie 5566
            $pProg->addItem('OBJS', "\$(OBJDIR)/$obj");
227 dpurdie 5567
            next;
5568
        }
5569
 
5570
        #
5571
        #   Don't know how to handle this type of argument
5572
        #
5573
        Error ("Prog: Don't know how to handle: $_" );
5574
    }
5575
}
5576
 
5577
#-------------------------------------------------------------------------------
5578
# Function        : ProgAddExtra
5579
#
5580
# Description     : This (internal) function allows a toolset to list additional
5581
#                   binaries as a part of a program. This will ensure that the
5582
#                   binaries are generated in the 'make_prog' phase with the main
5583
#                   program.
5584
#
5585
#                   The files are not listed for packaging, by this function
5586
#
5587
#                   The function does not ensure that the files are not already
5588
#                   listed as a @PROG ( as @PROGS is not fully resolved at this point )
5589
#
5590
# Inputs          :     $name               - Tag name of program being built
5591
#                                             Not used (yet)
5592
#                       $prog               - Fully resolved path to a file
5593
#
5594
# Returns         : Nothing
5595
#
5596
sub ProgAddExtra
5597
{
5598
    my ($name, $prog) = @_;
5599
    Debug2( "ProgAddExtra($name: $prog)" );
5600
 
5601
    UniquePush(\@PROGS_EXTRA, $prog);
5602
}
5603
 
4261 dpurdie 5604
our %PROJECTS;                          # Project information
5605
my  @PROJECTS_ORDER;
227 dpurdie 5606
#-------------------------------------------------------------------------------
4261 dpurdie 5607
# Function        : MakeProjectName 
5608
#
5609
# Description     : Create a uniq project name
5610
#
5611
# Inputs          : srcPath 
5612
#
5613
# Returns         : A unique project name 
5614
#
5615
sub MakeProjectName
5616
{
5617
    my ($srcPath) = @_;
5618
    my $suffix = "";
5619
    my $index = 1;
5620
 
5621
    my $proj = StripDir( $srcPath );
5622
    while (exists $PROJECTS{$proj . $suffix})
5623
    {
5624
        $suffix = '.' . $index++;
5625
    }
5626
    return $proj . $suffix; 
5627
}
5628
 
5629
#-------------------------------------------------------------------------------
227 dpurdie 5630
# Function        : MakeProject
5631
#
5632
# Description     : A nasty directive that is intended to build a Microsoft
5633
#                   project for WINCE, WIN32 and .NET builds.
5634
#
5635
#                   There are many constraints:
5636
#                       Cannot be mixed with multi-platform builds
5637
#                       Some parameters are tool specific
5638
#
267 dpurdie 5639
#                   Allow programs to be Installed as well as Packaged
5640
#                   The 'Progect' is treated' as a program and it doesn't work
5641
#                   to well if we Install libraries.
227 dpurdie 5642
#
267 dpurdie 5643
#                   Only Reason to Install Programs is to allow the Cab Maker
5644
#                   to locate them.
5645
#
227 dpurdie 5646
# Inputs          : Platform        - Active platform
5647
#                   Project         - Project Name with extension
5648
#                   Options         - Many options
5649
#
5650
# Returns         :
5651
#
5652
sub MakeProject
5653
{
5654
    my( $platforms, $proj, @elements ) = @_;
5655
 
5656
    Debug2( "MakeProject($platforms, $proj, @elements)" );
5657
 
5658
    return if ( ! ActivePlatform($platforms) );
5659
 
5660
    #
5661
    #   Sanity test
5662
    #
5663
    Error ("MakeProject: Project name not defined") unless ( $proj );
5664
 
5665
    #
5666
    #   Take the project name and convert it into a full path
4261 dpurdie 5667
    #   Need to create a uniq project name - allowing for multiple uses
227 dpurdie 5668
    #
5669
    my $project = MakeSrcResolve ( $proj );
4261 dpurdie 5670
    $proj = MakeProjectName($project);
5671
 
237 dpurdie 5672
    Error ("Project File Not found: $project") unless ( -f $project );
227 dpurdie 5673
 
5674
    my $basedir = StripFileExt( $project );
5675
 
5676
    #
5677
    #   Collect user arguments
5678
    #   They are all processed within the toolset
5679
    #
5680
    my @tool_options;
5411 dpurdie 5681
    my $unit_tests;
5682
    my $auto_tests;
227 dpurdie 5683
    foreach ( @elements )
5684
    {
5685
        if ( m/^--Debug/ ) {
5686
            $PROJECTS{$proj}{'Debug'} = 1;
5687
 
5688
        } elsif ( m/^--Prod/ ) {
5689
            $PROJECTS{$proj}{'Prod'} = 1;
5690
 
267 dpurdie 5691
        } elsif ( m/^--(Package|Install)ProgDebug=(.*)/ ) {
5692
            _PackageFromProject( $1, $proj, $basedir,'Prog', 'D', $2 );
227 dpurdie 5693
 
267 dpurdie 5694
        } elsif ( m/^--(Package|Install)Prog(Prod)*=(.*)/ ) {
5695
            _PackageFromProject( $1, $proj, $basedir, 'Prog', 'P', $3 );
227 dpurdie 5696
 
267 dpurdie 5697
        } elsif ( m/^--(Package)LibDebug=(.*)/ ) {
5698
            _PackageFromProject( $1, $proj, $basedir, 'Lib', 'D', $2 );
227 dpurdie 5699
 
267 dpurdie 5700
        } elsif ( m/^--(Package)Lib(Prod)*=(.*)/ ) {
5701
            _PackageFromProject( $1, $proj, $basedir, 'Lib', 'P', $3 );
227 dpurdie 5702
 
267 dpurdie 5703
        } elsif ( m/^--(Package)SharedLibDebug=(.*)/ ) {
5704
            _PackageFromProject( $1, $proj, $basedir, 'Lib', 'D', $2 );
227 dpurdie 5705
 
267 dpurdie 5706
        } elsif ( m/^--(Package)SharedLib(Prod)*=(.*)/ ) {
5707
            _PackageFromProject( $1, $proj, $basedir, 'Lib', 'P', $3 );
227 dpurdie 5708
 
267 dpurdie 5709
        } elsif ( m/^--(Package)Hdr=(.*)/ ) {
5710
            _PackageFromProject( $1, $proj, $basedir, 'Hdr', undef, $2 );
227 dpurdie 5711
 
267 dpurdie 5712
        } elsif ( m/^--(Package)File=(.*)/ ) {
5713
            _PackageFromProject( $1, $proj, $basedir, 'File', undef, $2 );
227 dpurdie 5714
 
267 dpurdie 5715
        } elsif ( m/^--(Package)Tool(Prod)*=(.*)/ ) {
5716
            _PackageFromProject( $1, $proj, $basedir, 'Tool', 'P', $3 );
241 dpurdie 5717
 
267 dpurdie 5718
        } elsif ( m/^--(Package)ToolDebug=(.*)/ ) {
5719
            _PackageFromProject( $1, $proj, $basedir, 'Tool', 'D', $2 );
241 dpurdie 5720
 
267 dpurdie 5721
        } elsif ( m/^--(Package|Install)/ ) {
5722
            Error("MakeProject. Unknown $1 option: $_");
227 dpurdie 5723
 
5411 dpurdie 5724
        } elsif ( m/^--UnitTest/ ) {
5725
            $unit_tests = 1;
5726
 
5727
        } elsif ( m/^--AutoTest/ ) {
5728
            $auto_tests = 1;
5729
 
227 dpurdie 5730
        } else {
5731
            push @tool_options, $_;
5732
        }
5733
    }
5734
 
5735
    #
6353 dpurdie 5736
    #   Validate some of the arguments
5737
    #   Ensure has not specified both --Prod and --Debug
5738
    #
5739
    Error ("Makeproject. Conflicting options --Debug and --Prod" )
5740
        if ( $PROJECTS{$proj}{'Debug'}  && $PROJECTS{$proj}{'Prod'} );
5741
 
5742
    #   Ensure that global --OnlyProd/Debug don't prevent builds
5743
    $PROJECTS{$proj}{'Debug'} = 1 if ($ScmBuildType eq 'D');
5744
    $PROJECTS{$proj}{'Prod'} = 1 if ($ScmBuildType eq 'P');
5745
    Error ("Makeproject. Global and Local options --Debug and --Prod prevent project being built" )
5746
        if ( $PROJECTS{$proj}{'Debug'}  && $PROJECTS{$proj}{'Prod'} );
5747
 
5748
    #
227 dpurdie 5749
    #   Save the information
5750
    #
5751
    $PROJECTS{$proj}{'options'} = \@tool_options;
5752
    $PROJECTS{$proj}{'name'} = $proj;
5753
    $PROJECTS{$proj}{'project'} = $project;
5754
    $PROJECTS{$proj}{'basedir'} = $basedir;
5411 dpurdie 5755
    $PROJECTS{$proj}{'unittest'} = $unit_tests if ( $unit_tests );
5756
    $PROJECTS{$proj}{'autotest'} = $auto_tests if ( $auto_tests );
227 dpurdie 5757
    UniquePush (\@PROJECTS_ORDER, $proj);
5758
 
5759
}
5760
 
5761
#-------------------------------------------------------------------------------
5762
# Function        : _PackageFromProject
5763
#
5764
# Description     : Save Packaged data from the project
5765
#
267 dpurdie 5766
# Inputs          : $tgt        - Install or Package
5767
#                   $proj       - Name of the project
227 dpurdie 5768
#                   $base       - Base directory of files
5769
#                   $etype      - Type of Package (Progs, Libs, ... )
5770
#                   $type       - Debug or Production or both
5771
#                   $items      - Item to add. It may be comma seperated
5772
#
267 dpurdie 5773
my %PackageToData = ( 'Package' =>
5774
                        { 'Hdr'   => \%PACKAGE_HDRS,
5775
                          'Lib'   => \%PACKAGE_LIBS,
5776
                          'Prog'  => \%PACKAGE_PROGS,
5777
                          'File'  => \%PACKAGE_FILES,
5778
                          'Tool'  => \%PACKAGE_FILES,
5779
                          '_BASE' => 'PBase',
5780
                        },
5781
                      'Install' =>
5782
                        { 'Hdr'   => \%INSTALL_HDRS,
5783
                          'Lib'   => \%INSTALL_LIBS,
5784
                          'Prog'  => \%INSTALL_PROGS,
5785
                          'File'  => undef,
5786
                          'Tool'  => undef,
5787
                          '_BASE' => 'IBase',
5788
                        },
227 dpurdie 5789
                    );
5790
 
5791
sub _PackageFromProject
5792
{
267 dpurdie 5793
    my( $tgt, $proj, $base, $etype, $type, $items ) = @_;
227 dpurdie 5794
    my $subdir = '';
5795
 
5796
    #
267 dpurdie 5797
    #   Sanity test
5798
    #
5799
    $type = '' unless ( $type );
5800
    Error ("INTERNAL. Bad packaging option: $tgt")   unless ( exists $PackageToData{$tgt} );
5801
    Error ("INTERNAL. Bad packaging option: $etype") unless ( exists $PackageToData{$tgt}{$etype} );
5802
    Error ("Unsupported packaging combination: $tgt$etype$type=$items") unless ( defined $PackageToData{$tgt}{$etype} );
5803
 
5804
    #
5805
    #   Determine the index into the 'PackageInfo' structure
5806
    #   This provides the symbolic name for the target package path
5807
    #   for Package or Install
5808
    #
5809
    #   The key '_BASE' is internal. Used only to provide this information
5810
    #
5811
    my $tbase = $PackageToData{$tgt}{'_BASE'};
5812
 
5813
    #
227 dpurdie 5814
    #   Process options
5815
    #
5816
    foreach my $item ( split (/,/, $items ) )
5817
    {
5818
        next unless ( $item =~ m/^--/ );
5819
        if ( $item =~ m/^--Subdir=(.*)/ )
5820
        {
5821
            $subdir = '/' . $1;
5822
            $subdir =~ s~//~/~g;
5823
            $subdir =~ s~/$~~g;
5824
        }
5825
        else
5826
        {
5827
            Warning( "MakeProject: Unknown packaging option ignored: $_" );
5828
        }
5829
    }
5830
 
5831
    #
5832
    #   Process files
5833
    #
5834
    foreach my $item ( split (/,/, $items ) )
5835
    {
5836
        next if ( $item =~ m/^--/ );
5837
 
267 dpurdie 5838
        my $tdir = $PackageInfo{$etype}{$tbase} . $PackageInfo{$etype}{'Dir'} . $subdir ;
227 dpurdie 5839
        my $fname = StripDir( $item );
5840
        my $target = $tdir . '/' . $fname;
5841
 
5842
        $item = "$base/$item" if ( $base );
5843
 
5844
        #
5845
        #   Do not use $(GBE_TYPE) in the target name
5846
        #   The existing package mechanism does not handle different
5847
        #   production and debug file naming mechanism, whereas the project
5848
        #   must. Convert $(GBE_TYPE) into P or D to ensure uniquness
5849
        #
5850
        $target =~ s~\$\(GBE_TYPE\)~$type~ if ($type);
5851
 
5852
        #
5853
        #   Create a PACKAGE entry suitable for processing by the normal packaging
5854
        #   routines. This is complicated because the Projects do not adhere to
267 dpurdie 5855
        #   the JATS file name conventions
227 dpurdie 5856
        #
5857
        my %package_entry;
5858
        $package_entry{'src'}   = $item;
5859
        $package_entry{'dir'}   = $tdir;
267 dpurdie 5860
        $package_entry{'set'}   = 'ALL' if ($tgt eq 'Package');
227 dpurdie 5861
        $package_entry{'type'}  = $type if ($type);
5862
 
267 dpurdie 5863
        $PackageToData{$tgt}{$etype}->{$target} = {%package_entry};
227 dpurdie 5864
    }
5865
}
5866
 
5867
#-------------------------------------------------------------------------------
5868
# Function        : MakeAnt
5869
#
5870
# Description     : A nasty directive to create JAR files via ANT
5871
#                   There are several limitations
5872
#                   This is closely related to the MakeProject directive
5873
#
5874
#
5875
# Inputs          : Platform            - Active platform
5876
#                   buildfile           - Name of the build.xml file
5877
#                   Options             - A few options
5878
#                                         --Jar=file
5879
#                                               Generated JAR file(s)
5880
#                                         --GeneratedFile=file
5881
#                                               Other generated files
5882
#                                               Used to flag JNI that must
5883
#                                               Occur early
5884
#                                          --AutoTest=<name>
5885
#                                               Supports unitAutomated unit test
5886
#                                               by calling build target <name>
5887
#                                          --UnitTest=<name>
5888
#                                               Supports unit test
5889
#                                               by calling build target <name>
5890
#                                          --PackageBase
5891
#                                               Provides path to base of all packages
6294 dpurdie 5892
#                                          --AllPackages
5893
#                                               Provide paths to both LinkPkgArchive and BuildPkgArchive
227 dpurdie 5894
#
5895
# Returns         :
5896
#
5897
our %JAR_FILES;
5898
sub MakeAnt
5899
{
5900
    my( $platforms, $proj, @elements ) = @_;
5901
 
5902
    Debug2( "MakeAnt($platforms, $proj, @elements)" );
5903
 
5904
    return if ( ! ActivePlatform($platforms) );
5905
 
5906
    #
5907
    #   Sanity test
5908
    #
5909
    Error ("MakeAnt: build.xml name not defined") unless ( $proj );
5910
 
5911
    #
5912
    #   Take the project name and convert it into a full path
5913
    #
5914
    my $project;
5915
    $project = MakeSrcResolve ( $proj );
4261 dpurdie 5916
    $proj = MakeProjectName($project);
237 dpurdie 5917
    Error ("Build File Not found: $project") unless ( -f $project );
227 dpurdie 5918
 
5919
    my $basedir = StripFileExt( $project );
5920
 
5921
    #
5922
    #   Collect user arguments
5923
    #   They are all processed within the toolset
5924
    #
5925
    my @tool_options;
5926
    my @generated;
5927
    my $unit_tests;
5928
    my $auto_tests;
5929
    my $package_base;
6294 dpurdie 5930
    my $allPackages;
227 dpurdie 5931
 
5932
    foreach ( @elements )
5933
    {
5934
        if ( m/^--Debug/ ) {
5935
            $PROJECTS{$proj}{'Debug'} = 1;
5936
 
5937
        } elsif ( m/^--Prod/ ) {
5938
            $PROJECTS{$proj}{'Prod'} = 1;
5939
 
5940
        } elsif ( m/^--Jar=(.*)/ ) {
5941
            my $tgt = $1;
5942
               $tgt = "$basedir/$tgt" if ( $basedir );
5943
            my $fn = StripDir( $1 );
5944
            $JAR_FILES{$fn} = $tgt;
5945
            GenerateSrcFile( 0, $tgt );
5946
 
5947
        } elsif ( m/^--GeneratedFile=(.*)/ ) {
5948
            my $tgt = $1;
5949
            $tgt = "$basedir/$tgt" if ( $basedir );
5950
            push @generated, $tgt;
5951
            GenerateSrcFile( 2, $tgt );
5952
 
5953
        } elsif ( m/^--UnitTest=(.*)/ ) {
5954
            $unit_tests = $1
5955
 
5956
        } elsif ( m/^--AutoTest=(.*)/ ) {
5957
            $auto_tests = $1
5958
 
5959
        } elsif ( m/^--PackageBase/ ) {
5960
            $package_base = 1;
5961
 
6294 dpurdie 5962
        } elsif ( m/^--AllPackages/i ) {
5963
            $allPackages = 1;
227 dpurdie 5964
 
5965
        } elsif ( m/^--/ ) {
5966
            Error("MakeAnt. Unknown option ignored: $_");
5967
 
5968
        } else {
5969
            push @tool_options, $_;
5970
        }
5971
    }
5972
 
5973
    #
5974
    #   Extend option arguments to include the base dir of packages
5975
    #   Create definitions of the form PACKAGE_<name>
5976
    #
6294 dpurdie 5977
    for my $entry (getPackageList())
227 dpurdie 5978
    {
6294 dpurdie 5979
        my $pkgType = $entry->getType();
5980
        next if $pkgType eq 'interface'  ;
5981
        next unless ( ( $pkgType eq 'link') || $allPackages);
5982
        my $dir = $entry->getBase(2);
5983
        my $name = $entry->getName();
227 dpurdie 5984
        unless ( $package_base )
5985
        {
5986
            $dir .= '/jar';
5987
            next unless ( -d $dir );
5988
        }
6294 dpurdie 5989
        push @tool_options, "-DPACKAGE_$name=\$(call myabspath,$dir)";
227 dpurdie 5990
    }
5991
    #
5992
    #   Extend options to include the base dir of the created package
5993
    #   Allows careful use for direct packaging of artifacts
5994
    #
6294 dpurdie 5995
    push @tool_options, '-DPACKAGEDIR=$(call myabspath,$(PKGDIR))';
227 dpurdie 5996
 
5997
    #
5998
    #   Save the information
5999
    #
6000
    $PROJECTS{$proj}{'options'} = \@tool_options;
6001
    $PROJECTS{$proj}{'generated'} = \@generated if ( @generated );
6002
    $PROJECTS{$proj}{'name'}    = $proj;
6003
    $PROJECTS{$proj}{'project'} = $project;
6004
    $PROJECTS{$proj}{'basedir'} = $basedir;
6005
    $PROJECTS{$proj}{'type'}    = 'ant';
6006
    $PROJECTS{$proj}{'unittest'} = $unit_tests if ( $unit_tests );
6007
    $PROJECTS{$proj}{'autotest'} = $auto_tests if ( $auto_tests );
6008
    UniquePush (\@PROJECTS_ORDER, $proj);
6009
 
6010
    $TESTS_TO_AUTORUN = 1 if ( $auto_tests );
4501 dpurdie 6011
    $TESTS_TO_RUN     = 1 if ( $unit_tests || $auto_tests );
227 dpurdie 6012
 
6013
    #
6014
    #   Validate some of the arguments
6015
    #
6016
    Error ("MakeAnt. Conflicting options --Debug and --Prod" )
6017
        if ( $PROJECTS{$proj}{'Debug'}  && $PROJECTS{$proj}{'Prod'} );
6018
}
6019
 
6020
###############################################################################
6021
#
6022
#   Installation/Packaging util functions
6023
#
6024
#-------------------------------------------------------------------------------
6025
# Function        : __TargetDir
6026
#
6027
# Description     : Internal function to process common arguments for
6028
#                   the PackageXxx directives
6029
#
6030
# Inputs          : flags           - Indicate how to handle this argument
6031
#                   base            - Base directory for this type of package
6032
#                   argument        - Argument to process
6033
#                   pdir            - Reference to resultant directory
6034
#                   ptype           - Reference to resultant type (P or D)(optional)
6035
#
6036
# Returns         : 0               - Agument not consumed
6037
#                   1               - Argument consumed
6038
#                   2               - Skip this directive
6039
#
6040
my $T_TYPE  = 0x0001;                           # Postfix GBE_TYPE
6041
my $T_PKG   = 0x0002;                           # Special --Dir handling
6042
my $T_MACH  = 0x0004;                           # Allow --Machine too
6043
my $T_GBE   = 0x0008;                           # Allow --Gbe too
6044
my $T_FILE  = 0x0010;                           # Suffix or prefix subdir
6045
 
6046
sub __TargetDir
6047
{
6048
    my( $flags, $base, $argument, $pdir, $ptype ) = @_;
6049
    my $dir  = "";
6050
    my $consumed = 0;
6051
 
6052
    #
6053
    #   Generate basic parts
6054
    #   Note Product will default to Platform
6055
    #
6056
    my $str_platform = '$(GBE_PLATFORM)';
6057
    my $str_product = $ScmProduct ? '$(GBE_PRODUCT)' : '$(GBE_PLATFORM)';
6058
    my $str_target = '$(GBE_TARGET)';
6059
    my $str_common = '$(GBE_OS_COMMON)';
6060
 
6061
    my $str_common_avail = 0;
6062
       $str_common_avail = 1 if ( exists( $::BUILDINFO{$ScmPlatform}{OS_COMMON} ));
6063
 
6064
 
6065
    #
6066
    #   Add requested suffix
6067
    #
6068
    if ($flags & $T_TYPE)
6069
    {
6070
        $str_platform .= '$(GBE_TYPE)';
6071
        $str_product  .= '$(GBE_TYPE)';
6072
        $str_target   .= '$(GBE_TYPE)';
6073
        $str_common   .= '$(GBE_TYPE)';
6074
    }
6075
 
6076
    #
6077
    #   Process the argument
6078
    #
6079
    $_ = $argument;
6080
    if ( /^--Debug/ ) {                         # In the Debug build only
6081
        if ( $ptype ) {
6082
            $$ptype = "D";
6083
            $consumed = 1;
6084
        }
6085
 
6086
    } elsif ( /^--Prod$/ || /^--Production$/ ) { # In the Production build only
6087
        if ( $ptype ) {
6088
            $$ptype = "P";
6089
            $consumed = 1;
6090
        }
6091
 
6092
    } elsif (/^--Prefix=(.*)/) {                # Prefix with subdir
6093
        $dir = "$base/$1";
6094
 
6095
    } elsif (/^--Subdir=(.*)/) {                # same as 'prefix'
6096
        $dir = "$base/$1";
6097
 
6098
    } elsif (/^--Platform$/) {                  # Platform installation
6099
        $dir = "$base/$str_platform";
6100
 
6101
    } elsif (/^--Platform=(.*?),(.*)/) {        # prefix and suffix with platform specific subdir
6102
        $dir = "$base/$1/$str_platform/$2";
6103
 
6104
    } elsif (/^--Platform=(.*)/) {              # prefix with platform specific subdir
6105
        if ($flags & $T_FILE) {
6106
            $dir = "$base/$1/$str_platform";
6107
        } else {
6108
            $dir = "$base/$str_platform/$1";
6109
        }
6110
 
6111
    } elsif (/^--Product$/) {                   # Product installation
6112
        $dir = "$base/$str_product";
6113
 
6114
    } elsif (/^--Product=(.*?),(.*)/) {         # prefix and suffix with product specific subdir
6115
        $dir = "$base/$1/$str_product/$2";
6116
 
6117
    } elsif (/^--Product=(.*)/) {               # prefix with product specific subdir
6118
        if ($flags & $T_FILE) {
6119
            $dir = "$base/$1/$str_product";
6120
        } else {
6121
            $dir = "$base/$str_product/$1";
6122
        }
6123
 
6124
    } elsif (/^--Target$/) {                    # Target installation
6125
        $dir = "$base/$str_target";
6126
 
6127
    } elsif (/^--Target=(.*?),(.*)/) {          # prefix and suffix with target specific subdir
6128
        $dir = "$base/$1/$str_target/$2";
6129
 
6130
    } elsif (/^--Target=(.*)/) {                # prefix with target specific subdir
6131
        if ($flags & $T_FILE) {
6132
            $dir = "$base/$1/$str_target";
6133
        } else {
6134
            $dir = "$base/$str_target/$1";
6135
        }
6136
 
6137
    } elsif (/^--OsCommon/) {
6138
 
6139
        unless ( $str_common_avail ) {
6140
            Warning("Packaging option --OsCommon not supported on this platform($ScmPlatform). Directive skipped");
6141
            $consumed = 2;
6142
 
6143
        } elsif (/^--OsCommon$/) {                  # OS installation
6144
            $dir = "$base/$str_common";
6145
 
6146
        } elsif (/^--OsCommon=(.*?),(.*)/) {        # prefix and suffix with target specific subdir
6147
            $dir = "$base/$1/$str_common/$2";
6148
 
6149
        } elsif (/^--OsCommon=(.*)/) {              # prefix with target specific subdir
6150
            if ($flags & $T_FILE) {
6151
                $dir = "$base/$1/$str_common";
6152
            } else {
6153
                $dir = "$base/$str_common/$1";
6154
            }
6155
        }
6156
 
6157
    } elsif (/^--Derived=(.*?),(.*?),(.*)/) {   # Derived target + prefix + subdir
6158
        $dir = "$base/$2/$1_$str_platform/$3";
6159
 
6160
    } elsif (/^--Derived=(.*?),(.*)/) {         # Derived target + subdir
6161
        if ($flags & $T_FILE) {
6162
            $dir = "$base/$2/$1_$str_platform";
6163
        } else {
6164
            $dir = "$base/$1_$str_platform/$2";
6165
        }
6166
 
6167
    } elsif (/^--Derived=(.*)/) {               # Derived target
6168
        $dir = "$base/$1_$str_platform";
6169
 
6170
    } elsif ($flags & $T_MACH && /^--Machine(([=])(.*))?$/) {   # Allow Machine and Machine=xxx specfic target
6171
        #
6172
        #   Special: Append machine type to user dir
6173
        #            Intended to create tools/bin/win32 and tools/bin/sparc directories
6174
        my $path = ( defined( $3) ) ? "/$3" : "";
6175
        $dir = "$base$path/\$(GBE_HOSTMACH)";
6176
 
6177
    } elsif ($flags & $T_GBE && /^--Gbe(([=])(.*))?$/) {   # Allow Gbe and Gbe=xxx specfic target
6178
        my $path = ( defined( $3) ) ? "/$3" : "";
6179
        $dir = "$base/gbe$path";
6180
 
6181
    } elsif (/^--Dir=(.*)/) {                   # prefix with target specific subdir
6182
        Error ('Packaging directive with --Dir option does not specify a directory.',
6183
               'Possible bad use of option of the form:--Dir=$xxx',
6184
               'Note: Use of package.pl and this construct is deprecated') unless ( $1 );
241 dpurdie 6185
        my $udir = $1;
6186
 
6187
        #
6188
        #   Remove leading ./
6189
        #   Check for leading ../
5568 dpurdie 6190
        #   
6191
        #   Remove any stupid path manipulation elements
6192
        #   
5827 dpurdie 6193
        if ($udir =~ s~^([./]*/)~~)
6194
        {
6195
            Warning("Packaging directive with --Dir option contains path manipulation elements (removed)", "Option: $_");
6196
        }
241 dpurdie 6197
 
227 dpurdie 6198
        if ($flags & $T_PKG) {
241 dpurdie 6199
            $dir = __PkgDir( $udir );
227 dpurdie 6200
        } else {
6387 dpurdie 6201
            $dir = $base . "/" . $udir;
227 dpurdie 6202
        }
6203
    }
6204
 
6205
    return ($consumed) if ($dir eq "");
6206
    $dir =~ s~//~/~g;
6207
    $dir =~ s~/$~~;
6208
    $$pdir = $dir;
6209
    return (1);
6210
}
6211
 
6212
 
6213
#   __PkgDir ---
6214
#       Convert --Dir Package directives, removing leading subdir if
6215
#       matching the global $Pbase value.
6216
#
6217
#       Required as PKGDIR has the value 'GBE_ROOT/pkg/$Pbase'.
6218
#       Required to maintain compatability with older (package.pl) constructs
6219
#..
6220
 
6221
sub __PkgDir
6222
{
6223
    my( $dir ) = @_;
6224
    my $org = $dir;
6225
 
245 dpurdie 6226
    $dir =~ s~^\Q$::Pbase\E[/]?~~;
227 dpurdie 6227
    Debug2( "  PkgDir: converted \"$org\" to \"$dir\"" );
6228
 
6229
    $dir = "\$(PKGDIR)/$dir";
6230
    return $dir;
6231
}
6232
 
6233
 
6234
#   getMajorMinor ---
6235
#       Just a little help to deal with major/minor stuff for shared libs -
6236
#       given the name of the library as the argument, split out major and
6237
#       minor parts and return the basename, i.e name without major and minor
6238
#       and the pair of major and minor.
6239
#..
6240
 
285 dpurdie 6241
sub getMajorMinor
227 dpurdie 6242
{
6243
    my @bits = split ('\.', $_[0]);
6244
    my $stop;
6245
    my $major;
6246
    my $minor;
6247
 
6248
    if ( $#bits > 2 )
6249
    {
6250
        $stop = $#bits - 2;
6251
        $major = $bits[$#bits-1];
6252
        $minor = $bits[$#bits];
6253
    }
6254
    elsif ($#bits > 1)
6255
    {
6256
        $stop = $#bits-1;
6257
        $major = $bits[$#bits];
6258
        $minor=0;
6259
    }
6260
    else
6261
    {
6262
        $stop = $#bits; $major = 1; $minor = 0;
6263
    }
6264
 
6265
    my $base = $bits[0];
6266
    for ( my $i=1; $i <= $stop; $i++ ) {
6267
        $base = join ('.', $base, $bits[$i]);
6268
    }
6269
 
6270
    return ($base, $major, $minor);
6271
}
6272
 
6273
###############################################################################
6274
#
6275
#   Installation
6276
#
6277
 
6278
sub InstallHdr
6279
{
6280
    my( $platforms, @elements ) = @_;
335 dpurdie 6281
    my( $base, $dir, $srcfile, $full, $strip, $package );
227 dpurdie 6282
    my( $len, $name, $basename );
6283
 
6284
    Debug2( "InstallHdr($platforms, @elements)" );
6285
 
6286
    return if ( ! ActivePlatform($platforms) );
6287
    Warning ("InstallHdr: Needs local directory specified in build.pl") unless ( $::ScmLocal );
6288
 
6289
#.. Arguments
6290
#
6291
    $base = $PackageInfo{'Hdr'}{'IBase'};       # Base of target
6292
    $dir = $base . $PackageInfo{'Hdr'}{'Dir'};  # Installation path (default)
335 dpurdie 6293
    $full = $strip = 0;
227 dpurdie 6294
 
285 dpurdie 6295
    foreach ( @elements )
227 dpurdie 6296
    {
6297
                                                # Standard targets
6298
        my $rv = __TargetDir(0, $base, $_, \$dir);
6299
        next if ( $rv == 1 );
6300
        return if ( $rv == 2 );
6301
 
6302
        if (/^--Full/) {                        # using full (resolved) path
6303
            $full = 1;
6304
 
6305
        } elsif (/^--Strip$/) {                 # Strip path from source files
6276 dpurdie 6306
            $strip = -1;
227 dpurdie 6307
 
6276 dpurdie 6308
        } elsif (/^--Strip=(\d+)$/) {           # Strip some f the path from source files
6309
            $strip = $1;
227 dpurdie 6310
                                                # Package
6311
        } elsif (/^--Package$/ || /^--Package=(.*)/) {
6312
            $package = 1;
6313
 
6314
        } elsif (/^--(.*)/) {
6315
            Message( "InstallHdr: unknown option $_ -- ignored\n" );
6316
        }
6317
    }
6318
 
6319
#.. Files
6320
#
285 dpurdie 6321
    foreach ( @elements )
227 dpurdie 6322
    {
6323
        my %package_entry;
6324
        if ( ! /^--(.*)/ )
6325
        {
6326
            $name = $_;
6327
            $basename = StripDir( $name );
335 dpurdie 6328
            if ( !($srcfile = $SRCS{ $basename }) ) {
6329
                $srcfile = $name;
6330
            }
6331
 
227 dpurdie 6332
            if ( $full )
6333
            {
335 dpurdie 6334
                my $subdir = StripFileExt($srcfile);
6335
                $subdir = $1
6336
                    if ( $subdir =~ m~^$ProjectBase/(.*)~ );
6337
                $dir .= '/' . $subdir;
6338
                $dir =~ s~//~/~g;
6339
                $dir =~ s~/./~/~g;
6340
                $dir =~ s~/$~~g;
6341
                $name = $basename;
227 dpurdie 6342
            }
6343
 
6276 dpurdie 6344
            $name = StripPath($name, $strip) if ($strip);
227 dpurdie 6345
 
6346
            Debug( "InstallHdr( $dir/$name, src: $srcfile, dest: $dir)" );
6347
 
6348
            $package_entry{'src'} = $srcfile;
6349
            $package_entry{'dir'} = StripFileExt( "$dir/$name" );
6350
            $INSTALL_HDRS{ "$dir/$name" } = {%package_entry};
6351
        }
6352
    }
6353
 
6354
#.. Package
6355
#
6356
    PackageHdr( @_ )                            # auto package
6357
        if ( $package );
6358
}
6359
 
6360
 
6361
sub InstallLib
6362
{
6363
    my( $platforms, @elements ) = @_;
6364
    my( $base, $dir, $package );
6365
    my( $lib, $strip );
289 dpurdie 6366
    my $org_lib;
227 dpurdie 6367
 
6368
    Debug2( "InstallLib($platforms, @elements)" );
6369
 
6370
    return if ( ! ActivePlatform($platforms) );
6371
    Warning ("InstallLib: Needs local directory specified in build.pl") unless ( $::ScmLocal );
6372
 
6373
#.. Arguments
6374
#
6375
    $base = $PackageInfo{'Lib'}{'IBase'};       # Base of target
6376
    $dir = $base . $PackageInfo{'Lib'}{'Dir'};  # Installation path (default)
6377
 
285 dpurdie 6378
    foreach ( @elements )
227 dpurdie 6379
    {
6380
                                                # Standard targets
6381
        my $rv = __TargetDir(0, $base, $_, \$dir);
6382
        next if ( $rv == 1 );
6383
        return if ( $rv == 2 );
6384
 
6385
        if (/^--Package$/ || /^--Package=(.*)/) {
6386
            $package = 1;
6387
 
6388
        } elsif (/^--Strip$/) {                 # Strip path from source files
6276 dpurdie 6389
            $strip = -1;
227 dpurdie 6390
 
6276 dpurdie 6391
        } elsif (/^--Strip=(\d+)$/) {           # Strip some f the path from source files
6392
            $strip = $1;
6393
 
227 dpurdie 6394
        } elsif (/^--(.*)/) {
6395
            Message( "InstallLib: unknown option $_ -- ignored\n" );
6396
        }
6397
    }
6398
 
6399
#.. Files
6400
#
285 dpurdie 6401
    foreach ( @elements )
227 dpurdie 6402
    {
6403
        my %package_entry;
6404
        if ( ! /^--(.*)/ )
6405
        {
6276 dpurdie 6406
            $_ = StripPath($_, $strip) if ($strip);
289 dpurdie 6407
            $org_lib = $_;                      # Original name
227 dpurdie 6408
 
6409
            if ( $ScmTargetHost eq "Unix" ) {
6410
                $lib = "lib$_";                 # Prefix "lib" ....
6411
                $lib =~ s/^liblib/lib/;         # @LIBS already has lib added
6412
            } else {
6413
                $lib = $_;
6414
            }
6415
 
289 dpurdie 6416
            if (  my $libp = $SHLIBS->Get($lib) )
227 dpurdie 6417
            {
6418
                Debug( "InstallLib( $dir/$lib\$(GBE_TYPE).$::so, " .
6419
                    "src: \$(LIBDIR)/$lib\$(GBE_TYPE).$::so, dest: $dir)" );
6420
 
6421
                #
6422
                #   Create a "placekeeper" entry within $INSTALL_SHLIBS
6423
                #   The exact format of the name of the shared library is
6424
                #   toolset specific. Create an entry to allow the toolset
6425
                #   to extend the packaging information when the shared library
6426
                #   recipe is constructed.
6427
                #
289 dpurdie 6428
                my $ver = $libp->{ VERSION };
227 dpurdie 6429
                my $name = "$dir/$lib.$ver.PlaceKeeper";
6430
 
6431
                $package_entry{'placekeeper'} = 1;
6432
                $package_entry{'version'} = $ver;
6433
                $package_entry{'lib'} = $lib;
6434
                $package_entry{'dir'} = $dir;
289 dpurdie 6435
 
6436
                push @{$SHLIB_INS{$lib}}, $name;
227 dpurdie 6437
                $INSTALL_SHLIBS{$name} = {%package_entry};
6438
            }
6439
 
289 dpurdie 6440
            #
6441
            #   Clean up the package_entry
6442
            #   Insert common items
6443
            #
6444
            %package_entry = ();
6445
            $package_entry{'lib'} = $lib;
6446
            $package_entry{'dir'} = $dir;
6447
 
321 dpurdie 6448
            if ( my $libfile = $SRCS{$org_lib} )
227 dpurdie 6449
            {
6450
                #
6451
                #   Allow the user to package a sourced file as a library
289 dpurdie 6452
                #   But must be the un-massaged name of the file.
227 dpurdie 6453
                #
289 dpurdie 6454
                $package_entry{'dst'} = "$dir/$org_lib";
6455
                $package_entry{'src'} = $libfile;
6456
            }
6457
            elsif ( $LIBS->Get($lib) )
6458
            {
6459
                #
6460
                #   Install a library known to the makefile
6461
                #
6462
                my $libp = $LIBS->Get($lib);
227 dpurdie 6463
 
289 dpurdie 6464
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
6465
                $package_entry{'src'}    = $libp->getPath();
227 dpurdie 6466
            }
289 dpurdie 6467
            elsif ( ! $SHLIBS->Get($lib) )
227 dpurdie 6468
            {
289 dpurdie 6469
                #
6470
                #   Not a known shared lib
6471
                #   Not a known static lib
6472
                #   Not a 'sourced' file
6473
                #   Assume the a static library has magically appeared
6474
                #   in the standard LIB directory. May have been placed there
6475
                #   by a 'rule'
6476
                #
6477
                my $libp = $LIBS->New($lib);
227 dpurdie 6478
 
289 dpurdie 6479
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
6480
                $package_entry{'src'}    = $libp->getPath();
6481
            }
227 dpurdie 6482
 
289 dpurdie 6483
            #
6484
            #   Add entry to various lists if required
6485
            #
6486
            PackageLib_AddEntry ('InstallLib', \%LIB_INS, \%INSTALL_LIBS, \%package_entry )
6487
                if ( exists $package_entry{'dst'} );
227 dpurdie 6488
        }
6489
    }
6490
 
6491
#.. Package
6492
#
6493
    PackageLib( @_ )                            # auto package
6494
        if ( $package );
6495
}
6496
 
6497
 
6498
sub InstallJar
6499
{
6500
    my( $platforms, @elements ) = @_;
6501
    my( $base, $dir, $package );
6502
    my( $jar );
6503
 
6504
    Debug2( "InstallJar($platforms, @elements)" );
6505
 
6506
    return if ( ! ActivePlatform($platforms) );
6507
    Warning ("InstallJar: Needs local directory specified in build.pl") unless ( $::ScmLocal );
6508
 
6509
#.. Arguments
6510
#
6511
    $base = $PackageInfo{'Jar'}{'IBase'};       # Base of target
6512
    $dir = $base . $PackageInfo{'Jar'}{'Dir'};  # Installation path (default)
6513
 
285 dpurdie 6514
    foreach ( @elements )
227 dpurdie 6515
    {
6516
                                                # Standard targets
6517
        my $rv = __TargetDir(0, $base, $_, \$dir);
6518
        next if ( $rv == 1 );
6519
        return if ( $rv == 2 );
6520
 
6521
        if (/^--Package$/ || /^--Package=(.*)/) {
6522
            $package = 1;
6523
 
6524
        } elsif (/^--(.*)/) {
6525
            Message( "InstallJar: unknown option $_ -- ignored\n" );
6526
        }
6527
    }
6528
 
6529
 
6530
#.. Files
6531
#
285 dpurdie 6532
    foreach ( @elements )
227 dpurdie 6533
    {
6534
        my %package_entry;
6535
        if ( ! /^--(.*)/ )
6536
        {
6537
            $jar = $_;
6538
            my $src;
6539
            my $dest;
6540
 
6541
            if ( $JAR_FILES{$jar} )
6542
            {
6543
                $src = $JAR_FILES{$jar};
6544
                $dest = $jar;
6545
            }
6546
            else
6547
            {
6548
                $src = "\$(CLSDIR)/$jar\$(GBE_TYPE).jar";
6549
                $dest = "$jar\$(GBE_TYPE).jar";
6550
            }
6551
 
6552
 
6553
            Debug( "InstallJar( $dir/$dest, " .
6554
                "src: $src, dest: $dir)" );
6555
 
6556
            $package_entry{'src'} = $src;
6557
            $package_entry{'dir'} = $dir;
6558
            $INSTALL_CLSS{ "$dir/$dest" } = {%package_entry};
6559
 
6560
        }
6561
    }
6562
 
6563
#.. Package
6564
#
6565
    PackageJar( @_ )                            # auto package
6566
        if ( $package );
6567
}
6568
 
6569
 
6570
sub InstallProg
6571
{
6572
    my( $platforms, @elements ) = @_;
6573
    my( $base, $dir, $package );
6574
    my( $prog );
6575
 
6576
    Debug2( "InstallProg($platforms, @elements)" );
6577
 
6578
    return if ( ! ActivePlatform($platforms) );
6579
    Warning ("InstallProg: Needs local directory specified in build.pl") unless ( $::ScmLocal );
6580
 
6581
#.. Arguments
6582
#
6583
    $base = $PackageInfo{'Prog'}{'IBase'};       # Base of target
6584
    $dir = $base . $PackageInfo{'Prog'}{'Dir'};  # Installation path (default)
6585
 
285 dpurdie 6586
    foreach ( @elements )
227 dpurdie 6587
    {
6588
                                                # Standard targets
6589
        my $rv = __TargetDir($T_TYPE, $base, $_, \$dir);
6590
        next if ( $rv == 1 );
6591
        return if ( $rv == 2 );
6592
 
6593
        if (/^--Package$/ || /^--Package=(.*)/) {
6594
            $package = 1;
6595
 
6596
        } elsif (/^--(.*)/) {
6597
            Message( "InstallProg: unknown option $_ -- ignored\n" );
6598
        }
6599
    }
6600
 
6601
#.. Files
6602
#
285 dpurdie 6603
    foreach ( @elements )
227 dpurdie 6604
    {
6605
        my %package_entry;
6606
        if ( ! /^--(.*)/ )
6607
        {
6608
            my $ext = "";
6609
            $prog = $_;
6610
 
6611
            #
6612
            #   If the named target is a program then append the correct
6613
            #   extension. Otherwise assume that the target is either a script
6614
            #   or a some other file - and don't append an extension
6615
            #
6616
            $ext = $::exe
289 dpurdie 6617
                if ( $PROGS->Get($prog) );
227 dpurdie 6618
 
6619
            #
6620
            #   A "file" that is specified with a "Src" directive may be
6621
            #   installed as though it were a program
6622
            #
6623
            my $progfile;
6624
            $progfile = "\$(BINDIR)/$prog$ext"
6625
                unless ( $progfile = $SRCS{$prog} );
6626
 
6627
            Debug( "InstallProg( $dir/$prog$ext, " .
6628
                 "src: $progfile, dest: $dir)" );
6629
 
6630
            push @{$PROG_INS{$prog}}, "$dir/$prog$ext";
6631
 
6632
            $package_entry{'src'} = $progfile;
6633
            $package_entry{'dir'} = $dir;
6634
            $INSTALL_PROGS{ "$dir/$prog$ext" } = {%package_entry};
6635
        }
6636
    }
6637
 
6638
#.. Package
6639
#
6640
    PackageProg( @_ )                           # auto package
6641
        if ( $package );
6642
}
6643
 
6276 dpurdie 6644
#-------------------------------------------------------------------------------
6645
# Function        : StripPath 
6646
#
6647
# Description     : Internal function to strip bits from a pathname
6648
#                   Will never strip the filename, even if asked to strip too much
6649
#
6650
# Inputs          : $name       - Name to process
6651
#                   $stripCount - Strip part
6652
#                                 <0 - strip all paths
6653
#                                 =0  - Do nothing
6654
#                                 >0 - Strip count
6655
#
6656
# Returns         : Processed name
6657
#
6658
sub StripPath
6659
{
6660
    my( $name, $stripCount) = @_;
227 dpurdie 6661
 
6276 dpurdie 6662
    if ($stripCount)
6663
    {
6664
        $name =~ s~\\~/~g;
6619 dpurdie 6665
        $name =~ s~//~/~g;
6276 dpurdie 6666
 
6667
        my @items = split('/', $name);
6668
        if ($stripCount > 0)
6669
        {
6670
            my $len = scalar @items;
6671
            my $remove = $stripCount; 
6672
            if ($stripCount >= $len ) {
6673
                $remove = $len - 1;
6674
            }
6675
            splice @items, 0, $remove;
6676
            $name = join('/', @items);
6677
        }
6678
        else
6679
        {
6680
            $name = pop @items;
6681
        }
6682
    }
6683
    return $name;
6684
}
6685
 
6686
 
227 dpurdie 6687
###############################################################################
6688
#
6689
#   Packaging
6690
#
6691
sub PackageDist
6692
{
6693
    my( $name, @elements ) = @_;
6694
 
6695
    Debug2( "PackageDist($name, @elements)" );
6696
 
6697
    foreach ( @elements )
6698
    {
6699
    #.. Distribution sets
6700
    #
6701
        HashJoin( \%PACKAGE_DIST, $;, $name, "$_" );
6702
 
6703
    #.. Summary of distribution sets
6704
    #
267 dpurdie 6705
        $PACKAGE_SETS{ $_ }{'TAG'} = 1
6706
            if ( ! exists $PACKAGE_SETS{ $_ }{'TAG'} );
227 dpurdie 6707
    }
6708
}
6709
 
311 dpurdie 6710
#-------------------------------------------------------------------------------
6387 dpurdie 6711
# Function        : PackageDir 
6712
#                   InstallDir
6713
#
6714
# Description     : Directive to package an entire directory tree
6715
#                   Will package the contents of the directory without regard as to there content
6716
#                   
6717
#                   Differs from PackageFile (... --DirTree ) in that the process is dynamic
6718
#                   It will support the packaging of files that are generated
6719
#                   
6720
#                   NOT intended to support the JATS BIN and LIB structure
6721
#                   It knows nothing of these types of files
6722
#
6723
# Inputs          : platforms   - Active platform list
6724
#                   Options:    - Many from PackageFile
6725
#                       --DirTree=xxx   Source Tree [Mandatory]
6726
#                       --Subdir=yyy    Target [ Mandatory]
6727
#
6728
sub PackageDir { 
6729
    return if ( !$ScmPackage );                 # Packaging enabled ?
6730
    _PackageInstallDir('PackageDir', 'PBase', \@PACKAGE_DIRS, @_);
6731
    }
6732
 
6733
sub InstallDir { 
6734
    Warning ("InstallDir: Needs local directory specified in build.pl") unless ( $::ScmLocal );
6735
    _PackageInstallDir('InstallDir', 'IBase', \@INSTALL_DIRS, @_);
6736
    }
6737
 
6738
sub _PackageInstallDir
6739
{
6740
    my( $cmdName, $tbase, $dirRef, $platforms, @elements ) = @_;
6741
    my( $base, $dir, $path, $type );
6742
    my %data;
6743
 
6744
    Debug2( "$cmdName($platforms, @elements)" );
6745
 
6746
    return if ( ! ActivePlatform($platforms) );
6747
 
6748
#.. Arguments
6749
#
6750
    $base = $PackageInfo{'File'}{$tbase};           # Base of target
6751
    $dir = $base . $PackageInfo{'File'}{'Dir'};     # Installation path (default)
6752
 
6753
    foreach ( @elements )
6754
    {
6755
        my $rv = __TargetDir($T_MACH|$T_GBE|$T_FILE, $base, $_, \$dir, \$type);
6756
        next if ( $rv == 1 );
6757
        return if ( $rv == 2 );
6758
 
6759
        if (/^--Executable$/) {                  # Mark the file as executable
6760
            $data{exefile} = "X";
6761
 
6762
        } elsif (/^--PreserveSymlink/i) {        # Preserve symlink to local file
6763
            delete $data{noPreserveSymlink};
6764
 
6765
        } elsif (/^--NoPreserveSymlink/i) {      # Preserve symlink to local file
6766
            $data{noPreserveSymlink} = 1;
6767
 
6768
        } elsif ( /^--DirTree=(.*)/ ) {
6769
            Error("DirTree. Multiple directories not allowed.") if ( $data{dirTree} );
6770
            $data{dirTree} =  $1;
6771
 
6772
        } elsif ( /^--FilterOut=(.*)/ ) {
6773
            push @{$data{exclude}}, $1;
6774
 
6775
        } elsif ( /^--FilterIn=(.*)/ ) {
6776
            push @{$data{include}}, $1;
6777
 
6778
        } elsif ( /^--FilterOutRe=(.*)/ ) {
6779
            push @{$data{excludeRe}}, $1;
6780
 
6781
        } elsif ( /^--FilterInRe=(.*)/ ) {
6782
            push @{$data{includeRe}}, $1;
6783
 
6784
        } elsif ( /^--StripDir/ ) {
6785
            $data{strip_base} = 1;
6786
 
6787
        } elsif ( m/^--Recurse/ ) {
6788
            delete $data{noRecurse};
6789
 
6790
        } elsif ( m/^--NoRecurse/ ) {
6791
            $data{noRecurse} = 1;
6792
 
6793
        } elsif (/^--(.*)/) {
6794
            Message( "$cmdName: unknown option $_ -- ignored\n" );
6795
        }
6796
    }
6797
    Error("DirTree. No path specified") unless ( defined($data{dirTree}) && $data{dirTree} ne "" );
6798
    Debug2( "$cmdName. Raw DirTree: $data{dirTree}" );
6799
 
6800
    # Prevent the user from escaping from the current directory
6801
    Error("$cmdName. Absolute paths are not allowed",
6802
          "Directory: $data{dirTree}") if ( $data{dirTree} =~ m~^/~ || $data{dirTree} =~ m~^.\:~ );
6803
 
6804
    #
6805
    #   Convert the relative path to one that is truely relative to the current
6806
    #   directory. This may occur when the user uses $ProjectBase
6807
    #
6808
    my $abs_dir_tree = AbsPath($data{dirTree});
6809
    $data{dirTree} = RelPath($abs_dir_tree);
6810
 
6811
    #
6812
    #   Ensure that the user is not trying to escape the package
6813
    #   Don't allow the user to attempt to package the entire package either
6814
    #
6815
    #   Calculate the relative path from $ProjectBase to the target directory
6816
    #   It must not be above the $ProjectBase 
6817
    #
6818
    if ( $data{dirTree} =~ m~^\.\.~)
6819
    {
6820
        my $dirFromBase = RelPath($abs_dir_tree, AbsPath($ProjectBase));
6821
        Error("$cmdName. DirTree cannot extend outside current package.",
6822
              "Directory: $dirFromBase") if ( $dirFromBase =~ m~\.\.~ );
6823
        Error("$cmdName. DirTree cannot package entire package.",
6824
            "Directory: $dirFromBase") if ( $dirFromBase eq '.' );
6825
    }
6826
 
6827
    Debug( "$cmdName( $data{dirTree}");
6828
    $data{dir} = $dir;
6829
    $data{type} = $type if defined $type;
6830
    #DebugDumpData("$cmdName", \%data);
6831
    push @{$dirRef}, \%data;
6832
}
6833
 
6834
#-------------------------------------------------------------------------------
311 dpurdie 6835
# Function        : PackageFile
6836
#
6837
# Description     : Directive to package files
6838
#                   Not to be used to package libraries, executables, headers
6839
#                   as this should be done by specialised directives
6840
#
6841
#                   Use to package other files
6842
#                   Can package an entire tree (ugly)
6843
#
6844
# Inputs          : 
6845
#
6846
#
227 dpurdie 6847
sub PackageFile
6848
{
6849
    my( $platforms, @elements ) = @_;
335 dpurdie 6850
    my( $base, $dir, $full, $path, $dist, $strip, $exefile, $type );
227 dpurdie 6851
    my( $name, $basename, $len, $srcfile );
4257 dpurdie 6852
    my( $dir_tree, @dir_tree_exclude, @dir_tree_include, $strip_base, $strip_dots );
335 dpurdie 6853
    my $recurse = 1;
6133 dpurdie 6854
    my $preserveSymlink = 0;
227 dpurdie 6855
 
6856
    Debug2( "PackageFile($platforms, @elements)" );
6857
 
6858
    return if ( !$ScmPackage );                 # Packaging enabled ?
6859
    return if ( ! ActivePlatform($platforms) );
6860
 
6861
#.. Arguments
6862
#
6863
    $dist = "ALL";                                  # Default set (ALL)
6864
    $base = $PackageInfo{'File'}{'PBase'};          # Base of target
6865
    $dir = $base . $PackageInfo{'File'}{'Dir'};     # Installation path (default)
335 dpurdie 6866
    $full = 0;
227 dpurdie 6867
    $strip = 0;
341 dpurdie 6868
    $strip_base = 0;
4257 dpurdie 6869
    $strip_dots = 0;
227 dpurdie 6870
    $exefile = 0;
6871
 
285 dpurdie 6872
    foreach ( @elements )
227 dpurdie 6873
    {
6874
        my $rv = __TargetDir($T_PKG|$T_MACH|$T_GBE|$T_FILE, $base, $_, \$dir, \$type);
6875
        next if ( $rv == 1 );
6876
        return if ( $rv == 2 );
6877
 
6878
        if (/^--Full/) {                        # Using full (resolved) path
6879
            $full = 1;
6880
 
6881
        } elsif (/^--Set=(.*)/) {               # Distribution set
6882
            $dist = "$1";
6883
 
6884
        } elsif (/^--Package$/) {               # Package .. call by InstallFile
6885
        } elsif (/^--Package=(.*)/) {
6886
            $dist = "$1";
6887
 
6888
        } elsif (/^--Strip$/) {                 # Strip path from source files
6276 dpurdie 6889
            $strip = -1;
227 dpurdie 6890
 
6294 dpurdie 6891
        } elsif (/^--Strip=(\d+)$/) {           # Strip path from source files
6276 dpurdie 6892
            $strip = $1;
6893
 
227 dpurdie 6894
        } elsif (/^--Executable$/) {            # Mark the file as executable
6895
            $exefile = "X";
6896
 
6133 dpurdie 6897
        } elsif (/^--PreserveSymlink/i) {       # Preserve symlink to local file
6898
            $preserveSymlink = 1;
6899
 
227 dpurdie 6900
        } elsif ( /^--DirTree=(.*)/ ) {
6901
            Error("DirTree. Multiple directories not allowed.") if ( $dir_tree );
4163 dpurdie 6902
            $dir_tree =  $1;
4257 dpurdie 6903
            Error("DirTree. No path specified") unless ( defined($dir_tree) && $dir_tree ne "" );
227 dpurdie 6904
 
4163 dpurdie 6905
            # Prevent the user from escaping from the current directory
6906
            Error("DirTree. Absolute paths are not allowed",
6907
                  "Directory: $dir_tree") if ( $dir_tree =~ m~^/~ || $dir_tree =~ m~^.\:~ );
6908
 
6909
            #
6910
            #   Convert the relative path to one that is truely relative to the current
6911
            #   directory. This may occur when the user uses $ProjectBase
6912
            #
4257 dpurdie 6913
            my $abs_dir_tree = AbsPath($dir_tree);
6914
            $dir_tree = RelPath($abs_dir_tree);
6915
 
6916
            #
6917
            #   Ensure that the user is not trying to escape the package
4265 dpurdie 6918
            #   Don't allow the user to attempt to package the entire package either
4257 dpurdie 6919
            #
6920
            #   Calculate the relative path from $ProjectBase to the target directory
6921
            #   It must not be above the $ProjectBase 
6922
            #
4265 dpurdie 6923
            if ( $dir_tree =~ m~^\.\.~)
6924
            {
6925
                my $dirFromBase = RelPath($abs_dir_tree, AbsPath($ProjectBase));
6926
                Error("DirTree cannot extend outside current package.",
6927
                      "Directory: $dirFromBase") if ( $dirFromBase =~ m~\.\.~ );
6928
                Error("DirTree cannot package entire package.",
6929
                    "Directory: $dirFromBase") if ( $dirFromBase eq '.' );
6930
            }
4257 dpurdie 6931
 
4163 dpurdie 6932
            Debug2( "PackageFile. DirTree: $dir_tree" );
6933
 
227 dpurdie 6934
            Error("DirTree. Directory not found",
6935
                  "Directory: $dir_tree") unless  ( -d $dir_tree );
6936
 
4257 dpurdie 6937
            # If packaging a parent directory then force dot_stripping of the base directory
6938
            # strip_base will have precedence if both are active
6939
            if ( $dir_tree =~ m~\.\.~ )
6940
            {
6941
                $dir_tree =~ m~(\.\./)+~;
6942
                $strip_dots = length($1);
6943
            }
6944
 
227 dpurdie 6945
        } elsif ( /^--FilterOut=(.*)/ ) {
6946
            push @dir_tree_exclude, $1;
6947
 
6948
        } elsif ( /^--FilterIn=(.*)/ ) {
6949
            push @dir_tree_include, $1;
6950
 
6951
        } elsif ( /^--StripDir/ ) {
341 dpurdie 6952
            $strip_base = 1;
227 dpurdie 6953
 
335 dpurdie 6954
        } elsif ( m/^--Recurse/ ) {
6955
            $recurse = 1;
6956
 
6957
        } elsif ( m/^--NoRecurse/ ) {
6958
            $recurse = 0;
6959
 
227 dpurdie 6960
        } elsif (/^--(.*)/) {
6961
            Message( "PackageFile: unknown option $_ -- ignored\n" );
6962
        }
6963
    }
6964
 
6965
 
6966
    #.. DirTree expansion
6967
    #   Note: Uses REs, not simple globs
6968
    #         Use JatsLocateFiles to do the hard work
6969
    if ( $dir_tree )
6970
    {
335 dpurdie 6971
        my $search = JatsLocateFiles->new('FullPath' );
6972
        $search->recurse($recurse);
227 dpurdie 6973
        $search->filter_in_re ( $_ ) foreach ( @dir_tree_include );
6974
        $search->filter_out_re( $_ ) foreach ( @dir_tree_exclude );
1431 dpurdie 6975
        $search->filter_out_re( '/\.svn/' );
5848 dpurdie 6976
        $search->filter_out_re( '/\.git/' );
227 dpurdie 6977
        @elements = $search->search ( $dir_tree );
4257 dpurdie 6978
        if ($strip_base){
6979
            $strip_base = length( $dir_tree ) if ( $strip_base );
6980
        } elsif ($strip_dots) {
6981
            $strip_base = $strip_dots;
6982
        }
6403 dpurdie 6983
    } else {
6984
        $strip_base = 0;
227 dpurdie 6985
    }
6986
 
6987
#.. Files
6988
#
285 dpurdie 6989
    foreach ( @elements )
227 dpurdie 6990
    {
6991
        my %package_entry;
299 dpurdie 6992
        $name = $_;
6133 dpurdie 6993
        my $symlink;
299 dpurdie 6994
 
227 dpurdie 6995
        #
299 dpurdie 6996
        #   Trap special files
7352 dpurdie 6997
        #       DPACKAGE - but only if we have a DPackageLibrary directive in the same makefile.
6998
        #                  Ignored for backward compatability
299 dpurdie 6999
        #
7000
        if ( m~^DPACKAGE$~ && $DPackageDirective ) {
7352 dpurdie 7001
            next;
299 dpurdie 7002
        }
7003
 
227 dpurdie 7004
        if ( ! /^--(.*)/ )
7005
        {
7006
            $basename = StripDir( $name );
335 dpurdie 7007
            if ( !($srcfile = $SRCS{ $basename }) ) {
7008
                $srcfile = $name;
7009
            }
7010
 
227 dpurdie 7011
            if ( $full )
7012
            {
335 dpurdie 7013
                my $subdir = StripFileExt($srcfile);
7014
                $subdir = $1
7015
                    if ( $subdir =~ m~^$ProjectBase/(.*)~ );
7016
                $dir .= '/' . $subdir;
7017
                $dir =~ s~//~/~g;
7018
                $dir =~ s~/./~/~g;
7019
                $dir =~ s~/$~~g;
7020
                $name = $basename;
227 dpurdie 7021
            }
6276 dpurdie 7022
            $name = StripPath($name, $strip) if ($strip);
227 dpurdie 7023
 
341 dpurdie 7024
            if ( $strip_base )
7025
            {
7026
                $name = substr $name, $strip_base;
7027
                $name =~ s~^/~~;
7028
            }
7029
 
227 dpurdie 7030
            $dir =~ s~//~/~g;
7031
            $dir =~ s~/$~~;
7032
 
7033
            #
6133 dpurdie 7034
            #   Preserve Symlink
7035
            #
7036
            if ($preserveSymlink && -l $srcfile)
7037
            {
7038
                $symlink = 1;
7039
            }
7040
 
7041
            #
227 dpurdie 7042
            #   Sanity test the source filename
7043
            #   User may have misused an option
7044
            #
6387 dpurdie 7045
            if ( !$dir_tree && ( ( $srcfile =~ m/=/ ) || ( $srcfile =~ m/^-/ ) || ( $srcfile =~ m~/-~ ))  )
227 dpurdie 7046
            {
7047
               Warning ("PackageFile: Suspect source filename: $srcfile");
7048
            }
7049
 
7050
            Debug( "PackageFile( $dir/$name, " .
7051
                "src: $srcfile, dest: $dir, dist: $dist, exe: $exefile )" );
7052
 
7053
            $package_entry{'src'} = $srcfile;
7054
            $package_entry{'dir'} = StripFileExt( "$dir/$name" );
7055
            $package_entry{'set'} = $dist;
7056
            $package_entry{'exe'} = $exefile if $exefile;
7057
            $package_entry{'type'} = $type if ( $type );
6133 dpurdie 7058
            $package_entry{'symlink'} = 1 if ( $symlink );
227 dpurdie 7059
 
7060
            $PACKAGE_FILES{ "$dir/$name" } = {%package_entry};
7061
        }
7062
    }
7063
}
7064
 
7065
sub PackageHdr
7066
{
7067
    my( $platforms, @elements ) = @_;
335 dpurdie 7068
    my( $base, $dir, $full, $path, $dist, $strip );
227 dpurdie 7069
    my( $name, $basename, $len, $srcfile );
7070
 
7071
    Debug2( "PackageHdr($platforms, @elements)" );
7072
 
7073
    return if ( !$ScmPackage );                 # Packaging enabled ?
7074
    return if ( ! ActivePlatform($platforms) );
7075
 
7076
#.. Arguments
7077
#
7078
    $dist = "ALL";                                  # Default set (ALL)
7079
    $base = $PackageInfo{'Hdr'}{'PBase'};           # Base of target
7080
    $dir = $base . $PackageInfo{'Hdr'}{'Dir'};      # Installation path (default)
335 dpurdie 7081
    $full = 0;
227 dpurdie 7082
    $strip = 0;
7083
 
285 dpurdie 7084
    foreach ( @elements )
227 dpurdie 7085
    {
7086
        my $rv = __TargetDir($T_PKG, $base, $_, \$dir);
7087
        next if ( $rv == 1 );
7088
        return if ( $rv == 2 );
7089
 
7090
        if (/^--Full/) {                        # Using full (resolved) path
7091
            $full = 1;
7092
 
7093
        } elsif (/^--Set=(.*)/) {               # Distribution set
7094
            $dist = "$1";
7095
 
7096
        } elsif (/^--Package$/) {               # Package .. call by InstallHdr
7097
        } elsif (/^--Package=(.*)/) {
7098
            $dist = "$1";
7099
 
7100
        } elsif (/^--Strip$/) {                 # Strip path from source files
6276 dpurdie 7101
            $strip = -1;
227 dpurdie 7102
 
6276 dpurdie 7103
        } elsif (/^--Strip=(\d+)$/) {           # Strip some f the path from source files
7104
            $strip = $1;
7105
 
227 dpurdie 7106
        } elsif (/^--(.*)/) {
7107
            Message( "PackageHdr: unknown option $_ -- ignored\n" );
7108
        }
7109
    }
7110
 
7111
#.. Files
7112
#
285 dpurdie 7113
    foreach ( @elements )
227 dpurdie 7114
    {
7115
        my %package_entry;
7116
        if ( ! /^--(.*)/ )
7117
        {
5991 dpurdie 7118
            $name = $_;
227 dpurdie 7119
            $basename = StripDir( $name );
335 dpurdie 7120
            if ( !($srcfile = $SRCS{ $basename }) ) {
7121
                $srcfile = $name;
7122
            }
7123
 
227 dpurdie 7124
            if ( $full )
7125
            {
335 dpurdie 7126
                my $subdir = StripFileExt($srcfile);
7127
                $subdir = $1
7128
                    if ( $subdir =~ m~^$ProjectBase/(.*)~ );
7129
                $dir .= '/' . $subdir;
7130
                $dir =~ s~//~/~g;
7131
                $dir =~ s~/./~/~g;
7132
                $dir =~ s~/$~~g;
7133
                $name = $basename;
227 dpurdie 7134
            }
7135
 
6276 dpurdie 7136
            $name = StripPath($name, $strip) if ($strip);
227 dpurdie 7137
 
7138
            Debug( "PackageHdr( $dir/$name, " .
7139
                "src: $srcfile, dest: $dir, dist: $dist )" );
7140
 
7141
            $package_entry{'src'} = $srcfile;
7142
            $package_entry{'dir'} = StripFileExt( "$dir/$name" );
7143
            $package_entry{'set'} = $dist;
7144
 
7145
            $PACKAGE_HDRS{ "$dir/$name" } = {%package_entry};
7146
        }
7147
    }
7148
}
7149
 
7150
 
7151
sub PackageLib
7152
{
7153
    my( $platforms, @elements ) = @_;
7154
    my( $base, $dir, $dist, $type );
7155
    my( $lib, $org_lib, %extras, $strip );
7156
 
7157
    Debug2( "PackageLib($platforms, @elements)" );
7158
 
7159
    return if ( !$ScmPackage );                 # Packaging enabled ?
7160
    return if ( ! ActivePlatform($platforms) );
7161
 
7162
#.. Arguments
7163
#
7164
    $dist = "ALL";                              # Default set (ALL)
7165
    $base = $PackageInfo{'Lib'}{'PBase'};       # Base of target
7166
    $dir = $base . $PackageInfo{'Lib'}{'Dir'};  # Installation path (default)
7167
    $type = "";
7168
 
285 dpurdie 7169
    foreach ( @elements )
227 dpurdie 7170
    {
7171
                                                # Standard targets
7172
        my $rv = __TargetDir($T_PKG, $base, $_, \$dir, \$type);
7173
        next if ( $rv == 1 );
7174
        return if ( $rv == 2 );
7175
 
7176
        if (/^--Set=(.*)/) {                    # Distribution set(s)
7177
            $dist = "$1";
7178
 
7179
        } elsif (/^--Package$/) {               # Package .. call by PackageLib
7180
        } elsif (/^--Package=(.*)/) {
7181
            $dist = "$1";
7182
 
7183
        } elsif (/^--Extras=(.*)/) {            # Extras=[none, .. ,all]
7184
            foreach my $elem ( split( ',', $1 ) )
7185
            {
7186
                Error ("PackageLib: Unknown Extras mode: $elem")
7187
                    unless ( grep m/$elem/, qw(none stub map lint debug all) );
7188
                $extras{$elem} = 1;
7189
            }
7190
            %extras = () if ( $extras{'all'} );
7191
 
7192
        } elsif (/^--Strip$/) {                 # Strip path from source files
6276 dpurdie 7193
            $strip = -1;
227 dpurdie 7194
 
6276 dpurdie 7195
        } elsif (/^--Strip=(\d+)$/) {           # Strip some f the path from source files
7196
            $strip = $1;
7197
 
227 dpurdie 7198
        } elsif (/^--(.*)/) {
7199
            Message( "PackageLib: unknown option $_ -- ignored\n" );
7200
        }
7201
    }
7202
 
7203
#.. Files
7204
#
285 dpurdie 7205
    foreach ( @elements )
227 dpurdie 7206
    {
7207
        my %package_entry;
7208
        if ( ! /^--(.*)/ )
7209
        {
6276 dpurdie 7210
            $_ = StripPath($_, $strip) if ($strip);
227 dpurdie 7211
 
7212
            $org_lib = $_;                      # Original name
7213
            if ( $ScmTargetHost eq "Unix" ) {
7214
                $lib = "lib$_";                 # Prefix "lib" ....
7215
                $lib =~ s/^liblib/lib/;         # @LIBS already has lib added
7216
            } else {
7217
                $lib = $_;
7218
            }
7219
 
289 dpurdie 7220
            if (  my $libp = $SHLIBS->Get($lib) )
227 dpurdie 7221
            {
7222
                Debug( "PackageLib( $dir/$lib\$(GBE_TYPE).$::so, " .
7223
                    "src: \$(LIBDIR)/$lib\$(GBE_TYPE).$::so, dest: $dir, dist: $dist, type: $type )" );
7224
 
7225
                #
7226
                #   Create a "placekeeper" entry within $PACKAGE_SHLIBS
7227
                #   The exact format of the name of the shared library is
7228
                #   toolset specific. Create an entry to allow the toolset
7229
                #   to extend the packaging information when the shared library
7230
                #   recipe is constructed.
7231
                #
7232
                #
289 dpurdie 7233
                my $ver = $libp->{ VERSION };
227 dpurdie 7234
                my $name = "$dir/$lib.$ver.PlaceKeeper";
7235
 
7236
                $package_entry{'placekeeper'} = 1;
7237
                $package_entry{'version'} = $ver;
7238
                $package_entry{'lib'} = $lib;
7239
                $package_entry{'dir'} = $dir;
7240
                $package_entry{'set'} = $dist;
7241
                $package_entry{'type'} = $type if ( $type );
7242
                $package_entry{'extras'} = {%extras} if ( scalar %extras );
289 dpurdie 7243
 
7244
                push @{$SHLIB_PKG{$lib}}, $name;
227 dpurdie 7245
                $PACKAGE_SHLIBS{$name} = {%package_entry};
7246
            }
7247
 
289 dpurdie 7248
            #
7249
            #   Clean up the package_entry
7250
            #   Insert common items
7251
            #
7252
            %package_entry = ();
7253
            $package_entry{'lib'} = $lib;
7254
            $package_entry{'dir'} = $dir;
7255
            $package_entry{'set'} = $dist;
7256
            $package_entry{'extras'} = {%extras} if ( scalar %extras );
7257
            $package_entry{'type'} = $type if ( $type );
7258
 
227 dpurdie 7259
            if ( my $libfile = $SRCS{$org_lib} )
7260
            {
7261
                #
7262
                #   Allow the user to package a sourced file as a library
7263
                #   But must be the un-massaged name of the file.
7264
                #
5991 dpurdie 7265
                $package_entry{'dst'} = "$dir/$org_lib";
7266
                $package_entry{'src'} = $libfile;
289 dpurdie 7267
            }
7268
            elsif ( $LIBS->Get($lib) )
7269
            {
7270
                #
7271
                #   Package up a library known to the makefile
7272
                #
7273
                my $libp = $LIBS->Get($lib);
227 dpurdie 7274
 
289 dpurdie 7275
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
7276
                $package_entry{'src'}    = $libp->getPath();
227 dpurdie 7277
            }
289 dpurdie 7278
            elsif ( ! $SHLIBS->Get($lib) )
227 dpurdie 7279
            {
289 dpurdie 7280
                #
7281
                #   Not a known shared lib
7282
                #   Not a known static lib
7283
                #   Not a 'sourced' file
7284
                #   Assume the a static library has magically appeared
7285
                #   in the standard LIB directory. May have been placed there
7286
                #   by a 'rule'
7287
                #
7288
                my $libp = $LIBS->New($lib);
227 dpurdie 7289
 
289 dpurdie 7290
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
7291
                $package_entry{'src'}    = $libp->getPath();
7292
            }
227 dpurdie 7293
 
289 dpurdie 7294
            #
7295
            #   Add entry to various lists if required
7296
            #
7297
            PackageLib_AddEntry ('PackageLib', \%LIB_PKG, \%PACKAGE_LIBS, \%package_entry )
7298
                if ( exists $package_entry{'dst'} );
227 dpurdie 7299
        }
7300
    }
7301
}
7302
 
289 dpurdie 7303
#-------------------------------------------------------------------------------
7304
# Function        : PackageLib_AddEntry
7305
#
7306
# Description     : Helper function to add a package entry
7307
#                   to the lists
7308
#
7309
# Inputs          : $directive          - Directive name
7310
#                   $pList              - Ref to array list to maintain
7311
#                   $pHash              - Ref to hash to maintain
7312
#                   $pData              - Packaging Data
7313
#                                         Must Take a copy.
7314
#
7315
# Returns         : 
7316
#
227 dpurdie 7317
 
289 dpurdie 7318
sub PackageLib_AddEntry
7319
{
7320
    my ($directive, $pList, $pHash, $pData) = @_;
7321
 
7322
    my $lib = delete $pData->{'lib'};
7323
    my $dst = delete $pData->{'dst'};
7324
 
7325
    Error ("INTERNAL PackageLib_AddEntry: lib or dst not defined")
7326
        unless ( $lib && $dst );
7327
 
7328
    Debug( "$directive( ",$dst,
7329
            ", src: " ,$pData->{'src'},
7330
            ", dest: ",$pData->{'dir'},
7331
            ", dist: ",$pData->{'set'},
7332
            ", type: ",$pData->{'type'} || '',
7333
            " )" );
7334
 
7335
    push @{$pList->{$lib }}, $dst;
7336
    $pHash->{$dst } = {%$pData};
7337
}
7338
 
7339
 
227 dpurdie 7340
sub PackageProg
7341
{
7342
    my( $platforms, @elements ) = @_;
7343
    my( $base, $dir, $dist, $type );
7344
    my( $prog, %extras, $strip );
7345
 
7346
    Debug2( "PackageProg($platforms, @elements)" );
7347
 
7348
    return if ( !$ScmPackage );                 # Packaging enabled ?
7349
    return if ( ! ActivePlatform($platforms) );
7350
 
7351
#.. Arguments
7352
#
7353
    $dist = "ALL";                              # Default set (ALL)
7354
    $base = $PackageInfo{'Prog'}{'PBase'};       # Base of target
7355
    $dir = $base . $PackageInfo{'Prog'}{'Dir'};  # Installation path (default)
7356
    $type = "";
7357
 
285 dpurdie 7358
    foreach ( @elements )
227 dpurdie 7359
    {
7360
                                                # Standard targets
7361
        my $rv = __TargetDir($T_PKG|$T_TYPE, $base, $_, \$dir, \$type);
7362
        next if ( $rv == 1 );
7363
        return if ( $rv == 2 );
7364
 
7365
        if (/^--Set=(.*)/) {                    # Distribution set(s)
7366
            $dist = "$1";
7367
 
7368
        } elsif (/^--Package$/) {               # Package .. call by PackageLib
7369
        } elsif (/^--Package=(.*)/) {
7370
            $dist = "$1";
7371
 
7372
        } elsif (/^--Tool(([=])(.*))?$/) {      # Allow Tool and Tool=xxx specfic target
7373
            my $path = ( defined( $3) ) ? "/$3" : "";
261 dpurdie 7374
            $dir = "\$(PKGDIR)$path/\$(GBE_HOSTMACH)";
227 dpurdie 7375
 
7376
        } elsif (/^--Extras=(.*)/) {            # Extras=[none, .. ,all]
7377
            foreach my $elem ( split( ',', $1 ) )
7378
            {
7379
                Error ("PackageLib: Unknown Extras mode: $elem")
7380
                    unless ( grep m/$elem/, qw(none stub map lint debug all) );
7381
                $extras{$elem} = 1;
7382
            }
7383
            %extras = () if ( $extras{'all'} );
7384
 
7385
        } elsif (/^--Strip$/) {                 # Strip path from source files
6276 dpurdie 7386
            $strip = -1;
227 dpurdie 7387
 
6276 dpurdie 7388
        } elsif (/^--Strip=(\d+)$/) {           # Strip some f the path from source files
7389
            $strip = $1;
7390
 
227 dpurdie 7391
        } elsif (/^--(.*)/) {
7392
            Message( "PackageProg: unknown option $_ -- ignored\n" );
7393
        }
7394
    }
7395
 
7396
#.. Files
7397
#
285 dpurdie 7398
    foreach ( @elements )
227 dpurdie 7399
    {
7400
        my %package_entry;
7401
        if ( m~descpkg~ ) {
7402
            PackageFile($platforms, @elements);
7403
 
7404
        } elsif ( ! /^--(.*)/ ) {
6276 dpurdie 7405
            $_ = StripPath($_, $strip) if ($strip);
227 dpurdie 7406
 
7407
            my $ext = "";
7408
            $prog = $_;
7409
 
7410
            #
7411
            #   If the named target is a program then append the correct
7412
            #   extension. Otherwise assume that the target is either a script
7413
            #   or a some other file - and don't append an extension
7414
            #
7415
            #   A program may not have any object files, only libraries
7416
            #
7417
            $ext = $::exe
289 dpurdie 7418
                if ( $PROGS->Get($prog) );
227 dpurdie 7419
 
7420
            #
7421
            #   A "file" that is specified with a "Src" directive may be
7422
            #   installed as though it were a program
7423
            #
7424
            my $progfile;
387 dpurdie 7425
            if ( $progfile = $SRCS{$prog} )
7426
            {
5991 dpurdie 7427
                $progfile = $progfile;
7428
                $prog = $prog;
387 dpurdie 7429
            }
7430
            else
7431
            {
7432
                $progfile = "\$(BINDIR)/$prog$ext";
7433
            }
227 dpurdie 7434
 
7435
            Debug( "PackageProg( $dir/$prog$ext, " .
7436
                 "src: $progfile, dest: $dir, dist: $dist, type: $type )" );
7437
 
7438
            my $target = "$dir/$prog$ext";
7439
            push @{$PROG_PKG{$prog}}, $target;
7440
 
7441
            $package_entry{'src'}   = $progfile;
7442
            $package_entry{'dir'}   = $dir;
7443
            $package_entry{'set'}   = $dist;
7444
            $package_entry{'extras'}= {%extras} if ( scalar %extras );
7445
            $package_entry{'type'}  = $type if ( $type );
7446
 
7447
            $PACKAGE_PROGS{$target} = {%package_entry};
7448
        }
7449
    }
7450
}
7451
 
7452
 
7453
sub PackageJar
7454
{
7455
    my( $platforms, @elements ) = @_;
7456
    my( $base, $dir, $dist, $type );
7457
    my( $jar );
7458
 
7459
    Debug2( "PackageJar($platforms, @elements)" );
7460
 
7461
    return if ( !$ScmPackage );                 # Packaging enabled ?
7462
    return if ( ! ActivePlatform($platforms) );
7463
 
7464
#.. Arguments
7465
#
7466
    $dist = "ALL";                              # Default set (ALL)
7467
    $base = $PackageInfo{'Jar'}{'PBase'};       # Base of target
7468
    $dir = $base . $PackageInfo{'Jar'}{'Dir'};  # Installation path (default)
7469
    $type = "";
7470
 
285 dpurdie 7471
    foreach ( @elements )
227 dpurdie 7472
    {
7473
                                                # Standard targets
7474
        my $rv = __TargetDir($T_PKG, $base, $_, \$dir, \$type);
7475
        next if ( $rv == 1 );
7476
        return if ( $rv == 2 );
7477
 
7478
        if (/^--Set=(.*)/) {                    # Distribution set(s)
7479
            $dist = "$1";
7480
 
7481
        } elsif (/^--Package$/) {               # Package .. call by InstallJar
7482
        } elsif (/^--Package=(.*)/) {
7483
            $dist = "$1";
7484
 
7485
        } elsif (/^--(.*)/) {
7486
            Message( "PackageJar: unknown option $_ -- ignored\n" );
7487
        }
7488
    }
7489
 
7490
#.. Files
7491
#
285 dpurdie 7492
    foreach ( @elements )
227 dpurdie 7493
    {
7494
        my %package_entry;
7495
        if ( ! /^--(.*)/ )
7496
        {
7497
            $jar = $_;
7498
            my $src;
7499
            my $dest;
7500
 
7501
            if ( $JAR_FILES{$jar} )
7502
            {
7503
                $src = $JAR_FILES{$jar};
7504
                $dest = $jar;
7505
            }
7506
            else
7507
            {
7508
                $src = "\$(CLSDIR)/$jar\$(GBE_TYPE).jar";
7509
                $dest = "$jar\$(GBE_TYPE).jar";
7510
            }
7511
 
7512
 
7513
            Debug( "PackageJar( $dir/$dest, " .
7514
                "src: $src, dest: $dir, dist: $dist, type: $type )" );
7515
 
7516
            $package_entry{'src'} = $src;;
7517
            $package_entry{'dir'} = $dir;
7518
            $package_entry{'set'} = $dist;
7519
            $package_entry{'type'} = $type if ( $type );
7520
 
7521
            $PACKAGE_CLSS{ "$dir/$dest" } = {%package_entry};
7522
 
7523
        }
7524
    }
7525
}
7526
 
7527
#-------------------------------------------------------------------------------
7528
# Function        : PackageProgAddFiles         - Add files to a PackageProg
7529
#                   PackageLibAddFiles          - Add files to a PackageLib
7530
#                   PackageShlibAddFiles        - Add files to a PackageLib (shared lib)
7531
#                   PackageShlibAddLibFiles     - Add files to a PackageLib (shared lib)
7532
#                                                 Add static library files
7533
#
7534
# Description     : Add files to a Program package or installation
7535
#                   For use by Tool sets to allow additional files to be
7536
#                   packaged with a program.
7537
#
7538
#                   The files are only added if the named program is being
7539
#                   packaged and/or installed.
7540
#
7541
#
7542
# Inputs          : prog        - program identifier
7543
#                   file        - A file to be add
7544
#                   args        - Additional packageing arguments
7545
#
7546
# Returns         : Nothing
7547
#
7548
 
7549
sub PackageProgAddFiles
7550
{
7551
    Debug("PackageProgAddFiles");
7552
 
7553
    PackageAddFiles ( \%PACKAGE_PROGS, \%PACKAGE_PROGS, \%PROG_PKG, @_);
7554
    PackageAddFiles ( \%INSTALL_PROGS, \%INSTALL_PROGS, \%PROG_INS, @_);
7555
}
7556
 
7557
sub PackageLibAddFiles
7558
{
7559
    Debug("PackageLibAddFiles");
7560
 
7561
    PackageAddFiles ( \%PACKAGE_LIBS, \%PACKAGE_LIBS, \%LIB_PKG, @_ );
7562
    PackageAddFiles ( \%INSTALL_LIBS, \%INSTALL_LIBS, \%LIB_INS, @_ );
7563
}
7564
 
7565
sub PackageShlibAddFiles
7566
{
7567
    my ($prog, $file, @args) = @_;
7568
    Debug("PackageShlibAddFiles");
7569
 
7570
    PackageAddFiles ( \%INSTALL_SHLIBS, \%INSTALL_SHLIBS, \%SHLIB_INS, @_ );
7571
    PackageAddFiles ( \%PACKAGE_SHLIBS, \%PACKAGE_SHLIBS, \%SHLIB_PKG, @_ );
7572
 
7573
    #
7574
    #   These files become the target of the "make_install_shlib" operation unless:
7575
    #       Conditionally packaged files are not always created
7576
    #       RemoveOnly files are not always generated
7577
    #
7578
    my $no_add;
7579
    foreach ( @args )
7580
    {
4382 dpurdie 7581
        if ( m/^defined=/ or m/^RemoveOnly=/ or /NoTarget=/ )
227 dpurdie 7582
        {
7583
            $no_add = 1;
7584
            last;
7585
        }
7586
    }
7587
 
7588
    push (@SHLIB_TARGETS, $file ) unless $no_add;
7589
}
7590
 
7591
sub PackageShlibAddLibFiles
7592
{
7593
    Debug("PackageShlibAddLibFiles");
7594
 
7595
    PackageAddFiles ( \%PACKAGE_SHLIBS, \%PACKAGE_LIBS, \%SHLIB_PKG, @_ , 'Class=lib');
7596
    PackageAddFiles ( \%INSTALL_SHLIBS, \%INSTALL_LIBS, \%SHLIB_INS, @_ , 'Class=lib');
7597
}
7598
 
7599
#-------------------------------------------------------------------------------
7600
# Function        : PackageAddFiles
7601
#
7602
# Description     : Internal function to add files to the data structures that
7603
#                   describe a package or installation
7604
#
7605
#                   Use this function to package or install additional files with
7606
#                   the Progs and Libs
7607
#
7608
#                   ie: Add a LIB file to be packaged with a Shared Library
7609
#                   ie: Add a MAP file to be packaged with a program
7610
#
7611
# Inputs          : ref_spkg  - Reference to the hash that contains the package data
7612
#                   ref_dpkg  - Reference to the target package/install hash
7613
#                               Normally the same as ref_dpkg, but does allow
289 dpurdie 7614
#                               a static library to be added to a dynamic library
227 dpurdie 7615
#                               package.
7616
#                   ref_list  - Reference to a hash that may contain package keys to process
7617
#                   prog      - Key for index to above
7618
#                   file      - A file to be added
7619
#                   args      - Additional packaging arguments
7620
#
7621
# Returns         :
7622
#
7623
sub PackageAddFiles
7624
{
7625
    my ($ref_spkg, $ref_dpkg, $ref_list, $prog, $file, @args ) = @_;
7626
 
7627
    #
7628
    #   Process entry
7629
    #   The files may need to be added to multiple packages
7630
    #
7631
    Debug("PackageAddFiles: $file");
7632
 
7633
    return unless ( $ref_list->{$prog} );
7634
 
7635
    #
7636
    #   Parse arguments and extract the "Class=xxx" argument. This may be used
7637
    #   to limit the extra files piggybacked with the base file
7638
    #   All files without a class will be treated as base files
7639
    #
7640
    my $class;
7641
    foreach ( @args )
7642
    {
7643
        next unless ( m~^Class=(.*)$~ );
7644
        $class = $1 unless ( $1 eq 'none' );
7645
    }
7646
    Debug("PackageAddFiles: Class: ", $class || 'Default=None');
7647
 
7648
    foreach my $entry_key ( @{$ref_list->{$prog}} )
7649
    {
7650
        Debug("PackageAddFiles: Entry found: $entry_key");
7651
 
7652
        #
7653
        #   Copy of the template entry
7654
        #
7655
        my %package_entry = %{$ref_spkg->{$entry_key}};
7656
        Error ("INTERNAL: Expected entry in PACKAGE_ hash not found: $entry_key" )
7657
            unless ( %package_entry );
7658
 
7659
        #
7660
        #   Do not add the file if the user has limited the extra files added
7661
        #   to the packaging list and the current file is not in the class list
7662
        #
7663
        if ( $class && $package_entry{'extras'} )
7664
        {
7665
            next unless ( $package_entry{'extras'}{$class} );
7666
        }
7667
 
7668
        #
7669
        #   Create new entries for the file
7670
        #
7671
        $package_entry{'src'} = $file;
7672
        foreach ( @args )
7673
        {
7674
            m~^(.*)=(.*)$~;
7675
            $package_entry{$1} = $2;
7676
        }
7677
 
7678
        #
7679
        #   Clean out useless fields
7680
        #   Must remove the placekeeper marker to allow the entry to be visible
7681
        #
7682
        delete $package_entry{'placekeeper'};
7683
        delete $package_entry{'version'};
7684
        delete $package_entry{'lib'};
261 dpurdie 7685
#       delete $package_entry{'extras'};                   # Keep these
227 dpurdie 7686
        delete $package_entry{'Class'};
7687
 
7688
        #
7689
        #   Add the entry
7690
        #
7691
        #   Under some conditions is it possible to attempt to add the same named
7692
        #   file. This will result in a circular dependancy in the makefile
7693
        #
7694
        #   The condition is when merged libaries with PDBs (WINCE+WIN32) are merged
261 dpurdie 7695
        #   and the source for the merge is the "local directory.
227 dpurdie 7696
        #
7697
        #
7698
        my $dst = $package_entry{'dir'} ;
7699
        ( my $dfile = $file) =~ s~.*/~~;
7700
        Debug( "    added $dst/$dfile = $file" );
7701
 
7702
        $ref_dpkg->{"$dst/$dfile"} = {%package_entry}
7703
            unless ( "$dst/$dfile" eq "$file" );
7704
    }
7705
}
7706
 
7707
#-------------------------------------------------------------------------------
7708
# Function        : PackageProgRemoveFiles
7709
#
7710
# Description     : Flag a Packaged program to be not packaged
7711
#                   This mechanism is used to remove a program from packageing
7712
#                   under conditions where the toolset has generated a different
7713
#                   program.
7714
#
7715
#                   The entry is flagged as a placeholder
7716
#
7717
# Inputs          : prog        - Program to process
7718
#
7719
# Returns         : Nothing
7720
#
7721
sub PackageProgRemoveFiles
7722
{
7723
    my ($prog) = @_;
7724
    Verbose ("PackageProgRemoveFiles: $prog" );
7725
    return unless (exists($PROG_PKG{$prog}));
7726
 
7727
    #
7728
    #   Must lookup the TAG to locate the  required entry
7729
    #
7730
    my $tag = $PROG_PKG{$prog};
7731
    foreach my $entry ( @$tag )
7732
    {
7733
        Verbose("Do not package: $entry");
7734
        if ( exists $PACKAGE_PROGS{$entry} )
7735
        {
7736
            $PACKAGE_PROGS{$entry}{placekeeper} = 'ProgRemoved';
7737
        }
7738
    }
7739
}
7740
 
7741
#-------------------------------------------------------------------------------
7742
# Function        : DPackageLibrary
7743
#
7744
# Description     : Collect information to allow the generation of a DPACKAGE
299 dpurdie 7745
#                   file. This directive allows the generation of "Library"
227 dpurdie 7746
#                   directives within the final DPACKAGE
7747
#
7748
#                   This directive does generate the DPACKAGE file.
7749
#
7750
# Inputs          : platform    - This does not need to be an active platform
7751
#                                 it is simply passed to the DPACKAGE builder
7752
#
7753
#                   using       - The "using" target
7754
#
7755
#                   ...         - Arguments for the Library directive
7756
#
7757
# Returns         :
7758
#
7759
sub DPackageLibrary
7760
{
7761
    JatsDPackage::DPackageAdd ( @_ );
299 dpurdie 7762
    $DPackageDirective = 1;
227 dpurdie 7763
}
7764
 
7765
#-------------------------------------------------------------------------------
7766
# Function        : SetProjectBase
7767
#
7768
# Description     : Allows the user to modify the build's concept of the Base
7769
#                   of the build. By default the base is the same directory as
7770
#                   the build.pl file, but in some contorted environments it
7771
#                   is a great deal simpler to specify a differnt base.
7772
#
7773
#                   The use may use the variable $ProjectBase as a path
7774
#                   specifier to locate files and directories
7775
#
7776
#                   Both absolute and relative paths are supported
7777
#                   If the initial value of $ProjectBase is relative then
7778
#                   it will be maintained as a relative path.
7779
#
7780
# Inputs          : elements        path to base
7781
#                                   These may be:
7782
#                                       --Up=xx
7783
#                                       name
7784
#
7785
# Returns         : Nothing
7786
#
7787
 
7788
#
7789
#   Allow the user to modify the project base variable
7790
#
7791
sub SetProjectBase
7792
{
7793
    my $rip = 0;
7794
    my $path = "";
7795
    my $is_relative;
7796
 
7797
    Debug("ProjectBase Initial: $ProjectBase, @_");
7798
 
7799
    #
7800
    #   Ensure that the ProjectBase is in a "nice" form
7801
    #   1) No /./ bits
7802
    #   2) No trailing /
7803
    #   3) Not equal to .
7804
    #   4) No training /.
7805
    #   5) No //
7806
    #
7807
    $ProjectBase =~ s~/\./~/~g;
7808
    $ProjectBase =~ s~/$~~g;
7809
    $ProjectBase =~ s~^\.$~~g;
7810
    $ProjectBase =~ s~/\.$~~g;
7811
    $ProjectBase =~ s~//$~/~g;
7812
 
7813
    #
7814
    #   ProjectBase may be absolute or relative
7815
    #   Determine this before we mess with it
7816
    #
7817
    $is_relative = ($ProjectBase !~ m~^/~);
7818
 
7819
    #
7820
    #   Process each argument
7821
    #
7822
    foreach ( @_ )
7823
    {
7824
        if ( /^--Up=([0-9]*)/ ) {
7825
            $rip = $1;
7826
        } elsif ( /^--/ ) {
7827
            Warning( "SetProjectBase - unknown option \"$_\" - ignored" );
7828
        } else {
7829
            $path = $_;
7830
        }
7831
    }
7832
 
7833
    #
7834
    #   Process the UP requests
7835
    #   If the tail directory is a ".." then up is done by adding another ".."
7836
    #   If the tail directory is not a "..", then up is done by removing it
7837
    #
7838
    #   If we go past the start of the path then simply add ".."
7839
    #
7840
    while ( $rip-- > 0 )
7841
    {
7842
        Debug2("ProjectBase: $ProjectBase, Up: $rip, IsRel: $is_relative");
7843
 
7844
        #
7845
        #   If ending in a /.. or is exactly equal to ..
7846
        #   Then its a dot-dot and the way to go UP is to append another ..
7847
        #
7848
        if ( $ProjectBase =~ m~(/\.\.$)|(^\.\.$)~ )
7849
        {
7850
            $ProjectBase .= '/..';
7851
        }
7852
        else
7853
        {
7854
            #
7855
            #   Not a dot-dot ending
7856
            #   Attempt to remove the last directory of the form
7857
            #       /xxxxx
7858
            #   Where the leading / is optional
7859
            #   Note: Must have at least one character in the dirname
7860
            #         This prevents leading / from matching - which is needed
7861
            #
7862
            unless ($ProjectBase =~ s~/?[^/]+$~~)
7863
            {
7864
                #
7865
                #   Removal failed
7866
                #   If a relative path then we can keep on going up,
7867
                #   otherwise we are dead.
7868
                #
7869
                Error ("ProjectBase outside project") unless ($is_relative);
7870
                $ProjectBase = '..';
7871
            }
7872
 
7873
            #
7874
            #   Ensure that the leading / in an absolute path is not deleted
7875
            #
7876
            $ProjectBase = '/'
7877
                unless ( $is_relative || $ProjectBase );
7878
        }
7879
    }
7880
 
7881
    #
7882
    #   Append the user path
7883
    #
7884
    $ProjectBase .= '/' . $path if ( $path );
7885
    $ProjectBase = '.' unless ( $ProjectBase );
7886
    Debug("ProjectBase set to : $ProjectBase");
7887
 
7888
    #
7889
    #   Once upon a time I tried to convert paths that contained spaces into
7890
    #   short (mangled) names. This was not sucessful because:
7891
    #       1) Clearcase dynamic views do not support name mangling
7892
    #       2) Samba file system does not appear to support name mangling
7893
    #
7894
    #   Spaces in paths are not good for MAKE
7895
    #   Now I simple generate a message
7896
    #
7897
    Warning( "ProjectBase contains a space: $ProjectBase")
7898
        if ( $ProjectBase =~ m/ / );
7899
 
7900
    #
7901
    #   Sanity check
7902
    #   Absolute paths can be checked easily
7903
    #   Checking of relative paths does not appear to work
7904
    #   When I tested it chdir, opendir and stat would limit themselves
7905
    #   and drop into the root directory ( under windows )
7906
    #
7907
    #   Solution: Check the path does not extend beyond the file tree
7908
    #
7909
    my $distance = 1;
7910
    my $tpath = $ProjectBase;
7911
 
7912
    if ( $is_relative && $tpath ne '.' )
7913
    {
7914
        #
7915
        #   Build up the complete pathname by merging it with the
7916
        #   current directory. Then clean it up.
7917
        #
7918
        $tpath = $::Cwd . '/' . $ProjectBase;
7919
 
7920
        #
7921
        #   Scan the list of diretories and count the distance from the root
7922
        #   This should not be greater than zero for sanity
7923
        #   Note: Get an empty elemement from the split due to
7924
        #         the leading / of the ABS path
7925
        #
7926
        $distance = 0;
7927
        foreach (  split ('/', $tpath) )
7928
        {
7929
            if ( m~\.\.~ )
7930
            {
7931
                $distance--;
7932
            }
7933
            else
7934
            {
7935
                $distance++;
7936
            }
7937
        }
7938
    }
7939
 
7940
    #
7941
    #   Warn if not a valid directory
7942
    #
7943
    Warning( "ProjectBase is not a directory: $ProjectBase")
7944
        if ( $distance <= 0 || !  -d $tpath  );
7945
 
7946
    #
7947
    #   $ProjectBase will always be a valid directory, but if its the top
7948
    #   directory (/) and it is added to a path we will get //path
7949
    #   This is not good, so // will be removed later in the AddIncDir and
7950
    #   AddSrcDir commands where $ProjectBase is really used.
7951
    #
7952
    #   Alternatively we could set $ProjectBase to an empty string, but then
7953
    #   this may be confused with an empty relative directory
7954
    #
7955
    Debug("ProjectBase Final  : $ProjectBase");
7956
}
7957
 
7958
#-------------------------------------------------------------------------------
7959
# Function        : DeployPackage
7960
#
7961
# Description     : Generate a deployed package
7962
#                   This is a gateway to a different packaging system
7963
#
7964
#                  DeployPackage and PackageXxxxx directives are mutually
7965
#                  exclusive. Only one person can play in the package area.
7966
#
7967
# Inputs          : Platform Specifier
7968
#                   Package Name    (Optional)
7969
#                   Options
7970
#                       --Name : Base name of the package. The default is taken
7971
#                                from the build.pl file
7972
#                       --Dir  : Package directory
7973
#                                The default is based on the package name
7974
#
7975
# Returns         :
7976
#
7977
sub DeployPackage
7978
{
7979
    my( $platforms, @elements ) = @_;
7980
    my $dir;
7981
    my $name;
7982
 
267 dpurdie 7983
    #
7984
    #   Flag that this build creates a deployable package, even if its not
7985
    #   active on this platform.
7986
    #
7987
    $DEPLOYPACKAGE = 1;
7988
 
7989
 
227 dpurdie 7990
    Debug2( "DeployPackage($platforms, @elements)" );
7991
    return if ( ! ActivePlatform($platforms) );
7992
 
7993
    #
7994
    #   Only allow one use of this directive
7995
    #
7996
    Error("DeployPackage can only be used once" ) if ( %DEPLOYPACKAGE );
267 dpurdie 7997
    $DEPLOYPACKAGE = 2;
227 dpurdie 7998
 
7999
    #
8000
    #   Ensure that the deployment file is available
8001
    #
8002
    my $command_file = $ScmDeploymentPatch ? "deploypatch.pl" : "deployfile.pl";
8003
    Error("DeployPackage: $command_file not found") unless (-f "./$command_file");
8004
    #
8005
    #   Collect arguments
8006
    #
8007
    foreach (@elements )
8008
    {
8009
        if ( m/^--Dir=(.*)/ ) {
8010
            Error ("DeployPackage: Package directory defined multiple times") if $dir;
8011
            $dir = $1;
8012
 
8013
        } elsif ( m/^--Name=(.*)/ ) {
8014
            Error ("DeployPackage: Package name defined multiple times") if $name;
8015
            $name = $1;
8016
 
8017
        } elsif ( m/^--/ ) {
8018
            Warning( "DeployPackage: Unknown option ignored: $_");
8019
 
8020
        } else {
8021
            Error ("DeployPackage: Package name defined multiple times") if $name;
8022
            $name = $_;
8023
 
8024
        }
8025
    }
8026
 
8027
    $name = $::ScmBuildPackage unless ( $name );
8028
 
8029
    #
8030
    #   Save the deployment data
8031
    #
8032
    $dir = lc($name) unless ( $dir );
8033
    $DEPLOYPACKAGE{'name'} = $name;
8034
    $DEPLOYPACKAGE{'dir'} = $dir;
8035
    $DEPLOYPACKAGE{'cmdfile'} = $command_file;
8036
 
8037
    #
8038
    #   Flag that toolset tests should be supressed
8039
    #   The Deploy world does not really use the full makefiles and if the
8040
    #   compilers are not installed will not be able to create deployment
8041
    #   packages
8042
    #
8043
    $ScmNoToolsTest = 1;
8044
}
8045
 
8046
 
8047
###############################################################################
8048
###############################################################################
8049
# Private function section.
8050
#       The following functions are used INTERNALLY by makelib.pl2.
8051
###############################################################################
8052
 
8053
###############################################################################
8054
#   A collection of functions to write to the MAKEFILE handle
8055
#
8056
#   MakeHeader          - Write a nice section header
8057
#   MakeNewLine         - Print a new line
8058
#   MakePrint           - Print a line ( without trailing \n)
8059
#   MakeQuote           - Escape \ and " character, then print a line
8060
#   MakePrintList       - Print an array
8061
#   MakeEntry           - Complex line printer
8062
#   MakePadded          - Padded line printer (internal)
8063
#   PadToPosn           - Calc space+tabs to tabstop (internal)
8064
#   MakeEntry3          - Complex Line Printer
8065
#   MakeDefEntry        - Print a definition line (Production + Debug support)
8066
#   MakeIfDefEntry      - Print ifdef entry
261 dpurdie 8067
#   MakeIfnDefEntry     - Print ifndef entry
8068
#   MakeIfZeroEntry     - Print ifeq entry
227 dpurdie 8069
#
8070
###############################################################################
8071
 
8072
sub MakeHeader
8073
{
8074
    my ($text, @rest) = @_;
8075
    my $length = length ($text);
8076
 
8077
    print MAKEFILE "\n";
8078
    print MAKEFILE "#--------- $text ", '-' x (80 - 12 - $length)  ,"\n";
8079
    print MAKEFILE "#    $_\n" foreach  ( @rest ) ;
8080
    print MAKEFILE "#\n";
8081
}
8082
 
8083
sub MakeNewLine         # Print a newline to the current 'Makefile'
8084
{
8085
    print MAKEFILE "\n";
8086
}
8087
 
8088
sub MakePrint           # Print to the current 'Makefile'
8089
{
8090
    print MAKEFILE @_
8091
        if ( defined $_[0] );
8092
}
8093
 
8094
sub MakeQuote           # Quote a makefile text line
8095
{
8096
    my( $line ) = @_;
8097
    $line =~ s/\\/\\\\/g;                       # quote all '\' characters
8098
    $line =~ s/"/\\"/g;                         # Then quote '"' characters
255 dpurdie 8099
    $line =~ s/=#/=\\#/g;                       # Then quote '=#' sequence
227 dpurdie 8100
    print MAKEFILE $line;
8101
}
8102
 
8103
sub MakePrintList
8104
{
8105
    print MAKEFILE $_ . "\n" foreach (@{$_[0]});
8106
}
8107
 
2429 dpurdie 8108
sub QuoteArray
8109
{
8110
    my $quote = "'";
8111
    if ( @_ ) {
8112
        return ($quote . join("$quote $quote", @_) . $quote);
8113
    }
8114
    return '';
8115
}
227 dpurdie 8116
 
8117
#-------------------------------------------------------------------------------
8118
# Function        : MakeEntry
8119
#
8120
# Description     : Build a entry based on the element list
8121
#                   Creates text of the form
8122
#                       $(BINDIR)/prog.exe: object1.obj \
8123
#                                           object2.obj
8124
#
8125
#
8126
# Inputs          : $prelim         - Preamble (one-off)
8127
#                   $postlim        - Postamble (one-off)
8128
#                   $prefix         - Pefix (to each element of array)
8129
#                   $postfix        - Postfix (to each element of array )
8130
#                   @elements       - Array of element to wrap
8131
#
8132
# Returns         :   1 Always
8133
#
8134
# Notes:
8135
#       The above description means that the following entry format is
8136
#       produced:
8137
#
8138
#           <preliminary><prefix><variant1><prefix><variant2>...<final>
8139
#
8140
#       With judicious use of newline and tab characters, a target
8141
#       and dependency list along with the command(s) to build the
8142
#       target can be constructed.
8143
#
8144
sub MakeEntry
8145
{
8146
    my( $prelim, $postlim, $prefix, $postfix, @elements ) = @_;
8147
 
8148
    MakePrint $prelim;
8149
    MakePrint "${prefix}${_}${postfix}" foreach ( @elements );
8150
    MakePrint $postlim if ($postlim);
8151
    return 1;
8152
}
8153
 
8154
#-------------------------------------------------------------------------------
8155
# Function        : MakePadded
8156
#
8157
# Description     : Generate aligned output of the form
8158
#                       Prefix_text           Aligned_text
8159
#                   where the aligned text is at a specified TAB boundary
8160
#
8161
# Inputs          : $align      - Tab stop (One tab = 8 chars)
8162
#                   $prefix     - Text to print before alignment occurs
8163
#                   @line       - Remainder of the line
8164
#
8165
sub MakePadded          # Print to the current 'Makefile', tab aligning
8166
{
8167
    my( $align, $prefix, @line ) = @_;
8168
 
8169
    my $strlen = length( $prefix );
8170
    my $pad = PadToPosn( $strlen, $align * 8 );
8171
 
8172
    print MAKEFILE $prefix . $pad;
8173
    print MAKEFILE @line;
8174
}
8175
 
8176
#-------------------------------------------------------------------------------
8177
# Function        : PadToPosn
8178
#
8179
# Description     : Given that we are at $startposn return a tab and space
8180
#                   string to place us at $endposn
8181
#
8182
sub PadToPosn
8183
{
8184
    my ($startposn, $endposn ) = @_;
8185
 
8186
 
8187
    #
8188
    #   Case where we are already too far into the line
8189
    #
8190
    return ( ' ' )if ( $endposn <= $startposn );
8191
 
8192
    my $tcount = 0;
8193
    my $scount = 0;
8194
 
8195
    while ( $startposn < $endposn )
8196
    {
8197
        $tcount ++;
8198
        $startposn = ($startposn >> 3) * 8 + 8;
8199
 
8200
        my $delta = $endposn - $startposn;
8201
        if ( $delta < 8 )
8202
        {
8203
            $scount = $delta;
8204
            last;
8205
        }
8206
 
8207
    }
8208
    return ( "\t" x $tcount .  ' ' x $scount );
8209
}
8210
 
8211
#-------------------------------------------------------------------------------
8212
# Function        : MakeEntry3
8213
#
8214
# Description     : Build a makefile entry based on the element list, tab aligned
8215
#                   Can creat text of the form:
8216
#                       TAG = NAME0 \       TAG : NAME0 \ 
8217
#                             NAME1               NAME1
8218
#
8219
#
8220
# Inputs          : $prelim             - Preliminary text
8221
#                   $presep             - Preliminary seperator
8222
#                   $elem_ref           - Either a single name or a reference to
8223
#                                         and array of names, or a hash.
8224
#
8225
# Returns         : Writes directly to the Makefile
8226
#
8227
sub MakeEntry3
8228
{
8229
    my( $prelim, $presep, $elem_ref ) = @_;
8230
 
8231
    #
8232
    #   The prelim may have some "\n" characters at the start
8233
    #   These simplify formatting, but mess up the nice formatting
8234
    #
8235
    if ($prelim =~ m~(^\n+)(.*)~ )
8236
    {
8237
        MakePrint $1;
8238
        $prelim = $2;
8239
    }
8240
 
8241
    #
8242
    #   Print the definition and the sep with nice padding
8243
    #
8244
    MakePadded ( 3, $prelim, $presep );
8245
    my $leadin = ' ';
8246
 
8247
    #
8248
    #   If a HASH reference then use a sorted list of keys from the hash.
8249
    #
8250
    if ( ref ($elem_ref) eq "HASH" )
8251
    {
8252
        my @hash_list;
8253
        @hash_list = sort keys ( %{$elem_ref} );
8254
        $elem_ref = \@hash_list;
8255
    }
8256
 
8257
    #
8258
    #   If the list is only one element long, then create a simple form
8259
    #   If the list is not an array ref, then treat it as a single element
8260
    #
8261
    if ( ref ($elem_ref) eq "ARRAY" )
8262
    {
8263
        my $line = 0;
8264
        foreach my $element ( @$elem_ref )
8265
        {
8266
            print MAKEFILE $leadin . $element;
8267
            $leadin = " \\\n" . PadToPosn(0,24 + length( $presep ) + 1 ) unless ($line++);
8268
        }
8269
    }
8270
    elsif ( defined $elem_ref )
8271
    {
8272
            print MAKEFILE $leadin . $elem_ref;
8273
    }
8274
    MakeNewLine();
8275
    return 1;
8276
}
8277
 
8278
#-------------------------------------------------------------------------------
8279
# Function        : MakeDefEntry
8280
#
8281
# Description     : Make a definition entry of the form
8282
#
8283
#                       TAG = NAME0 \
8284
#                             NAME1
8285
#
8286
#                   Support a list of definitions that will always be created
8287
#                   as well as a production and a debug list.
8288
#
8289
#                   Will always generate the "TAG = " string, even if the list
8290
#                   is empty.
8291
#
8292
#                   Will supress the TAG if there is no data if the FIRST opr starts with a '+'
8293
#
8294
# Inputs          : TAG         - Text tag to create
8295
#                   FIRST       - First assignement opr. = or +=
8296
#                   ALL_LIST    - A reference to a list of names to assign
8297
#                                 or a single name.
8298
#                   PROD_LIST   - Optional list to extend the definition with for a production build
8299
#                   DEBUG_LIST  - Optional list to extend the definition with for a debug build
8300
#
8301
# Returns         : Nothing
8302
#
8303
 
8304
sub MakeDefEntry
8305
{
8306
    my( $tag, $assign, $all, $prod, $debug ) = @_;
8307
 
8308
    #
8309
    #   Do not generate anything if the $opr is "+=" and there is no data
8310
    #   to output. ie: Supress empty TAG += statements
8311
    #
8312
    return if ( $assign =~ m/\+/ && ( ref($all) && ! defined $all->[0] ) );
8313
 
8314
    #
8315
    #   TAG for all entries
8316
    #
8317
    MakeEntry3( $tag, $assign, $all );
8318
 
8319
 
8320
    #
8321
    #   TAGs for PROD build
8322
    #   TAGs for DEBUG build
8323
    #
8324
    if ( defined $prod && defined $prod->[0] )
8325
    {
8326
        print MAKEFILE 'ifeq "$(DEBUG)" "0"' . "\n";
8327
        MakeEntry3( $tag, "+=", $prod );
267 dpurdie 8328
        print MAKEFILE 'endif' . "\n";
227 dpurdie 8329
    }
8330
 
8331
    if ( defined $debug && defined $debug->[0] )
8332
    {
8333
        print MAKEFILE 'ifeq "$(DEBUG)" "1"' . "\n";
8334
        MakeEntry3( $tag, "+=", $debug );
267 dpurdie 8335
        print MAKEFILE 'endif' . "\n";
227 dpurdie 8336
    }
8337
 
8338
}
8339
 
8340
sub MakeIfDefEntry
8341
{
8342
    my( $iftag, @rest ) = @_;
8343
 
8344
    print MAKEFILE "ifdef $iftag\n";
8345
    MakeDefEntry (@rest);
8346
    print MAKEFILE "endif\n\n";
8347
}
8348
 
8349
sub MakeIfnDefEntry
8350
{
8351
    my( $iftag, @rest ) = @_;
8352
 
8353
    print MAKEFILE "ifndef $iftag\n";
8354
    MakeDefEntry (@rest);
8355
    print MAKEFILE "endif\n\n";
8356
}
8357
 
261 dpurdie 8358
sub MakeIfZeroEntry
8359
{
8360
    my( $iftag, @rest ) = @_;
8361
 
8362
    print MAKEFILE "ifeq (\$($iftag),0)\n";
8363
    MakeDefEntry (@rest);
8364
    print MAKEFILE "endif\n\n";
8365
}
8366
 
227 dpurdie 8367
#-------------------------------------------------------------------------------
8368
# Function        : CreateNameList
8369
#
8370
# Description     : Create a list of names by adding a prefix and suffix to a
8371
#                   list of items. This is used to add a directory prefix and a
8372
#                   file suffix to a list of files.
8373
#
8374
# Inputs          : $prefix             ie: '$(OBJDIR)/'
8375
#                   $suffix             ie: '.obj'
8376
#                   $elem_ref           ie: A list of files ( passed be ref )
8377
#                                           If a Hash then its sorted keys is used
8378
#
8379
# Returns         : A ref to the resulting list
8380
#
8381
sub CreateNameList
8382
{
8383
    my( $prefix, $suffix, $elem_ref ) = @_;
8384
    my @result;
8385
 
8386
    if ( ref ($elem_ref) eq "HASH" )
8387
    {
8388
        my @hash_list;
8389
        @hash_list = sort keys ( %{$elem_ref} );
8390
        $elem_ref = \@hash_list;
8391
    }
8392
 
8393
    foreach  ( @$elem_ref )
8394
    {
8395
        push @result, $prefix . $_ . $suffix;
8396
    }
8397
    return \@result;
8398
}
8399
 
8400
#-------------------------------------------------------------------------------
8401
# Function        : ListGeneratedProjects
8402
#
8403
# Description     : Return a list of generated/nongenerated projects
8404
#                   Used in conjunction with CreateNameList
8405
#
8406
# Inputs          : $type       - TRUE : Generated
8407
#                                 FALSE: Not Generated
8408
#
8409
# Returns         : A reference to a list of projects
8410
#                   undef will be retuend if there are no projects
8411
#
8412
sub ListGeneratedProjects
8413
{
8414
    my ($type) = @_;
8415
    my @list;
8416
    foreach my $project ( @PROJECTS_ORDER )
8417
    {
8418
        if ( exists($PROJECTS{$project}->{'generated'}) xor $type )
8419
        {
8420
            push @list, $project;
8421
        }
8422
    }
8423
    return @list ? \@list : undef;
8424
}
8425
 
8426
#-------------------------------------------------------------------------------
8427
# Function        : ListCleanGenerated
8428
#
8429
# Description     : return a list of generated targets that have 'clean'
8430
#                   operations. This is used in conjunction with CreateNameList
8431
#
8432
# Inputs          : None
8433
#
8434
# Returns         : A list of project indexes, that can be cleaned
8435
#
8436
sub ListCleanGenerated
8437
{
8438
    my @list;
8439
    foreach my $i ( @GENERATE_FILES )
8440
    {
8441
        push @list, $i->{'index'}
8442
            if ( $i->{'clean'} );
8443
    }
8444
    return \@list;
8445
}
8446
 
251 dpurdie 8447
#-------------------------------------------------------------------------------
8448
# Function        : MakeResolve
8449
#
8450
# Description     : Internal Function
8451
#                   Locate a source file by examining a list of directories
8452
#
8453
#                   Don't use directly
8454
#                   Use MakeSrcResolve or MakeSrcResolveExtended
8455
#
8456
# Inputs          : $dirs           - Ref to an array of directories to scan
8457
#                   $source         - File to locate
8458
#
8459
# Returns         : Resolved path to the file
8460
#                   Will warn if multiple instances of the file are found
8461
#
227 dpurdie 8462
sub MakeResolve
8463
{
8464
    my( $dirs, $source ) = @_;
285 dpurdie 8465
    my( $first, $count );
227 dpurdie 8466
 
237 dpurdie 8467
    #
8468
    #   If the path contains a '$' then its assumed to be
8469
    #   a variable name in the path. Just assume that it exists
8470
    #
8471
    return $source if ( $source =~ m#\$# );
8472
 
8473
    #
8474
    #   If the path is absolute or contains a leading ., then don't search
8475
    #   Warn if it can't be found
8476
    #
8477
    if ( $source =~ m#^(/|\.)# )
8478
    {
8479
        Warning( "Unable to resolve '$source' path" ) unless -f $source;
8480
        return $source;
227 dpurdie 8481
    }
8482
 
6276 dpurdie 8483
    my @found;
8484
    # Search the local path first
8485
    push (@found, $source ) if -f ($source);
237 dpurdie 8486
 
285 dpurdie 8487
    foreach my $dir (@$dirs)
227 dpurdie 8488
    {
331 dpurdie 8489
        next if ( $dir eq '.' );
6276 dpurdie 8490
        my $temp = $dir . '/' . $source;
227 dpurdie 8491
        Debug2( "MakeResolve: Looking in: $temp" );
6276 dpurdie 8492
        push (@found, $temp) if (-f $temp);
227 dpurdie 8493
    }
8494
 
6276 dpurdie 8495
    Warning( "Unable to resolve path to '$source'" ) unless $found[0];
8496
    if (scalar @found > 1)
8497
    {
8498
        Warning("Duplicates for '$source'. Using the first", @found);
227 dpurdie 8499
    }
6276 dpurdie 8500
 
6504 dpurdie 8501
    return $found[0] || $source;
227 dpurdie 8502
}
8503
 
251 dpurdie 8504
#-------------------------------------------------------------------------------
8505
# Function        : MakeSrcResolve
8506
#
8507
# Description     : Locate a source file by examining the list of source
8508
#                   directories. There are a few frills
8509
#
8510
#                   Look for a source file in
8511
#                       1) %::BUILD_KNOWNFILES
8512
#                       2) %SRCS
8513
#                       3) Dirs specified by the array @SRCSDIRS
8514
#
8515
# Inputs          : Name of a file to resolve
8516
#
8517
# Returns         : Resolved path.
283 dpurdie 8518
#                   Input file - if not found at all
251 dpurdie 8519
#
227 dpurdie 8520
sub MakeSrcResolve
8521
{
8522
    my ($name) = @_;
8523
    my $file;
8524
 
251 dpurdie 8525
    if ( exists ( $::BUILD_KNOWNFILES{$name} ) ) {
8526
        #
8527
        #   The Known Files list is relative to ScmRoot
8528
        #   This must be included in the full path
8529
        #
8530
        $file = $ScmRoot . '/' . $::BUILD_KNOWNFILES{$name};
8531
 
8532
    } elsif ( exists $SRCS{$name} ) {
8533
        $file = $SRCS{$name};
8534
 
8535
    } else {
6469 dpurdie 8536
        $file = MakeResolve( \@SRCDIRS, @_ );
251 dpurdie 8537
    }
227 dpurdie 8538
    return $file;
8539
}
8540
 
8541
 
8542
# MakeSrcResolveExtended
8543
#   from_global = 0 : Search user specified directories
8544
#               = 1 : Search LinkPkgArchive list
8545
#
8546
our @PkgSrcDirList;
8547
sub MakeSrcResolveExtended
8548
{
8549
    my ( $from_global, $file ) = @_;
8550
 
8551
    #
8552
    #   Simple Case. Resolve source from known source directories
8553
    #
8554
    #
8555
    return MakeSrcResolve( $file )
8556
        unless ( $from_global );
8557
 
8558
    #
8559
    #   Not so simple Case
8560
    #   Resolve the source from the imported packages
8561
    #
8562
    #   Create a list of directores to search, but only the first time
311 dpurdie 8563
    #       - Interface directories - from BuildPkgArchive
227 dpurdie 8564
    #       - LnkPkgArchive directories
8565
    #         Using target,product,platform include directories
8566
    #
8567
    unless ( @PkgSrcDirList )
8568
    {
8569
        for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} })
8570
        {
311 dpurdie 8571
            next if ( $entry->{'TYPE'} eq 'build' ); # Ignore BuildPkgArchives
8572
 
227 dpurdie 8573
            for (@{$entry->{'PINCDIRS'}}, @{$entry->{'THXDIRS'}}, '' )
8574
            {
8575
                my $dir = $entry->{'ROOT'} . "/" . $_ ;
8576
                $dir =~ s~//~/~g;
8577
                $dir =~ s~/$~~;
311 dpurdie 8578
                push ( @PkgSrcDirList, $dir );
227 dpurdie 8579
            }
8580
        }
311 dpurdie 8581
    }
227 dpurdie 8582
 
8583
    return MakeResolve( \@PkgSrcDirList, $file );
8584
}
8585
 
8586
#-------------------------------------------------------------------------------
8587
# Function        : GetPackageRoot
8588
#
8589
# Description     : Determine the root directory for a given package
8590
#                   This routine is intended for non-standard JATS scripts that
8591
#                   access package contents directly
8592
#
8593
#                   Note: This routine does not attempt to handle multiple
8594
#                         instances of a package ( sysbasetypes ).
8595
#
8596
# Inputs          : $pname          - Name of the package
8597
#
8598
# Returns         :
8599
#
8600
sub GetPackageRoot
8601
{
8602
    my( $pname ) = @_;
8603
    Debug( "GetPackageRoot(@_)" );
8604
 
8605
    my $result = undef;
8606
    my $pkg = GetPackageEntry( $pname );
8607
    if ( $pkg )
8608
    {
8609
        $result = $pkg->{'ROOT'};
8610
        Debug( "GetPackageRoot: $result" );
8611
    }
8612
 
8613
    return $result;
8614
}
8615
 
8616
#-------------------------------------------------------------------------------
8617
# Function        : ActiveProject
8618
#
8619
# Description     : Determine if the specified project is currenly 'active'
8620
#
345 dpurdie 8621
# Inputs          : $project            - one or more project names separated
8622
#                                         by either a comma or a colon
227 dpurdie 8623
#
8624
# Returns         : TRUE    if the project is active
8625
#
8626
sub ActiveProject
8627
{
8628
    my ($project) = @_;
345 dpurdie 8629
    foreach (  split( '\s*[:,]\s*', $project ) )
227 dpurdie 8630
    {
8631
        return 1
8632
            if ( $_ eq $::ScmBuildProject );
8633
    }
8634
    return 0;
8635
}
8636
 
345 dpurdie 8637
#-------------------------------------------------------------------------------
8638
# Function        : ActiveDefine
8639
#
8640
# Description     : Determine if the specified definition is currenly 'active'
8641
#
8642
# Inputs          : $defs               - one or more variable names separated
8643
#                                         by either a comma or a colon
8644
#
8645
# Returns         : TRUE    if any of the definitions are known
8646
#
8647
sub ActiveDefine
8648
{
8649
    my ($defs) = @_;
8650
    no strict 'refs';
8651
    foreach (  split( '\s*[:,]\s*', $defs ) )
8652
    {
8653
        return 1
4455 dpurdie 8654
            if ( defined( $$_ ) || ( @$_ ) );
345 dpurdie 8655
    }
8656
    use strict 'refs';
8657
    return 0;
8658
}
227 dpurdie 8659
 
8660
#-------------------------------------------------------------------------------
345 dpurdie 8661
# Function        : ActiveMachType
8662
#
8663
# Description     : Determine if the specified MachType is currenly 'active'
8664
#
8665
# Inputs          : $mtype              - one or more machine names separated
8666
#                                         by either a comma or a colon
8667
#
8668
# Returns         : TRUE    if any of the current MachType is in the list
8669
#
8670
sub ActiveMachType
8671
{
8672
    my ($mtype) = @_;
8673
    foreach (  split( '\s*[:,]\s*', $mtype ) )
8674
    {
8675
        return 1
8676
            if ( uc($_) eq uc($::GBE_MACHTYPE) );
8677
    }
8678
    return 0;
8679
}
8680
 
8681
#-------------------------------------------------------------------------------
6133 dpurdie 8682
# Function        : ActiveAlias
8683
#
8684
# Description     : Determine if the specified Alias is currenly 'active'
8685
#
8686
# Inputs          : $mtype              - one or more alias names separated
8687
#                                         by either a comma or a colon
8688
#
8689
# Returns         : TRUE    if any of the current Aliases is in the list
8690
#
8691
sub ActiveAlias
8692
{
8693
    my ($mtype) = @_;
8694
    foreach (  split( '\s*[:,]\s*', $mtype ) )
8695
    {
8696
        return 1
8697
            if ( isAnAlias( uc($_) ) );
8698
    }
8699
    return 0;
8700
}
8701
 
8702
 
8703
#-------------------------------------------------------------------------------
227 dpurdie 8704
# Function        : ActivePlatform
8705
#
8706
# Description     : Determine if the specified platform is currently 'active'
8707
#                   This is used by all user directives in order to determine
8708
#                   if the directive should be ignored for the current platform
8709
#
8710
# Inputs          : $platform_spec      - A platform specifier
8711
#                                         This is a bit complex.
8712
#
241 dpurdie 8713
#                   Format of platform_spec. One or more of
8714
#                       PlatformName
8715
#                       AliasName
6133 dpurdie 8716
#                       TargetName[,--Target]
345 dpurdie 8717
#                   Special Options (Must all be True)
8718
#                       --Project=ProjectName[:ProjectName]+
8719
#                       --Defined=SomeValue[:SomeValue]+
6133 dpurdie 8720
#                       --MachType=SomeMachType[:SomeMachType]+
8721
#                       --Alias=SomeAlias[:SomeAlias]+
8722
#                   Some shortcuts
8723
#                       '*'     ==> Always true
8724
#
345 dpurdie 8725
#                   Each can be prefixed with a '!' to negate the test
6133 dpurdie 8726
#                   
8727
#                   PlatformNames are either additive or negative(prefixed with !)
8728
#                       Order is not important                   
8729
#                       All additive names are accumulated before the negative items are considered.
8730
#                           ie: aa,!bb => !bb,aa
8731
#                       If only negative names are provided then JATS assumes a leading '*'
8732
#                           ie: !aaa => *,!aaa
8733
#                   
241 dpurdie 8734
#                   Valid options are:
271 dpurdie 8735
#                       --Target        - indicates that the platform is a 'target'
241 dpurdie 8736
#
8737
# Returns         : TRUE if the platform spec is satisfied
8738
#
227 dpurdie 8739
sub ActivePlatform
8740
{
8741
    my( $platform_spec ) = @_;
8742
    my( @platforms, $scmplatform, $platform );
6133 dpurdie 8743
    my( %arguments, @args );
241 dpurdie 8744
    my @plist;
227 dpurdie 8745
 
241 dpurdie 8746
    #
8747
    #   Short circuit check
6133 dpurdie 8748
    #       '*' is used so often that it pays to check it first
241 dpurdie 8749
    #
8750
    if ( $platform_spec eq '*' )
8751
    {
8752
        Debug3( " ActivePlatform(@_) = TRUE" );
8753
        return 1;
8754
    }
227 dpurdie 8755
 
241 dpurdie 8756
    #
8757
    #   Platform specifier may be a comma seperated list
8758
    #   ie:  WIN32,MOS,XXX
8759
    #   Extract non-platform arguments
279 dpurdie 8760
    #   Process to yield a dummy platform of '0' or '1' - these will be seen later
241 dpurdie 8761
    #
8762
    foreach ( split( '\s*,\s*', $platform_spec ) )
8763
    {
345 dpurdie 8764
        my ($result, $not);
8765
        if ( m~^(!?)--Project=(.+)~ ) {
325 dpurdie 8766
            $not = $1;
345 dpurdie 8767
            $result = ActiveProject($2);
277 dpurdie 8768
 
345 dpurdie 8769
        } elsif ( m~^(!?)--Defined=(.+)~ ) {
325 dpurdie 8770
            $not = $1;
345 dpurdie 8771
            $result = ActiveDefine($2);
241 dpurdie 8772
 
345 dpurdie 8773
        } elsif ( m~^(!?)--MachType=(.+)~ ) {
325 dpurdie 8774
            $not = $1;
345 dpurdie 8775
            $result = ActiveMachType($2);
8776
 
6133 dpurdie 8777
        } elsif ( m~^(!?)--Alias=(.+)~ ) {
8778
            $not = $1;
8779
            $result = ActiveAlias($2);
8780
 
325 dpurdie 8781
        } else {
8782
            #
8783
            #   Must be a platform argument
8784
            #   Add to a list
8785
            #
8786
            push @platforms, $_;
241 dpurdie 8787
            next;
8788
        }
8789
 
8790
        #
325 dpurdie 8791
        #   Continue processing non-platform arguments
345 dpurdie 8792
        #   Each one must be TRUE, allowing for negation.
241 dpurdie 8793
        #
325 dpurdie 8794
        $result = $result ? 1 : 0;
345 dpurdie 8795
        $result = ! $result if ( $not );
8796
        return 0 unless ( $result );
241 dpurdie 8797
    }
8798
 
4128 dpurdie 8799
    #
8800
    #   If we have no platforms then the test was purely non-platform arguments.
8801
    #
6133 dpurdie 8802
    if ($platform_spec ne '' && ! @platforms) {
8803
        Debug3( " ActivePlatform(@_ == $ScmPlatform) = TRUE" );
4128 dpurdie 8804
        return 1;
8805
    }
8806
 
6133 dpurdie 8807
    unless (@platforms) {
8808
        Debug3( " ActivePlatform(@_ == $ScmPlatform) = FALSE" );
8809
        return 0;
8810
    }
8811
 
8812
 
241 dpurdie 8813
    #   Platform specified may be an Alias
8814
    #   Perform alias expansion
8815
    #
8816
    @platforms = ExpandPlatforms( @platforms );         # aliasing
227 dpurdie 8817
    Debug3( " ActivePlatform(@_)" );
6198 dpurdie 8818
#    Debug0( " Platforms(@platforms)" );
227 dpurdie 8819
 
8820
#.. Arguments
241 dpurdie 8821
#   At this point we have a list of platforms and arguments
8822
#   Build up a hash of arguments for each platform being parsed
227 dpurdie 8823
#   Multiple arguments can follow a platform name
241 dpurdie 8824
#   Arguments apply to the preceeding platform name
227 dpurdie 8825
#
241 dpurdie 8826
    $platform = undef;
227 dpurdie 8827
    foreach ( @platforms )
8828
    {
241 dpurdie 8829
        if ( /^--Target/ ) {                     # Arguments
8830
            if ( $platform ) {
8831
                $arguments{$platform}{'Target'} = 1;
8832
            } else {
317 dpurdie 8833
                Warning ("No Platform preceding platform option: $_");
241 dpurdie 8834
            }
8835
 
305 dpurdie 8836
        } elsif ( /^--Only(Prod)|(Debug)/ || /--board=/ ) {
273 dpurdie 8837
            # Known arguments
305 dpurdie 8838
            # Bit of a kludge. Must be a better way
273 dpurdie 8839
 
241 dpurdie 8840
        } elsif ( /^--/ ) {
8841
            Warning ("Unknown platform option: $_");
8842
 
227 dpurdie 8843
        } else {                                # Target
8844
            $platform = $_;
241 dpurdie 8845
            push @plist, $platform;
227 dpurdie 8846
        }
8847
    }
8848
 
241 dpurdie 8849
#.. Scan the expression
227 dpurdie 8850
#
6198 dpurdie 8851
    $scmplatform = uc( $ScmPlatform );              # current platform
6133 dpurdie 8852
    my @add;
8853
    my @remove;
8854
    foreach ( @plist ) {
6198 dpurdie 8855
        my $platform = uc( Trim( $_ ) );            # trim white and convert case
6133 dpurdie 8856
        my $pname = $platform;
8857
        my $invert = 0;
8858
        if (substr($platform, 0, 1) eq '!') {
8859
            $invert = 1;
8860
            $pname = substr($platform, 1)
8861
        }
325 dpurdie 8862
 
227 dpurdie 8863
        #
241 dpurdie 8864
        #   Determine filter comparison
6133 dpurdie 8865
        #       Either a Platform or a Target
241 dpurdie 8866
        #
6133 dpurdie 8867
        if ( $arguments{$platform}{'Target'} ) {
8868
            $pname = $scmplatform if ($pname eq  uc( $ScmTarget ));
227 dpurdie 8869
        }
241 dpurdie 8870
 
6133 dpurdie 8871
        #
8872
        #   Catch some historically bad practices
8873
        #
8874
        $pname = $scmplatform if ( $pname eq '*'  || $pname eq '1' ); 
227 dpurdie 8875
 
6133 dpurdie 8876
        Debug3( "   Platform=$platform, PName=$pname" );
8877
 
227 dpurdie 8878
        #
8879
        #   Examine platform names
6133 dpurdie 8880
        #   Allow negation (removal) of the name
227 dpurdie 8881
        #
6133 dpurdie 8882
        if ( substr($platform, 0, 1) eq '!' )  {
8883
            push @remove, $pname; 
8884
        } else {
8885
            push @add, $pname; 
227 dpurdie 8886
        }
8887
    }
8888
 
241 dpurdie 8889
    #
6133 dpurdie 8890
    #   Build complete list of allowed platforms
8891
    #       Process additive rules before removal rules
8892
    #       If there are no additive rules, then assume all protaforms
241 dpurdie 8893
    #
6133 dpurdie 8894
    my %calcList;
8895
    @add = @::BUILDPLATFORMS unless @add;
6204 dpurdie 8896
    $calcList{uc $_} = 1 foreach (@add);
8897
    delete $calcList{uc $_} foreach (@remove);
6133 dpurdie 8898
#DebugDumpData("Add", \@add);
8899
#DebugDumpData("Remove", \@remove);
8900
#DebugDumpData("calcList", \%calcList);
241 dpurdie 8901
 
8902
    #
6133 dpurdie 8903
    #   If the current build target is left in the platform list, then we are building for it
8904
    #   
6198 dpurdie 8905
    if (exists $calcList{$scmplatform}) {
227 dpurdie 8906
        Debug3( " ActivePlatform(@_ == $ScmPlatform) = TRUE" );
8907
        return 1;
8908
    }
241 dpurdie 8909
 
227 dpurdie 8910
    Debug3( " ActivePlatform(@_ == $ScmPlatform) = FALSE" );
8911
    return 0;
8912
}
8913
 
8914
#-------------------------------------------------------------------------------
321 dpurdie 8915
# Function        : If
8916
#
8917
# Description     : Function for embedding arguments in directives
8918
#                   To be used within another directive
8919
#                   ie:
8920
#                       AnyDirective ('*',  arg1, arg2, ...
8921
#                                           If (SomePlatform, arg1, .. ,argn))
8922
#
7266 dpurdie 8923
# Inputs          : $platform               - Active Platform specifier
321 dpurdie 8924
#                   @args                   - Args
8925
#
8926
# Returns         : @args or nothing
8927
#
8928
sub  If
8929
{
8930
    my $platform = shift;
8931
    return @_
8932
        if ( ActivePlatform( $platform ));
8933
    return;
8934
}
8935
 
8936
#-------------------------------------------------------------------------------
227 dpurdie 8937
# Function        : RegisterMakefileGenerate
8938
#
8939
# Description     : Register a function to be called at the start of the
8940
#                   makefile generation process
8941
#
8942
# Inputs          : $fname      - Name of the function
8943
#                   $args       - Function Arguments
8944
#
8945
# Returns         : Nothing
8946
#
8947
our @MF_Generators;
8948
sub RegisterMakefileGenerate
8949
{
8950
   my ($fref) = @_;
8951
   my $rtype = ref($fref) || 'not a reference';
8952
 
8953
   Error ("RegisterMakefileGenerate called incorrectly",
8954
          "First argument MUST be a code reference",
8955
          "It is a $rtype"
8956
          ) unless ( $rtype eq 'CODE' );
8957
 
8958
   #
8959
   #    Save the arguments by reference in an array
8960
   #    The array will be processed later
8961
   #
8962
   push @MF_Generators, \@_;
8963
}
8964
 
8965
#-------------------------------------------------------------------------------
271 dpurdie 8966
# Function        : RegisterSrcHook
8967
#
8968
# Description     : Register a function to be called when a source file is
8969
#                   declared
8970
#
8971
# Inputs          : $ext        - Extension of interest
8972
#                                 '*' will be used by all
8973
#                   $fname      - Name of the function
8974
#                   $args       - Function Arguments
8975
#
8976
# Returns         : Nothing
8977
#
8978
sub RegisterSrcHook
8979
{
8980
    my $ext = shift;
8981
    my ($fref) = @_;
8982
    my $rtype = ref($fref) || 'not a reference';
8983
 
8984
    Error ("RegisterSrcHook called incorrectly",
8985
           "Second argument MUST be a code reference",
8986
           "It is a $rtype"
8987
           ) unless ( $rtype eq 'CODE' );
8988
 
8989
    #
8990
    #    Save the arguments by reference in an array
8991
    #    The array will be processed later
8992
    #
8993
    push @{$MF_RegisterSrcHooks{$ext}}, \@_;
8994
}
8995
 
8996
 
8997
#-------------------------------------------------------------------------------
227 dpurdie 8998
# Function        : MakefileHeader
8999
#
9000
# Description:    : Generate a "standard" makefile header.
9001
#
9002
#..
9003
 
9004
sub MakefileHeader
9005
{
9006
    my ($file, $desc, $by, @trailing) = @_;
9007
    my ($diff);
9008
 
9009
    $diff = 0 if (($diff = ((80-5) - length($desc))) < 0);
9010
    $desc .= ' ' . ('-' x $diff);
9011
 
9012
    print $file <<EOF;
9013
#-- $desc
9014
#
9015
#                   -- Please do not edit this file. --
9016
#
9017
#       To do so may result in a system failure, in additional to any
9018
#       changes made shall be overwritten.
9019
#
9020
# Created by $by
9021
#         on $::CurrentTime
9022
#
9023
EOF
9024
    #
9025
    #   Print out the trailer
9026
    #   This is an array. Place each entry on a new line
9027
    #
9028
    print $file $_ . "\n" for ( @trailing );
9029
}
9030
 
9031
###############################################################################
9032
# MakeFileGenerate:
9033
#       This subroutine does all of the actual make file generation based
9034
#       on information provided in the calls to the various public
9035
#       interface routines.
9036
#
9037
# Inputs:
9038
#
9039
# Returns:
9040
###############################################################################
9041
 
9042
my $MakefileGenerate_once = 0;
9043
sub MakefileGenerate
9044
{
9045
    my $Makefile = "$ScmPlatform.mk";
9046
    Debug( "MakefileGenerate: $Makefile" );
9047
 
9048
    #
9049
    #   Nasty things happen when we generate a makefile twice
9050
    #   Just warn the user and do nothing
9051
    #   If its in the common makefile.pl then just ignore it
9052
    #
9053
    if ( $ScmProcessingRootMake )
9054
    {
9055
        Warning ("MakefileGenerate directive is not allowed in common makefile.pl");
9056
        return;
9057
    }
9058
 
9059
    if ( $MakefileGenerate_once )
9060
    {
9061
        Warning ("MakefileGenerate should only be called once.",
9062
                 "Dir: $::Cwd");
9063
        return;
9064
    }
9065
    $MakefileGenerate_once = 1;
9066
 
9067
    #
9068
    #   Invoke all registered Makefile Generator functions
9069
    #   These allow clever directives to collect information to be
9070
    #   processed before the makefiles are created
9071
    #
9072
    while ( @MF_Generators )
9073
    {
9074
        Debug( "MakefileGenerate: Invoke RegisterMakefileGenerate function" );
9075
        my ($fname, @args) = @{shift @MF_Generators};
9076
        &$fname ( @args );
9077
    }
9078
 
9079
    #
9080
    #   Allow the toolset the opportunity to process all the collected data
9081
    #   before the makefile is created. This is optional
9082
    #
9083
    my( $if ) = MakeIf::Factory();              # build interface
9084
    $if->Preprocess();
9085
 
9086
    #
343 dpurdie 9087
    #   If we have supressed the Toolset use, then we need to sanity test
9088
    #   the use of the toolset
9089
    #
9090
    if ( $ScmNoToolsTest )
9091
    {
9092
        ReportError ("Building programs not supported with --NoToolset") if ( @PROGS || @TESTPROGS );
9093
        ReportError ("Building libraries not supported with --NoToolset") if ( @LIBS || @MLIBS || @SHLIBS );
9094
        ReportError ("Building projects not supported with --NoToolset") if ( %PROJECTS );
9095
        ErrorDoExit();
9096
    }
9097
 
9098
    #
227 dpurdie 9099
    #   Auto package the 'descpkg' file
9100
    #   If this makefile packages any files, then it can also package the descpkg file
9101
    #   The descpkg will be piggybacked into all makefiles that do a package
9102
    #
9103
    if ( %PACKAGE_FILES || %PACKAGE_HDRS || %PACKAGE_CLSS || %PACKAGE_LIBS
6387 dpurdie 9104
                        || %PACKAGE_SHLIBS || %PACKAGE_PROGS || @PACKAGE_DIRS )
227 dpurdie 9105
    {
251 dpurdie 9106
        Src ('*', 'descpkg') unless ($SRCS{ descpkg });
9107
        PackageFile ('*', 'descpkg');
227 dpurdie 9108
    }
9109
 
9110
    #
9111
    #   Some toolsets NEED a relative root
261 dpurdie 9112
    #   Note: At the moment ScmRoot is relative anyway, thus this code
9113
    #         does nothing
227 dpurdie 9114
    #
9115
    my $gbe_root = $::ScmRoot;
9116
    if ( $::UseRelativeRoot )
9117
    {
9118
        $gbe_root =  RelPath( $::ScmRoot );
9119
    }
9120
 
9121
    #
9122
    #   Now start to create the makefile
9123
    #
6133 dpurdie 9124
    ToolsetFiles::AddFile($Makefile);
285 dpurdie 9125
    open( MAKEFILE, '>', $Makefile ) || Error( "Cannot create $Makefile" );
227 dpurdie 9126
    ::MakefileHeader( *MAKEFILE,
9127
                      'Auto-generated Platform Dependent Makefile',
9128
                      "$ScmMakelib (version $ScmVersion)",
6177 dpurdie 9129
                      "# COPYRIGHT - VIX IP PTY LTD (\"VIX\"). ALL RIGHTS RESERVED.",
227 dpurdie 9130
                      '#',
9131
                      "# Located in $::Cwd",
9132
                      "# Platform $::ScmPlatform",
9133
                      '#' . ('-' x 79),
9134
                      );
9135
 
9136
    #
9137
    #   Ensure that some essential variables are set
9138
    #
9139
    print MAKEFILE <<EOF;
9140
#
9141
#   Validate essential environment variables
9142
#
9143
ifndef GBE_BIN
9144
    \$(error ERROR: GBE_BIN is not available)
9145
endif
9146
ifndef GBE_PERL
9147
    \$(error ERROR: GBE_PERL is not available)
9148
endif
9149
ifndef DEBUG
9150
    \$(error ERROR: DEBUG is not defined)
9151
endif
9152
EOF
9153
 
9154
 
9155
    print MAKEFILE <<EOF;
9156
 
9157
#
9158
#   Basic definitions
9159
#
343 dpurdie 9160
GBE_ROOT      := $gbe_root
9161
GBE_ROOT_ABS  := \$(abspath \$(GBE_ROOT))
9162
GBE_HOST      := $::ScmHost
9163
GBE_HOSTMACH  := $::GBE_MACHTYPE
9164
GBE_TARGET    := $::ScmTarget
9165
GBE_MACHTYPE  := $::ScmMachType
9166
GBE_PLATFORM  := $::ScmPlatform
9167
GBE_PBASE     := $::Pbase
9168
GBE_TYPE      := \$(if \$(findstring 1,\$(DEBUG)),D,P)
227 dpurdie 9169
EOF
9170
 
343 dpurdie 9171
MakePrint( "GBE_ARGS      := @ScmPlatformArgs\n" )
227 dpurdie 9172
    if ( scalar @ScmPlatformArgs );
9173
 
343 dpurdie 9174
MakePrint( "GBE_PRODUCT   := $ScmProduct\n" )
227 dpurdie 9175
    if ( $ScmProduct ne "" );
9176
 
343 dpurdie 9177
MakePrint( "GBE_OS_COMMON := $::BUILDINFO{$ScmPlatform}{OS_COMMON}\n" )
227 dpurdie 9178
    if ( exists($::BUILDINFO{$ScmPlatform}{OS_COMMON}) );
9179
 
9180
    print MAKEFILE <<EOF;
9181
 
9182
SHELL           := \$(GBE_BIN)/sh
9183
SHELLARGS       :=
9184
EXTENDED_LINE   := \$(GBE_BIN)/extend.lst
9185
export EXTENDED_LINE MAKE
9186
 
343 dpurdie 9187
MFLAGS           := --no-print --warn -r
9188
BUILDNAME        := $::ScmBuildName
9189
BUILDVER         := $::ScmBuildVersionFull
9190
BUILDVERNUM      := $::ScmBuildVersion
227 dpurdie 9191
BUILDPREVIOUSVER := $::ScmBuildPreviousVersion
343 dpurdie 9192
DEPLOYPATCH      := $ScmDeploymentPatch
9193
GBE_NOTOOLSTEST  := $ScmNoToolsTest
4781 dpurdie 9194
MAKEFILEUID      := $ScmMakeUid
9195
export MAKEFILEUID
227 dpurdie 9196
 
9197
#
9198
#   Ensure PWD is correctly set
9199
#
9200
PWD             := \$(CURDIR)
9201
export PWD
9202
 
261 dpurdie 9203
#
9204
#   NODEPEND    - Used to suppress generated dependency file checking
9205
#                 Mostly done in jmake.pl
9206
#   EXPERT      - Used to suppress dependency on this makefile
9207
#
9208
EOF
9209
 
285 dpurdie 9210
MakePrint( "EXPERT\t\t?= " . ($ScmExpert ? '1' : '0' ) . "\n" );
9211
MakePrint( "NODEPEND\t?= 0\n" );
261 dpurdie 9212
 
9213
print MAKEFILE <<EOF;
9214
 
9215
#
9216
#   SCM_MAKEFILE - The name of the file to depend upon
9217
#                  Supressed in EXPERT mode
9218
#
9219
ifneq (\$(EXPERT),0)
9220
SCM_MAKEFILE	:=
9221
else
9222
SCM_MAKEFILE	:= $Makefile
9223
endif
9224
EOF
9225
 
267 dpurdie 9226
#
9227
#   Setup the base directory for the packaging process
9228
#   When building a deployable package the base directory is changed to match
9229
#   that used by the deployment world. This is done so that the descpkg file
9230
#   can be created in the correct location
9231
#
9232
my  $PKGDIR = "pkg/$::Pbase";
9233
    $PKGDIR = "build/deploy" if ( $DEPLOYPACKAGE );
9234
Verbose("Setting PKGDIR: $PKGDIR");
9235
 
261 dpurdie 9236
print MAKEFILE <<EOF;
9237
 
227 dpurdie 9238
#--------- Targets -------------------------------------------------------------
9239
 
9240
.PHONY: 	default all build install package unpackage uninstall \\
9241
		clean unbuild clobber deploy
9242
 
373 dpurdie 9243
default:
227 dpurdie 9244
all:		install package deploy
9245
build:		make_init generate install_hdr depend make_lib \\
6387 dpurdie 9246
		install_lib make_install_shlib make_prog install_class install_dirs
227 dpurdie 9247
install:	build install_prog
6387 dpurdie 9248
package:	package_dirs package_files package_hdr package_lib package_shlib \\
9249
		package_prog package_class
227 dpurdie 9250
unpackage:	unpackage_class unpackage_prog unpackage_shlib \\
6387 dpurdie 9251
		unpackage_lib unpackage_hdr unpackage_files unpackage_dirs 
9252
uninstall:	uninstall_dirs uninstall_class uninstall_prog uninstall_shlib \\
227 dpurdie 9253
		uninstall_lib uninstall_hdr
9254
clean:		make_clean unmake_prog unmake_test unmake_lib unobj \\
261 dpurdie 9255
		undepend ungenerate rmlitter unmake_dir
227 dpurdie 9256
unbuild:	clean uninstall
6898 dpurdie 9257
clobber:	unpackage unbuild clobberfiles clobberdirs
227 dpurdie 9258
deploy:		install run_deploy
9259
 
9260
#--------- Macros --------------------------------------------------------------
9261
 
9262
OBJDIR		= \$(GBE_PLATFORM)\$(GBE_TYPE).OBJ
9263
LIBDIR		= \$(GBE_PLATFORM).LIB
9264
BINDIR		= \$(GBE_PLATFORM)\$(GBE_TYPE).BIN
9265
CLSDIR		= classes\$(GBE_TYPE)
9266
 
267 dpurdie 9267
PKGDIR		= \$(GBE_ROOT)/$PKGDIR
227 dpurdie 9268
INCDIR_PKG	= \$(PKGDIR)/include
9269
LIBDIR_PKG	= \$(PKGDIR)/lib
9270
BINDIR_PKG	= \$(PKGDIR)/bin
9271
CLSDIR_PKG	= \$(PKGDIR)/classes
4996 dpurdie 9272
UTFDIR_PKG	= \$(GBE_ROOT_ABS)/$PKGDIR/utfResults
227 dpurdie 9273
 
9274
LOCALDIR	= \$(GBE_ROOT)/local
9275
INCDIR_LOCAL	= \$(LOCALDIR)/inc
9276
LIBDIR_LOCAL	= \$(LOCALDIR)/lib
9277
BINDIR_LOCAL	= \$(LOCALDIR)/bin
9278
CLSDIR_LOCAL	= \$(LOCALDIR)/classes
9279
BINDIR_LOCAL_PATH = \$(GBE_ROOT_ABS)/local/bin/\$(GBE_PLATFORM)\$(GBE_TYPE)
9280
 
9281
INTERFACEDIR	= \$(GBE_ROOT)/$ScmInterface
9282
INCDIR_INTERFACE= \$(INTERFACEDIR)/include
9283
LIBDIR_INTERFACE= \$(INTERFACEDIR)/lib
9284
BINDIR_INTERFACE= \$(INTERFACEDIR)/bin
9285
CLSDIR_INTERFACE= \$(INTERFACEDIR)/classes
9286
 
9287
.SUFFIXES:		# Delete the default suffixes
9288
 
9289
EOF
9290
 
9291
    MakePrintList( \@DEFINES );
9292
    MakeNewLine();
9293
 
9294
#-------------------------------------------------------------------------------
9295
#
9296
#
261 dpurdie 9297
    MakeHeader ("Defines, flags and file sets");
227 dpurdie 9298
 
9299
    # Flags
6177 dpurdie 9300
    foreach my $opt ( sort keys %ScmCompilerOpts )
261 dpurdie 9301
    {
9302
        MakeDefEntry ( $opt, "=", $ScmCompilerOpts{$opt} );
9303
    }
227 dpurdie 9304
 
261 dpurdie 9305
    MakeDefEntry( "CFLAGS",         "=", \@CFLAGS, \@CFLAGS_PROD, \@CFLAGS_DEBUG );
9306
    MakeDefEntry( "CLINTFLAGS",     "=", \@CLINTFLAGS, \@CLINTFLAGS_PROD, \@CLINTFLAGS_DEBUG );
9307
    MakeDefEntry( "CDEPENDFLAGS",   "=", \@CFLAGS, \@CFLAGS_PROD, \@CFLAGS_DEBUG );
9308
    MakeDefEntry( "CXXFLAGS",       "=", \@CXXFLAGS, \@CXXFLAGS_PROD, \@CXXFLAGS_DEBUG );
9309
    MakeDefEntry( "CXXLINTFLAGS",   "=", \@CXXLINTFLAGS, \@CXXLINTFLAGS_PROD, \@CXXLINTFLAGS_DEBUG );
9310
    MakeDefEntry( "CXXDEPENDFLAG",  "=", \@CXXFLAGS, \@CXXFLAGS_PROD, \@CXXFLAGS_DEBUG );
267 dpurdie 9311
    MakeDefEntry( "ASFLAGS",        "=", \@ASFLAGS, \@ASFLAGS_PROD, \@ASFLAGS_DEBUG );
9312
    MakeDefEntry( "LDFLAGS",        "=", \@LDFLAGS, \@LDFLAGS_PROD, \@LDFLAGS_DEBUG );
227 dpurdie 9313
 
9314
 
9315
#-------------------------------------------------------------------------------
9316
#   
9317
#
261 dpurdie 9318
    MakeHeader ("Tool Search Path",
9319
                "Extend the PATH seen by all the tools to include",
9320
                "The tools/bin directories discovered in Packages" );
9321
    my $put_PATH;
9322
    my $put_LD_LIBRARY_PATH;
6504 dpurdie 9323
 
9324
    MakePrint( "PATH := \$(BINDIR_LOCAL_PATH)$::ScmPathSep\$(PATH)\n" );
9325
    $put_PATH = 1;
9326
 
261 dpurdie 9327
    for my $path ( ToolExtensionPaths() )
9328
    {
9329
        MakePrint( "PATH := $path$::ScmPathSep\$(PATH)\n" );
9330
        $put_PATH = 1;
227 dpurdie 9331
 
261 dpurdie 9332
        if ( $::ScmHost eq "Unix" )
9333
        {
227 dpurdie 9334
        MakePrint( "LD_LIBRARY_PATH ?= \n" );
9335
        MakePrint( "LD_LIBRARY_PATH := $path$::ScmPathSep\$(LD_LIBRARY_PATH)\n" );
261 dpurdie 9336
            $put_LD_LIBRARY_PATH =1;
9337
        }
227 dpurdie 9338
    }
9339
 
261 dpurdie 9340
    #   Export the appropriate environment variables
9341
    #   Note: Windows has an issue with PATH and Path
9342
    #         Haven't got to the bottom of it yet, but it would appear that DLL
9343
    #         searching uses Path and other stuff uses PATH. Not too sure how we
9344
    #         end up with two (or more in the environment)
9345
    #
9346
    #
9347
    if ( $put_LD_LIBRARY_PATH )
9348
    {
343 dpurdie 9349
        MakePrint( "export LD_LIBRARY_PATH\n" );
261 dpurdie 9350
    }
227 dpurdie 9351
 
261 dpurdie 9352
    if ( $put_PATH )
9353
    {
343 dpurdie 9354
        MakePrint( "Path := \$(PATH)\n" );
9355
        MakePrint( "export PATH Path\n" );
261 dpurdie 9356
    }
227 dpurdie 9357
 
9358
#-------------------------------------------------------------------------------
9359
#   
9360
#
261 dpurdie 9361
    MakeHeader ("Perl Module Search Path",
9362
                "Extend the PERL5LIB seen by invocations of perl");
227 dpurdie 9363
 
261 dpurdie 9364
    my $perl_module_found;
9365
    for my $path ( ToolExtensionPaths() )
227 dpurdie 9366
    {
6276 dpurdie 9367
        if (my @results =  glob( "$path/*.pm"))
261 dpurdie 9368
        {
6276 dpurdie 9369
            MakePrint( "PERL5LIB := $path$::ScmPathSep\$(PERL5LIB)\n" );
261 dpurdie 9370
            $perl_module_found = 1;
9371
        }
227 dpurdie 9372
    }
261 dpurdie 9373
    if ( $perl_module_found  )
9374
    {
227 dpurdie 9375
    MakePrint( "export PERL5LIB\n" );
261 dpurdie 9376
    }
227 dpurdie 9377
 
261 dpurdie 9378
#-------------------------------------------------------------------------------
227 dpurdie 9379
#   
9380
#
261 dpurdie 9381
    MakeHeader ("Include Search Paths",
367 dpurdie 9382
                "Package Include Paths for header files and libraries" );
227 dpurdie 9383
 
6177 dpurdie 9384
    MakeDefEntry( 'PINCDIRS'  , '=', '# includes');
9385
    MakeDefEntry( 'PINCDIRS_INTERFACE', '=', '# Interface includes');
9386
    MakeDefEntry( 'PINCDIRS_LOCAL', '=', '# Local includes');
9387
    MakeDefEntry( 'PLIBDIRS'  , '=', '# libraries');
9388
    MakeDefEntry( 'PLIBDIRS_INTERFACE', '=', '# Interface libraries');
9389
    MakeDefEntry( 'PLIBDIRS_LOCAL', '=', '# Local libraries');
367 dpurdie 9390
 
9391
    for my $package (@{$::ScmBuildPkgRules{$ScmPlatform} })
9392
    {
9393
        #
9394
        #   Skip the pseudo package that encapsulates the interface
9395
        #   directory. Currently the makefiles do this in a different
9396
        #   manner - to be resolved
9397
        #
9398
        #   Just comment out the lines so that the data is visible
9399
        #   Its a hint to make use of the data
9400
        #
9401
        my $prefix = '';
6177 dpurdie 9402
        my $suffix = '';
367 dpurdie 9403
        $prefix = '# ' if ( $package->{'TYPE'} eq 'build' );
9404
 
6177 dpurdie 9405
        #
9406
        #   The interface directory is a little bit different
9407
        #
9408
        my ($name,$base);
9409
        if ( $package->{'TYPE'} eq 'interface' ) {
9410
            $base = '$(INTERFACEDIR)';
9411
            $name = 'Interface Directory';
9412
            $suffix = '_INTERFACE';
9413
        } else {
9414
            $name = $package->{'NAME'} . '/' . $package->{'VERSION'};
9415
            $base = $package->{'ROOT'};
9416
        }
367 dpurdie 9417
 
1329 dpurdie 9418
        my @doc;
9419
        push (@doc, "From: $base");
9420
        push (@doc, 'BuildPkgArchive via Interface' )if $package->{'TYPE'} eq 'build' ;
367 dpurdie 9421
 
1329 dpurdie 9422
        MakeHeader ("Source: $name", @doc);
9423
 
367 dpurdie 9424
        #
9425
        #   List include and library directories
9426
        #   Note: Need the True Path for windows.
9427
        #       Some makefile functions (wildcard) only work as expected
9428
        #       if the case of the pathname is correct. Really only a problem
6177 dpurdie 9429
        #       with badly formed legacy packages where the Windows user
367 dpurdie 9430
        #       guessed at the package format.
9431
        #
9432
        #       The conversion to a TruePath is done when ScmBuildPkgRules
6177 dpurdie 9433
        #       is created. Create once, use many time.
367 dpurdie 9434
        #
6177 dpurdie 9435
        for my $type (qw (PINCDIRS PLIBDIRS) ) {
9436
            for my $path ( @{$package->{$type}} ) {
9437
                MakeDefEntry ( "$prefix$type$suffix", "+=", $base . $path);
367 dpurdie 9438
            }
9439
        }
9440
    }
9441
 
6177 dpurdie 9442
    #
9443
    #   Local Paths
9444
    #   These are a little bit special
9445
    #
9446
    MakeHeader ('Source: Local',  'From: Package Local');
9447
 
9448
    sub MakeLocalPaths 
9449
    {
9450
        my ($name, $root, $addRoot) = @_;
9451
        my @pathlist;
9452
 
9453
        foreach my $tag ( $ScmPlatform, $ScmProduct, $ScmTarget ) {
9454
            UniquePush( \@pathlist, "$root/$tag" ) if ( $tag );
9455
        }
9456
 
9457
        #   Add the root directory too
9458
        UniquePush( \@pathlist, $root) if $addRoot;
9459
 
9460
        MakeDefEntry ( $name , "+=", \@pathlist);
9461
    }
9462
 
9463
    MakeLocalPaths ( 'PINCDIRS_LOCAL', '$(INCDIR_LOCAL)', 1 );
9464
    MakeLocalPaths ( 'PLIBDIRS_LOCAL', '$(LIBDIR_LOCAL)', 0 );
9465
 
9466
 
367 dpurdie 9467
#-------------------------------------------------------------------------------
9468
#   
9469
#
9470
    MakeHeader ("Include Search Paths",
9471
                "Local Include Paths",
9472
                " LINKDIRS - Local include search path (short)",
9473
                " INCDIRS  - Include search path (complete)",
9474
                " NODEPDIRS - ",
9475
                " SRCDIRS - ",
9476
                " LIBDIRS - Library search path",
9477
 
9478
                );
9479
 
227 dpurdie 9480
    # Include search path
9481
    #
9482
    #   user-local
367 dpurdie 9483
    #   local
9484
    #   interface
9485
    #       BuildPkgArchive
9486
    #       LinkPkgArchive
227 dpurdie 9487
    #   user-global
9488
    #
9489
 
6177 dpurdie 9490
    MakeDefEntry ( "\nLINCDIRS",    "= ", \@L_INCDIRS );                    # .. Local
9491
    MakeDefEntry ( "LINCDIRS",      "+=", '$(PINCDIRS_LOCAL)');             # .. Sandbox local
9492
    MakeDefEntry ( "LINCDIRS",      "+=", '$(PINCDIRS_INTERFACE)');         # .. Sandbox interface
9493
    MakeDefEntry ( "LINCDIRS",      "+=", \@G_INCDIRS );                    # .. Global
227 dpurdie 9494
 
6177 dpurdie 9495
    MakeDefEntry ( "INCDIRS",  "= ", '$(LINCDIRS)' );                       # Local
9496
    MakeDefEntry ( "INCDIRS",  "+=", '$(PINCDIRS)' );                       # Package
9497
    MakeDefEntry ( "LINCDIRS", "+=", \@S_INCDIRS );                         # System
227 dpurdie 9498
 
9499
    # Source search path
9500
 
261 dpurdie 9501
    MakeDefEntry( "\nNODEPDIRS",        "=", \@NODEPDIRS );
227 dpurdie 9502
 
6177 dpurdie 9503
    MakeDefEntry( "\nSRCDIRS","= "  , [ @L_SRCDIRS, @G_SRCDIRS ] );         # Local
9504
    MakeDefEntry ( "SRCDIRS", "+=" , '$(PINCDIRS)' );                       # Package
9505
    MakeDefEntry ( "SRCDIRS", "+=" , \@S_INCDIRS );                         # System
227 dpurdie 9506
 
9507
    # Library search path
9508
    #
9509
    #   user-local
367 dpurdie 9510
    #   local
9511
    #   interface
9512
    #       BuildPkgArchive
9513
    #       LinkPkgArchive
227 dpurdie 9514
    #   user-global
6177 dpurdie 9515
    #   
9516
    #   Kludge Note:
9517
    #       The LIBDIRS path needs an element with a directory seperator in it
9518
    #       Needed by (broken) cmdfile o determine the file seperator to use
9519
    #       
227 dpurdie 9520
 
367 dpurdie 9521
    MakeDefEntry( "\nLIBDIRS",  "= ", '$(LIBDIR)' );                    # User Local
261 dpurdie 9522
    MakeDefEntry( "LIBDIRS",    "+=", \@L_LIBDIRS );                    # Local
6177 dpurdie 9523
    MakeDefEntry( "LIBDIRS",    "+=", '$(PLIBDIRS_LOCAL)' );            # Sandbox/local
9524
    MakeDefEntry( "LIBDIRS",    "+=", '$(PLIBDIRS_INTERFACE)' );        # Sandbox/interface
9525
    MakeDefEntry( "LIBDIRS",    "+=", '$(LIBDIR_INTERFACE)' );          # Kludge. See note above
261 dpurdie 9526
    MakeDefEntry( "LIBDIRS",    "+=", \@G_LIBDIRS );                    # Global
367 dpurdie 9527
    MakeDefEntry( "LIBDIRS",    "+=", '$(PLIBDIRS)' );                  # Package
261 dpurdie 9528
    MakeDefEntry( "LIBDIRS",    "+=", \@S_LIBDIRS );                    # System
227 dpurdie 9529
 
9530
#-------------------------------------------------------------------------------
9531
#
9532
#   Subdir creation and deletion
9533
#   Creation is done on the fly
9534
#   Deletion is done AFTER the toolset functions have been invoked to create the
9535
#   build artifacts so that the toolsets can create directories too
9536
 
9537
    MakeHeader ("Subdir creation");
9538
    CreateMkdirRules();
6177 dpurdie 9539
    MkdirRule( '$(OBJDIR)', 'OBJDIR', '--Extra=depend,depend.err' );    # Object build directory
2429 dpurdie 9540
    MkdirRule( '$(OBJDIR)/'.$_ ) foreach (@SHLIBS);                     # Shared library build directory
9541
    MkdirRule( '$(LIBDIR)', 'LIBDIR' );                                 # Library directory
9542
    MkdirRule( '$(BINDIR)', 'BINDIR' );                                 # Binary directory
227 dpurdie 9543
 
261 dpurdie 9544
    #
9545
    #   Create a directory for library merge tool to work within
9546
    #
9547
    MkdirRule( "\$(MLIBDIR)", 'MLIBDIR', '--Path=$(GBE_PLATFORM).MRG', '--RemoveAll' ) if (@MLIBS);
9548
 
227 dpurdie 9549
#-------------------------------------------------------------------------------
9550
#   Generate rules and recipes to create all the toolset specific parts
9551
#   This is done fairly early to allow the toolsets to extend various
9552
#   definitions that may be used later in the makefile construction
9553
#
9554
    MakeHeader ("Construct Programs");
9555
 
9556
    foreach my $i ( @PROGS )
9557
    {
289 dpurdie 9558
        my $pProg = $PROGS->Get($i);
9559
        my $pArgs = $pProg->getItems('ARGS');
9560
        my $pObjs = $pProg->getItems('OBJS');
9561
        my $pLibs = $pProg->getItems('LIBS');
227 dpurdie 9562
 
289 dpurdie 9563
        #
9564
        #   Create a list of program object files
9565
        #
9566
        push @PROGOBJS, @$pObjs;
227 dpurdie 9567
 
9568
        MakePrint( "#---- (${i})\n\n" );
9569
        if ( $ScmToolsetProgDependancies )
9570
        {
261 dpurdie 9571
            #
9572
            #   Original style Prog Interface
271 dpurdie 9573
            #   Write some dependency information here and some in the toolset
9574
            #   Problems:
9575
            #       1) Errors in library dependency generation will be
9576
            #          reported after all the object files have been created
9577
            #          Thus the error message and the make-stop are seperated
9578
            #          by many,many lines of output. This makes it difficult
9579
            #          to see the error.
261 dpurdie 9580
            #
271 dpurdie 9581
            #       2) Lack of Flexability
9582
            #
293 dpurdie 9583
            MakeEntry( "\$(BINDIR)/$i$::exe: ", "", "\\\n\t\t", ".$::o ", @$pObjs );
227 dpurdie 9584
        }
9585
        else
9586
        {
261 dpurdie 9587
            #
9588
            #   New Style Prog Interface
9589
            #   The toolset does it all
9590
            #
9591
            #   Flag the progam packaging as a placeholder.
9592
            #   The toolset will replace/update it.
9593
            #
227 dpurdie 9594
            PackageProgRemoveFiles( $i );
9595
        }
9596
 
289 dpurdie 9597
        $if->LD    ( $i, $pArgs, $pObjs, $pLibs );
9598
        $if->LDLINT( $i, $pArgs, $pObjs, $pLibs );
227 dpurdie 9599
    }
9600
 
9601
#-------------------------------------------------------------------------------
9602
#   
9603
#
9604
    MakeHeader ("Construct Test Programs");
289 dpurdie 9605
    foreach my $i ( @TESTPROGS )
227 dpurdie 9606
    {
289 dpurdie 9607
        my $pProg = $TESTPROGS->Get($i);
9608
        my $pArgs = $pProg->getItems('ARGS');
9609
        my $pObjs = $pProg->getItems('OBJS');
9610
        my $pLibs = $pProg->getItems('LIBS');
227 dpurdie 9611
 
289 dpurdie 9612
        #
9613
        #   Create a list of program object files
9614
        #
9615
        push @TESTPROGOBJS, @$pObjs;
9616
 
227 dpurdie 9617
        MakePrint( "#---- (${i})\n\n" );
9618
        if ( $ScmToolsetProgDependancies )
9619
        {
293 dpurdie 9620
            MakeEntry( "\$(BINDIR)/$i$::exe: ", "", "\\\n\t\t", ".$::o ", @$pObjs );
227 dpurdie 9621
        }
9622
        else
9623
        {
9624
            PackageProgRemoveFiles( $i );
9625
        }
9626
 
289 dpurdie 9627
        $if->LD    ( $i, $pArgs, $pObjs, $pLibs );
9628
        $if->LDLINT( $i, $pArgs, $pObjs, $pLibs );
227 dpurdie 9629
    }
9630
 
9631
#-------------------------------------------------------------------------------
9632
#
9633
#
9634
    MakeHeader ("Transfer Scripts to BINDIR");
9635
    foreach my $i ( sort ( values %SCRIPTS ))
9636
    {
9637
        my $tname = "\$(BINDIR)/" . StripDir( $i );
9638
 
9639
 
9640
        MakePrint( "$i:\t\tmakefile.pl\n" .
6177 dpurdie 9641
            "\t\$(XX_PRE)if [ ! -f \"$i\" ]; then echo 'Script [$i] not found'; exit 2; fi\n\n" );
227 dpurdie 9642
 
9643
        #
9644
        #   Create a rule to copy the script into the BIN directory
9645
        #   Mark the script as executable - It can't hurt and its there
9646
        #   to be run as part of a test.
9647
        #
9648
        MakePrint "$tname:\t\$(GBE_BINDIR) $i\n" .
9649
                  "\t\$(XX_PRE)\$(cp) -f $i $tname\n" .
9650
                  "\t\$(XX_PRE)\$(chmod) -f +wx $tname\n\n"
9651
    }
9652
 
9653
#-------------------------------------------------------------------------------
9654
#   
9655
#
9656
    MakeHeader ("Construct Libraries");
9657
    foreach my $i ( @LIBS )
9658
    {
289 dpurdie 9659
        my $pLib  = $LIBS->Get($i);
9660
        my $pArgs = $pLib->getItems('ARGS');
9661
        my $pObjs = $pLib->getItems('OBJS');
227 dpurdie 9662
 
363 dpurdie 9663
        unless ( $ScmToolsetNillLibSrc )
9664
        {
9665
            Error ("Library has no component objects: $i")
9666
                if ( scalar @$pObjs <= 0 );
9667
        }
299 dpurdie 9668
 
227 dpurdie 9669
        MakePrint "#---- (${i})\n\n";
289 dpurdie 9670
        $if->AR(     $i, $pArgs, $pObjs, $pLib);
9671
        $if->ARLINT( $i, $pArgs, $pObjs, $pLib );
227 dpurdie 9672
    }
9673
 
289 dpurdie 9674
#-------------------------------------------------------------------------------
9675
#   
9676
#
9677
    MakeHeader ("Construct Merged Libraries");
227 dpurdie 9678
    sub MlibEntry
9679
    {
289 dpurdie 9680
        my( $mlib, $plib, $pLibs ) = @_;
227 dpurdie 9681
        my @flib;
9682
 
289 dpurdie 9683
        MakePrint '$(LIBDIR)/' . GenLibName($mlib) . ":";
9684
        foreach my $lib ( @$pLibs )
227 dpurdie 9685
        {
289 dpurdie 9686
            #
9687
            #   Each library name may contains one embedded option which
9688
            #   specifies the source directory
9689
            #       libname[,--Option | BaseSubdir]
9690
            #
227 dpurdie 9691
            my ($slib, $sdir) = split( ',', $lib );
343 dpurdie 9692
            my $mode;
227 dpurdie 9693
 
9694
            #
283 dpurdie 9695
            #   By default the librares are pulled from LOCAL unless the
9696
            #   library is built in this directory, in which case it will
289 dpurdie 9697
            #   be used.
227 dpurdie 9698
            #
289 dpurdie 9699
            $sdir = ( $LIBS->Get($slib) ) ? '--Here' : '--Local'
9700
                unless ( $sdir );
227 dpurdie 9701
 
9702
            #
9703
            #   --Interface     - Pull library from the interface directory
9704
            #   --Local         - Pull library from the local directory
9705
            #   --SubDir=xxxx   - Pull library from specified subdirectory
283 dpurdie 9706
            #   --Here          - Pull from local directory if built locally
227 dpurdie 9707
            #   otherwise       - Pull library from specified subdirectory
9708
            #
9709
            if ($sdir eq '--Interface') {
9710
                $sdir = '$(LIBDIR_INTERFACE)/$(GBE_PLATFORM)';
9711
 
343 dpurdie 9712
 
9713
            } elsif ($sdir eq '--InterfacePlain') {
9714
                $sdir = '$(LIBDIR_INTERFACE)/$(GBE_PLATFORM)';
9715
                $mode = 1;
9716
 
227 dpurdie 9717
            } elsif ( $sdir eq '--Local') {
9718
                $sdir = $PackageInfo{'Lib'}{'IBase'} .  # Base of Installed libs
9719
                        $PackageInfo{'Lib'}{'Dir'};     # Default subdir
9720
 
9721
            } elsif ( $sdir =~ m~^--SubDir=(.*)~ ) {
9722
                $sdir = $1 . '/$(LIBDIR)';
9723
 
283 dpurdie 9724
            } elsif ( $sdir eq '--Here') {
9725
                $sdir = '$(LIBDIR)';
9726
 
227 dpurdie 9727
            } else {
9728
                $sdir .= '/$(LIBDIR)';
9729
            }
9730
 
343 dpurdie 9731
            MakePrint " \\\n\t\t${sdir}/" . GenLibName($slib, $mode);
227 dpurdie 9732
            push @flib, "${sdir}/${slib}";
9733
        }
289 dpurdie 9734
        return \@flib;
227 dpurdie 9735
    }
9736
 
9737
    foreach my $i ( @MLIBS )
9738
    {
289 dpurdie 9739
        my $pLib  = $MLIBS->Get($i);
9740
        my $pArgs = $pLib->getItems('ARGS');
9741
        my $pLibs = $pLib->getItems('LIBS');
227 dpurdie 9742
 
261 dpurdie 9743
        MakePrint "#---- (${i})\n\n";
9744
 
227 dpurdie 9745
        unless ( defined &ToolsetARMerge )
9746
        {
9747
            Warning( "Merging of libraries not supported in this toolset yet" );
9748
            Warning( "MergeLibrary: \"$i\" will not be created" );
9749
        }
9750
        else
9751
        {
9752
            #
9753
            #   Create the dependency rule
9754
            #       Target library : source library list
9755
            #           Recipe - generated by the toolset
9756
            #
289 dpurdie 9757
            foreach ( @$pArgs )
227 dpurdie 9758
            {
9759
                Warning( "Ignoring unknown argument to MergeLibrary. $_" );
9760
            }
289 dpurdie 9761
            $pLibs = MlibEntry( $i, $pLib, $pLibs );
9762
            $if->ARMerge( $i, $pArgs, $pLibs, $pLib );
227 dpurdie 9763
        }
9764
    }
9765
 
289 dpurdie 9766
#-------------------------------------------------------------------------------
9767
#   
9768
#
9769
    MakeHeader ("Construct Shared Libraries");
339 dpurdie 9770
 
227 dpurdie 9771
    foreach my $i ( @SHLIBS )
9772
    {
289 dpurdie 9773
        my $pShlib  = $SHLIBS->Get($i);
9774
        my $pArgs = $pShlib->getItems('ARGS');
9775
        my $pObjs = $pShlib->getItems('OBJS');
9776
        my $pLibs = $pShlib->getItems('LIBS');
9777
        my $version = $pShlib->{VERSION};
227 dpurdie 9778
 
289 dpurdie 9779
        $if->SHLD    ( $i, $pArgs, $pObjs, $pLibs, $version );
9780
        $if->SHLDLINT( $i, $pArgs, $pObjs, $pLibs, $version );
227 dpurdie 9781
    }
9782
 
9783
#-------------------------------------------------------------------------------
9784
#   Construct Objects
9785
#   For each object within OBJSOURCE construct the following:
9786
#
9787
#   $(OBJDIR)/object-name:     source-name [makefile]
9788
#       Toolset ...
9789
#
9790
#   
9791
#
9792
    MakeHeader ("Construct Objects");
371 dpurdie 9793
 
227 dpurdie 9794
    foreach my $i ( sort keys %OBJSOURCE )
9795
    {
9796
        my( $src, $sname, $ext, $type, @args );
9797
 
9798
        $src  = $OBJSOURCE{ $i };
9799
        $sname = StripDir( $src );
9800
        $ext  = StripFile( $src );
9801
        $ext = lc($ext)
9802
            if ( $::ScmHost ne "Unix" );
381 dpurdie 9803
        $type = ($ScmSourceTypes{ $ext } || '')
227 dpurdie 9804
            unless (( $type = $SRC_TYPE{ $sname }) );
9805
 
9806
        #
9807
        #   Object source is an object file
9808
        #   No need the generate the object, just create makefile rule
261 dpurdie 9809
        #   [ddp] Not too sure how we get here
227 dpurdie 9810
        #
9811
        if ( $ext eq ".$::o" )
9812
        {
9813
            MakePrint "$src:";
261 dpurdie 9814
            MakePrint " \$(SCM_MAKEFILE)";
227 dpurdie 9815
            MakeNewLine();
9816
            next;
9817
        }
9818
 
9819
        #
9820
        #   Need to create object file
9821
        #
9822
        @args = split( /$;/, $SRC_ARGS{ StripDir( $sname ) } )
9823
            if $SRC_ARGS{ $sname };
9824
 
9825
        push( @args, "--Shared" )
9826
            if ( exists $SHOBJ_LIB{$i} );
9827
 
9828
        #
9829
        #   Convert relative paths to absolute paths if required by the
9830
        #   toolset. Some compilers need ABS paths to generate nice debug
9831
        #   information.
9832
        #
9833
        $src = AbsPath($src)
9834
            if ( $UseAbsObjects );
9835
 
9836
        #
9837
        #   Extract any user specified dependancies
261 dpurdie 9838
        #   These will be added to the dependency list
227 dpurdie 9839
        #
9840
        my @dlist;
9841
        @dlist = split( /$;/, $SRC_DEPEND{$sname} )
9842
            if ( exists $SRC_DEPEND{$sname} );
9843
 
261 dpurdie 9844
        #
9845
        #   Create the dependency part of the object rule
9846
        #   The source file MUST be the first dependent recipes
9847
        #   may assume that $< is the name source file
9848
        #
9849
        MakeEntry( "\$(OBJDIR)/$i.$::o: $src \$(SCM_MAKEFILE)", "", " \\\n\t", "", @dlist );
227 dpurdie 9850
 
9851
        if ( $type eq ".c" ) {
9852
            $if->CC(  $src, $i, \@args );
261 dpurdie 9853
 
227 dpurdie 9854
        } elsif ( $type eq ".cc" ) {
9855
            $if->CXX( $src, $i, \@args );
261 dpurdie 9856
 
227 dpurdie 9857
        } elsif ( $type eq ".asm" ) {
9858
            $if->AS( $src, $i, \@args );
261 dpurdie 9859
 
227 dpurdie 9860
        } else {
9861
            $if->EXT( $src, $i, \@args ) ||
9862
                Warning( "Don't know how to build '$ext' images' for $src, $i" );
9863
            MakeNewLine();
9864
        }
9865
    }
9866
 
9867
#-------------------------------------------------------------------------------
9868
#   Construct Projects
9869
#   Construct toolset specific projects
9870
#
9871
    MakeHeader ("Construct Projects");
9872
    while ( my($project, $entry) = each %PROJECTS)
9873
    {
9874
        $if->PROJECT( $entry );
9875
    }
9876
 
9877
#-------------------------------------------------------------------------------
4761 dpurdie 9878
#   Automated tests
9879
#
9880
    MakeHeader ("Automated tests");
9881
 
9882
    my $idx = 0;
9883
    my @copy_set = ();
9884
 
227 dpurdie 9885
    foreach my $pEntry ( @TESTS_TO_RUN )
9886
    {                                           # Foreach test
9887
        $idx++;
9888
        $pEntry->{'index'} = $idx;
9889
        $pEntry->{'test_name'} = "run_test_$idx";
5708 dpurdie 9890
        $pEntry->{'echoname'} = $pEntry->{'utfname'} || '';  
4781 dpurdie 9891
        $pEntry->{'utfname'} = $pEntry->{'test_name'} unless defined $pEntry->{'utfname'};  
227 dpurdie 9892
 
9893
        #
9894
        #   If the test is being run within a 'FrameWork' then the underlying
9895
        #   toolset must instantiate the frame work.
9896
        #
9897
        #   This may change. Perhaps frameworks shouldn't be a part of the
9898
        #   toolset. Perhaps they should be standalone. May change
9899
        #
9900
        if ( $pEntry->{framework} )
9901
        {
9902
            $if->TESTFRAMEWORK( $pEntry );
9903
        }
9904
 
9905
        #
9906
        #   Create a rule to run the test
9907
        #
9908
 
9909
        my $tdir_alias = $pEntry->{'testdir'};
9910
        my $tdir = '$(' . $tdir_alias . ')';
9911
 
9912
        my $test_name = $pEntry->{'test_name'};
4996 dpurdie 9913
        push @TESTPROJECT_TO_URUN, $test_name;
4501 dpurdie 9914
        push @TESTPROJECT_TO_ARUN, $test_name if     ($pEntry->{'auto'} );
227 dpurdie 9915
 
9916
        my $tprog = $tdir . '/' . StripDir( $pEntry->{'prog'} );
5695 dpurdie 9917
 
9918
        #
9919
        #   Determine the maximum time that the automated test should run
9920
        #       Default is 30 minutes
9921
        #   Non-auto tests are not time limited
9922
        #       
9923
        my $timeout = '';
5848 dpurdie 9924
        if ($pEntry->{'auto'})
5695 dpurdie 9925
        {
5848 dpurdie 9926
            $timeout = 'timeout -Time:' . ($pEntry->{'maxtime'} || '30m') . ' ';
5695 dpurdie 9927
        }
227 dpurdie 9928
 
9929
        my $me = MakeEntry::New( *MAKEFILE, $test_name, '--Phony' );
4781 dpurdie 9930
 
9931
        #
4996 dpurdie 9932
        #   Export GBE_UTF... for the duration of the test
4781 dpurdie 9933
        #
9934
        $me->AddDefn('export GBE_UTFNAME', $pEntry->{'utfname'});
9935
        $me->AddDefn('export GBE_UTFUID', '$(MAKEFILEUID)' . '_' . $pEntry->{'index'});
4996 dpurdie 9936
        $me->AddDefn('export GBE_UTFFILE','$(UTFDIR_PKG)/$(GBE_PLATFORM)-$(GBE_TYPE)-$(GBE_UTFUID)' . '.xml');
6619 dpurdie 9937
        $me->AddDefn('export GBE_UTFTEST','TEST-$(GBE_UTFNAME)-$(GBE_TYPE)-$(GBE_UTFUID)' );
4781 dpurdie 9938
 
6619 dpurdie 9939
        #
9940
        #   A bit of a kludge for 'googletest'
9941
        #       If we have another kludge like then then consider placing this work into a module based on the filter name
9942
        #       with some sort of interface to allow the ENVvars and format and command line args to be massaged
9943
        #       
9944
        #   For googletest
6898 dpurdie 9945
        #       Set EnvVar and then post process with junit
6619 dpurdie 9946
        #
6628 dpurdie 9947
        if ($pEntry->{'utfformat'})
9948
        {
9949
            if ($pEntry->{'utfformat'} eq 'gtest') {
9950
                $pEntry->{'utfformat'} = 'junit';
9951
                $me->AddDefn('export GTEST_OUTPUT ', 'xml:${GBE_UTFTEST}.xml');
9952
            }
6619 dpurdie 9953
        }
9954
 
5986 dpurdie 9955
        # Workaround for dirsep under windows when being wrapped in a timeout
9956
        $me->AddDefn('dirsep', '$(dirsep)$(dirsep)') if ($timeout && ($::ScmHost ne "Unix"));
9957
 
227 dpurdie 9958
        $me->AddDependancy( "\$(GBE_$tdir_alias)" );
9959
        $me->AddDependancy( "\$(INTERFACEDIR)/set_$::ScmPlatform.sh" );
9960
        $me->AddDependancy( $tprog ) if $pEntry->{'copyprog'};
9961
        $me->AddDependancy( @{ $pEntry->{'copyin' } } );
9962
        $me->AddDependancy( map { $tdir . '/' . StripDir($_) } @{ $pEntry->{'copyonce' } } );
9963
        $me->AddDependancy( @{ $pEntry->{'preq'} } );
9964
        $me->RecipePrefix ('$(XX_PRE)');
5708 dpurdie 9965
        $me->RecipeWrapper( $timeout . 'sh -c \'', '\'') if $timeout;
9966
        $me->RecipeComment( "------ Running test [$idx] $pEntry->{'echoname'} ..." );
227 dpurdie 9967
 
9968
        #
4996 dpurdie 9969
        #   Create package utfResults directory
9970
        #       Simplify use of the file
9971
        #
9972
        $me->AddShellRecipe ( 'mkdir -p $(UTFDIR_PKG)' );
9973
 
9974
        #
227 dpurdie 9975
        #   Extend the PATH seen by the script to include the local/bin directory
9976
        #   Allows programs and tests that have been created elsewhere in the component
9977
        #   to be accessed within the script.
9978
        #
9979
        $me->AddShellRecipe ( ". \$(INTERFACEDIR)/set_$::ScmPlatform.sh" );
9980
 
9981
        #
9982
        #   Copy in the files that we need
9983
        #
9984
        foreach my $file ( @{$pEntry->{'copyin'}} )
9985
        {
9986
            my $dst = $tdir . '/' . StripDir( $file );
9987
            UniquePush( \@COPYIN, $dst );
9988
            UniquePush( \@copy_set, $file );
9989
            $me->AddShellRecipe ( "\$(cp) -f $file $dst" );
9990
            $me->AddShellRecipe ( "\$(chmod) -f +wx $dst" );
9991
        }
9992
 
9993
        #
4778 dpurdie 9994
        #   Insert any FrameWork Recipe bits
227 dpurdie 9995
        #
9996
        $me->AddShellRecipe ( @{$pEntry->{'ShellRecipe'}} );
9997
 
4781 dpurdie 9998
        #
9999
        #   Insert command
5035 dpurdie 10000
        #       Save result code to a known file
4781 dpurdie 10001
        #
227 dpurdie 10002
        $me->AddShellRecipe ( "cd $tdir" );
10003
        $me->AddShellRecipe ( ["GBE_TYPE=\$(GBE_TYPE)",
10004
                               "GBE_HOST=\$(GBE_HOST)",
10005
                               "GBE_ROOT=\$(GBE_ROOT_ABS)",
4095 dpurdie 10006
                               "PATH=.\\$::ScmPathSep\$(BINDIR_LOCAL_PATH)\\$::ScmPathSep\$\$PATH",
5708 dpurdie 10007
                               $pEntry->{'command'},
227 dpurdie 10008
                               @{$pEntry->{'args'}},
5035 dpurdie 10009
                               ] , 
10010
                               'echo $$? > utf.$${GBE_UTFUID}.rc' );
10011
 
10012
        #
10013
        #   Create the basic command line for 'jats_runutf'
10014
        #       Use the simplistic 'internal' filter unless the user has provided one
10015
        #
10016
        my @cmdline;
10017
        push @cmdline, '--';
10018
        push @cmdline, '$(VERBOSE_OPT)';
10019
        push @cmdline, '-filter=' . ($pEntry->{'utfformat'} || 'internal');
10020
        push @cmdline, '-root=$(GBE_ROOT_ABS)' ;
10021
        push @cmdline, "-dir=$tdir";
10022
        push @cmdline, '-target=$(GBE_PLATFORM)';
10023
        push @cmdline, '-pkgdir=$(PKGDIR)';
10024
        push @cmdline, '-local=$(LOCALDIR)';
10025
        push @cmdline, '-interface=$(INTERFACEDIR)';
7226 dpurdie 10026
        push @cmdline, "-rcfile=$tdir/utf.\$\${GBE_UTFUID}.rc";
6898 dpurdie 10027
        push @cmdline, map { '-arg='. $_ } @{$pEntry->{'utfargs' }};
5035 dpurdie 10028
 
10029
        #
10030
        #   Insert commands to post process the test results according to the specified formatter
10031
        #
10032
        $me->NewSection     ();
10033
        $me->SectionIfDef   ('UTF_POSTPROCESS');
10034
        $me->RecipePrefix   ('$(XX_PRE)');
6898 dpurdie 10035
        $me->AddOneRecipe   ( "\$(GBE_PERL) -Mjats_runutf -e processUtf", @cmdline );
4778 dpurdie 10036
 
227 dpurdie 10037
        $me->Print();
10038
 
10039
 
10040
        #
10041
        #   Create entries to handle the copy-once files
10042
        #
10043
        foreach my $file ( @{ $pEntry->{'copyonce' } } )
10044
        {
10045
            my $tname = $tdir . '/' . StripDir($file);
10046
            my $me = MakeEntry::New( *MAKEFILE, $tname  );
10047
            $me->AddDependancy( $file );
10048
            $me->AddRecipe ( "\$(call CopyFile,CopyIn,$tname,$file,$tdir,)"  );
10049
            $me->Print();
10050
 
10051
            UniquePush( \@COPYIN, $tname );
10052
            UniquePush( \@copy_set, $file );
10053
 
10054
        }
10055
    }
10056
 
10057
    #
10058
    #   Generate sanity test for each copyin script
10059
    #   Simply to provide a nice error message for generated scripts
10060
    #   that do not exist at run-time
10061
    #
10062
    test_copy_in:
10063
    foreach my $i ( @copy_set )
10064
    {
10065
        next if ( $SCRIPTS{$i} );
10066
        foreach (  @SHLIB_TARGETS )
10067
        {
10068
            next test_copy_in if ( $i eq $_ );
10069
        }
10070
        MakePrint( "\n$i:\t\tmakefile.pl\n" .
6177 dpurdie 10071
            "\t\@if [ ! -f \"$i\" ]; then echo 'ERROR: CopyIn Script [$i] not found'; exit 2; fi\n" );
227 dpurdie 10072
    }
10073
 
261 dpurdie 10074
#-------------------------------------------------------------------------------
10075
#   Deploy rules
10076
#
10077
MakeHeader ("Deploy Rules");
227 dpurdie 10078
 
261 dpurdie 10079
print MAKEFILE <<EOF;
10080
.PHONY:		run_deploy
10081
EOF
227 dpurdie 10082
 
261 dpurdie 10083
#
10084
#   Build up the deployfile.pl command line from the available pieces
10085
#
10086
my $command_file = "";
10087
my @command_line;
10088
 
10089
if ( %DEPLOYPACKAGE )
10090
{
10091
    $command_file = $DEPLOYPACKAGE{'cmdfile'};
10092
 
10093
    push @command_line, "\$(XX_PRE)\$(GBE_PERL) -w $command_file";
10094
    push @command_line, "-r \"\$(GBE_ROOT)\"";
10095
    push @command_line, "-n \"$DEPLOYPACKAGE{'name'}\"";
10096
    push @command_line, "-d \"$DEPLOYPACKAGE{'dir'}\"";
10097
    push @command_line, "-v \"\$(BUILDVER)\"";
10098
    push @command_line, "-t \"\$(GBE_TYPE)\"";
10099
    push @command_line, "-o \"\$(BUILDPREVIOUSVER)\"";
10100
    push @command_line, "-m \"\$(GBE_PLATFORM)\"";
10101
    push @command_line, "-g \"\$(GBE_TARGET)\"";
10102
    push @command_line, "-k \"\$(GBE_PRODUCT)\""        if ( $ScmProduct );
10103
    push @command_line, "-p \"\$(DEPLOYPATCH)\""        if ( $ScmDeploymentPatch );
10104
 
10105
}
10106
 
10107
MakeEntry( "run_deploy:\t$command_file\n", "\n", "\t\t", " \\\n", @command_line );
10108
 
227 dpurdie 10109
#-------------------------------------------------------------------------------
261 dpurdie 10110
#   Custom Rules
10111
#
10112
    MakeHeader ("Custom Rules");
10113
    MakePrintList ( \@RULES );
10114
 
10115
#-------------------------------------------------------------------------------
10116
#   Generated Files
10117
#
10118
    MakeHeader ("Generated Files");
10119
    MakePrint ("\n.PHONY: phony_generate\n\n" );
6898 dpurdie 10120
    my $generateMustAddTestPostProcess;
261 dpurdie 10121
    foreach my $i ( @GENERATE_FILES )
10122
    {
10123
        my $gen_tag = $i->{'index'};
6898 dpurdie 10124
        my $genName = 'generate_' . $gen_tag;
10125
 
10126
        my $me = MakeEntry::New( *MAKEFILE );
10127
        $me->AddComment    ('Generate Files');
10128
        $me->AddName(@{$i->{'gen'}});
10129
 
6415 dpurdie 10130
        #
10131
        #   Generate user-provided recipe names to allow the rule to be called by name.
10132
        #
10133
        my $recipeTag = $i->{'recipeTag'} || '';
10134
        my $recipeName = '';
10135
        my $recipeCleanName = '';
261 dpurdie 10136
 
6415 dpurdie 10137
        if ($recipeTag) {
10138
            $recipeName = $recipeTag;
10139
            $recipeCleanName = 'clean_' . $recipeTag;
10140
 
10141
            # for 'jats make help'
10142
            $ScmRecipeTags{$recipeTag} = defined $i->{'clean'} ? 1 : 0;
10143
 
6898 dpurdie 10144
            $me->Phony() ;
10145
            $me->AddName($recipeName);
6415 dpurdie 10146
        }
10147
 
261 dpurdie 10148
        #
263 dpurdie 10149
        #   If predelete is enabled, then create a list of files to delete
10150
        #
6898 dpurdie 10151
        if ( $i->{'predelete'}  ) {
10152
            $me->AddDefn("generate_gen_$gen_tag", join(' ', @{$i->{'gen'}} )  );
263 dpurdie 10153
        }
10154
 
6898 dpurdie 10155
        my $target = join (' ', @{$i->{'gen'}}, $recipeName);
263 dpurdie 10156
 
10157
        #
6898 dpurdie 10158
        #   If a UnitTest then insert runtime defs
10159
        #
10160
        if ($i->{'isautf'})
10161
        {
10162
            my $test_name = $i->{'gen'}[0];
10163
            $generateMustAddTestPostProcess = 1;
10164
 
10165
            push @TESTPROJECT_TO_URUN, $test_name;
10166
            push @TESTPROJECT_TO_ARUN, $test_name if ($i->{'utfauto'} );
10167
 
10168
            $me->AddComment    ('  This is a Unit Test');
10169
            $me->AddDefn('export GBE_UTFNAME', $test_name );
10170
            $me->AddDefn('export GBE_UTFUID', 'G$(MAKEFILEUID)' . '_' . $i->{'index'});
10171
            $me->AddDefn('export GBE_UTFFILE','$(UTFDIR_PKG)/$(GBE_PLATFORM)-$(GBE_TYPE)-$(GBE_UTFUID)' . '.xml');
10172
            $me->AddDefn('export GBE_UTFTEST','TEST-$(GBE_UTFNAME)-$(GBE_TYPE)-$(GBE_UTFUID)' );
10173
        }
10174
 
10175
        #
261 dpurdie 10176
        #   Generate the basic generate rule and recipe
10177
        #   together with the prerequisites
10178
        #
10179
        unless ( $i->{'clean'} && $i->{'shell'} )
10180
        {
6898 dpurdie 10181
            $me->AddDependancy(@{$i->{'preq'}});
10182
            $me->AddDependancy("phony_generate") if $i->{'preq_sus'};
10183
            $me->AddDependancy("\$(SCM_MAKEFILE)");
10184
            $me->RecipePrefix   ('$(AA_PRE)');
10185
            $me->AddRecipe("\$(echo) '[$i->{'text'}] generating..'");
10186
            $me->RecipePrefix   ('$(XX_PRE)');
10187
            $me->AddRecipe("\$(call RmFiles,generate_gen_$gen_tag)") if ( $i->{'predelete'}  );
261 dpurdie 10188
 
6898 dpurdie 10189
            if ($i->{'isautf'}) {
10190
                my $filter = $i->{'utfformat'} || 'internal';
10191
                my $uargs = join(' ', map { '-arg='. $_ } @{$i->{'utfargs' }});
10192
                my $tdir = $i->{'utfdir'} || '.';
10193
                $me->AddShellRecipe (  [
10194
                                       "PATH=.\\$::ScmPathSep\$(BINDIR_LOCAL_PATH)\\$::ScmPathSep\$\$PATH",
10195
                                       "\$(call $genName,)"
10196
                                       ] , 
10197
                                       'echo $$? > ${INTERFACEDIR}/utf.$${GBE_UTFUID}.rc',
10198
                                       "\$(call UtfPostProcess,$filter,$tdir,$uargs)" );
10199
 
10200
            } else {
10201
                $me->AddRecipe("\$(call $genName,)");
263 dpurdie 10202
            }
261 dpurdie 10203
        }
6898 dpurdie 10204
        $me->Print();
261 dpurdie 10205
 
10206
        #
10207
        #   Generate 'clean' rules and recipes
10208
        #
10209
        if ( $i->{'clean'} )
10210
        {
6898 dpurdie 10211
            my $me = MakeEntry::New( *MAKEFILE, "clean_$genName", '--Phony' );
10212
            $me->AddName($recipeCleanName) if $recipeCleanName;
10213
            $me->RecipePrefix('$(XX_PRE)');
10214
            $me->AddRecipe("-\$(call $genName,$i->{'clean'})");
10215
            $me->Print();
261 dpurdie 10216
        }
10217
 
10218
        #
10219
        #   Define a function to contain the body of the generation call
10220
        #   The first argument will be a 'clean' argument
10221
        #
6898 dpurdie 10222
        my $md = MakeEntry::New( *MAKEFILE, $genName, '--Define' );
10223
        if ( $i->{'shell'} ) {
10224
            $md->AddShellRecipe( @{$i->{'toolargs'}} );
10225
 
10226
        } else {
10227
            $md->AddOneRecipe( $i->{'tool'} . ' $1' ,@{$i->{'toolargs'}} );
261 dpurdie 10228
        }
6898 dpurdie 10229
        $md->Print();
261 dpurdie 10230
    }
10231
 
6898 dpurdie 10232
    if ($generateMustAddTestPostProcess)
10233
    {
10234
        #
10235
        #   Define the UTF post processing
10236
        #   Define amacro thattakes two arguments
10237
        #       $1 - name of the filter
10238
        #       $2 - Directory to process
10239
        #       $3 - additional arguments
10240
        #
10241
 
10242
        #
10243
        #   Create the basic command line for 'jats_runutf'
10244
        #       Use the simplistic 'internal' filter unless the user has provided one
10245
        #
10246
        my @cmdline;
10247
        push @cmdline, '--';
10248
        push @cmdline, '$(VERBOSE_OPT)';
10249
        push @cmdline, '-filter=$1';
10250
        push @cmdline, '-root=$(GBE_ROOT_ABS)' ;
10251
        push @cmdline, '-dir=$2';
10252
        push @cmdline, '-target=$(GBE_PLATFORM)';
10253
        push @cmdline, '-pkgdir=$(PKGDIR)';
10254
        push @cmdline, '-local=$(LOCALDIR)';
10255
        push @cmdline, '-interface=$(INTERFACEDIR)';
10256
        push @cmdline, '-rcfile=${INTERFACEDIR}/utf.$${GBE_UTFUID}.rc';
10257
        push @cmdline, '$3';
10258
 
10259
        #
10260
        #   Insert commands to post process the test results according to the specified formatter
10261
        #
10262
        my $me = MakeEntry::New( *MAKEFILE, 'UtfPostProcess', '--Define' );
10263
        $me->AddComment    ('Post Process a UNIT TEST');
10264
        $me->AddComment    ('  arg1 - utffile name');
10265
        $me->AddComment    ('  arg2 - Directory to start scan for Unit Test Results');
10266
        $me->AddComment    ('  arg3 - Additional arguments to the filter');
10267
        $me->SectionIfDef  ('UTF_POSTPROCESS');
10268
        $me->AddOneRecipe  ("\$(GBE_PERL) -Mjats_runutf -e processUtf", @cmdline );
10269
        $me->Print();
10270
    }
10271
 
10272
 
261 dpurdie 10273
#-------------------------------------------------------------------------------
10274
#   Toolset Post Processing
10275
#   Allow the toolset to perform any post processing, before we finally write
10276
#   out any definitions.
10277
#
10278
#   We will not interprete any more user directives, but new stuff may get added
10279
#
10280
#
10281
MakeHeader ("Toolset Post Processing");
10282
$if->Postprocess();
10283
 
10284
################################################################################
10285
#   All interactions with the toolset are now complete
10286
#   All lists are now complete
10287
#
10288
#   Can now create internal definitions
10289
#   
10290
################################################################################
10291
 
10292
    #
10293
    #   Would be nice if this would work
10294
    #   Unfortunatelty we still need $if for the CCDEPENDS and CTAGS work
10295
    #   These must be defined AFTER the definitions
10296
    #
10297
    #   Ideally we should construct our makefile in sections
10298
    #   and then we can order the sections when we write them out
10299
    #
10300
#$if = 0;                            # Ensure the MakeIf class is not called
10301
                                     # If this file is modified
10302
 
10303
#-------------------------------------------------------------------------------
227 dpurdie 10304
#   Sources
10305
#
10306
MakeHeader  ( "Sources");
10307
MakeDefEntry( "CSRCS",      "=",  \@CSRCS );
10308
MakeDefEntry( "CXXSRCS",    "=",  \@CXXSRCS );
10309
MakeDefEntry( "ASSRCS",     "=",  \@ASSRCS );
10310
 
10311
#-------------------------------------------------------------------------------
10312
#   Generated, Installed and Packaged components
10313
#
10314
MakeHeader  ("Generated, Installed and Packaged components");
10315
MakeDefEntry( "INITS",           "=",  \@INITS )   if ( @INITS );
10316
MakeDefEntry( "GENERATED",       "=",  \@GENERATED ) if ( @GENERATED );
10317
MakeDefEntry( "GENERATED_NOTSRC","=",  \@GENERATED_NOTSRC ) if ( @GENERATED_NOTSRC );
10318
MakeDefEntry( "GENERATEDCLEAN",  "=",  CreateNameList( 'clean_generate_', '', ListCleanGenerated() ));
10319
MakeDefEntry( "INSTALL_HDRS",    "=",  \%INSTALL_HDRS ) if ( %INSTALL_HDRS );
10320
MakeDefEntry( "INSTALL_CLSS",    "=",  \%INSTALL_CLSS ) if ( %INSTALL_CLSS );
10321
MakeDefEntry( "OBJS",            "=", CreateNameList( '$(OBJDIR)/', ".$::o", \@OBJS) );
10322
MakeDefEntry( "SHOBJS",          "=", CreateNameList( '$(OBJDIR)/', ".$::o", \%SHOBJ_LIB ));
289 dpurdie 10323
MakeDefEntry( "PROGOBJS",        "=", CreateNameList( '', ".$::o", \@PROGOBJS ));
10324
MakeDefEntry( "TESTPROGOBJS",    "=", CreateNameList( '', ".$::o", \@TESTPROGOBJS ));
10325
MakeDefEntry( "LIBS",            "=", $LIBS->AllTargets() ) if ($::a);
10326
MakeDefEntry( "MLIBS",           "=", $MLIBS->AllTargets() ) if ($::a);
227 dpurdie 10327
MakeDefEntry( "SHNAMES",         "=", \@SHLIBS );
10328
MakeDefEntry( "SHDIRS",          "=", CreateNameList( '$(OBJDIR)/', "", \@SHLIBS ));
10329
MakeDefEntry( "SHLIBS",          "=", \@SHLIB_TARGETS );
10330
MakeDefEntry( "SCRIPTS",         "=", CreateNameList( '$(BINDIR)/', "", \%SCRIPTS ));
10331
MakeDefEntry( "COPYIN",          "=", \@COPYIN );
289 dpurdie 10332
MakeDefEntry( "PROGS",           "=", $PROGS->AllTargets() );
227 dpurdie 10333
MakeDefEntry( "PROGS_EXTRA",     "=", \@PROGS_EXTRA );
289 dpurdie 10334
MakeDefEntry( "TESTPROGS",       "=", $TESTPROGS->AllTargets());
227 dpurdie 10335
MakeDefEntry( "LINTLIBS",        "=", CreateNameList( 'lib_', '_lint', \@LINTLIBS ));
10336
MakeDefEntry( "LINTSHLIBS",      "=", CreateNameList( 'shlib_', '_lint', \@LINTSHLIBS ));
10337
MakeDefEntry( "LINTPROGS",       "=", CreateNameList( 'prog_', '_lint', \@PROGS ));
289 dpurdie 10338
MakeDefEntry( "LINTPROGS",      "+=", CreateNameList( 'prog_', '_lint', \@TESTPROGS ));
227 dpurdie 10339
MakeDefEntry( "PROJECTS",        "=", CreateNameList( 'Project_', '', ListGeneratedProjects(1) ));
10340
MakeDefEntry( "PROJECTSGEN",     "=", CreateNameList( 'Project_', '', ListGeneratedProjects(0) ));
10341
MakeDefEntry( "PROJECTSCLEAN",   "=", CreateNameList( 'ProjectClean_', '', \%PROJECTS ));
10342
 
4501 dpurdie 10343
MakeDefEntry( "UNITTESTS",       "=", \@TESTPROJECT_TO_URUN );
10344
MakeDefEntry( "AUTOUNITTESTS",   "=", \@TESTPROJECT_TO_ARUN );
10345
 
4778 dpurdie 10346
MakeDefEntry( "AUTOUNITTESTS_PRE",    "=", \@TOOLSET_UTF_PRE );
10347
MakeDefEntry( "AUTOUNITTESTS_POST",   "=", \@TOOLSET_UTF_POST );
10348
MakeDefEntry( "AUTOUNITTESTS_COLLATE","=", \@TOOLSET_UTF_COLLATE );
10349
 
10350
 
261 dpurdie 10351
MakeHeader ("Toolset components");
10352
MakeDefEntry( "USERGENERATED",        "=", \@USERGENERATED )    if ( @USERGENERATED );
10353
MakeDefEntry( "TOOLSETGENERATED",     "=", \@TOOLSETGENERATED ) if ( @TOOLSETGENERATED );
10354
MakeDefEntry( "TOOLSETOBJS",          "=", \@TOOLSETOBJS )      if ( @TOOLSETOBJS );
10355
MakeDefEntry( "TOOLSETLIBS",          "=", \@TOOLSETLIBS )      if ( @TOOLSETLIBS );
10356
MakeDefEntry( "TOOLSETPROGS",         "=", \@TOOLSETPROGS )     if ( @TOOLSETPROGS );
10357
MakeDefEntry( "TOOLSETDIRS",          "=", \@TOOLSETDIRS )      if ( @TOOLSETDIRS );
10358
MakeDefEntry( "TOOLSETDIRTREES",      "=", \@TOOLSETDIRTREES )  if ( @TOOLSETDIRTREES );
6898 dpurdie 10359
MakeDefEntry( "TOOLSETCLOBFILES",      "=", \@CLOBBERFILES )    if ( @CLOBBERFILES );
10360
MakeDefEntry( "TOOLSETCLOBDIRS",       "=", \@CLOBBERDIRS )      if ( @CLOBBERDIRS );
227 dpurdie 10361
 
6898 dpurdie 10362
 
227 dpurdie 10363
#--------- Determine compiler flag groups to use ----------------------------
10364
#
10365
#   Allows the compiler options to be controlled for both the debug and
10366
#   the production builds. Allows control over
10367
#       1) Optimisations
10368
#       2) Debug Information
10369
#
10370
MakeHeader ("Determine compiler flag groups to use");
10371
 
10372
print MAKEFILE <<EOF;
10373
 
10374
ifneq "\$(DEBUG)" "1"
10375
USE_OPTIMISE	:= \$(PROD_USE_OPTIMISE)
10376
USE_DEBUGINFO	:= \$(PROD_USE_DEBUGINFO)
10377
else
10378
USE_OPTIMISE	:= \$(DEBUG_USE_OPTIMISE)
10379
USE_DEBUGINFO	:= \$(DEBUG_USE_DEBUGINFO)
10380
endif
10381
 
10382
EOF
10383
 
261 dpurdie 10384
#-------------------------------------------------------------------------------
10385
#   Source browsing tools
10386
#
10387
MakeHeader ("Source browsing tools");
10388
    print MAKEFILE <<EOF;
10389
.PHONY:			ctags
10390
ctags:
10391
EOF
10392
    $if->CTAGS()
10393
        if (@CSRCS || @CXXSRCS);
227 dpurdie 10394
 
261 dpurdie 10395
#-------------------------------------------------------------------------------
10396
#   Depend
10397
#   If we are build C or C++ source files then create rules and recipes
10398
#   to invoke a dependency generator.
227 dpurdie 10399
#
261 dpurdie 10400
#   NODEPEND is used to disable, at make-time, the dependency generation
10401
#   and inclusion process.
10402
#
10403
#
10404
MakeHeader ("Depend");
6133 dpurdie 10405
if ($::o && (@CSRCS || @CXXSRCS) && $ScmNotGeneric)
261 dpurdie 10406
{
10407
    $ScmDependTags = 1;
10408
    print MAKEFILE <<EOF;
10409
depend:			\$(OBJDIR)/depend
10410
 
10411
\$(OBJDIR)/depend:	\$(SCM_MAKEFILE) \$(GBE_OBJDIR)
10412
\$(OBJDIR)/depend:	\$(CSRCS) \$(CXXSRCS)
10413
ifeq (\$(NODEPEND),0)
6177 dpurdie 10414
	\@echo '[\$@] Doing a make depend..'
261 dpurdie 10415
	-\$(XX_PRE)\$(rm) -f \$(OBJDIR)/depend
10416
EOF
10417
    $if->CCDepend( "\$(OBJDIR)/depend", "\$(CSRCS)" )
10418
        if ( @CSRCS );
10419
    $if->CXXDepend( "\$(OBJDIR)/depend", "\$(CXXSRCS)" )
10420
        if ( @CXXSRCS );
10421
    MakePrint
10422
        "\t-\@\$(touch) -f \$(OBJDIR)/depend\n";
10423
    print MAKEFILE <<EOF;
10424
else
6177 dpurdie 10425
	\@echo '[\$@] Skipping make depend..'
261 dpurdie 10426
	-\$(XX_PRE)\$(rm) -f \$(OBJDIR)/depend
10427
endif
10428
EOF
10429
}
10430
else
10431
{
10432
    print MAKEFILE <<EOF;
10433
depend:
10434
EOF
10435
}
10436
 
10437
#
10438
#   Rule to unmake the depend file
2429 dpurdie 10439
#       No longer neeed.
10440
#       The file is deleted as a part of the OBJDIR cleanup
261 dpurdie 10441
#
10442
    print MAKEFILE <<EOF;
10443
 
10444
undepend:
10445
EOF
10446
 
10447
#--------- IFLAG Documentation -------------------------------------------------
10448
#
10449
#   IFLAG - iteration flag. This is setting by the calling process
10450
#                           and is a function of the phase being processed
227 dpurdie 10451
#       0   No external dependencies.
10452
#       1   Source dependency list.
261 dpurdie 10453
#       2   Shared library dependency list
10454
#       3   Application dependency list
227 dpurdie 10455
#
10456
#
261 dpurdie 10457
#--------- Dependencies --------------------------------------------------------
10458
#   Include the 'depend' file if required
10459
#
10460
    MakeHeader ("Dependency Inclusion");
10461
    print MAKEFILE <<EOF;
10462
ifeq (\$(NODEPEND),0)
10463
 ifdef IFLAG
10464
  ifneq "\$(IFLAG)" "0"
10465
-include	\$(OBJDIR)/depend
10466
  endif
227 dpurdie 10467
 endif
10468
endif
10469
 
10470
EOF
10471
 
10472
#-------------------------------------------------------------------------------
10473
#   Standard rules
10474
#
5991 dpurdie 10475
    MakeHeader ("Standard rules");
10476
    print MAKEFILE <<EOF;
373 dpurdie 10477
.PHONY:		make_clean
227 dpurdie 10478
make_clean:
10479
	-\@echo "Removing generated files (objects, libraries, binaries etc)";
10480
 
10481
.PHONY:		rmlitter
10482
rmlitter:
2429 dpurdie 10483
	-\$(AA_PRE)JatsFileUtil 'D0' 'Removing litter' '.' 'core' '*.bak' '*.tmp' '*.err'
227 dpurdie 10484
 
261 dpurdie 10485
.PHONY:		lint_init
10486
lint_init:
10487
 
227 dpurdie 10488
EOF
10489
 
261 dpurdie 10490
#
10491
#   Dependencies for 'make_init'
10492
#
10493
#
10494
my @initdep;
10495
push @initdep, '$(INITS)' if ( @INITS );
227 dpurdie 10496
 
261 dpurdie 10497
#
10498
#   Dependencies for 'make_dir'
10499
#
10500
my @mkdirdep;
289 dpurdie 10501
push @mkdirdep, '$(GBE_OBJDIR)' if ( @CSRCS || @CXXSRCS || @OBJS || @PROGOBJS || @TESTPROGOBJS );
261 dpurdie 10502
push @mkdirdep, '$(SHDIRS)'     if ( %SHOBJ_LIB || @SHLIBS);
10503
push @mkdirdep, '$(GBE_LIBDIR)' if ( @LIBS || @MLIBS || @SHLIBS || %INSTALL_LIBS || %PACKAGE_LIBS );
289 dpurdie 10504
push @mkdirdep, '$(GBE_BINDIR)' if ( @SHLIBS || %SCRIPTS || @PROGS || @TESTPROGS || %INSTALL_PROGS || %PACKAGE_PROGS );
227 dpurdie 10505
 
261 dpurdie 10506
#
10507
#   Actions for for 'unobj'
10508
#
10509
my @unobjact;
10510
push @unobjact, RmFilesCmd( 'OBJS' )            if ( @OBJS );
10511
push @unobjact, RmFilesCmd( 'SHOBJS' )          if ( %SHOBJ_LIB );
10512
push @unobjact, RmFilesCmd( 'PROGOBJS' )        if ( @PROGOBJS );
289 dpurdie 10513
push @unobjact, RmFilesCmd( 'TESTPROGOBJS' )    if ( @TESTPROGOBJS );
261 dpurdie 10514
push @unobjact, RmFilesCmd( 'TOOLSETOBJS' )     if ( @TOOLSETOBJS );
227 dpurdie 10515
 
261 dpurdie 10516
#
10517
#   Dependencies for 'make_lib'
10518
#
10519
my @libdep;
10520
push @libdep, '$(GBE_OBJDIR)', '$(GBE_LIBDIR)', '$(LIBS)' if ( @LIBS );
227 dpurdie 10521
 
261 dpurdie 10522
#
10523
#   Dependencies for 'lint_lib'
10524
#
10525
my @liblintdep;
10526
push @liblintdep, 'lint_init', '$(GBE_OBJDIR)', '$(GBE_LIBDIR)', '$(LINTLIBS)' if ( @LIBS );
227 dpurdie 10527
 
261 dpurdie 10528
#
10529
#   Dependencies for 'make_mlib'
10530
#
10531
my @mlibdep;
10532
push @mlibdep, '$(GBE_OBJDIR)', '$(GBE_LIBDIR)', '$(GBE_MLIBDIR)', '$(MLIBS)' if ( @MLIBS );
227 dpurdie 10533
 
261 dpurdie 10534
#
10535
#   Dependencies for 'make_install_shlib' (tag)
10536
#
10537
my @shlibdep;
10538
push @shlibdep, '$(SHDIRS)', '$(SHLIBS)' if ( @SHLIBS );
227 dpurdie 10539
 
261 dpurdie 10540
#
10541
#   Dependencies for 'lint_shlib'
10542
#
10543
my @shliblintdep;
10544
push @shliblintdep, 'lint_init', '$(GBE_LIBDIR)', '$(LINTSHLIBS)' if ( @SHLIBS );
227 dpurdie 10545
 
261 dpurdie 10546
#
10547
#   Actions for 'unmake_lib'
10548
#
10549
my @unlibact;
10550
push @unlibact, RmFilesCmd( 'SHLIBS' )      if ( @SHLIBS );
10551
push @unlibact, RmFilesCmd( 'MLIBS' )       if ( @MLIBS );
10552
push @unlibact, RmFilesCmd( 'LIBS' )        if ( @LIBS );
10553
push @unlibact, RmFilesCmd( 'TOOLSETLIBS' ) if ( @TOOLSETLIBS );
227 dpurdie 10554
 
261 dpurdie 10555
#
10556
#   Actions for 'unmake_mlib'
10557
#
10558
my @unmlibact;
10559
push @unmlibact, RmFilesCmd( 'MLIBS' ) if ( @MLIBS );
227 dpurdie 10560
 
261 dpurdie 10561
#
10562
#   Dependencies for 'make_script'
10563
#
10564
my @scriptdep;
10565
push @scriptdep, '$(GBE_BINDIR)', '$(SCRIPTS)' if ( %SCRIPTS );
227 dpurdie 10566
 
261 dpurdie 10567
#
10568
#   Actions for 'unmake_script'
10569
#
10570
my @unscriptact;
10571
push @unscriptact , RmFilesCmd( 'SCRIPTS' ) if ( %SCRIPTS );
10572
push @unscriptact , RmFilesCmd( 'COPYIN' )  if ( @COPYIN );
227 dpurdie 10573
 
261 dpurdie 10574
#
10575
#   Dependencies for 'make_prog'
10576
#
10577
my @progdep;
10578
push @progdep, '$(GBE_OBJDIR)', '$(GBE_BINDIR)', '$(PROGS)' if ( @PROGS );
10579
push @progdep, '$(PROGS_EXTRA)' if (@PROGS_EXTRA);
227 dpurdie 10580
 
261 dpurdie 10581
#
10582
#   Dependencies for 'make_prog' created for 'projects'
10583
#
10584
my @projectdep;
10585
push @projectdep, '$(PROJECTS)' if (ListGeneratedProjects(1) );
227 dpurdie 10586
 
261 dpurdie 10587
#
10588
#   Dependencies for 'generate' created for 'projects'
10589
#
10590
my @projectgendep;
10591
push @projectgendep, '$(PROJECTSGEN)' if (ListGeneratedProjects(0) );
227 dpurdie 10592
 
261 dpurdie 10593
#
10594
#   Dependencies for 'unmake_prog' created for 'projects'
10595
#
10596
my @projectcleandep;
10597
push @projectcleandep, '$(PROJECTSCLEAN)' if (%PROJECTS);
227 dpurdie 10598
 
261 dpurdie 10599
#
10600
#   Dependencies for 'lint_prog'
10601
#
10602
my @proglintdep;
289 dpurdie 10603
push @proglintdep, 'lint_init', '$(GBE_OBJDIR)', '$(GBE_BINDIR)', '$(LINTPROGS)' if ( @PROGS || @TESTPROGS );
227 dpurdie 10604
 
261 dpurdie 10605
#
10606
#   Actions for 'unmake_prog'
10607
#
10608
my @unprogact;
10609
push @unprogact, RmFilesCmd( 'PROGS' )        if ( @PROGS );
10610
push @unprogact, RmFilesCmd( 'TOOLSETPROGS' ) if ( @TOOLSETPROGS );
227 dpurdie 10611
 
261 dpurdie 10612
#
4728 dpurdie 10613
#   Dependencies for 'exec_tests'
261 dpurdie 10614
#
10615
my @testprogdep;
289 dpurdie 10616
push @testprogdep, '$(GBE_OBJDIR)', '$(GBE_BINDIR)', '$(TESTPROGS)' if ( @TESTPROGS );
227 dpurdie 10617
 
4501 dpurdie 10618
my @autoruntestdep;
10619
push @autoruntestdep, 'makefile.pl', '$(AUTOUNITTESTS)' if ( @TESTPROJECT_TO_ARUN );
10620
 
10621
my @runtestdep;
4996 dpurdie 10622
push @runtestdep    , 'makefile.pl', '$(UNITTESTS)' if ( @TESTPROJECT_TO_URUN );
4501 dpurdie 10623
 
227 dpurdie 10624
#
4728 dpurdie 10625
#   Dependencies for 'exec_tests' and friends
261 dpurdie 10626
#
10627
my @untestprogact;
289 dpurdie 10628
push @untestprogact ,RmFilesCmd( 'TESTPROGS' ) if ( @TESTPROGS );
227 dpurdie 10629
 
261 dpurdie 10630
#
10631
#   Dependencies for 'generated'
10632
#
10633
my @generatedep;
10634
push @generatedep, '$(GENERATED)' if ( @GENERATED );
10635
 
10636
#
10637
#   Actions for 'ungenerate'
10638
#
10639
my @ungenact;
10640
push @ungenact, RmFilesCmd( 'GENERATED' ) if ( @GENERATED );
10641
push @ungenact, RmFilesCmd( 'GENERATED_NOTSRC' ) if ( @GENERATED_NOTSRC );
10642
push @ungenact, RmFilesCmd( 'TOOLSETGENERATED' ) if ( @TOOLSETGENERATED );
10643
push @ungenact, RmFilesCmd( 'USERGENERATED' ) if ( @USERGENERATED );
10644
 
10645
#
10646
#   Dependencies for 'ungenerate'
10647
#
10648
my @ungeneratedep;
10649
push @ungeneratedep, '$(GENERATEDCLEAN)';
10650
 
6898 dpurdie 10651
#
10652
#   Actions for clobberfiles
10653
#   
10654
my @clobberfiles;
10655
push @clobberfiles, RmFilesCmd('TOOLSETCLOBFILES') if (@CLOBBERFILES); 
10656
 
227 dpurdie 10657
#-------------------------------------------------------------------------------
261 dpurdie 10658
# Function        : PrintPhonyRule
227 dpurdie 10659
#
261 dpurdie 10660
# Description     : Helper function to print some internal phony makefile targets
10661
#                   These are used to hold the basic makefile together
10662
#
10663
# Inputs          : $target         - Name of the phony target
10664
#                   $prereq         - Prerequisites
10665
#                                     Leading spaces removed
10666
#                   $recipe         - Optional Reference to an array of recipes
10667
#                                     Will be printed one per line
10668
#
10669
#
10670
sub PrintPhonyRule
227 dpurdie 10671
{
261 dpurdie 10672
    my ($target, $prereq, $recipe) = @_;
10673
    $prereq =~ s/^\s+//;
227 dpurdie 10674
 
261 dpurdie 10675
    MakePadded( 2, '.PHONY:', $target, "\n");
10676
    MakePadded( 2,"$target:", $prereq, "\n");
10677
    MakePrint ("\t\t" . $_ . "\n") foreach ( @{$recipe} );
10678
    MakePrint ("\n");
227 dpurdie 10679
}
10680
 
261 dpurdie 10681
#   make_init - Test toolset presence and sanity
10682
#   Will only be called ONCE for each platform in a recursive build
10683
#   Should be used to ensure that the required toolset is present
10684
#
4778 dpurdie 10685
PrintPhonyRule ('make_init',            "@initdep" );
227 dpurdie 10686
 
261 dpurdie 10687
#   make_dir    - Create required subdirectories
10688
#   Will be invoked as a part of most targets that create files
10689
#   Will be invoked by the calling wrappers
10690
#   Should not be invoked when cleaning
10691
#
4778 dpurdie 10692
PrintPhonyRule ('make_dir',             "@mkdirdep" );
261 dpurdie 10693
 
4778 dpurdie 10694
PrintPhonyRule ('generate',             "@generatedep @projectgendep" );
10695
PrintPhonyRule ('ungenerate',           "@ungeneratedep",  \@ungenact);
10696
PrintPhonyRule ('unobj',                "",  \@unobjact);
10697
PrintPhonyRule ('make_lib',             "@libdep" );
10698
PrintPhonyRule ('lint_lib',             "@liblintdep" );
10699
PrintPhonyRule ('make_mlib',            "@mlibdep" );
10700
PrintPhonyRule ('lint_shlib',           "@shliblintdep" );
10701
PrintPhonyRule ('unmake_lib',           "", \@unlibact );
10702
PrintPhonyRule ('unmake_mlib',          "", \@unmlibact );
10703
PrintPhonyRule ('make_script',          "@scriptdep" );
10704
PrintPhonyRule ('unmake_script',        "", \@unscriptact );
10705
PrintPhonyRule ('make_prog',            "make_script @progdep @projectdep" );
10706
PrintPhonyRule ('unmake_prog',          "unmake_script @projectcleandep", \@unprogact );
10707
PrintPhonyRule ('lint_prog',            "@proglintdep" );
10708
PrintPhonyRule ('exec_tests',           "make_script @testprogdep @runtestdep" );
10709
PrintPhonyRule ('exec_unit_tests',      "make_script @testprogdep @autoruntestdep" );
10710
PrintPhonyRule ('make_test',            "make_script @testprogdep" );
10711
PrintPhonyRule ('unmake_test',          "unmake_script", \@untestprogact );
10712
PrintPhonyRule ('preprocess_tests',     '$(AUTOUNITTESTS_PRE)' );
10713
PrintPhonyRule ('postprocess_tests',    '$(AUTOUNITTESTS_POST)' );
10714
PrintPhonyRule ('collate_test_results', '$(AUTOUNITTESTS_COLLATE)' );
6898 dpurdie 10715
PrintPhonyRule ('clobberfiles',         "",\@clobberfiles );
261 dpurdie 10716
 
227 dpurdie 10717
#-------------------------------------------------------------------------------
10718
#   Package and Installation Summary
10719
#
10720
    MakeHeader ("Package and Installation Summary");
10721
    sub InstallTarget
10722
    {
10723
        my( $target, $hashp, $prereq, $fprereq ) = @_;
10724
        my( $element );
10725
 
5991 dpurdie 10726
        my $me = MakeEntry::New( *MAKEFILE, $target, '--Phony' );
10727
        $me->AddDependancy( $fprereq ) if ($fprereq);
227 dpurdie 10728
        foreach my $element ( sort keys %{$hashp} )
10729
        {
10730
            #
10731
            #   Skip placekeepers
10732
            #
10733
            next if ( $hashp->{$element}{'placekeeper'} );
10734
 
10735
            #
10736
            #   Prepend any prerequisites (once)
10737
            #
5991 dpurdie 10738
            $me->AddDependancy( $prereq ) if ( $prereq );
10739
            $prereq = 0;
227 dpurdie 10740
 
5991 dpurdie 10741
            $me->AddDependancyEscaped( $element );
227 dpurdie 10742
        }
5991 dpurdie 10743
        $me->Print();
10744
 
227 dpurdie 10745
    }
10746
 
10747
InstallTarget( "install_hdr",       \%INSTALL_HDRS );
10748
InstallTarget( "install_lib",       \%INSTALL_LIBS,  'make_mlib' );
261 dpurdie 10749
InstallTarget( "make_install_shlib",\%INSTALL_SHLIBS, '', "@shlibdep" );
227 dpurdie 10750
InstallTarget( "install_prog",      \%INSTALL_PROGS, 'make_script' );
10751
InstallTarget( "install_class",     \%INSTALL_CLSS );
10752
 
10753
InstallTarget( "package_files",     \%PACKAGE_FILES );
10754
InstallTarget( "package_hdr",       \%PACKAGE_HDRS );
10755
InstallTarget( "package_lib",       \%PACKAGE_LIBS );
10756
InstallTarget( "package_shlib",     \%PACKAGE_SHLIBS );
10757
InstallTarget( "package_prog",      \%PACKAGE_PROGS, 'make_script' );
10758
InstallTarget( "package_class",     \%PACKAGE_CLSS );
10759
 
10760
#-------------------------------------------------------------------------------
10761
#   Installations
10762
 
10763
MakeHeader ("Installations");
6387 dpurdie 10764
PackageRule    ( \&InstallCmd, \%INSTALL_HDRS  );
10765
PackageRule    ( \&InstallCmd, \%INSTALL_CLSS  );
10766
PackageRule    ( \&InstallCmd, \%INSTALL_LIBS  );
10767
PackageRule    ( \&InstallCmd, \%INSTALL_SHLIBS  );
10768
PackageRule    ( \&InstallCmd, \%INSTALL_PROGS  );
10769
PackageDirRule ('install_dirs',    \@INSTALL_DIRS);
227 dpurdie 10770
 
10771
#-------------------------------------------------------------------------------
10772
#   Packaging
10773
#
10774
MakeHeader ("Packaging");
6387 dpurdie 10775
PackageRule    ( \&PackageCmd, \%PACKAGE_FILES );
10776
PackageRule    ( \&PackageCmd, \%PACKAGE_HDRS );
10777
PackageRule    ( \&PackageCmd, \%PACKAGE_CLSS );
10778
PackageRule    ( \&PackageCmd, \%PACKAGE_LIBS );
10779
PackageRule    ( \&PackageCmd, \%PACKAGE_SHLIBS );
10780
PackageRule    ( \&PackageCmd, \%PACKAGE_PROGS );
10781
PackageDirRule ('package_dirs', \@PACKAGE_DIRS);
227 dpurdie 10782
 
10783
#-------------------------------------------------------------------------------
10784
#   Uninstall/unpackaging
10785
#
10786
MakeHeader ("Uninstall/unpackaging");
10787
 
6387 dpurdie 10788
UnpackageRule  ( 'uninstall_hdr',         \&UninstallCmd, \%INSTALL_HDRS );
10789
UnpackageRule  ( 'uninstall_lib',         \&UninstallCmd, \%INSTALL_LIBS );
10790
UnpackageRule  ( 'uninstall_shlib',       \&UninstallCmd, \%INSTALL_SHLIBS );
10791
UnpackageRule  ( 'uninstall_prog',        \&UninstallCmd, \%INSTALL_PROGS );
10792
UnpackageRule  ( 'uninstall_class',       \&UninstallCmd, \%INSTALL_CLSS );
10793
PackageDirRule ( 'uninstall_dirs',        \@INSTALL_DIRS);
227 dpurdie 10794
 
6387 dpurdie 10795
UnpackageRule  ( 'unpackage_files',       \&UnpackageCmd, \%PACKAGE_FILES );
10796
UnpackageRule  ( 'unpackage_hdr',         \&UnpackageCmd, \%PACKAGE_HDRS );
10797
UnpackageRule  ( 'unpackage_lib',         \&UnpackageCmd, \%PACKAGE_LIBS );
10798
UnpackageRule  ( 'unpackage_shlib',       \&UnpackageCmd, \%PACKAGE_SHLIBS );
10799
UnpackageRule  ( 'unpackage_prog',        \&UnpackageCmd, \%PACKAGE_PROGS );
10800
UnpackageRule  ( 'unpackage_class',       \&UnpackageCmd, \%PACKAGE_CLSS );
10801
PackageDirRule ( 'unpackage_dirs',        \@PACKAGE_DIRS);
227 dpurdie 10802
 
261 dpurdie 10803
#-------------------------------------------------------------------------------
267 dpurdie 10804
#   Distribution Sets
261 dpurdie 10805
#
267 dpurdie 10806
MakeHeader ("Distribution Sets");
10807
PackageSetRules();
10808
 
10809
#-------------------------------------------------------------------------------
10810
#
261 dpurdie 10811
#   Subdir deletion
10812
#   This is done AFTER the toolset functions have been invoked to create the
10813
#   build artifacts so that the toolsets can create directories too
10814
#
10815
#   Note: Toolset directories are deleted first
10816
#   Note: User Directories are deleted in the reverse order of creation
10817
#
2429 dpurdie 10818
#   Add them into the directory data structure
10819
#
10820
    foreach my $path ( @TOOLSETDIRS )
10821
    {
10822
        MkdirRule( $path, '', '--NoCreate' );
10823
    }
10824
 
10825
    foreach my $path ( @TOOLSETDIRTREES )
10826
    {
10827
        MkdirRule( $path, '', '--NoCreate' , '--RemoveAll');
10828
    }
10829
 
261 dpurdie 10830
    MakeHeader ("Subdir deletion");
10831
    RmdirRules();
6898 dpurdie 10832
    ClobberDirsRule();
261 dpurdie 10833
    MakeNewLine();
227 dpurdie 10834
 
261 dpurdie 10835
#--------- Toolset Rules -------------------------------------------------------
10836
    MakeHeader ("Toolset Rules");
10837
    MakePrintList ( \@TOOLSETRULES );
10838
 
10839
#--------- Maketags ------------------------------------------------------------
227 dpurdie 10840
 
10841
    Maketag( "make_init",           @INITS );
261 dpurdie 10842
    Maketag( "make_dir",            @mkdirdep );
10843
    Maketag( "generate",            @generatedep || @projectgendep || @USERGENERATED || ($ScmToolsetGenerate != 0) );
227 dpurdie 10844
    Maketag( "depend",              $ScmDependTags != 0 );
261 dpurdie 10845
    Maketag( "make_lib",            @libdep );
10846
    Maketag( "make_mlib",           @mlibdep );
10847
    Maketag( "make_install_shlib",  %INSTALL_SHLIBS || @shlibdep);
10848
    Maketag( "make_script",         @scriptdep );
10849
    Maketag( "make_prog",           @progdep || @projectdep );
10850
    Maketag( "make_test",           @testprogdep );
4996 dpurdie 10851
    Maketag( "exec_tests",          $TESTS_TO_RUN     || @TESTPROJECT_TO_URUN );
4728 dpurdie 10852
    Maketag( "exec_unit_tests",     $TESTS_TO_AUTORUN || @TESTPROJECT_TO_ARUN );
4778 dpurdie 10853
    Maketag( "process_tests",       @TOOLSET_UTF_PRE || @TOOLSET_UTF_POST || @TOOLSET_UTF_COLLATE);
227 dpurdie 10854
    Maketag( "install_hdr",         %INSTALL_HDRS );
10855
    Maketag( "install_class",       %INSTALL_CLSS );
10856
    Maketag( "install_lib",         %INSTALL_LIBS );
10857
    Maketag( "install_prog",        %INSTALL_PROGS );
6387 dpurdie 10858
    Maketag( "install_dirs",        @INSTALL_DIRS );
227 dpurdie 10859
    Maketag( "deploy",              %DEPLOYPACKAGE );
10860
    Maketag( "package",             %PACKAGE_FILES || %PACKAGE_HDRS || %PACKAGE_CLSS ||
10861
                                    %PACKAGE_LIBS || %PACKAGE_SHLIBS || %PACKAGE_PROGS );
10862
 
261 dpurdie 10863
    #
10864
    #   Display tags in the MAKEFILE
4778 dpurdie 10865
    #       Not used here - just for show
261 dpurdie 10866
    #
10867
    MakeHeader ("Maketags");
10868
    foreach my $tag ( sort keys %MakeTags )
10869
    {
4778 dpurdie 10870
        MakePadded( 3, "#   $tag:", '1', "\n");
261 dpurdie 10871
    }
10872
 
227 dpurdie 10873
#-------------------------------------------------------------------------------
10874
#   End of Makefile
10875
#
10876
    MakeHeader ("End of Makefile");
10877
    close( MAKEFILE );
10878
 
10879
#
10880
#   Save all platform information
10881
#   Done after the makefile is written as toolsets can extend the data
10882
#
10883
    WriteParsedConfig();
10884
 
10885
#
10886
#   Write out any accumulated DPACKAGE data
10887
#
10888
    JatsDPackage::DPackageSave();
10889
 
10890
    return 0;
10891
}
10892
 
10893
#-------------------------------------------------------------------------------
387 dpurdie 10894
# Function        : QuoteForMake
10895
#
10896
# Description     : Escape/Quote a pathname for make
10897
#                       Allow files with a $ in the name
10898
#                       Allow files with a space in the name
10899
#                       Allow files with a comma in the name
10900
#                       Allow for paths that have make-varible prefixes
6423 dpurdie 10901
#                           $(GBE_...) or ${GBE_...} or $(OBJDIR) or $(BUILDVERNUM)
387 dpurdie 10902
#                           as these may be generated internally
5991 dpurdie 10903
#                       Allow for files with a colon in the name
10904
#                           Mode dependent
10905
#                               0 - No effect
10906
#                               T - \\\:
10907
#                               S = \:    
387 dpurdie 10908
#
399 dpurdie 10909
#                       Must also allow $(GBE_TYPE) in the remainder
10910
#
5991 dpurdie 10911
# Inputs          : uarg            - Arg to quote
10912
#                   mode            - Mode of operation
10913
#                                     T - Makefile target
10914
#                                     S - Makefile source
10915
#                                     0 - Neither
387 dpurdie 10916
#
10917
# Returns         : Quoted arg
10918
#
10919
 
5991 dpurdie 10920
sub QuoteForMake($;$)
387 dpurdie 10921
{
5991 dpurdie 10922
    my ($uarg, $mode) = @_;
10923
    $mode = '0' unless defined $mode;
387 dpurdie 10924
 
10925
    #
10926
    #   Split into two
10927
    #       $(xxx)/             - Makefile variables
10928
    #       Remainder           - Stuff to quote
10929
    #
10930
    $uarg =~ m~^((\$\(.*?\)/)*)(.*)~;
10931
    my $prefix = defined $1 ? $1 : '';
10932
    my $arg    = defined $3 ? $3 : '';
10933
 
6423 dpurdie 10934
    $arg =~ s~\$(?!\(GBE_[A-Z]+\)|{GBE_[A-Z]+}|\(OBJDIR\)|\(BUILDVERNUM\))~\$\$~g;       # $, not followed by (GBE_ or ${GBE_ or (OBJDIR)- is not $(GBE_ AND not $(OBJDIR)
387 dpurdie 10935
    $arg =~ s~ ~\\ ~g;
10936
    $arg =~ s~,~\$(comma)~g;
2764 dpurdie 10937
    $arg =~ s~%~\\%~g;
5999 dpurdie 10938
    $arg =~ s~:~\\\\\\:~g if ($mode eq 'T' &&  $::ScmHost eq "Unix");
10939
    $arg =~ s~:~\\:~g     if ($mode eq 'S' &&  $::ScmHost eq "Unix");
387 dpurdie 10940
    return $prefix . $arg;
10941
}
10942
 
10943
#-------------------------------------------------------------------------------
227 dpurdie 10944
# Function        : Maketag
10945
#
10946
# Description     : Create Makefile tags to speed up recursive makes
10947
#
10948
# Inputs          : tag_name
10949
#                   dep
10950
#
10951
# Returns         : 
10952
#
10953
sub Maketag
10954
{
10955
    my( $tag, $dep ) = @_;
10956
    $MakeTags{$tag} = 1 if ( defined($dep) && $dep );
10957
}
10958
 
10959
#-------------------------------------------------------------------------------
10960
#   Function to create and delete directories within the build system
10961
#
10962
#    To stop make regenerating directory dependent targets each time the
10963
#    directory content is modified, rule should only be dependent on a internally
10964
#    created alias file 'gbedir', which represents the time a dir was created not
10965
#    last modified.
10966
#
10967
#    Must use tags like GBE_BINDIR, GBE_LIBDIR and GBE_OBJDIR to ensure that the
10968
#    directories are created correctly.
10969
#
10970
my %MkdirRuleData;
10971
my @MkdirRuleOrder;
10972
my $MkdirRulePrinting = 0;
10973
my $MkdirRuleGbeFile = ( $::ScmHost eq "Unix" ) ? ".gbedir" : "_gbedir";
10974
 
10975
#-------------------------------------------------------------------------------
10976
# Function        : MkdirRule
10977
#
10978
# Description     : Create Rules and Recipes to create a directory at make-time
10979
#                   Mark the information for such that the directories will
10980
#                   be deleted in a 'clean'
10981
#
10982
#                   Can be called before we start writing the makefile
10983
#                   Such entries will be retained and dumped at a known time
10984
#
10985
# Inputs          : $subdir     - Symbolic name of the subdir $(OBJDIR)
10986
#                   $alias      - Optional script alias for the dir 'OBJDIR' --> GBE_OBJDIR
10987
#                   Options:
2429 dpurdie 10988
#                       --Path=path             Optional value of $subdir '$(GBE_PLATFORM)$(GBE_TYPE).OBJ'
10989
#                       --RemoveAll             Remove all files on clean
6177 dpurdie 10990
#                       --Extra=file[,file]     Additional files to remove
2429 dpurdie 10991
#                       --NoCreate              Do not Create the Directory, just delete it
227 dpurdie 10992
#
10993
# Returns         : Nothing
10994
#
10995
 
10996
sub MkdirRule
10997
{
10998
    my( $subdir, $alias, @opts ) = @_;
10999
 
11000
    #
11001
    #   Create data entry once
11002
    #
11003
    $alias =~ s~^GBE_~~ if $alias;
11004
    unless ( $MkdirRuleData{$subdir}  )
11005
    {
11006
        my %data;
11007
 
11008
        #
11009
        #   Parse options
11010
        #
11011
        foreach ( @opts )
11012
        {
11013
            if ( /^--Path=(.+)/ ) {
11014
                $data{path} = $1;
11015
            } elsif ( /^--RemoveAll/ ) {
11016
                $data{remove_all} = 1;
2429 dpurdie 11017
            } elsif ( /^--NoCreate/ ) {
11018
                $data{noCreate} = 1;
11019
            } elsif ( /^--Extra=(.+)/ ) {
11020
                @{$data{extraFiles}} = split(/,/, $1);
227 dpurdie 11021
            } else {
11022
                Error ("MkdirRule: Unknown option: $_");
11023
            }
11024
        }
11025
        $data{alias} = $alias if ( $alias );
11026
 
11027
        $MkdirRuleData{$subdir} = \%data;
11028
        push @MkdirRuleOrder, $subdir;
11029
    }
11030
 
11031
    #
11032
    #   Save or print
11033
    #
11034
    return unless ( $MkdirRulePrinting );
2429 dpurdie 11035
    return if ( $MkdirRuleData{$subdir}{noCreate} );
227 dpurdie 11036
 
11037
    #
11038
    #   Create a definition of the physical directory
11039
    #
11040
    my $path = $MkdirRuleData{$subdir}{path};
261 dpurdie 11041
    MakePadded (2, $alias, ":= $path\n") if ( $path && $alias );
227 dpurdie 11042
 
11043
    #   Create an alias to be used within rules
11044
    #   The defined aliase will be prefixed with 'GBE_'
11045
    #
261 dpurdie 11046
    MakePadded (2, "GBE_$alias", ":= $subdir/$MkdirRuleGbeFile\n") if ( $alias );
227 dpurdie 11047
 
11048
    #
11049
    #   Create a recipe to create the directory
11050
    #   This is not as simple as it sounds
11051
    #   The touch is required.
11052
    #       Had 'timestamp' issues on solaris'. The 'echo' did not appear
11053
    #       to be enough. Perhaps the output was not flushed
11054
    #
261 dpurdie 11055
    MakePadded (2, "$subdir", ": $subdir/$MkdirRuleGbeFile\n");
227 dpurdie 11056
    MakePrint
11057
        "$subdir/$MkdirRuleGbeFile:\n".
11058
        "\t\$(XX_PRE)if [ ! -d $subdir ]; then \$(mkdir) -p $subdir; fi; \\\n".
11059
        "\t\$(echo) '# DO NOT REMOVE.' > \$@; \\\n".
11060
        "\t\$(touch) \$@\n\n";
11061
}
11062
 
11063
#-------------------------------------------------------------------------------
11064
# Function        : RmdirRules
11065
#
2429 dpurdie 11066
# Description     : Create the body of a recipe to delete the directories that
227 dpurdie 11067
#                   have been created.
11068
#
2429 dpurdie 11069
#                   Use JatsFileUtil rather than shell script
11070
#                       Faster under windows (and others)
11071
#                       Solved long pathname issues
11072
#                       Simpler to use and control
227 dpurdie 11073
#
11074
# Inputs          : Uses $MkdirRuleData
11075
#
11076
# Returns         : Nothing.
11077
#                   Prints to the makefile
11078
#
11079
sub RmdirRules
11080
{
2429 dpurdie 11081
    MakePrint( ".PHONY:\tunmake_dir\n" );
11082
    MakePrint( "unmake_dir:\n" );
11083
 
227 dpurdie 11084
    #
11085
    #   Determine the list of directories to delete
2429 dpurdie 11086
    #   Sort such that subdirs are deleted first
227 dpurdie 11087
    #
2429 dpurdie 11088
    my $txt = 'Removing directories';
227 dpurdie 11089
    foreach my $subdir ( reverse sort keys %MkdirRuleData )
11090
    {
2429 dpurdie 11091
        my @args = $subdir;
11092
 
5816 dpurdie 11093
        push (@args, $MkdirRuleGbeFile, 'core', '*.bak', '*.tmp', '*.err', 'utf.*.rc')
2429 dpurdie 11094
            unless $MkdirRuleData{$subdir}{remove_all};
11095
 
11096
        push (@args, @{$MkdirRuleData{$subdir}{extraFiles}})
11097
            if ( $MkdirRuleData{$subdir}{extraFiles} );
11098
 
11099
        my $mode = $MkdirRuleData{$subdir}{remove_all} ? 'T0' : 'D0';
11100
 
11101
        MakePrint ("\t-\$(AA_PRE)JatsFileUtil ", QuoteArray( $mode, $txt, @args ), "\n");
11102
        $txt = '';
227 dpurdie 11103
    }
11104
}
11105
 
11106
#-------------------------------------------------------------------------------
6898 dpurdie 11107
# Function        : ClobberDirsRule 
11108
#
11109
# Description     : Create the body of a recipe to delete the directories that
11110
#                   will be removed in a clobber
11111
#
11112
#                   Use JatsFileUtil rather than shell script
11113
#                       Faster under windows (and others)
11114
#                       Solved long pathname issues
11115
#                       Simpler to use and control
11116
#
11117
# Inputs          : @CLOBBERDIRS
11118
#
11119
# Returns         : Nothing.
11120
#                   Prints to the makefile
11121
#
11122
sub ClobberDirsRule
11123
{
11124
    MakeNewLine();
11125
    MakePrint( ".PHONY:\tclobberdirs\n" );
11126
    MakePrint( "clobberdirs:\n" );
11127
 
11128
    #
11129
    #   Determine the list of directories to delete
11130
    #   Sort such that subdirs are deleted first
11131
    #
11132
    my $txt = 'Removing toolset directories';
11133
    foreach my $subdir ( reverse sort @CLOBBERDIRS )
11134
    {
11135
        my @args = $subdir;
11136
        MakePrint ("\t-\$(AA_PRE)JatsFileUtil ", QuoteArray( 'T0', $txt, @args ), "\n");
11137
        $txt = '';
11138
    }
11139
}
11140
 
11141
#-------------------------------------------------------------------------------
227 dpurdie 11142
# Function        : CreateMkdirRules
11143
#
11144
# Description     : Create Rules to make dirs at runtime
11145
#                   This function is called to instantiate those entries
11146
#                   That have been requested before the makefile has has
11147
#                   started to be created.
11148
#
11149
#                   Once this function has been called all new MkdirRule calls
11150
#                   will result in the recipes being created in-line.
11151
#
11152
# Inputs          : Nothing
11153
#
11154
# Returns         : Even Less
11155
#
11156
#
11157
sub CreateMkdirRules
11158
{
11159
    $MkdirRulePrinting = 1;
11160
    foreach my $subdir ( @MkdirRuleOrder )
11161
    {
11162
        my $data = $MkdirRuleData{$subdir};
11163
        MkdirRule($subdir, $data->{alias}, $data->{path} );
11164
    }
11165
}
11166
 
11167
#-------------------------------------------------------------------------------
11168
# Function        : PackageRule
11169
#
11170
# Description     : Generate rules and recipes to "install" and "package" files
11171
#
11172
# Inputs          : codecmd     - A code reference to the actual installer routine
11173
#                   hashp       - A reference to a INSTALL or PACKAGE hash
11174
#
299 dpurdie 11175
#                   hashp is a reference to a hash
227 dpurdie 11176
#                       The key is the full path of the install target
11177
#                       The value is (another) hash that describes the install options
11178
#
11179
#                   Valid keys are:
11180
#                       src                 - Path of the source file [Mandatory]
11181
#                       dir                 - Target directory [Mandatory]
11182
#
11183
#                       defined             - Copy the file only if value is defined
4382 dpurdie 11184
#                       Exists              - Copy the file only if it exists
227 dpurdie 11185
#                       exe                 - Mark the file as executable
11186
#                       Mode                - File modes. Default is -w
11187
#                       placekeeper         - Marks SHARED library placekeepers
11188
#                       set                 - Distribution sets
11189
#                       type                - Copy the file in DEBUG or PROD mode
11190
#                                             Valid values are "D" or "P"         
11191
#                       version             - Shared library version information
5882 dpurdie 11192
#                       symlink             - File is a symlink
227 dpurdie 11193
#                       RemoveOnly          - Do not install the file. Entries are
11194
#                                             created to allow the removal of the file
4382 dpurdie 11195
#                       NoTarget            - Reserved - Implemented elsewhere
227 dpurdie 11196
#
11197
# Returns         :
11198
#
11199
sub PackageRule
11200
{
11201
    my ($codecmd, $hashp) = @_;
11202
 
11203
    foreach my $dest ( keys %{$hashp} )
11204
    {
11205
 
11206
        my $entry = $hashp->{$dest};
5991 dpurdie 11207
        my $destText = QuoteForMake($dest,'T');
227 dpurdie 11208
        #
11209
        #   Skip placekeepers
11210
        #
11211
        next if ( $entry->{'placekeeper'} );
11212
 
11213
        #
11214
        #   Some entries are not installed via this mechanism, but can be removed
11215
        #   if they exist. Mark these as PHONY to keep targets happy
11216
        #
11217
        if ( $entry->{'RemoveOnly'} )
11218
        {
5991 dpurdie 11219
            MakePrint ".PHONY:\t$destText\n";
11220
            MakePrint "$destText:\n\n";
227 dpurdie 11221
            next;
11222
        }
11223
 
11224
        my $fname = $entry->{'src'};
5991 dpurdie 11225
        my $fnameText = QuoteForMake($fname,'S');
227 dpurdie 11226
        my $fmode = $entry->{'Mode'};
11227
        $fmode .= "+x" if ( $entry->{'exe'}  );
5882 dpurdie 11228
        $fmode .= "+l" if ( $entry->{'symlink'}  );
227 dpurdie 11229
 
11230
        #
11231
        #   User conditionional
11232
        #   Mark both the source and the target as PHONY if the condition is not met
11233
        #   This will ensure that the target need not be built.
11234
        #
11235
        my $udef = $entry->{'defined'};
11236
        if ( $udef )
11237
        {
11238
            MakePrint "ifndef $udef \n";
5991 dpurdie 11239
            MakePrint ".PHONY:\t\t$destText\n";
11240
            MakePrint ".PHONY:\t\t$fnameText\n";
11241
            MakePrint "$destText:\n";
227 dpurdie 11242
            MakePrint "else\n"
11243
        }
11244
 
11245
        #
4382 dpurdie 11246
        #   File exists
11247
        #   Only package the file if it has been generated. ie: .exe.manifest
11248
        #
11249
        my $fexist = $entry->{'Exists'};
11250
        if ($fexist)
11251
        {
5991 dpurdie 11252
            MakePrint "ifeq (\"\$(wildcard $fnameText)\",\"\")\n";
11253
            MakePrint ".PHONY:\t\t$destText\n";
11254
            MakePrint "$destText:\n";
4382 dpurdie 11255
            MakePrint "else\n"
11256
        }
11257
 
11258
        #
227 dpurdie 11259
        #   Conditional installation for DEBUG/PRODUCTION
11260
        #
11261
        my $type = $entry->{'type'};
11262
        if ( $type )
11263
        {
11264
            if ( $type eq "D" ) {
11265
                MakePrint 'ifeq "$(DEBUG)" "0"'."\n";
11266
            } elsif ( $type eq "P" ) {
11267
                MakePrint 'ifneq "$(DEBUG)" "0"'."\n";
11268
            } else {
11269
                Error("INTERNAL: Unexpected packaging type: $type");
11270
            }
5991 dpurdie 11271
            MakePrint ".PHONY:\t\t$destText\n";
11272
            MakePrint "$destText:\n";
227 dpurdie 11273
            MakePrint "else\n"
11274
        }
11275
 
11276
        #
11277
        #   The body of the copy
11278
        #
5991 dpurdie 11279
        MakePadded( 4, $destText . ':' );
11280
        MakePrint "\t" . $fnameText . "\n";
2429 dpurdie 11281
        MakePrint $codecmd->( $dest, $fname, $fmode );
227 dpurdie 11282
        MakeNewLine();
11283
 
11284
        #
11285
        #   Unwind conditionals
11286
        #
11287
        MakePrint "endif\n" if ( $type );
4382 dpurdie 11288
        MakePrint "endif\n" if ( $fexist );
227 dpurdie 11289
        MakePrint "endif\n" if ( $udef );
11290
 
11291
        #
11292
        #   Distribution sets
11293
        #
11294
        my $dist = $entry->{'set'};
11295
        if ( $dist )
11296
        {
267 dpurdie 11297
            foreach my $set ( split( ',', $dist ) )
11298
            {
11299
                push @{$PACKAGE_SETS{$set}{LIST}}, $dest;
227 dpurdie 11300
            }
11301
            MakeNewLine();
11302
        }
11303
    }
11304
}
11305
 
11306
#-------------------------------------------------------------------------------
6387 dpurdie 11307
# Function        : PackageDirRule 
11308
#
11309
# Description     : Generate special rules for dynamic packaging/installation of directories 
11310
#
11311
# Inputs          : $mode        - package_dirs/unpackage_dirs/install_dirs/uninstall_dirs
11312
#                   $dataRef     - Ref to package/install list
11313
#                       
11314
#
11315
# Returns         : 
11316
#
11317
sub PackageDirRule
11318
{
11319
    my ($mode, $dataRef) = @_;
11320
    my $me = MakeEntry::New( *MAKEFILE, $mode , '--Phony' );
11321
 
11322
    my $modeText = 'packaging';
11323
    my $cmdText = 'PackageDir';
11324
    if ($mode =~ m~install~) {
11325
        $modeText = 'installing';
11326
        $cmdText = 'InstallDir';
11327
    }
11328
    my $cmd = 'copyDir'; 
11329
    if ($mode =~ m~^un~) {
11330
        $cmd = 'unCopyDir';
11331
        $modeText = 'un' . $modeText;
11332
        $cmdText = 'Un' . $cmdText;
11333
    }
11334
 
11335
 
11336
    foreach my $entry ( @{$dataRef}) {
11337
        $me->NewSection();
11338
 
11339
        #
11340
        #   Conditional installation for DEBUG/PRODUCTION
11341
        #
11342
        my $type = $entry->{'type'};
11343
        if ( $type )
11344
        {
11345
           if ( $type eq "D" ) {
11346
               $me->SectionIfNeq('$(DEBUG)','0');
11347
           } elsif ( $type eq "P" ) {
11348
               $me->SectionIfEq('$(DEBUG)','0');
11349
           } else {
11350
               Error("INTERNAL: Unexpected packaging type: $type");
11351
           }
11352
        }
11353
 
11354
        #
11355
        #   Quote the REs so that they can be passed to a command line
11356
        #       Replace $ with $$
11357
        #
11358
        my $QuoteRe = sub {
11359
            my ($arg) = @_;
11360
            $arg=~ s~\$~\$\$~g;
11361
            return $arg;
11362
            };
11363
 
11364
        #
11365
        #   The body of the copy
11366
        #   Create a command line for run-time command
11367
        #   
11368
        my @cmd;
11369
        push @cmd, '$(JatsRunTime)', $cmd, '--', '-$(VERBOSE_OPT)', '--Name='. $cmdText, '--';
11370
        push @cmd, '-mode=' . $modeText;
11371
        push @cmd, "'" . '-src=' . $entry->{dirTree} . "'";
11372
        push @cmd, "'" . '-dst=' . $entry->{dir} . "'";
11373
        push (@cmd, '-execute' ) if $entry->{exefile};
11374
        push (@cmd, '-noSymlink' ) if $entry->{noPreserveSymlink};
11375
        push (@cmd, '-noRecurse' ) if $entry->{noRecurse};
11376
        push (@cmd, '-stripBase' ) if $entry->{strip_base};
11377
        push (@cmd, "'" . '-exclude+=' . $QuoteRe->($_) . "'" ) foreach @{$entry->{exclude}};
11378
        push (@cmd, "'" . '-include+=' . $QuoteRe->($_) . "'" ) foreach @{$entry->{include}};
11379
        push (@cmd, "'" . '-excludeRe+=' . $QuoteRe->($_) . "'" ) foreach @{$entry->{excludeRe}};
11380
        push (@cmd, "'" . '-includeRe+=' . $QuoteRe->($_) . "'" ) foreach @{$entry->{includeRe}};
11381
 
11382
        $me->AddRecipe(join(' ', @cmd ) );
11383
    }
11384
    $me->Print();
11385
}
11386
 
11387
#-------------------------------------------------------------------------------
267 dpurdie 11388
# Function        : PackageSetRules
11389
#
11390
# Description     : Generate the packageset rules
11391
#                   These appear to be a now-defuct feature
11392
#
11393
#                   By default all packaged files are a part of package_setALL
11394
#
11395
# Inputs          : None
11396
#                   Takes data from %PACKAGE_SET
11397
#
11398
# Returns         : Nothing
11399
#
11400
sub PackageSetRules
11401
{
11402
    foreach my $set ( sort keys %PACKAGE_SETS )
11403
    {
11404
        my $me = MakeEntry::New( *MAKEFILE, "package_set$set", '--Phony' );
5991 dpurdie 11405
        $me->AddDependancyEscaped( @{$PACKAGE_SETS{$set}{LIST}} );
267 dpurdie 11406
        $me->Print();
11407
    }
11408
}
11409
 
11410
#-------------------------------------------------------------------------------
227 dpurdie 11411
# Function        : UnPackageRule
11412
#
11413
# Description     : Generate rules and recipes to "uninstall" and "unpackage" files
11414
#
11415
# Inputs          : target      - Name of the target
11416
#                   codecmd     - A code reference to the actual installer routine
11417
#                   hashp       - A reference to a INSTALL or PACKAGE hash
11418
#
11419
# Returns         :
11420
#
11421
sub UnpackageRule
11422
{
11423
    my ($target, $codecmd, $hashp) = @_;
11424
 
11425
    MakePrint ".PHONY:\t\t"."$target\n";
11426
    MakePrint "$target:\t";
11427
 
11428
    foreach my $dest ( sort keys %{$hashp} )
11429
    {
11430
 
11431
        my $entry = $hashp->{$dest};
11432
 
11433
        #
11434
        #   Skip placekeepers
11435
        #
11436
        next if ( $entry->{'placekeeper'} );
11437
 
11438
        MakePrint "\n" . $codecmd->($dest);
11439
    }
11440
    MakePrint "\n\n";
11441
}
11442
 
11443
 
11444
#
11445
#   Internal macro interface, see RULE.STD for definitions:
11446
#
11447
sub RmFilesCmd
11448
{
11449
    my ( $list ) = @_;
261 dpurdie 11450
    return "\$(call RmFiles,$list)";
227 dpurdie 11451
}
11452
 
11453
sub InstallCmd
11454
{
2429 dpurdie 11455
    my( $dest, $file, $fmode ) = @_;
227 dpurdie 11456
 
11457
    $fmode = "-w"                           # default, read-only
11458
        if ( !defined( $fmode ) || $fmode eq "" );
11459
 
5991 dpurdie 11460
    $dest = QuoteForMake($dest);
11461
    $file = QuoteForMake($file);
2429 dpurdie 11462
    return "\t\$(call InstallFile,$dest,$file,$fmode)";
227 dpurdie 11463
}
11464
 
11465
sub UninstallCmd
11466
{
11467
    my( $file ) = @_;
5991 dpurdie 11468
    $file = QuoteForMake($file);
227 dpurdie 11469
    return "\t\$(call UninstallFile,$file)";
11470
}
11471
 
11472
sub PackageCmd
11473
{
2429 dpurdie 11474
    my( $dest, $file, $fmode ) = @_;
227 dpurdie 11475
 
11476
    $fmode = "-w"                           # default, read-only
11477
        if ( !defined( $fmode ) || $fmode eq "" );
11478
 
5991 dpurdie 11479
    $dest = QuoteForMake($dest);
11480
    $file = QuoteForMake($file);
2429 dpurdie 11481
    return "\t\$(call PackageFile,$dest,$file,$fmode)";
227 dpurdie 11482
}
11483
 
11484
sub UnpackageCmd
11485
{
11486
    my( $file ) = @_;
5991 dpurdie 11487
    $file = QuoteForMake($file);
227 dpurdie 11488
    return "\t\$(call UnpackageFile,$file)";
11489
}
11490
 
11491
1;
11492