Subversion Repositories DevTools

Rev

Rev 6387 | Rev 6415 | 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
131
                                                # Known values: UnitTests, AutoUnitTests
6133 dpurdie 132
our  %ScmGlobalOptions       = ();              # Hash of Global(platform) options. Access via functions
363 dpurdie 133
 
227 dpurdie 134
our $ScmRoot                = "";
135
our $ScmMakelib             = "";
136
our $ScmPlatform            = "";
137
our $ScmMachType            = "";
138
our $ScmSrcDir              = "";
139
our @ScmPlatformDirs        = ();
140
our @ScmPlatformArgs        = ();
289 dpurdie 141
our $ScmBuildType           = 0;                # 0, P, D. 0 == P and D
227 dpurdie 142
our $ScmProduct             = "";
143
our $ScmTarget              = "";
144
our $ScmTargetHost          = "";
145
our $ScmToolset             = "";
146
our @ScmToolsetArgs         = ();
147
our @ScmDepends             = ();
148
our %ScmSourceTypes         = ();
149
our $ScmDeploymentPatch     = "";
150
our $ProjectBase            = "";               # Base of the user's project
151
our $ScmNoToolsTest         = "";               # Supress compiler tests
152
our $ScmDependTags          = 0;                # Create dependancy scanning tag
4781 dpurdie 153
our $ScmMakeUid;                                # Unique makefile id (number 1 .. )
227 dpurdie 154
 
155
our @CFLAGS                 = ();
156
our @CFLAGS_DEBUG           = ();
157
our @CFLAGS_PROD            = ();
158
our @CLINTFLAGS             = ();
159
our @CLINTFLAGS_DEBUG       = ();
160
our @CLINTFLAGS_PROD        = ();
161
our @CXXFLAGS               = ();
162
our @CXXFLAGS_DEBUG         = ();
163
our @CXXFLAGS_PROD          = ();
164
our @CXXLINTFLAGS           = ();
165
our @CXXLINTFLAGS_DEBUG     = ();
166
our @CXXLINTFLAGS_PROD      = ();
167
our @ASFLAGS                = ();
267 dpurdie 168
our @ASFLAGS_DEBUG          = ();
169
our @ASFLAGS_PROD           = ();
227 dpurdie 170
our @LDFLAGS                = ();
267 dpurdie 171
our @LDFLAGS_DEBUG          = ();
172
our @LDFLAGS_PROD           = ();
227 dpurdie 173
 
174
our @INCDIRS                = ();
175
our @NODEPDIRS              = ();
176
our @S_INCDIRS              = ();
177
our @G_INCDIRS              = ();
178
our @L_INCDIRS              = ();
179
our @SRCDIRS                = ();
180
our @S_SRCDIRS              = ();
181
our @G_SRCDIRS              = ();
182
our @L_SRCDIRS              = ();
183
our @LIBDIRS                = ();
184
our @S_LIBDIRS              = ();
185
our @G_LIBDIRS              = ();
186
our @L_LIBDIRS              = ();
187
 
188
our %SRCS                   = ();
189
our %SRC_ARGS               = ();
190
our %SRC_TYPE               = ();
191
our %SRC_DEPEND             = ();
192
our %SCRIPTS                = ();
193
our @COPYIN                 = ();
194
our @INITS                  = ();
195
our @DEFINES                = ();
196
our @OBJS                   = ();
197
our %SHOBJ_LIB              = ();
198
our @PROGOBJS               = ();
289 dpurdie 199
our @TESTPROGOBJS           = ();
227 dpurdie 200
our %OBJSOURCE              = ();
201
our @CHDRS                  = ();
202
our @CSRCS                  = ();
203
our @CXXSRCS                = ();
204
our @ASHDRS                 = ();
205
our @ASSRCS                 = ();
206
our @GENERATED              = ();
207
our @GENERATED_NOTSRC       = ();
208
our @RULES                  = ();
209
our @TOOLSETRULES           = ();
210
our @TOOLSETDIRS            = ();
211
our @TOOLSETDIRTREES        = ();
212
our @TOOLSETGENERATED       = ();
213
our @USERGENERATED          = ();
214
our @TOOLSETOBJS            = ();
215
our @TOOLSETLIBS            = ();
216
our @TOOLSETPROGS           = ();
217
our %INSTALL_HDRS           = ();
218
our %INSTALL_CLSS           = ();
219
 
4778 dpurdie 220
our @TOOLSET_UTF_PRE        = ();       # Toolsets can extend rules run before all unit tests
221
our @TOOLSET_UTF_POST       = ();       # Toolsets can extend rules run after all unit tests
222
our @TOOLSET_UTF_COLLATE    = ();       # Toolsets can extend rules run to collate unit tests results
223
 
227 dpurdie 224
our @LIBS                   = ();
289 dpurdie 225
our $LIBS                   = ();
227 dpurdie 226
our %LIB_PKG                = ();
227
our %LIB_INS                = ();
228
our %INSTALL_LIBS           = ();
229
 
230
our @MLIBS                  = ();
289 dpurdie 231
our $MLIBS                  = ();
227 dpurdie 232
 
233
our @SHLIBS                 = ();
289 dpurdie 234
our $SHLIBS                 = ();
227 dpurdie 235
our @SHLIB_TARGETS          = ();
236
our %SHLIB_PKG              = ();
237
our %SHLIB_INS              = ();
238
our %INSTALL_SHLIBS         = ();
6387 dpurdie 239
our @INSTALL_DIRS           = ();
227 dpurdie 240
 
289 dpurdie 241
our $TESTPROGS              = ();
242
our @TESTPROGS              = ();
227 dpurdie 243
 
289 dpurdie 244
our $PROGS                  = ();           # Simplify tracking of progs
227 dpurdie 245
our @PROGS                  = ();
289 dpurdie 246
our @PROGS_EXTRA            = ();           # Look at doing better !!
227 dpurdie 247
our %PROG_PKG               = ();
248
our %PROG_INS               = ();
249
our %INSTALL_PROGS          = ();
250
 
251
our %PACKAGE_DIST           = ();
252
our %PACKAGE_SETS           = ();
253
our %PACKAGE_HDRS           = ();
254
our %PACKAGE_LIBS           = ();
255
our %PACKAGE_CLSS           = ();
256
our %PACKAGE_SHLIBS         = ();
257
our %PACKAGE_PROGS          = ();
258
our %PACKAGE_FILES          = ();
6387 dpurdie 259
our @PACKAGE_DIRS           = ();
227 dpurdie 260
 
261
our @LINTLIBS               = ();
262
our @LINTSHLIBS             = ();
263
 
4501 dpurdie 264
our @TESTS_TO_RUN           = ();                           # Info from 'RunTest' directives
227 dpurdie 265
 
4996 dpurdie 266
our @TESTPROJECT_TO_URUN    = ();                           # List of Unit Tests and Projects names (Auto and Non Auto in order defined in makefile)
267
our @TESTPROJECT_TO_ARUN    = ();                           # List of Auto Tests and Projects names in order defined in makefile
4501 dpurdie 268
my  $TESTS_TO_AUTORUN       = undef;                        # Flag - Auto Test found
269
my  $TESTS_TO_RUN           = undef;                        # Flag - Unit Test found
270
 
227 dpurdie 271
#our $CurrentTime           = "";
272
#our $CurrentDate           = "";
273
#our $Cwd                   = "";
274
 
275
our @GENERATE_FILES         = ();
276
our %DEPLOYPACKAGE          = ();
267 dpurdie 277
our $DEPLOYPACKAGE          = 0;
261 dpurdie 278
our %MakeTags;
227 dpurdie 279
 
280
#
281
#   Some toolset options that affect the generation of the makefile
282
#
283
our $UseAbsObjects          = 0;                # Default is relative paths to objects
284
our $UseRelativeRoot        = 0;                # Default is absolute paths to build root
299 dpurdie 285
our $DPackageDirective      = 0;
227 dpurdie 286
 
271 dpurdie 287
#
288
#   Arrays of hook functions
289
#
290
our %MF_RegisterSrcHooks;                       # Hook source file discovery
291
 
227 dpurdie 292
###############################################################################
293
#
294
#   Packaging and Installation Information
295
#   Held in a structure as its used in a few places
296
#   Items
297
#       PBase   - Package Base directory. Used for user overrides
298
#       IBase   - Local Install Base directory
299
#       Dir     - Default directory suffix for components. Added to Pbase and IBase
300
#
301
#
302
our %PackageInfo = (
303
    'File' => { 'PBase' => '$(PKGDIR)'       ,'IBase' => '$(LOCALDIR)'       , 'Dir' => '' },
304
    'Hdr'  => { 'PBase' => '$(INCDIR_PKG)'   ,'IBase' => '$(INCDIR_LOCAL)'   , 'Dir' => ''},
305
    'Lib'  => { 'PBase' => '$(LIBDIR_PKG)'   ,'IBase' => '$(LIBDIR_LOCAL)'   , 'Dir' => '/$(GBE_PLATFORM)'},
306
    'Prog' => { 'PBase' => '$(BINDIR_PKG)'   ,'IBase' => '$(BINDIR_LOCAL)'   , 'Dir' => '/$(GBE_PLATFORM)$(GBE_TYPE)'},
307
    'Jar'  => { 'PBase' => '$(CLSDIR_PKG)'   ,'IBase' => '$(CLSDIR_LOCAL)'   , 'Dir' => ''},
241 dpurdie 308
    'Tool' => { 'PBase' => '$(PKGDIR)'       ,'IBase' => '$(LOCALDIR)'       , 'Dir' => '/tools/bin/$(GBE_HOSTMACH)'},
227 dpurdie 309
    );
310
 
4778 dpurdie 311
###############################################################################
312
#
313
#   An array of reserved names
314
#   Used to attempt to prevent developers from naming toolset targets with names reserved
315
#   within the build system
316
our @reservedMakeTargets = qw (
317
    preprocess_tests postprocess_tests collate_test_results
318
);
319
 
227 dpurdie 320
MakeLib2Init();                                 # Runtime initialisation
321
 
322
sub MakeLib2Init
323
{
324
#.. Test environment
325
#
326
    EnvImport( "GBE_CORE" );
327
    EnvImport( "GBE_BIN" );
328
    EnvImport( "GBE_PERL" );
329
    EnvImport( "GBE_TOOLS" );
330
    EnvImport( "GBE_CONFIG" );
331
    EnvImport( "GBE_MACHTYPE" );
332
 
333
#.. Common stuff
334
#
335
    require "$::GBE_TOOLS/common.pl";           # Common stuff
336
    push( @ScmDepends, "$::GBE_TOOLS/common.pl" );
337
 
338
    CommonInit( "makelib2" );
339
    Debug( "version:   $ScmVersion" );
340
 
341
#.. Cache arguments
342
#
343
    CommandLine();
344
 
345
#.. Build defaults
346
#
347
    $ScmSourceTypes{ ".h" }     = ".h";
348
    $ScmSourceTypes{ ".hpp" }   = ".h";
349
    $ScmSourceTypes{ ".c" }     = ".c";
350
    $ScmSourceTypes{ ".C" }     = ".c";
351
    $ScmSourceTypes{ ".cpp" }   = ".cc";
352
    $ScmSourceTypes{ ".cc" }    = ".cc";
353
    $ScmSourceTypes{ ".asm" }   = ".asm";
354
    $ScmSourceTypes{ ".x" }     = "--Ignore";
355
    $ScmSourceTypes{ ".ini" }   = "--Ignore";
356
    $ScmSourceTypes{ ".sh" }    = "--Ignore";
357
    $ScmSourceTypes{ ".pl" }    = "--Ignore";
358
    $ScmSourceTypes{ ".awk" }   = "--Ignore";
359
 
360
#.. Get the stuff from the build configuration file
361
#
362
    ConfigLoad();
4781 dpurdie 363
    $ScmMakeUid = GetMakfilefileUid();
364
    Debug("ScmMakeUid: $ScmMakeUid");
227 dpurdie 365
 
369 dpurdie 366
    if ( (%::ScmBuildPlatforms) )        # Interface/build.cfg
227 dpurdie 367
    {
368
        AddPlatformArg( split( /$;/, $::ScmBuildPlatforms{ $ScmPlatform } ));
369
    }
370
 
369 dpurdie 371
    if ( (%::ScmBuildIncludes) )         # Interface/build.cfg
227 dpurdie 372
    {
373
        my( @includes ) = split( ',', $::ScmBuildIncludes{ $ScmPlatform } );
374
        my( $global ) = $ScmGlobal;
375
 
376
        $ScmGlobal = 1;                         # Follow defs are "global's" ...
377
        foreach my $elem ( @includes )
378
        {
379
            AddIncDir( "*", $elem ) if ($elem);
380
        }
381
        $ScmGlobal = $global;                   # Restore global status ...
382
    }
383
 
369 dpurdie 384
    if ( (%::ScmBuildLibraries) )        # Interface/build.cfg
227 dpurdie 385
    {
386
        my( @libraries ) = split( ',', $::ScmBuildLibraries{ $ScmPlatform } );
387
        my( $global ) = $ScmGlobal;
388
 
389
        $ScmGlobal = 1;                         # Follow defs are "global's" ...
390
        foreach my $elem ( @libraries )
391
        {
392
            AddLibDir( "*", $elem ) if ($elem);
393
        }
394
        $ScmGlobal = $global;                   # Restore global status ...
395
    }
396
 
397
#.. Determine the value of $ScmMachType
398
#   In the makefile GBE_MACHTYPE will be set to $ScmMachType.
399
#
400
#   There is an compatibility issue here.
401
#   A lot of (legacy) package.pl files use GBE_MACHTYPE to specify platform
402
#   specfic directories and names. This is not to be encouraged.
403
#
404
#   Allow for a platformm specific override
405
#
406
    if ( exists( $::BUILDINFO{$ScmPlatform}{'SCMMACHTYPE'} ))
407
    {
408
        $ScmMachType = $::BUILDINFO{$ScmPlatform}{'SCMMACHTYPE'};
409
        Verbose("Override ScmMachType: $ScmMachType");
410
    }
411
    else
412
    {
413
        $ScmMachType = $ScmPlatform;
414
    }
415
 
416
 
417
#.. Get the stuff from the Package definition file
418
#   A convention is that package.pl provide a package name via $Pbase
419
#   This may be different to the BUILDNAME. Generate a default $Pbase
420
#   to allow the package.pl to use the package name part of the buildname
421
#
422
    $::Pbase = $::ScmBuildPackage;
423
    if ( -f "$ScmRoot/package.pl" )
424
    {
425
        Warning ("package.pl file used. Use is being deprecated");
426
 
427
        my( $global ) = $ScmGlobal;             # Follow defs are "global's" ...
428
        $ScmGlobal = 1;
429
        require "$ScmRoot/package.pl";
430
        $ScmGlobal = $global;                   # Restore global status ...
431
 
432
        if ( defined ($::ScmBuildPackage) && defined ($::Pbase) )
433
        {
434
            #   Special case.
435
            #   $Pbase is set to ".". Set $Pbase to the Build Name to force
436
            #   construction of a well formatted package.
437
            #
438
            $::Pbase = $::ScmBuildPackage
439
                if ( $::Pbase eq "." );
440
 
441
            #
442
            #   Error if Pbase has changed
443
            #
444
            Error ("Pbase is not the same as the BuildName (Check package.pl)",
445
                   "Pbase    : $::Pbase",
446
                   "BuildName: $::ScmBuildPackage")
447
                if ( $::Pbase ne $::ScmBuildPackage );
448
        }
449
    }
289 dpurdie 450
 
451
    #
452
    #   Create objects to keep track of Libraies and Programs
453
    #
454
    $LIBS       = MakeObject::NewType( 'Library',       \@LIBS,     '$(LIBDIR)/', \&GenLibName);
455
    $MLIBS      = MakeObject::NewType( 'MergedLibrary', \@MLIBS,    '$(LIBDIR)/', \&GenLibName);
456
    $SHLIBS     = MakeObject::NewType( 'SharedLibrary', \@SHLIBS,   '$(LIBDIR)/', \&GenLibName);
457
    $PROGS      = MakeObject::NewType( 'Program',       \@PROGS,    '$(BINDIR)/', \&GenProgName);
458
    $TESTPROGS  = MakeObject::NewType( 'TestProgram',   \@TESTPROGS,'$(BINDIR)/', \&GenProgName);
227 dpurdie 459
}
460
 
261 dpurdie 461
#-------------------------------------------------------------------------------
289 dpurdie 462
# Function        : GenLibName
463
#
464
# Description     : Helper function to generate a (static) library name
465
#                   Used by MakeObject::NewType
466
#
467
#                   If the toolset doesn't support Debug and Prod, then
468
#                   The library name will not have the suffix
469
#
470
# Inputs          : arg0        - Base name of the library
343 dpurdie 471
#                   arg1        - Mode: 1 == Plain. No P or D
289 dpurdie 472
#
473
# Returns         : Name of the library as used in the makefiles
474
#                   Does not include base directory
475
#
476
sub GenLibName
477
{
343 dpurdie 478
    if ( $ScmToolsetSingleType || $_[1] ) {
289 dpurdie 479
        return "$_[0].$::a"
480
    } else {
481
        return "$_[0]\$(GBE_TYPE).$::a"
482
    }
483
}
484
 
485
#-------------------------------------------------------------------------------
486
# Function        : GenProgName
487
#
488
# Description     : Helper function to generate a program name
489
#                   Used by MakeObject::NewType
490
#
491
# Inputs          : arg0        - Base name of the library
492
#
493
# Returns         : Name of the program as used in the makefiles
494
#                   Does not include base directory
495
#
496
sub GenProgName
497
{
498
    return "$_[0]$::exe"
499
}
500
 
501
 
502
#-------------------------------------------------------------------------------
261 dpurdie 503
# Function        : CommandLine
504
#
505
# Description     : Process the command line.
506
#                   Arguments describes below
507
#
508
# Arguments       : ARG0        - Root of the project
509
#                   ARG1        - Path to this script
510
#                   ARG2        - Target Platform
511
#
512
#                   Options follow
513
#                       --interface=name    - Name of interface dir
514
#                       --arg=xxx           - Platform argument
515
#
516
#                   Otherwise display a usage message
517
#
518
# Returns         : Nothing
519
#
227 dpurdie 520
sub CommandLine
521
{
261 dpurdie 522
    Verbose ("Command Line: @ARGV");
227 dpurdie 523
 
261 dpurdie 524
    #
525
    #   Extract options first
526
    #
527
    my $opt_help = 0;
528
    my $result = GetOptions (
529
                "help+"         => \$opt_help,
530
                "interface=s"   => \$::ScmInterface,
531
                "arg=s"         => sub{ AddPlatformArg( "--$_[1]") }
532
                );
533
    Usage() if ( $opt_help || !$result );
534
 
535
    #
536
    # Need 3 Arguments
537
    #
227 dpurdie 538
    $ScmRoot     = ${ARGV[0]};
261 dpurdie 539
    $ScmRoot     = RelPath( $ScmRoot );
227 dpurdie 540
    $ProjectBase = $ScmRoot;
541
 
542
    $ScmMakelib  = ${ARGV[1]};
543
    $ScmPlatform = ${ARGV[2]};
544
    $ScmTarget   = $ScmPlatform;
545
 
546
    Message ("[$ScmPlatform] Generate Makefile");
547
    Debug( "root\t=$ScmRoot" );
548
    Debug( "makelib\t=$ScmMakelib" );
549
    Debug( "platform\t=$ScmPlatform" );
550
}
551
 
552
#   Usage ---
553
#       Command line usage help.
554
#..
555
 
556
sub Usage
557
{
261 dpurdie 558
    Error ( "Usage: perl makefile.pl2 <ROOTDIR> <makelib.pl2> <PLATFORM> [options ...]",
559
            "Valid options:",
560
            "    --interface=name  Set interface directory",
561
            "    --arg=text        Specify platform argument",
562
            );
227 dpurdie 563
}
564
 
565
 
566
#-------------------------------------------------------------------------------
567
# Function        : SubDir
568
#
569
# Description     : Include a sub-makefile
570
#                   When called when processing by this script this directive
571
#                   does nothing. The processing will be done by makelib.pl
572
#
573
#                   This directive MUST occur before the Platform directive
574
#
575
# Inputs          : None that are used
576
#
577
# Returns         : Nothing
578
#
579
 
580
sub SubDir
581
{
582
    Error ("SubDir directive not allowed after the Platform directive")
583
        if ( $ScmPlatformSeen );
584
}
585
 
586
 
587
###############################################################################
588
#   Platform support
589
###############################################################################
590
 
591
sub Platform
592
{
593
    my( $global, $file );
594
 
595
    Debug( "Platform( $ScmPlatform, @ScmPlatformArgs )" );
596
 
597
#.. Sanity test
598
#
599
    Error ("Platform directive is not allowed in common makefile.pl")
600
        if ( $ScmProcessingRootMake );
601
 
602
    Error ("Only one Platform directive is allowed")
603
        if ( $ScmPlatformSeen );
604
    $ScmPlatformSeen = 1;
605
 
606
#.. Arguments
607
#
608
    $ScmTargetHost = $::ScmHost;                # default
609
 
610
#.. Common configuration
611
#
612
    $global = $ScmGlobal;                       # Follow defs are "global's" ...
613
    $ScmGlobal = 1;
614
 
615
#.. Common rules (ScmHost specific)
616
#
617
    push( @ScmDepends, "$ScmMakelib" );         # parent
618
 
619
    $file = Require( "$::GBE_CONFIG", "Rules", "Common rules " );
620
    push( @ScmDepends, "$file" );
621
 
622
#.. Platform (defines ScmToolset)
623
#
369 dpurdie 624
    if ( ( %::ScmBuildProducts ) &&      # interface/build.cfg
4551 dpurdie 625
           $::ScmBuildProducts{ $ScmPlatform } )
227 dpurdie 626
    {
627
        my( @args ) = split( ',', $::ScmBuildProducts{ $ScmPlatform } );
628
 
629
        $ScmProduct = $args[0];
630
        $ScmTarget = $args[1];
631
 
632
        Debug( " mapping to product $ScmProduct" );
633
 
634
                                                # Platform/target specific
635
        MakeIf::PackageDirs( \@ScmPlatformDirs, $ScmPlatform, $ScmTarget );
636
        push @ScmPlatformDirs, "$::GBE_CONFIG"; # .. plus default
637
 
638
        @ScmPlatformArgs = ( "--product=$ScmProduct", @ScmPlatformArgs );
639
        $file = Require( "PLATFORM", $ScmTarget,
640
                    "Platform definition ", @ScmPlatformDirs );
641
    }
642
    else                                        # standard
643
    {
644
        Debug( " native platform" );
645
 
646
                                                # Platform specific
647
        MakeIf::PackageDirs( \@ScmPlatformDirs, $ScmPlatform );
648
        push @ScmPlatformDirs, "$::GBE_CONFIG"; # .. plus default
649
 
6133 dpurdie 650
        #   Map all GENERIC builds onto the one platform definition
4551 dpurdie 651
        my $platformDefs = $ScmPlatform;
6133 dpurdie 652
        if ($::BUILDINFO{$ScmPlatform}{IS_GENERIC})
653
        {
654
            $ScmNotGeneric = 0;
655
            $platformDefs = 'GENERIC' ;
656
        }
4551 dpurdie 657
 
658
        $file = Require( "PLATFORM", $platformDefs,
227 dpurdie 659
                    "Platform definition ", @ScmPlatformDirs );
660
    }
661
    push( @ScmDepends, "$file" );
662
 
663
    Error( "Toolset undefined for platform $ScmPlatform ...")
664
        unless( $ScmToolset );
665
 
666
#.. Toolset
667
#
668
    $file = Require( "$::GBE_CONFIG/TOOLSET", $ScmToolset, "Toolset definition " );
669
    push( @ScmDepends, "$file" );
670
 
671
#.. Package definitions
672
#
367 dpurdie 673
#   Global DPACKAGE definitions, which may pull in $ScmTarget specific definitions.
227 dpurdie 674
#
675
 
676
    MakeIf::PackageLoad( $ScmPlatform );        # DPACKAGE's (if any)
677
 
678
 
679
#.. Package extensions
680
#   Import, into the current package, files of the form gbe/DIRECTIVES
681
#   These allow the JATS directives to be extended by the contents of a package
682
#   without the need to update the core JATS release.
683
#
684
#   Intended use: Associate a directive with a tool script, such that the
685
#   new directive simplifies the use of the tool script.
686
#
687
#
688
#   First: Extend the Perl Search Space to include the toolset extensions
689
#          Although the directives are in gbe/DIRECTIVES/*.pm, they may need
690
#          to reference other packages that are not.
691
#
311 dpurdie 692
#           Look in the 'interface' and 'link' packages
693
#           The 'build' packages are duplicated into the 'interface'
694
#
227 dpurdie 695
    for my $path ( ToolExtensionPaths() )
696
    {
697
        UniquePush (\@INC, $path)
698
            if (glob( "$path/*.pm") || glob( "$path/*/*.pm"));
699
    }
700
 
701
    for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} })
702
    {
311 dpurdie 703
        next if ( $entry->{'TYPE'} eq 'build' );
227 dpurdie 704
        my $cfgdir = $entry->{'CFGDIR'};
705
        next unless ( $cfgdir );
706
        my $base_dir = $entry->{'ROOT'} . $cfgdir . '/DIRECTIVES';
707
        next unless ( -d $base_dir );
708
        foreach my $file  ( glob ("$base_dir/*.pm") )
709
        {
710
            push( @ScmDepends, "$file" );
711
            require $file;
712
        }
713
    }
714
 
715
    #
271 dpurdie 716
    #   Include local toolset extensions
717
    #   These are rooted in the build directory and are not to be confused with
718
    #   extensions that may be packaged
6387 dpurdie 719
    #   Simplify life - add the directory to the BUILDTOOLSPATH
271 dpurdie 720
    #
721
    my $local_base_dir = "$ScmRoot/gbe/DIRECTIVES";
722
    if ( -d $local_base_dir )
723
    {
6387 dpurdie 724
        unshift @::BUILDTOOLSPATH, AbsPath($local_base_dir); 
271 dpurdie 725
        foreach my $file  ( glob ("$local_base_dir/*.pm") )
726
        {
727
            push( @ScmDepends, "$file" );
728
            require $file;
729
        }
730
    }
731
 
732
    #
227 dpurdie 733
    #   All makefile.pl's will include a makefile.pl found in the build
734
    #   root directory ( The same directory as build.pl ). This makefile.pl
735
    #   is a little bit different - It should not "require "$ARGV[1]", nor
736
    #   should it use a Platform directive.
737
    #
738
    #   Note: This makefile is processed AFTER the toolset has been initialised
739
    #         so that toolset extensions are available to the directives
740
    #
741
    $file = "$ScmRoot/makefile.pl";
742
    if ( -e $file ) {
743
        $ScmProcessingRootMake = 1;
744
        require "$file";
745
        $ScmProcessingRootMake = 0;
746
        push( @ScmDepends, "$file" );
747
    }
748
 
749
    #
289 dpurdie 750
    #   Sanity Test for platforms that do not support both debug and production
751
    #   builds at the same time. This information is flagged by the toolset
752
    #   which we have now loaded.
753
    #
754
    if ( $ScmToolsetSingleType  )
755
    {
756
        unless ( $ScmBuildType )
757
        {
758
            Error ("The toolset used by the \"$ScmPlatform\" platform does not support",
759
                   "both Production and Debug Builds" );
760
        }
761
    }
762
 
763
    #
227 dpurdie 764
    #   Restore global status ...
765
    #
766
    $ScmGlobal = $global;
767
}
768
 
769
 
770
sub PlatformRequire
771
{
772
    my( $script, @arguments ) = @_;
773
    my( $file );
774
 
775
    Debug( "PlatformRequire($script, @arguments)" );
776
 
777
    push( @ScmPlatformArgs, @arguments );       # additional arguments
778
 
779
    $file = Require( "PLATFORM", $script,
780
                "PlatformRequire ", @ScmPlatformDirs );
781
 
782
    push( @ScmDepends, "$file" );
783
}
784
 
785
 
786
sub PlatformInclude
787
{
788
    my( $script, @arguments ) = @_;
789
    my( $file );
790
 
791
    Debug( "PlatformInclude( @_ )" );
792
 
793
    $file = Require2( \@arguments, "PLATFORM", $script,
794
                "PlatformInclude ", @ScmPlatformDirs );
795
 
796
    push( @ScmDepends, "$file" );
797
}
798
 
799
 
800
sub PlatformDefine
801
{
802
    Debug2( "PlatformDefine(@_)" );
803
 
804
    Define( @_ );
805
}
806
 
807
 
808
sub PlatformDefines
809
{
810
    my( $script ) = @_;
811
    my( $line );
812
 
813
    Debug2( "PlatformDefine(@_)" );
814
 
815
    $script = Exists( "PLATFORM", $script,      # locate image
816
                "PlatformDefines", @ScmPlatformDirs );
817
 
271 dpurdie 818
    push( @DEFINES, "# PlatformDefines from: $script" );
285 dpurdie 819
    open( my $fh, '<', $script ) || Error( "Opening $script" );
820
    while (<$fh>) {
227 dpurdie 821
        $_ =~ s/\s*(\n|$)//;                    # kill trailing whitespace & nl
822
        push( @DEFINES, $_ );
823
    }
824
    push( @ScmDepends, "$script" );             # makefile dependencies
285 dpurdie 825
    close( $fh );
227 dpurdie 826
}
827
 
828
 
829
sub PlatformEntry
830
{
831
    my( $prelim, $postlim, $prefix, $postfix, @elements ) = @_;
832
 
285 dpurdie 833
    my $str = "$prelim";
834
    foreach my $element ( @elements )
227 dpurdie 835
    {
836
        $str .= "${prefix}${element}${postfix}";
837
    }
838
    $str .= "$postlim";
839
    PlatformDefine( $str );
840
}
841
 
842
 
843
#
844
#   Add arguments to the ScmPlatformArgs, but remove "Global" arguments
845
#       --OnlyDebug
846
#       --OnlyProduction
343 dpurdie 847
#       --NoToolSet
227 dpurdie 848
#
289 dpurdie 849
#   Capture OnlyDebug and OnlyProd information
850
#   Will be sanitized by caller.
851
#
227 dpurdie 852
sub AddPlatformArg
853
{
854
    Debug("AddPlatformArg: @_" );
289 dpurdie 855
    foreach  ( @_ )
856
    {
857
        if ( m~^--OnlyDebug~ ) {
858
            $ScmBuildType = 'D';
859
        } elsif ( m~--OnlyProd~ ) {
860
            $ScmBuildType = 'P';
343 dpurdie 861
        } elsif ( m~--NoToolSet~ ) {
862
            $ScmNoToolsTest = 1;
289 dpurdie 863
        } else {
343 dpurdie 864
            UniquePush( \@::ScmPlatformArgs, $_ );
289 dpurdie 865
        }
866
    }
227 dpurdie 867
 
868
    Debug("AddPlatformArg: Result: @::ScmPlatformArgs" );
869
    1;
870
}
871
 
872
###############################################################################
873
# Toolset support
874
#
875
#   Toolset( 'platform [, ... ]', name, [arg, ... ] )
876
#       Specify the toolset for a platform
877
#
878
#   ToolDefine( )
879
#   ToolDefines( )
880
#       Specifies toolset defines for insertion into the target makefile.
881
#
882
#   ToolsetDir
883
#       Define toolset created directory(s) for removal during
884
#       'clean' operations.
885
#
886
#   ToolsetGenerate
887
#       Define toolset created file(s) for removal during
888
#       'clean' operations.
889
#
890
#   ToolsetObj
891
#       Define toolset created object(s) for removal during
892
#       'clean' operations.
893
#
894
#   ToolsetLib
895
#       Define toolset created library(s) for removal during
896
#       'clean' operations.
897
#
898
#   ToolsetProg
899
#       Define toolset created prog(s) for removal during
900
#       'clean' operations.
901
#
902
#   ToolsetRule( )
903
#   ToolsetRules( )
904
#       Specifies toolset rules for insertion into the target makefile.
905
#
906
##############################################################################
907
 
908
sub Toolset
909
{
910
    my( $platforms, $toolset, @arguments ) = @_;
911
 
912
    Debug2( "Toolset(@_)" );
913
 
4309 dpurdie 914
    return 1 if ( ! ActivePlatform($platforms) );
227 dpurdie 915
 
916
    $ScmToolset = $toolset;
917
    @ScmToolsetArgs = @arguments;
4309 dpurdie 918
    return 1;
227 dpurdie 919
}
920
 
921
 
922
sub ToolsetRequire
923
{
924
    my( $script, @arguments ) = @_;
925
    my( $file );
926
 
927
    Debug2( "ToolsetRequire(@_)" );
928
 
929
    @ScmToolsetArgs = @arguments;
930
    $file = Require( "",
931
                     $script,
932
                     "ToolsetRequire",
933
                     "$::GBE_CONFIG/TOOLSET", @::BUILDTOOLSPATH );
934
    push( @ScmDepends, "$file" );
935
}
936
 
937
 
938
sub ToolsetDefine
939
{
940
    Debug2( "ToolsetDefine(@_)" );
941
 
942
    Define( @_ );
943
}
944
 
945
 
946
sub ToolsetDefines
947
{
948
    Debug2( "ToolsetDefines(@_)" );
949
 
261 dpurdie 950
    Defines( "$::GBE_CONFIG/TOOLSET", @_ );
227 dpurdie 951
}
952
 
953
 
954
sub ToolsetDir
955
{
956
    Debug2( "ToolsetDir(@_)" );
957
 
261 dpurdie 958
    UniquePush ( \@TOOLSETDIRS, @_ );
227 dpurdie 959
}
960
 
961
 
962
sub ToolsetDirTree
963
{
964
    Debug2( "ToolsetDirTree(@_)" );
965
 
261 dpurdie 966
    UniquePush ( \@TOOLSETDIRTREES, @_);
227 dpurdie 967
}
968
 
969
 
970
sub ToolsetGenerate
971
{
972
    Debug2( "ToolsetGenerate(@_)" );
973
 
974
    UniquePush( \@TOOLSETGENERATED, @_ );
975
}
976
 
977
 
978
sub ToolsetObj
979
{
980
    Debug2( "ToolsetObj(@_)" );
981
 
261 dpurdie 982
    foreach my $obj ( @_ )
227 dpurdie 983
    {
261 dpurdie 984
        UniquePush( \@TOOLSETOBJS, "$obj.$::o"  );
227 dpurdie 985
    }
986
}
987
 
988
 
989
sub ToolsetLib
990
{
991
    Debug2( "ToolsetLib(@_)" );
992
 
261 dpurdie 993
    foreach my $lib ( @_ )
227 dpurdie 994
    {
289 dpurdie 995
        UniquePush( \@TOOLSETLIBS, GenLibName( $lib ) );
227 dpurdie 996
    }
997
}
998
 
999
 
1000
sub ToolsetProg
1001
{
1002
    Debug2( "ToolsetProg(@_)" );
1003
 
261 dpurdie 1004
    foreach my $prog ( @_ )
227 dpurdie 1005
    {
289 dpurdie 1006
        UniquePush( \@TOOLSETPROGS, GenProgName( $prog ) );
227 dpurdie 1007
    }
1008
}
1009
 
1010
 
1011
sub ToolsetRule
1012
{
1013
    Debug2( "ToolsetRule(@_)" );
1014
 
1015
    push( @TOOLSETRULES, @_ );
1016
}
1017
 
1018
 
1019
sub ToolsetRules
1020
{
1021
    my( $script ) = @_;
1022
    my( $line );
1023
 
1024
    Debug2( "ToolsetRules(@_)" );
1025
 
1026
    $script = Exists( "$::GBE_CONFIG/TOOLSET", $script, "ToolsetRules" );
271 dpurdie 1027
    push( @TOOLSETRULES, "# ToolsetRules from: $script" );
285 dpurdie 1028
    open( my $fh, '<', $script ) || Error( "Opening $script" );
1029
    while (<$fh>) {
227 dpurdie 1030
        $_ =~ s/\s*(\n|$)//;                    # kill trailing whitespace & newline
1031
        push( @TOOLSETRULES, $_ );
1032
    }
1033
    push( @ScmDepends, "$script" );             # makefile dependencies
285 dpurdie 1034
    close( $fh );
227 dpurdie 1035
}
1036
 
4778 dpurdie 1037
#-------------------------------------------------------------------------------
4902 dpurdie 1038
# Function        : SetGlobalOption  
1039
#
1040
# Description     : Set a global toolset option
1041
#                   The global options are intended to allow platform-specific
1042
#                   operation of various tools and utilities. The scope is wider than 
1043
#                   just the underlying tooolset 
1044
#
1045
# Inputs          : $name           - Name of the option
1046
#                   $value          - Value to save            
1047
#
1048
# Returns         : Nothing
1049
#
1050
 
1051
sub SetGlobalOption
1052
{
1053
    my ($name, $value) = @_;
4928 dpurdie 1054
    Debug( "SetGlobalOption.", $name, $value );
4902 dpurdie 1055
    $ScmGlobalOptions{$name} = $value;
1056
}
1057
 
1058
#-------------------------------------------------------------------------------
1059
# Function        : GetGlobalOption   
1060
#
1061
# Description     : Get a global toolset option
1062
#
1063
# Inputs          : $name           - Name of the option to fetch
1064
#                   $default        - Default value to return, if the option
1065
#                                     is not present.
1066
#
1067
# Returns         : The value of the option, or the default value
1068
#
1069
 
1070
sub GetGlobalOption 
1071
{
1072
    my ($name, $default) = @_;
1073
    if (exists $ScmGlobalOptions{$name})
1074
    {
1075
        $default = $ScmGlobalOptions{$name};
1076
    }
4928 dpurdie 1077
    Debug( "GetGlobalOption .", $name, $default  );
4902 dpurdie 1078
    return $default;
1079
}
1080
 
1081
 
1082
#-------------------------------------------------------------------------------
4778 dpurdie 1083
# Function        : ToolsetAddUnitTestPreProcess
1084
#                   ToolsetAddUnitTestPostProcess
1085
#                   ToolsetAddUnitTestCollateProcess
1086
#
1087
# Description     : Functions to allow toolsets to add recipes to be run before
1088
#                   and after Unit Tests are run.    
1089
#
1090
# Inputs          : $target         - Name of the recipe to be run 
1091
#
1092
# Returns         : Nothing
1093
#
1094
sub ToolsetAddUnitTestPreProcess
1095
{
1096
    _ToolsetAddUnitTest(\@TOOLSET_UTF_PRE, @_ );
1097
}
227 dpurdie 1098
 
4778 dpurdie 1099
sub ToolsetAddUnitTestPostProcess
1100
{
1101
    _ToolsetAddUnitTest(\@TOOLSET_UTF_POST, @_ );
1102
}
1103
 
1104
sub ToolsetAddUnitTestCollateProcess
1105
{
1106
    _ToolsetAddUnitTest(\@TOOLSET_UTF_COLLATE, @_ );
1107
}
1108
 
1109
#-------------------------------------------------------------------------------
1110
# Function        : _ToolsetAddUnitTest  
1111
#
1112
# Description     : Internal helper function used by ToolsetAddUnitTest*
1113
#
1114
# Inputs          : $aref           - Ref to an array of names to extend
1115
#                   $target         - Name of recipe to run 
1116
#
1117
# Returns         : Nothing
1118
#
1119
sub _ToolsetAddUnitTest
1120
{
1121
    my ($aref, $target ) = @_;
1122
 
1123
    #   Determine name of parent function
1124
    my $fname = (caller(1))[3];
1125
    $fname =~ s~.*::~~;
1126
    Debug2( "$fname ($target)" );
1127
 
1128
    #
1129
    #   Ensure user is not using a reserved target
1130
    #
1131
    if (grep {$_ eq $target} @reservedMakeTargets) {
1132
        Error("Internal: $fname uses reserved make taget: $target");
1133
    }
1134
 
1135
    push @$aref, $target;
1136
 
1137
}
1138
 
227 dpurdie 1139
###############################################################################
1140
# User interface:
1141
#
1142
#   AddFlags( 'platform [, ... ]', 'flags' [, 'flag' ... ] )
1143
#       This subroutine takes the C and C++ compiler flags
1144
#       specified adding them to a global list for later
1145
#       inclusion in the built makefile.
1146
#
1147
#   AddCFlags( 'platform [, ... ]', 'flags' [, 'flag' ... ] )
1148
#       This subroutine takes the C compiler flags
1149
#       specified adding them to a global list for later
1150
#       inclusion in the built makefile.
1151
#
1152
#   AddCXXFlags( 'platform [, ... ]', 'flags' [, 'flag' ... ] )
1153
#       This subroutine takes the C++ compiler flags
1154
#       specified adding them to a global list for later
1155
#       inclusion in the built makefile.
1156
#
1157
#   AddLintFlags( 'platform [, ... ]', 'flags' [, ... ] )
1158
#       This subroutine takes the Lint flags specified
1159
#       adding them to a global list for later inclusion
1160
#       in the built makefile.
1161
#
1162
#   AddASFlags( 'platform [, ... ]', 'flags' [, ... ] )
1163
#       This subroutine takes the Assemler flags specified
1164
#       adding them to a global list for later inclusion
1165
#       in the built makefile.
1166
#
1167
#   AddLDFlags( 'platform [, ... ]', 'flags' [, ... ] )
1168
#       This subroutine takes the Linker flags specified
1169
#       adding them to a global list for later inclusion
1170
#       in the built makefile.
1171
#
1172
#   AddDir
1173
#       This subroutine takes the directories specified adding
1174
#       them to a global include and source directory list for
1175
#       later inclusion in the built makefile.
1176
#
1177
#   AddIncDir( 'platform [, ... ]', 'dir' [, ... ] )
1178
#       This subroutine takes the include file directories
1179
#       specified adding them to a global list for later
1180
#       inclusion in the built makefile.
1181
#
1182
#   AddSrcDir( 'platform [, ... ]', 'dir' [, ... ] )
1183
#       This subroutine takes the source file directories
1184
#       specified adding them to a global list used to resolve
1185
#       Src() definitions.
1186
#
1187
#   AddLibDir( 'platform [, ... ]', 'dir' [, ... ] )
1188
#       This subroutine takes the library directories
1189
#       specified adding them to a global list for later
1190
#       inclusion in the built makefile.
1191
#
1192
#   AddSourceType( 'ext', '.c|.cc|.asm' )
1193
#       This subroutine takes the extension(s) specified by the
1194
#       programmer and adds them to a global list for later
1195
#       inclusion in the built makefile.  This list contains
1196
#       the extensions to be recognised as 'C', 'C++' or
1197
#       assembler file types.
1198
#
1199
#   AddSourceFile( 'platform [, ... ]', 'file' [, ... ] )
1200
#       This subroutine takes the non-standard source file(s)
1201
#       and adds them add it to either C, C++ or assembler
1202
#       sources and the object list.
1203
#
1204
#   Init( 'platform [, ... ]', 'rule' )
1205
#       Initialisation rule
1206
#
1207
#   Generate( 'platform [, ... ]', 'file' [, ... ] )
1208
#       This subroutine is used to add the list of given
1209
#       source files to the generate sources list, and if
1210
#       the generated source is of type C, C++ or assember
1211
#       also adds it to either C, C++ or assembler sources and
1212
#       the object lists.
1213
#
1214
#       --c             Treat as a C source file.
1215
#       --cpp           Treat as a C++ source file.
1216
#       --asm           Treat as a assembler source file.
1217
#
1218
#   Rule( 'platform [, ... ]', definition )
1219
#       This subroutine is used to add the non-standard make
1220
#       rules required to build the system.  eg. any rules
1221
#       necessary to produce a .cc & .h file from a .x file.
1222
#
1223
#   Src( 'platform [, ... ]', 'file' [, ... ], [ 'arg' [, ...]] )
1224
#       This subroutine is used to add the list of given source
1225
#       files to the sources list, and if the source is of type
1226
#       C, C++ or assember also adds it to either C, C++ or
1227
#       assembler sources and the object lists.  The optional
1228
#       list of arguments is assigned to all source files.
1229
#
1230
#       --c             Treat as a C source file.
1231
#       --cpp           Treat as a C++ source file.
1232
#       --asm           Treat as a assembler source file.
1233
#       --Shared        Shared, produces position-independent
1234
#                       code (on targets where required).
1235
#
1236
#   Lib( 'platform [, ... ]', 'name', 'obj' [, ... ] [, '-arg' [, ... ]] )
1237
#       This subroutine takes a library definition list and adds
1238
#       the  entries to the 3 libraries definition lists. 'name'
1239
#       of the library to be created.  List of the object files
1240
#       'obj' that make up this library.  List of special
1241
#       arguments 'arg' to pass to the librarian.
1242
#
1243
#   MergeLibrary( 'platform [, ... ]', 'name', 'lib' [, ... ] )
1244
#       This subroutine takes a library merge list and adds
1245
#       the  entries to the 2 merge libraries definition lists. 'name'
1246
#       of the library to be created.  List of the libraries to be merged
1247
#
1248
#   LocalScript( 'platform [, ... ]', name, ['1'] )
1249
#   Script( 'platform [, ... ]', name, ['1'] )
1250
#       This subroutine takes a list that defines the name of
1251
#       the script to be placed in the platform 'bin' directory,
1252
#       and an optional second element that defines whether the
1253
#       script should be made executable or not.
1254
#
1255
#   Prog( 'platform [, ... ]', 'name', ['obj', ... ],
1256
#               ['-llib', ... ], ['options'] )
1257
#       This subroutine takes a list that defines which program
1258
#       (binary) is to be made, what libraries and object it is
1259
#       made from, and any special commands required to perform
1260
#       the program creation.
1261
#
1262
#       @PROGS          Updated list of programs to create
1263
#
1264
#   TestProg( 'platform [, ... ]', 'name', ['obj', ... ],
1265
#               ['-llib', ... ], ['options'] )
1266
#       This subroutine takes a list that defines which test program
1267
#       (binary) is to be made, what libraries and object it is
1268
#       made from, and any special commands required to perform
1269
#       the program creation.
1270
#
1271
#       @TESTPROGS      Updated list of programs to create
1272
#
1273
#   InstallHdr( 'platform [, ... ]', 'file' [, ...], ['-arg'] )
1274
#       This subroutine takes the given list of files and adds them
1275
#       to the install header files list.  Files in this list will be
1276
#       installed into the 'local header directory' area for public
1277
#       consumption.  This is generally API files for other modules
1278
#       to use.
1279
#
1280
#       --Strip         Strip directory from source
6276 dpurdie 1281
#       --Strip=n       Strip part of directory from source
227 dpurdie 1282
#       --Full          Install using full path
1283
#       --Subdir=subdir Install within the specified sub-directory
1284
#       --Prefix=subdir   "       "     "      "      "     "
1285
#
1286
#   InstallLib( 'platform [, ... ]', 'file', ['subdir'] )
1287
#       This subroutine takes the given list of files and adds them
1288
#       to the install libraries files list.  Files in this list will
1289
#       be installed into the 'local library directory' area for
1290
#       public consumption.
1291
#
1292
#   InstallProg( 'platform [, ... ]', 'file', ['subdir'] ) )
1293
#       This subroutine takes a list that defines the executable file
1294
#       that is to be installed.  The file in this list will be
1295
#       installed into the 'local executable directory' specified for
1296
#       public consumption.
1297
#
1298
###############################################################################
1299
 
1300
 
1301
sub Include                                     # User include
1302
{
1303
    my( $path, $name ) = @_;
1304
    my( $file );
1305
 
1306
    $file = Require( $path, $name, "Include" );
1307
    push( @ScmDepends, "$file" );
1308
}
1309
 
1310
sub ForceCCompile
1311
{
1312
    CompileOptions( $_[0], 'compile_as_c' );            # Backward compatability
1313
}
1314
 
1315
#-------------------------------------------------------------------------------
1316
#   Create a data structure to define the global compiler options
1317
#    The hash is keyed by compiler option
1318
#    The value contains another hash.
1319
#       The key is a makefile variable to set ( or remove )
1320
#       The value is the value to assign to the makefile variable
1321
#       If the value is 'undef' then the variable will be deleted
1322
#
1323
#   Keys of the form key=value are also supported
1324
#
1325
#   If the value is a CODE reference, then routine will be called with the key
1326
#   and value as arguments. The return value will be utilised.
1327
#
1328
our %ScmCompilerOptions =
1329
    (
1330
        'strict_ansi'           => { 'USE_STRICT_ANSI'    => '1' },
1331
        'no_strict_ansi'        => { 'USE_STRICT_ANSI'    => '' },      # Default
1332
 
1333
        'profile'               => { 'USE_PROFILE'        => '1' },
1334
        'no_profile'            => { 'USE_PROFILE'        => '' },       # Default
1335
 
1336
 
1337
        'prod_no_optimise'      => { 'PROD_USE_OPTIMISE'   => '' },
1338
        'prod_no_debuginfo'     => { 'PROD_USE_DEBUGINFO'  => '' },     # Default
1339
        'prod_optimise'         => { 'PROD_USE_OPTIMISE'   => '1' },    # Default
1340
        'prod_debuginfo'        => { 'PROD_USE_DEBUGINFO'  => '1' },
1341
 
1342
        'debug_no_optimise'     => { 'DEBUG_USE_OPTIMISE'  => '' },     # Default
1343
        'debug_no_debuginfo'    => { 'DEBUG_USE_DEBUGINFO' => '' },
1344
        'debug_optimise'        => { 'DEBUG_USE_OPTIMISE'  => '1' },
1345
        'debug_debuginfo'       => { 'DEBUG_USE_DEBUGINFO' => '1' },    # Default
1346
 
1347
        'compile_as_cpp'        => { 'FORCE_CC_COMPILE'    => '1',
1348
                                     'FORCE_C_COMPILE'     => undef },
1349
        'compile_as_c'          => { 'FORCE_C_COMPILE'     => '1',
1350
                                     'FORCE_CC_COMPILE'    => undef },
267 dpurdie 1351
 
1352
        'no_define_source_file' => { 'DISABLE__SOURCE__' => '1' },
4928 dpurdie 1353
        'define_source_file'    => { 'DISABLE__SOURCE__' => undef },        # Default
267 dpurdie 1354
 
4928 dpurdie 1355
        'warnings_as_errors'    => { 'WARNINGS_AS_ERRORS'        => '1' },
1356
        'no_warnings_as_errors' => { 'WARNINGS_AS_ERRORS'        => undef },       # Default
1357
 
227 dpurdie 1358
    );
1359
 
1360
#
1361
#   The toolset can extend the options by setting the following hash
1362
#
1363
our %ScmToolsetCompilerOptions = ();
1364
 
1365
#
1366
#   Define default compiler options
1367
#   These are makefile variables that will be assigned
1368
#
1369
our %ScmCompilerOpts =
1370
    (
1371
        'USE_STRICT_ANSI'       => '',
1372
        'USE_PROFILE'           => '',
1373
        'PROD_USE_DEBUGINFO'    => '',
1374
        'PROD_USE_OPTIMISE'     => '1',
1375
        'DEBUG_USE_OPTIMISE'    => '',
1376
        'DEBUG_USE_DEBUGINFO'   => '1',
1377
    );
1378
 
1379
 
1380
sub CompileOptions
1381
{
1382
    my( $platforms, @elements ) = @_;
1383
    return if ( ! ActivePlatform($platforms) );
1384
 
1385
    for (@elements)
1386
    {
1387
        my $oref;
1388
 
1389
        #
1390
        #   The toolset option may be a text string or a definition
1391
        #       Name        - A text string
1392
        #       Name=Value  - A value
1393
        #
1394
        my $value;
1395
        my $key = $_;
1396
        if ( $key =~ m~(.*=)(.*)~ )
1397
        {
1398
            $key = $1;
1399
            $value = $2 || '';
1400
        }
247 dpurdie 1401
        $key = lc( $key );
227 dpurdie 1402
 
1403
        #
1404
        #   Examine the global flags
1405
        #   Then the toolset extensions
1406
        #   Then just drop it
1407
        #
1408
        unless ( $oref = ($ScmCompilerOptions{$key} || $ScmToolsetCompilerOptions{$key}) )
1409
        {
1410
            Warning ("Compile Option ignored: $_");
1411
            next;
1412
        }
1413
 
1414
        #
1415
        #   Parse the definition and adjust makefile variables as required
1416
        #   Set the value of a make variable or remove the definition
1417
        #
1418
        #   If the user value is a code reference, then call the code
1419
        #   and use the returned value as the value.
1420
        #
1421
        while ( (my($ukey, $uvalue)) = each %{$oref} )
1422
        {
1423
            if ( defined( $uvalue) )
1424
            {
1425
                if ( ref($uvalue) eq "CODE" )
1426
                {
255 dpurdie 1427
                    $uvalue = &$uvalue( $key, $value, $ukey);
227 dpurdie 1428
                    unless ( defined $uvalue )
1429
                    {
1430
                        Warning ("Compile Option ignored: $_");
1431
                        next;
1432
                    }
1433
                }
247 dpurdie 1434
                elsif ( defined $value )
1435
                {
1436
                    $uvalue = $value;
1437
                }
227 dpurdie 1438
 
1439
                $ScmCompilerOpts{$ukey} = $uvalue;
1440
            }
1441
            else
1442
            {
1443
                delete $ScmCompilerOpts{$ukey};
1444
            }
1445
        }
1446
    }
1447
}
1448
 
1449
#-------------------------------------------------------------------------------
1450
# Function        : AddFlags
1451
#                   AddCFlags
1452
#                   AddCXXFlags
1453
#                   AddASFlags
1454
#                   AddLDFlags
1455
#                   AddLintFlags
1456
#
1457
# Description     : Add target specfic flags to the C compiler
1458
#                   This SHOULD only be used to add Defines to the compiler
1459
#                   but it can be absued.
1460
#
1461
# Inputs          : $platform       - Platforms for which the directive is active
1462
#                   ...             - list of flags to add
1463
#
1464
#                   Embedded options include:
1465
#                       --Debug     - Following options are added to the debug build
1466
#                       --Prod      - Following options are added to the production build
1467
#
1468
# Returns         : Nothing
1469
#
1470
 
1471
sub AddFlags
1472
{
1473
    my( $platforms, @elements ) = @_;
1474
 
1475
    AddCFlags( $platforms, @elements );
1476
    AddCXXFlags( $platforms, @elements );
1477
}
1478
 
1479
sub AddCFlags
1480
{
1481
    my( $platforms, @elements ) = @_;
1482
 
1483
    Debug2( "AddCFlags($platforms, @elements)" );
1484
    return if ( ! ActivePlatform($platforms) );
1485
 
1486
    WarnIfNastyFlag( @elements );
1487
    __AddFlags( "CFLAGS", \@elements,
1488
                \@CFLAGS, \@CLINTFLAGS,
1489
                \@CFLAGS_DEBUG, \@CLINTFLAGS_DEBUG,
1490
                \@CFLAGS_PROD,  \@CLINTFLAGS_PROD );
1491
}
1492
 
1493
sub AddCXXFlags
1494
{
1495
    my( $platforms, @elements ) = @_;
1496
 
1497
    Debug2( "AddCXXFlags($platforms, @elements)" );
1498
    return if ( ! ActivePlatform($platforms) );
1499
 
1500
    WarnIfNastyFlag( @elements );
1501
    __AddFlags( "CXXFLAGS", \@elements,
1502
               \@CXXFLAGS, \@CXXLINTFLAGS,
1503
               \@CXXFLAGS_DEBUG, \@CXXLINTFLAGS_DEBUG,
1504
               \@CXXFLAGS_PROD,  \@CXXLINTFLAGS_PROD );
1505
}
1506
 
1507
sub AddASFlags
1508
{
1509
    my( $platforms, @elements ) = @_;
1510
 
1511
    Debug2( "AddASFlags($platforms, @elements)" );
1512
 
1513
    return if ( ! ActivePlatform($platforms) );
1514
 
267 dpurdie 1515
    __AddFlags( "ASFLAGS", \@elements,
1516
                \@ASFLAGS, undef,
1517
                \@ASFLAGS_DEBUG, undef,
1518
                \@ASFLAGS_PROD, undef );
227 dpurdie 1519
}
1520
 
1521
sub AddLDFlags
1522
{
1523
    my( $platforms, @elements ) = @_;
1524
 
1525
    Debug2( "AddLDFlags($platforms, @elements)" );
1526
 
1527
    return if ( ! ActivePlatform($platforms) );
1528
 
1529
    foreach  ( @elements )
1530
    {
267 dpurdie 1531
        next if ( m~^--(Debug|Prod)~ );
227 dpurdie 1532
        Warning("Use of linker flag discouraged (will be used): $_");
1533
    }
267 dpurdie 1534
    __AddFlags( "LDFLAGS", \@elements,
1535
                \@LDFLAGS, undef,
1536
                \@LDFLAGS_DEBUG, undef,
1537
                \@LDFLAGS_PROD, undef );
227 dpurdie 1538
 
1539
}
1540
 
1541
sub AddLintFlags
1542
{
1543
    my( $platforms, @elements ) = @_;
1544
 
1545
    return if ( ! ActivePlatform($platforms) );
1546
 
1547
    Debug2( "AddLintFlags($platforms, @elements)" );
1548
 
1549
    __AddFlags( "LINTFLAG", \@elements,
1550
                \@CLINTFLAGS, \@CXXLINTFLAGS,
1551
                \@CLINTFLAGS_DEBUG, \@CXXLINTFLAGS_DEBUG,
1552
                \@CLINTFLAGS_PROD, \@CXXLINTFLAGS_PROD  );
1553
}
1554
 
1555
 
1556
#-------------------------------------------------------------------------------
1557
# Function        : __AddFlags
1558
#
1559
# Description     : Generic flag adding to lists routine
1560
#                   Internal use only
1561
#
1562
#                   Supports --Debug and --Prod options
1563
#                   if the appropriate list is present.
1564
#
1565
# Inputs          : Lots
1566
#                   References to compiler and lint flags for
1567
#                   common, debug and product builds.
1568
#
1569
#                   Not all the lists are needed.
1570
#
1571
# Returns         : Nothing
1572
#
1573
sub __AddFlags
1574
{
1575
    my ($textname, $eref,
1576
                   $f_all,      $flint_all,
1577
                   $f_debug,    $flint_debug,
1578
                   $f_prod,     $flint_prod ) = @_;
1579
 
1580
    #
1581
    #   Start added flags to the ALL lists
1582
    #
1583
    my $list = $f_all;
1584
    my $lintlist = $flint_all;
1585
    my $nowarn = 0;
1586
 
1587
    #
1588
    #   Process flags up front
1589
    #
1590
    $nowarn = 1 if ( grep (/^--NoWarn$/, @$eref) );
1591
 
1592
    #
1593
    #   Process all the user arguments
1594
    #
1595
    ADD:
1596
    foreach my $element ( @$eref )
1597
    {
1598
        #
1599
        #   Skip flags
1600
        #
1601
        if ( $element eq '--NoWarn' )
1602
        {
1603
            next;
1604
        }
1605
 
1606
        #
1607
        #   Detect --Debug and --Prod options and swap
1608
        #   lists accordingly.
1609
        #
1610
        if ( $element eq '--Debug' )
1611
        {
1612
            Error ("--Debug not supported for $textname") unless ( $f_debug );
1613
            $list = $f_debug;
1614
            $lintlist = $flint_debug;
1615
            next;
1616
        }
1617
 
1618
        if ( $element eq '--Prod' )
1619
        {
1620
            Error ("--Prod not supported for $textname") unless ( $f_prod );
1621
            $list = $f_prod;
1622
            $lintlist = $flint_prod;
1623
            next;
1624
        }
1625
 
1626
        #
1627
        #   Scan all the lists for a possible duplicates
1628
        #
1629
        foreach my $temp ( @$f_all, @$f_debug, @$f_prod ) {
1630
            if ($temp eq $element) {
1631
                Warning( "Duplicate $textname ignored '$element'") unless $nowarn;
1632
                next ADD;
1633
            }
1634
        }
1635
 
1636
        #
1637
        #   Add the flag to the compiler and lint lists
1638
        #
1639
        push( @$list, $element ) if $list;
1640
        push( @$lintlist, $element ) if $lintlist;
1641
    }
1642
}
1643
 
1644
sub WarnIfNastyFlag
1645
{
1646
    foreach  ( @_ )
1647
    {
1648
        Warning("Use of compiler flags discouraged (will be used): $_")
1649
            unless ( m/^-[DU]/ || m/^--Debug/ || m/^--Prod/ || /^--NoWarn/ );
1650
    }
1651
}
1652
 
1653
 
1654
sub AddDir
1655
{
1656
    AddIncDir( @_);
1657
    AddSrcDir( @_ );
1658
}
1659
 
1660
 
1661
sub AddIncDir
1662
{
1663
    _AddDir( 'AddIncDir', 'INCDIR', \@INCDIRS, \@S_INCDIRS, \@G_INCDIRS, \@L_INCDIRS, @_ );
1664
}                                                           
1665
 
1666
sub AddSrcDir                                               
1667
{                                                           
1668
    _AddDir( 'AddSrcDir', 'SRCDIR', \@SRCDIRS, \@S_SRCDIRS, \@G_SRCDIRS, \@L_SRCDIRS, @_ );
1669
}                                                           
1670
 
1671
sub AddLibDir                                               
1672
{                                                           
1673
    _AddDir( 'AddLibDir', 'LIBDIR', \@LIBDIRS, \@S_LIBDIRS, \@G_LIBDIRS, \@L_LIBDIRS, @_ );
1674
}
1675
 
1676
#-------------------------------------------------------------------------------
1677
# Function        : _AddDir
1678
#
1679
# Description     : Internal routine to add a directory to list of directories
1680
#                   Common code to simplify implementation of other directives
1681
#
1682
# Inputs          : $name           - Name of function
1683
#                   $udir           - User name of dir list
1684
#                   $dirref         - Reference to directory array
1685
#                   $s_dirref       - Reference to system directory array
1686
#                   $g_dirref       - Reference to global directory array
1687
#                   $l_dirref       - Reference to local directory array
1688
#                   @args           - User arguments
1689
#                                       - platforms
1690
#                                       - Directories and --Options
1691
#
1692
sub _AddDir
1693
{
1694
    my( $name, $udir, $dirref, $s_dirref, $g_dirref, $l_dirref, $platforms, @elements ) = @_;
1695
 
1696
    Debug ( "$name($platforms, @elements)" );
1697
    Error ( "$name: Insufficient arguments") unless ( @elements );
1698
    return if ( ! ActivePlatform($platforms) );
1699
 
1700
    #
1701
    #   Cleanup user parameters
1702
    #
1703
    foreach ( @elements )
1704
    {
1705
        s/^\s+//;                               # Remove leading space
1706
        s/\s+$//;                               # Remove trailing spaces
1707
        s~/$~~;                                 # Remove trailing /
1708
        s~//~/~g;                               # Remove multiple /
1709
    }
1710
 
1711
#.. Collect arguments
1712
    my $tlist_ref = $ScmGlobal ? $g_dirref : $l_dirref; # "current" scope ....
1713
    my $nowarn = 0;
1714
    my $nodepend = 0;
1715
    my @dirs;
1716
 
1717
    foreach ( @elements )
1718
    {
1719
        if ( ! /^--/ ) {                        # Collect directories
1720
            push @dirs, $_;
1721
 
1722
        } elsif (/^--Local$/) {                 # "local" scope ....
1723
            $tlist_ref = $l_dirref;
1724
 
1725
        } elsif (/^--Global$/) {                # "global" scope ...
1726
            $tlist_ref = $g_dirref;
1727
 
1728
        } elsif (/^--System$/) {                # "system" scope ...
1729
            $tlist_ref = $s_dirref;
1730
 
1731
        } elsif (/^--NoDepend$/) {              # Split from dependency list
1732
            if ( $udir eq 'INCDIR' ) {          # AddIncDir only
1733
                $nodepend = 1;
1734
            }
1735
 
1736
        } elsif (/^--NoWarn$/) {                # Disable warnings
1737
            $nowarn = 1;
1738
 
1739
        } elsif (/^--(.*)/) {
1740
            Message( "$name: unknown option $_ -- ignored\n" );
1741
 
1742
        }
1743
    }
1744
 
1745
    Error ( "$name: No directory specified: ($platforms, @elements)" )
1746
        unless ( @dirs );
1747
 
1748
 
1749
#.. Push source path(s)
1750
    foreach ( @dirs )
1751
    {
1752
        #
1753
        #   Add to complete list of directories
1754
        #   Warn on duplicates
1755
        #
1756
        unless ( UniquePush( $dirref, $_) )
1757
        {
1758
            Warning( "Duplicate $udir ignored '$_'" )
1759
                unless ( $nowarn );
1760
            next;
1761
        }
1762
 
1763
        #
1764
        #   Check that the directory actually exists
1765
        #   If the path contains a $(XXXXX) then it can't be checked
1766
        #
1767
        if ( index( $_, '$' ) == -1 )
1768
        {
1769
            Warning( "$name. Directory not found: $_",
1770
                     "Current directory         : $::Cwd",
2450 dpurdie 1771
                     "Cannot resolved Directory : " . AbsPath($_, $::Cwd, 1),
227 dpurdie 1772
                       )
1773
                unless ( $nowarn || -d $_ );
1774
        }
1775
 
1776
        #
1777
        #   Add to suitable list
1778
        #
1779
        push @{$tlist_ref}, $_;
6133 dpurdie 1780
        ToolsetFiles::AddDir($_, 'Include');
227 dpurdie 1781
 
1782
        #
1783
        #   Add to the no dependancy list (ie generated depend file)
1784
        #   Only used by AddIncDir, accepted by AddSrcDir
1785
        #
1786
        push( @NODEPDIRS, $_ )
1787
            if ($nodepend);
1788
    }
1789
}
1790
 
6177 dpurdie 1791
#-------------------------------------------------------------------------------
1792
# Function        : ExtendIncDir 
1793
#
1794
# Description     : Allow the directory search paths to be extended into sub
1795
#                   directories.
1796
#                   
1797
#                   Limit use, but ...
1798
#
1799
# Inputs          : $platform       - Active platforms
1800
#                   ...             - Path extensions
1801
#
1802
# Returns         : 
1803
#
1804
my  %ExtendIncDirSeen;
1805
sub ExtendIncDir
1806
{
1807
    my( $platforms, @paths ) = @_;
1808
    Debug2( "ExtendIncDir($platforms, @paths)" );
1809
    return if ( ! ActivePlatform($platforms) );
1810
    Error ('ExtendIncDir. No extensions listed') unless @paths;
1811
    #
1812
    #   Ensure the user only extends the paths once.
1813
    #   Could silently discard excess - better to force the user to get it right
1814
    #
1815
    foreach my $path ( @paths) {
1816
        ReportError ('ExtendIncDir. Multiple defintions for: ' . $path) if exists $ExtendIncDirSeen{$path}; 
1817
        $ExtendIncDirSeen{$path} = 0;
1818
    }
1819
    ErrorDoExit();
227 dpurdie 1820
 
6177 dpurdie 1821
    #
1822
    #   Zip though all the packages and extend the search paths
1823
    #   Also gets those in the interface directory
1824
    #
1825
    for my $package (@{$::ScmBuildPkgRules{$ScmPlatform} })
1826
    {
1827
        #DebugDumpData("package", $package);
1828
        foreach my $path ( @paths)
1829
        {
1830
            if ( $package->{PINCDIRS})
1831
            {
1832
                my @output;
1833
                foreach my $pdir ( @{$package->{PINCDIRS}})
1834
                {
1835
                    my $tdir = catdir ($pdir, $path);
1836
                    my $adir = catdir ($package->{ROOT}, $tdir);
1837
                    if ( -d $adir) {
1838
                        Verbose("Extending $package->{DNAME} $package->{VERSION}: $tdir");
1839
                        push @output, $tdir;
1840
                        $ExtendIncDirSeen{$path}++;
1841
                    }
1842
                    push @output, $pdir;
1843
                }
1844
              @{$package->{PINCDIRS}} = @output;
1845
            }
1846
        }
1847
    }
1848
 
1849
    #
1850
    #   Report extensions that have not been used
1851
    #
1852
    foreach my $path ( @paths) {
1853
        ReportError ('ExtendIncDir. Search path not extendable: ' . $path) unless $ExtendIncDirSeen{$path}; 
1854
    }
1855
 
1856
    ErrorDoExit();
1857
}
1858
 
1859
 
227 dpurdie 1860
sub AddProg
1861
{
1862
    my( $platforms, @progs ) = @_;
1863
 
1864
    Debug2( "AddProg($platforms, @progs)" );
1865
 
1866
    return if ( ! ActivePlatform($platforms) );
1867
 
285 dpurdie 1868
    foreach my $prog (@progs)
227 dpurdie 1869
    {
289 dpurdie 1870
        my $pProg = $PROGS->Get($prog);
227 dpurdie 1871
        Warning( "Duplicate prog ignored '$prog'" )
289 dpurdie 1872
            if ( $pProg );
1873
        $pProg = $PROGS->NewAdd($prog)
227 dpurdie 1874
    }
1875
}
1876
 
1877
 
1878
sub AddSourceType
1879
{
1880
    my( $ext, $type ) = @_;
1881
 
1882
    Debug2( "AddSourceType(@_)" );
1883
 
1884
    #
1885
    #   Default Source Type (C)
1886
    #
1887
    $type = ".c" unless ( $type );
1888
 
1889
    Error ("Source type '$ext' not allowed")
1890
        if ( $ext !~ /^\.\w+$/ );
1891
 
1892
    $type = lc($type)
1893
        if ( $::ScmHost ne "Unix" );
1894
    $ScmSourceTypes{ $ext } = $type;
1895
}
1896
 
1897
 
1898
sub AddSourceFile
1899
{
1900
    my( $platforms, @elements ) = @_;
1901
 
1902
    Debug2( "AddSourceFile($platforms, @elements)" );
1903
    return if ( ! ActivePlatform($platforms) );
1904
 
285 dpurdie 1905
    foreach my $path ( @elements )
227 dpurdie 1906
    {
1907
        __AddSourceFile( 1, $path );
1908
    }
1909
}
1910
 
1911
 
1912
#-------------------------------------------------------------------------------
1913
# Function        : __AddSourceFile
1914
#
1915
# Description     : Internal function
1916
#                   Add a source file to internal lists
1917
#
1918
#                   Assumes that the current platform is ACTIVE
1919
#
1920
# Inputs          : push    0: Don't push onto OBJS (non-shared objfiles)
1921
#                   path    Filename.extension
1922
#                   obj     object file name (optional)
1923
#                   type    Type of file. "" -> auto detect
1924
#
1925
# Returns         : True        - File is a 'known' source file
1926
#                   False       - File is not a 'known' source file
1927
#
1928
sub __AddSourceFile
1929
{
1930
    my( $push, $path, $obj, $type ) = @_;
271 dpurdie 1931
    my( $filename, $ext, $srcfile, $is_obj, $ext_type, $result );
227 dpurdie 1932
 
271 dpurdie 1933
    $filename = StripDir($path);                # file name
227 dpurdie 1934
 
1935
    $ext  = StripFile($path);                   # extension
1936
    $ext = lc($ext)
1937
        if ( $::ScmHost ne "Unix" );
1938
 
271 dpurdie 1939
    if (! ($srcfile = $SRCS{$filename})) {
227 dpurdie 1940
        $srcfile = $path;                       # generated
1941
    }
1942
 
271 dpurdie 1943
    $obj  = StripExt( $filename )               # Base name of object file
227 dpurdie 1944
        if ( ! defined($obj) || $obj eq "" );
1945
 
1946
    $type = ""                                  # optional type
1947
        if ( ! defined( $type ) );
1948
 
1949
    #
1950
    #   Push file onto a suitable source file list
1951
    #
1952
    $result = 0;
1953
    $ext_type = "";                             # map extension
1954
    $ext_type = $ScmSourceTypes{ $ext }
1955
        if ( exists( $ScmSourceTypes{ $ext } ) );
1956
    $result = 1 if ( $ext_type );
1957
 
1958
    if ( $type eq "" && defined $::ScmToolsetProgSource{$ext} )
1959
    {
1960
        Debug( "SourceFile: $path is ToolsetProgSource   -> $srcfile" );
1961
        push( @CSRCS, $srcfile );
1962
        $result = 1;
1963
    }
1964
    elsif ( ($type eq "" && $ext_type eq ".h") || ($type eq ".h") )
1965
    {
1966
        Debug( "SourceFile: $path is .h   -> $srcfile" );
1967
        push( @CHDRS, $srcfile );
1968
    }
1969
    elsif ( ($type eq "" && $ext_type eq ".inc") || ($type eq ".inc") )
1970
    {
1971
        Debug( "SourceFile: $path is .inc -> $srcfile" );
1972
        push( @ASHDRS, $srcfile );
1973
    }
1974
    elsif ( ($type eq "" && $ext_type eq ".c") || ($type eq ".c") )
1975
    {
1976
        Debug( "SourceFile: $path is .c   -> $srcfile=$obj" );
1977
        push( @CSRCS, $srcfile );
1978
        $is_obj = 1;
1979
    }
1980
    elsif ( ($type eq "" && $ext_type eq ".cc") || ($type eq ".cc") )
1981
    {
1982
        Debug( "SourceFile: $path is .cc  -> $srcfile=$obj" );
1983
        push( @CXXSRCS, $srcfile );
1984
        $is_obj = 1;
1985
    }
1986
    elsif ( ($type eq "" && $ext_type eq ".asm") || ($type eq ".asm") )
1987
    {
1988
        Debug( "SourceFile: $path is .asm -> $srcfile=$obj" );
1989
        push( @ASSRCS, $srcfile );
1990
        $is_obj = 1;
1991
    }
1992
    elsif ( $ext_type eq "--Ignore" )
1993
    {   # ignored ...
1994
        #   .x      "rpcgen" source files
1995
        #   .ini    Configuration
1996
        #   .sh     Shell script
1997
    }
1998
    else
1999
    {
2000
        Debug( "SourceFile: $path is unknown file type" );
2001
 
2002
        #
2003
        #   Insert source files with unknown extensions onto lists
2004
        #   of there own type
2005
        #
2006
        if ( $ext )
2007
        {
2008
            (my $varname = uc ( $ext . 'SRCS')) =~ s~\.~~g;
2009
            no strict 'refs';
2010
            push @$varname, $srcfile;
2011
            use strict 'refs';
2012
        }
2013
    }
2014
 
2015
    #
271 dpurdie 2016
    #   See if there is a hook function for this type of source file
2017
    #   Invoke user function to perform additional processing on the file
2018
    #
2019
    if ( %MF_RegisterSrcHooks )
2020
    {
2021
        my @listeners;
2022
        push @listeners, @{$MF_RegisterSrcHooks{$ext}} if ( exists $MF_RegisterSrcHooks{$ext} );
2023
        push @listeners, @{$MF_RegisterSrcHooks{'*'}}  if ( exists $MF_RegisterSrcHooks{'*'} );
2024
        while ( @listeners )
2025
        {
2026
            Debug( "RegisterSrcHook: Invoke SrcHook function" );
2027
            my ($fname, @args) = @{shift @listeners};
2028
            &$fname ( $srcfile ,$filename, $obj, $ext ,@args );
2029
        }
2030
    }
2031
 
2032
    #
227 dpurdie 2033
    #   Object files are saved in
2034
    #       OBJSOURCE   - Generate a recipe to create the object
2035
    #       OBJS        - A list of ALL non-shared object files
2036
    #
6133 dpurdie 2037
    if ( $is_obj && $::o && $ScmNotGeneric )
227 dpurdie 2038
    {
2039
        $OBJSOURCE{ "$obj" } = $srcfile;
2040
        push( @OBJS, $obj )
2041
            if ($push);
2042
    }
2043
 
2044
    #
2045
    #   Indicate to the user that the file is a 'known' source file
2046
    #   This implies that the file is required early in the build process
2047
    #   and may need to be generated early.
2048
    #
2049
    return $result;
2050
}
2051
 
2052
#-------------------------------------------------------------------------------
2053
# Function        : SetValue
2054
#
2055
# Description     : Defines a variable that can be used within the makefile.pl
2056
#                   Use sparingly
2057
#                   An attempt to formalise a mechanism that is used anyway, but
2058
#                   with correct platform detection
2059
#
2060
# Inputs          : $platform       - Platform selector
2061
#                   $name           - Name to set
2062
#                   $value          - Value to set
2063
#                   options         - Options
2064
#                                       --NoWarn
2065
#                                       --Project=xxxx[,xxxx]+
2066
#                                       --
2067
#
2068
sub SetValue
2069
{
2070
    my( $platforms, @elements ) = @_;
2071
    my $name;
2072
    my $value;
2073
    my $nowarn;
2074
    my $nomoreswicthes = 0;
2075
 
2076
    Debug2( "SetValue($platforms, @elements)" );
2077
 
2078
    return if ( ! ActivePlatform($platforms) );
2079
 
2080
    #
2081
    #   Process elements extracting values and options
2082
    #
2083
    foreach ( @elements )
2084
    {
2085
        if ( m/^--$/ ) {
2086
            $nomoreswicthes = ! $nomoreswicthes;
2087
            next;
2088
        }
2089
 
2090
        if ( m/^--/ && ! $nomoreswicthes )
2091
        {
2092
 
2093
            if ( m/^--NoWarn/ ) {
2094
                $nowarn = 1;
2095
 
2096
            } elsif ( m/^--Project=(.*)/ ) {
2097
                return unless ( ActiveProject( $1) );
2098
 
2099
            } else {
2100
                Error ("SetValue: Unknown option: $_");
2101
 
2102
            }
2103
 
2104
        } elsif ( ! defined $name ) {
2105
            $name = $_;
2106
 
2107
        } elsif ( ! defined $value ) {
2108
            $value = $_;
2109
 
2110
        } else {
2111
            Error ("SetValue: $name. Too many parameters" );
2112
 
2113
        }
2114
    }
2115
 
2116
    #
2117
    #   Warn if the named variable already exists
2118
    #   It may be a JATS internal or it may be a user.
2119
    #
2120
    unless ( $nowarn )
2121
    {
2122
        no strict 'refs';
2123
        Warning("SetValue: $name. Redefined") if defined ( $$name );
2124
        use strict 'refs';
2125
    }
2126
 
2127
    #
2128
    #   Set the value
2129
    #
2130
    no strict 'refs';
2131
    $$name = $value;
2132
    use strict 'refs';
2133
}
2134
 
2135
#-------------------------------------------------------------------------------
2136
# Function        : SetList
2137
#
2138
# Description     : Defines a list variable that can be used within the makefile.pl
2139
#                   Use sparingly
2140
#                   An attempt to formalise a mechanism that is used anyway, but
2141
#                   with correct platform detection
2142
#
2143
# Inputs          : $platform       - Platform selector
2144
#                   $name           - Name to set
2145
#                   $value,...      - Values to set
2146
#                   options         - Options
2147
#                                       --NoWarn
2148
#                                       --Project=xxxx[,xxxx]+
2149
#                                       --Unique
2150
#                                       --Clear
2151
#                                       --Append
2152
#                                       --
2153
#
2154
my %SetList_names;
2155
sub SetList
2156
{
2157
    my( $platforms, @elements ) = @_;
2158
    my $name;
2159
    my @value;
2160
    my $nowarn;
2161
    my $unique;
2162
    my $clear;
2163
    my $nomoreswicthes = 0;
2164
 
2165
    Debug2( "SetList($platforms, @elements)" );
2166
 
2167
    return if ( ! ActivePlatform($platforms) );
2168
 
2169
    #
2170
    #   Process elements extracting values and options
2171
    #
2172
    foreach ( @elements )
2173
    {
2174
        if ( m/^--$/ ) {
2175
            $nomoreswicthes = ! $nomoreswicthes;
2176
            next;
2177
        }
2178
 
2179
        if ( m/^--/ && ! $nomoreswicthes )
2180
        {
2181
            if ( m/^--NoWarn/ ) {
2182
                $nowarn = 1;
2183
 
2184
            } elsif ( m/^--Project=(.*)/ ) {
2185
                return unless ( ActiveProject( $1) );
2186
 
2187
            } elsif ( m/^--Unique/ ) {
2188
                $unique = 1;
2189
 
2190
            } elsif ( m/^--Clear/ ) {
2191
                $clear = 1;
2192
 
2193
            } elsif ( m/^--Append/ ) {
2194
                $clear = 0;
2195
 
2196
            } else {
2197
                Error ("SetList: Unknown option: $_");
2198
            }
2199
        } elsif ( ! defined $name ) {
2200
            $name = $_;
2201
 
2202
        } else {
2203
            push @value, $_;
2204
 
2205
        }
2206
    }
2207
 
2208
    Error ("SetList: No name specified") unless ( $name );
2209
 
2210
    #
2211
    #   Warn if the named variable already exists
2212
    #   It may be a JATS internal or it may be a user.
2213
    #
2214
    #   Only do this iff the name is not known to this function
2215
    #   Keep a list a names that have been set.
2216
    #
2217
    if ( ! $SetList_names{$name} && ! $nowarn )
2218
    {
2219
        no strict 'refs';
4455 dpurdie 2220
        Warning("SetList: $name. Defined outside the ScanList/SetList directive","May clash with Jats internals") if ( @$name );
227 dpurdie 2221
        use strict 'refs';
2222
    }
2223
    $SetList_names{$name} = 1;
2224
 
2225
    #
2226
    #   Clear list
2227
    #
2228
    if ( $clear )
2229
    {
2230
        no strict 'refs';
2231
        @$name = ();
2232
        use strict 'refs';
2233
    }
2234
 
2235
    #
2236
    #   Set the value
2237
    #
2238
    no strict 'refs';
2239
    if ( $unique ) {
2240
        UniquePush( \@$name, @value);
2241
    } else {
2242
        push @$name, @value;
2243
    }
2244
    use strict 'refs';
2245
}
2246
 
2247
#-------------------------------------------------------------------------------
2248
# Function        : ScanList
2249
#
2250
# Description     : Create a list by scanning for files in a directory
2251
#                   The files may be in a local directory or within a package
2252
#                   Care must be taken when using a package as the results
2253
#                   may differ bewteen BuildPkgArchive and LinkPkgArchive
2254
#
2255
#                   Interworks with SetList
2256
#
2257
# Inputs          : $platform       - Platform selector
2258
#                   $name           - Name to set
2259
#                   $value,...      - Values to set
2260
#                   options         - Options
2261
#                                       --NoWarn
2262
#                                       --Project=xxxx[,xxxx]+
2263
#                                       --Unique
2264
#                                       --Clear
2265
#                                       --Append
2266
#
2267
#                                       --Package=xxxx[,ext]
2268
#                                       --Dir=xxx
2269
#
2270
#                                       --Subdir=yyy
2271
#                                       --DirListOnly
2272
#                                       --FileListOnly
335 dpurdie 2273
#                                       --Recurse (default)
227 dpurdie 2274
#                                       --NoRecurse
335 dpurdie 2275
#                                       --FullPath (default)
2276
#                                       --NoFullPath
227 dpurdie 2277
#
2278
#                                       --FilterIn=xxx
2279
#                                       --FilterInRe=xxx
2280
#                                       --FilterOut=xxx
2281
#                                       --FilterOutRe=xxx
2282
#
2283
# Returns         :
2284
#
2285
sub ScanList
2286
{
2287
    my( $platforms, @elements ) = @_;
2288
    my $name;
2289
    my $package;
2290
    my $dir;
2291
    my $subdir;
2292
    my @set_args;
2293
    my $search = JatsLocateFiles->new('Recurse','FullPath' );
2294
 
2295
    Debug2( "ScanList($platforms, @elements)" );
2296
 
2297
    return if ( ! ActivePlatform($platforms) );
2298
 
2299
    #
2300
    #   Process elements extracting values and options
2301
    #
2302
    foreach ( @elements )
2303
    {
2304
        if ( m/^--Unique|--Clear|--Append|--NoWarn/ ) {
2305
            push @set_args, $_;
2306
 
2307
        } elsif ( m/^--Project=(.*)/ ) {
2308
            return unless ( ActiveProject( $1) );
2309
 
2310
        } elsif ( m/^--Package=(.*)/ ) {
2311
            $package = $1;
2312
 
2313
        } elsif ( m/^--Dir=(.*)/ ) {
2314
            $dir = $1;
2315
 
2316
        } elsif ( m/^--Subdir=(.*)/ ) {
2317
            $subdir = $1;
2318
 
2319
        } elsif ( $search->option( $_ ) ) {
2320
            Verbose ("Search Option: $_" );
2321
 
2322
        } elsif ( m/^--/ ) {
2323
            Error ("ScanList: Unknown option: $_");
2324
 
2325
        } elsif ( ! defined $name ) {
2326
            $name = $_;
2327
 
2328
        } else {
2329
                Error ("ScanList $name: Unknown option: $_");
2330
 
2331
        }
2332
    }
2333
 
2334
    Error ("ScanList: No variable name specified") unless ( $name );
2335
    Error ("ScanList: Must Specify --Dir or --Package") unless ( $dir || $package );
2336
    Error ("ScanList: --Dir and --Package are mutually exclusive") if ( $dir && $package );
2337
 
2338
    #
2339
    #   Locate the base of the scan
2340
    #   This may be either a package name or a local directory
2341
    #
2342
    #   Its no use allowing the user to use OBJ/LIB/BIN directories as the
2343
    #   directories MUST exist at build time. Don't really want the user doing
2344
    #   that level of poking out of a package
2345
    #
2346
    if ( $package )
2347
    {
2348
        $dir = GetPackageBase( "ScanList", $package );
2349
        Error ("ScanList: Package not found: $package") unless ( $dir );
2350
    }
2351
    else
2352
    {
2353
        Error ("ScanList: Root directory not found: $dir") unless ( -d $dir );
2354
    }
2355
    if ( $subdir )
2356
    {
2357
        $dir .= "/" . $subdir;
2358
        Error ("ScanList: Sub directory not found: $subdir") unless ( -d $dir );
2359
    }
2360
 
2361
    #
2362
    #   Use SetList to do the rest of the work
2363
    #
2364
    SetList( $platforms, $name, @set_args, '--', $search->search($dir) );
2365
}
2366
 
2367
 
2368
sub Init
2369
{
2370
    push( @INITS, @_ );
2371
}
2372
 
2373
#-------------------------------------------------------------------------------
2374
# Function        : Generate
2375
#
2376
# Description     : Legacy Function - don't use unless you have too.
2377
#                   Flags files that are to be generated during the
2378
#                   early 'generate' make phase. Will also add named files
2379
#                   to various internal lists
2380
#
2381
#                   Intended to be used in conjunction with the 'Rule' directive
2382
#                   to flag header and source files that need to be created early
2383
#                   in the build process.
2384
#
2385
# Inputs          : See GenerateSrcFile
2386
#
2387
# Returns         : 
2388
#
2389
sub Generate
2390
{
2391
    my( $platforms, @elements ) = @_;
2392
 
2393
    Debug2( "Generate($platforms, @elements)" );
2394
 
2395
    return if ( ! ActivePlatform($platforms) );
2396
    Message("Generate directive used. Consider replacing with GenerateFiles");
2397
 
2398
    #
2399
    #   Use Non-warning version to do the hard work
2400
    #
2401
    GenerateSrcFile( 1, @elements );
2402
}
2403
 
2404
#-------------------------------------------------------------------------------
2405
# Function        : Generated
2406
#
2407
# Description     : Legacy Function - don't use unless you have too.
2408
#                   Flags files that are generated by misc Rules
2409
#
2410
#                   Intended to be used in conjunction with the 'Rule' directive
2411
#                   to mark files that have been generated, so that they can be
2412
#                   cleaned up.
2413
#
2414
#                   Note the difference to the 'Generate' directive which will
2415
#                   ensure that the Rule will be run in the 'generate' phase,
2416
#                   this directive doesn't.
2417
#
2418
# Inputs          : Files with internal Makefile Paths and codes
2419
#                   Eg: Generated( '*', "\$(LIBDIR)/libcsf\$(GBE_TYPE).\${a}" );
2420
#                   See why its YUK!
2421
#
2422
# Returns         : 
2423
#
2424
sub Generated
2425
{
2426
    my( $platforms, @elements ) = @_;
2427
    my( @args );
2428
 
2429
    return if ( ! ActivePlatform($platforms) );
2430
    Debug2( "Generated($platforms, @elements)" );
2431
 
2432
    #.. Collect arguments
2433
    #
2434
    foreach ( @elements )
2435
    {
2436
        if ( /^-(.*)/ )
2437
        {
2438
            Debug( "Gen: arg $_" );
2439
            push ( @args, $_);
2440
        }
2441
    }
2442
 
2443
    #.. Push source file(s)
2444
    #
2445
    foreach ( @elements )
2446
    {
2447
        if ( ! /^-(.*)/ )
2448
        {
2449
            Debug( "Generated: $_ (@args)" );
2450
            push (@USERGENERATED, $_);
2451
 
2452
            #
2453
            #   Add the file to the list of known source files
2454
            #   This will allow them to be packaged
2455
            #
2456
            GenerateSrcFile (0, $_ );
2457
        }
2458
    }
2459
}
2460
 
2461
 
2462
#-------------------------------------------------------------------------------
2463
# Function        : GenerateSrcFile
2464
#
2465
# Description     : Internal Function (No $platform)
2466
#                   Determine how to handle a 'Generated' file
2467
#
2468
#
2469
# Inputs          : $generated          - 0: Don't add to GENERATED List
2470
#                                         1: Add to GENERATED List
2471
#                                         2: Add to GENERATED List, if a source file
2472
#                   FileName(s)         - Name of one or more files to process
2473
#                                         All files are processed in the same way
2474
#                                         These file may contain Makefile prefixes
2475
#                                         ie: $(OBJDIR)/file.obj
2476
#                   Options:
2477
#                       --c             - Hint: Its a "C" file
2478
#                       --cpp           - Hint: Its a C++ file
2479
#                       --asm           - Hint: Its an ASM file
2480
#                       -*              - Save as argument attached to the file
2481
#
303 dpurdie 2482
# Returns         : Number of 'source' file
227 dpurdie 2483
#
2484
sub GenerateSrcFile                             # Internal Function - no $platform
2485
{
2486
    my( $generated, @elements ) = @_;
2487
    my( $type, @args );
303 dpurdie 2488
    my $result = 0;
227 dpurdie 2489
 
2490
    Debug2( "GenerateSrcFile($generated,@elements)" );
2491
 
2492
    #.. Collect arguments
2493
    #
2494
    $type = "";
2495
    foreach ( @elements )
2496
    {
2497
        if ( /^--c$/ ) {
2498
            Debug( "Gen: --c" );
2499
            $type = ".c";
2500
 
2501
        } elsif ( /^--cpp$/ ) {
2502
            Debug( "Gen: --cpp" );
2503
            $type = ".cc";
2504
 
2505
        } elsif ( /^--asm$/ ) {
2506
            Debug( "Gen: --asm" );
2507
            $type = ".asm";
2508
 
2509
        } elsif ( /^-(.*)/ ) {
2510
            Debug( "Src: arg $_" );
2511
            push @args, $_;
2512
        }
2513
    }
2514
 
2515
    #.. Process source file(s)
2516
    #
2517
    #   Determine if file is already a known SRCS file - skip if already known
2518
    #   Update SRCS data
2519
    #   Update SRC_TYPE data
2520
    #   Update SRC_ARGS data
2521
    #   Add the file to a suitable source file list ie: @CHDRS,...
2522
    #   Flag as a GENERATED file - These will be processed during the 'generate' phase
2523
    #
2524
    foreach my $source ( @elements )
2525
    {
2526
        next if ( $source =~ /^-(.*)/ );                # Not a source file
2527
 
2528
        my $basename = StripDir( $source );
2529
        Debug( "Generate: $source=$basename (@args)" );
2530
 
2531
        if ($SRCS{ $basename }) {
2532
            Warning( "Duplicate src ignored '$source'" );
2533
            next;
2534
        }
2535
        $SRCS{ $basename } = $source;
2536
 
2537
        HashJoin( \%SRC_ARGS, $;, $basename, @args )
2538
            if (@args);
2539
 
2540
        $SRC_TYPE{ $basename } = $type
2541
            if ($type);
2542
 
2543
        #
5867 dpurdie 2544
        #   Add the file to any source file lists that may like to know
227 dpurdie 2545
        #   about this file.
2546
        #
2547
        #   If the file was a known source file, then it may need to be generated
2548
        #   very early in the build process.
2549
        #
2550
        my $src_file_type = __AddSourceFile( 1, $basename );
285 dpurdie 2551
        if ($generated == 1 || ($src_file_type && $generated > 1) )
227 dpurdie 2552
        {
2553
            push(@GENERATED, $source);
303 dpurdie 2554
            $result++;
227 dpurdie 2555
        }
2556
        else
2557
        {
2558
            push(@GENERATED_NOTSRC, $source);
2559
        }
2560
    }
303 dpurdie 2561
 
2562
    return $result;
227 dpurdie 2563
}
2564
 
2565
#-------------------------------------------------------------------------------
2566
# Function        : GenerateFiles
2567
#
2568
# Description     : Generate files in a controlled manner using a specified
2569
#                   tool to perform the task
2570
#
2571
# Inputs          : $1      - platform specifier '*' (comma delemitered)
2572
#                   $2      - Tool Name
2573
#                   $3...   - Command line argument to generate files with embedded information
2574
#                           - or options. Multiple command line arguments will be joind with
2575
#                             a single space
2576
#
2577
#                   The generated files will be placed in the OBJ directory for
2578
#                   the current target platform. This allows different files to
2579
#                   be generated for each platform, without collision.
2580
#
2581
#                   The full name of the generated files will be added to the list of
2582
#                   source files. Thus the user does not need to know the
2583
#                   full name of the file - it will be tracked by JATS.
2584
#
2585
#                   If a generated file is a header file, then the OBJ directory
2586
#                   will be added as AddIncDir() so that the header files can be
2587
#                   extracted
2588
#
2589
#                   If a generated file is a "C"/"C++" source file, then it will
2590
#                   compiled and the object file made available
2591
#
2592
#                   The tool name may be:
2593
#                       --Tool=name  or "name"
2594
#                               Look in the tool paths in Packages
2595
#                               Look in the JATS tool directory for named script
2596
#                               Look in the JATS bin directory for the named exe
2597
#                               Look in the users path ( and generate a warning )
2598
#                               Give up and hope magic happens later
2599
#                       --Script=name
2600
#                               Resolve the name using known Src paths
2601
#                               The script may be generated and need not exist
2602
#                               at the time the makefile is created.
2603
#                       --Shell
2604
#                               The command line argument is a shell script that
2605
#                               will be passed to a simple shell.
263 dpurdie 2606
#                       --Prog=name
2607
#                               Resolve to a program generated within this makefile
227 dpurdie 2608
#
2609
#
2610
#                   The command line argument contains keywords to allow
2611
#                   information to be extracted from the line. Keywords are:
2612
#
2613
#                       --Generated(xxx)        - xxx is a generated file
2614
#                                                 It will be placed in the OBJDIR
2615
#                       --GeneratedCommon(xxx)  - xxx is a generated file
2616
#                                                 File will be placed in the local directory
2617
#                                                 and will be shared by by all platforms
2618
#                       --GeneratedObject(xxx)  - xxx is a generated object file
2619
#                                                 It will be placed in the OBJDIR and will
2620
#                                                 have a suitable object suffix appended
2621
#                       --GeneratedProg(xxx)    - xxx is a generated program file
2622
#                                                 It will be placed in the BINDIR
2623
#                       --Prerequisite(xxx)     - xxx is a prerequisite file
2624
#                                                 The full name of the file will be located
2625
#                                                 and used within the command. The file will
2626
#                                                 be added to the list of recipe prerequisites
2627
#                       --GeneratedDirectory(xxx)
2628
#                       --GeneratedCommonDirectory(xxx)
2629
#                       --GeneratedObjectDirectory(xxx)
2630
#                       --GeneratedProgDirectory(xxx)
6177 dpurdie 2631
#                                               - xxx is a generated file
2632
#                                                 The containing directory will be placed on the command line
227 dpurdie 2633
#                       --PackageBase(xxx)      - xxx is a package. The keyword will be replaced
2634
#                                                 with the pathname to the package. If the package
2635
#                                                 has been copied in the the interface directory
2636
#                                                 then the interface directory will be used.
2637
#                       --PackageInfo(xxx,--opt)- xxx is a package. The keyword will be replaced
2638
#                                                 with the information requested.
2639
#                                                 Options are:
2640
#                                                   --path
2641
#                                                   --version
2642
#                                                   --fullversion
2643
#                                                   --project
2644
#
2645
#                       Where "xxx" may be of the form:
2646
#                           name,option[,option]
2647
#
2648
#                       Flag options are:
2649
#                           --file             - The file part of the full name
2650
#                           --dir              - The directory part of the full name
2651
#                           --abspath          - Abs path
2652
#                           --absdrive         - Abs path with drive letter
2653
#
2654
#                       --Var(Name,opt)         - Name is the name of a recognised varable
2655
#                                                 Refer to ExpandGenVar function for details
2656
#                                                 of Name and available options
2657
#                                                 The expanded text will be replaced with an
2658
#                                                 suitable makefile variables that will be
2659
#                                                 replaced at run-time.
2660
#
2661
#                   The keyword will be replaced with the resolved name. This may be a file,
2662
#                   a directory or other text.
2663
#
2664
#                   Options do not alter command line text. They do affect the way the command is
2665
#                   processed.
2666
#                   Options include:
2667
#                       --Prereq=name           - The name of a file to add as a prerequisite
2668
#                                                 The file does not form part of the command line
2669
#                       --Created=name          - The name of a file to treat as a generated file
2670
#                       --CreatedCommon=name      The file does not form part of the command line 
2671
#                       --CreatedObject=name
2672
#                       --CreatedProg=name
2673
#
2674
#                       --NoVarTag              - Modifes --Var operation to suppress tags
2675
#                       --NoWarn                - Don't warn if no prerequistes found
2676
#                       --NoGenerate            - Don't warn if no generated files are found
2677
#                                                 Will create a dummy rule name and the recipe will
2678
#                                                 always be executed during the 'GenerateFiles' phase
2679
#                       --UnknownPreq           - Prerequisites are not fully known.
2680
#                                                 Rebuild the target whenever it is required.
2681
#                       --AutoGenerate          - Examine the generated file to determine when the
2682
#                                                 tools is to be run.
261 dpurdie 2683
#                                                 Must be before any options that declare
2684
#                                                 creation of files.
227 dpurdie 2685
#                       --Text=<text>           - Display text for command
2686
#
263 dpurdie 2687
#                       --Clean[=arg]           - Call script with arg[-clean] for cleaning.
2688
#                       --PreDelete             - Delete generated files before running the command
227 dpurdie 2689
#
2690
#               Eg: GenerateFiles ( '*', "--Tool=mod_if.pl",
2691
#                                        "-src --Prerequisite(udh_module.cfg)",
2692
#                                        "-direct -hdr --Generated(udp.h) -quiet" );
2693
#
2694
my $NoGenIndex = 0;
2695
sub GenerateFiles
2696
{
2697
    my ( $platforms, $tool, @args) = @_;
2698
 
2699
    return if ( ! ActivePlatform($platforms) );
2700
 
2701
    Debug2( "GenerateFiles:($platforms, $tool, @args)" );
2702
 
2703
    my @preq_files;
2704
    my $preq_unknown;
2705
    my @gen_files;
2706
    my $shell_script;
2707
    my $shell_cmds;
2708
    my @tool_args;
2709
    my $no_warn;
2710
    my $clean_tag;
2711
    my $text;
2712
    my $gtype = 1;
303 dpurdie 2713
    my @has_source;
227 dpurdie 2714
    my @var_opts;
261 dpurdie 2715
    my @genreq_seen;
263 dpurdie 2716
    my $predelete;
227 dpurdie 2717
 
2718
    #
2719
    #   Process the first argument - this describes the program that will be used
2720
    #   to generate the files. It may be:
2721
    #       --Tool          - A Jats Tool or Plugin
2722
    #       --Script        - A shell script file
2723
    #       --Shell         - Raw shell commands
2724
    #       --Prog          - A program created within the Makefile
2725
    #
2726
    #
2727
    if ( $tool =~ /^--Tool=(.*)/ || $tool =~ /^([^-].*)/)
2728
    {
2729
        $tool = $1;
2730
        my $tool_no_prereq = 0;
2731
 
2732
        #
2733
        #   Process the Tool name and determine the location of the tool
2734
        #   Support --Tool=name and "name"
2735
        #   Locate the tool one of the many well known locations
2736
        #       1) Tool paths from Package Archives
2737
        #       2) JATS tool and binaries
2738
        #       3) User PATH (!YUK)
2739
        #
2740
 
2741
        #
2742
        #   Create a list of known extensions to scan
2743
        #   Basically present so that we can use .exe files without the .exe name
2744
        #
2745
        my @extension_list;
2746
        push @extension_list, '.exe' if ( $::ScmHost ne "Unix" );
2747
        push @extension_list, '.pl', '.sh', '.ksh', '';
2748
        TOOL_SEARCH:
2749
        {
2750
            #
2751
            #   Locate tool with package
2752
            #
2753
            if ( my $fname = ToolExtensionProgram( $tool, @extension_list ))
2754
            {
2755
                $tool = $fname;
2756
                last TOOL_SEARCH;
2757
            }
2758
 
2759
            #
2760
            #   Search the JATS tools and Bin directory
2761
            #   Retain the symbolic name of the JATS directory
2762
            #
2763
            for my $ext ( @extension_list )
2764
            {
2765
                foreach my $jdir ( qw( / /DEPLOY/ /LOCAL/ ) )
2766
                {
2767
                    if ( -f "$::GBE_TOOLS$jdir$tool$ext" )
2768
                    {
2769
                        $tool = "\$(GBE_TOOLS)$jdir$tool$ext";
2770
                        last TOOL_SEARCH;
2771
                    }
2772
                }
2773
 
2774
                if ( -f "$::GBE_BIN/$tool$ext" )
2775
                {
2776
                    $tool = "\$(GBE_BIN)/$tool$ext";
2777
                    last TOOL_SEARCH;
2778
                }
2779
            }
2780
 
2781
            #
2782
            #   Has the user provided an absolute PATH
2783
            #   This is not good, but for testing we can use it
2784
            #
2785
            if ( $tool =~ m~^/~ || $tool =~ m~^.:~ )
2786
            {
2787
                Warning("Absolute path program specified. Uncontrolled tool: $tool");
2788
                for my $ext ( @extension_list )
2789
                {
2790
                    if ( -f "$tool$ext" )
2791
                    {
2792
                        $tool = "$tool$ext";
2793
                        last TOOL_SEARCH;
2794
                    }
2795
                }
2796
            }
2797
 
2798
            #
2799
            #   May have a relative path to a local tool
2800
            #
2801
            if ( -f $tool )
2802
            {
2803
                UniquePush (\@preq_files, $tool);
2804
                last TOOL_SEARCH;
2805
            }
2806
 
2807
            #
2808
            #   Search the users PATH
2809
            #   Generate a warning if the program is found. These programs are
2810
            #   not nice as they are not really controlled.
2811
            #
2812
            for my $dir (split( $::ScmPathSep, $ENV{'PATH'} ) )
2813
            {
2814
                for my $ext ( @extension_list )
2815
                {
2816
                    if ( -f "$dir/$tool$ext" )
2817
                    {
2818
                        Warning("External program found in the user's PATH. Uncontrolled tool: $tool");
2819
                        $tool = "$dir/$tool$ext";
2820
 
2821
                        #
2822
                        #   Do not make the program a pre-requisite if we are running
2823
                        #   under Windows. This avoids two problems:
2824
                        #       1) May have spaces in pathname
2825
                        #       2) May have driver letter in pathname
2826
                        #
2827
                        $tool_no_prereq = 1 if ( $::ScmHost eq "WIN" );
2828
                        last TOOL_SEARCH;
2829
                    }
2830
                }
2831
            }
2832
 
2833
            #
2834
            #   Specified progrom not found
2835
            #   Generate a warning and use the raw name
2836
            #
2837
            Warning("Tool not found: $tool");
2838
            $tool_no_prereq = 1;
2839
        }
2840
        UniquePush (\@preq_files, $tool) unless ($tool_no_prereq);
2841
 
2842
    } elsif ( $tool =~ /^--Script=(.*)/ ) {
2843
 
2844
        #
2845
        #   Locate the script in a known source directory and make
2846
        #   the script a prerequisite of the target files, since the
2847
        #   script may be generated.
2848
        #
2849
        $tool = MakeSrcResolve ( $1 );
2850
        UniquePush (\@preq_files, $tool);
2851
 
2852
    } elsif ( $tool =~ /^--Shell$/ ) {
2853
        #
2854
        #   The user has provided a shell script within the command body
2855
        #   This will be executed directly by a shell
2856
        #   directores will need to use a "/" separator
2857
        #
2858
        $tool = "InternalShell";
2859
        $shell_script = 1;
2860
        $shell_cmds = 1;
2861
 
2862
 
2863
    } elsif ( $tool =~ /^--Prog=(.*)$/ ) {
2864
        #
2865
        #   Using a program that has been created within this script
2866
        #
2867
        my $prog = $1;
289 dpurdie 2868
        if ( my $pProg = $PROGS->Get($prog) )
227 dpurdie 2869
        {
289 dpurdie 2870
            $tool = $pProg->getPath()
227 dpurdie 2871
                unless ( $tool = $SRCS{$prog} );
2872
        UniquePush (\@preq_files, $tool);
2873
        }
2874
        else
2875
        {
2876
            Error ("Unknown program: $prog");
2877
        }
2878
 
2879
    } else {
2880
 
2881
        #
2882
        #   Currently generate a warning and then use the raw tool name
2883
        #
2884
        Error ("Unknown TOOL syntax: $tool");
2885
    }
2886
 
2887
    #
2888
    #   May need to quote the path
2889
    #   If the toolpath contains spaces then ugliness can occur - so quote the program
2890
    #
2891
    $tool = '"' . $tool . '"'
2892
        if ( (! $shell_script ) && $tool =~ m~\s~ );
2893
 
2894
    #
2895
    #   Determine special startup for various programs
2896
    #       Perl  - use known implemenatation
2897
    #       Shell - use known implemenatation
2898
    #       Otherwise - simply run it
2899
    #
2900
    #   Windows: Shell and Perl don't need '\' in paths
2901
    #
2902
    if ( $tool =~ /\.pl$/ )
2903
    {
2904
        $tool = "\$(GBE_PERL) $tool";
2905
        $shell_script = 1;
2906
    }
2907
    elsif ( $tool =~ /\.k?sh$/ )
2908
    {
2909
        $tool = "\$(GBE_BIN)/sh $tool";
2910
        $shell_script = 1;
2911
    }
2912
    Debug( "GenerateFiles: Tool: $tool" );
2913
 
2914
 
2915
    #
2916
    #   Process the remaining arguments
2917
    #   These will be command line arguments or options/flags
2918
    #   Command line arguments are concatenated together
2919
    #
2920
    for my $arg (@args)
2921
    {
263 dpurdie 2922
        if ( $arg =~ /^--PreDelete$/ )
2923
        {
2924
            #
2925
            #   Delete generated files before running the generation process
2926
            #   Some programs refuse to overwrite existing files
2927
            #
2928
            $predelete = 1;
2929
            next;
2930
        }
2931
 
227 dpurdie 2932
        if ( $arg =~ /^--NoVarTag$/ )
2933
        {
2934
            #
2935
            #   Modify the operation of --Var to supress the tags
6387 dpurdie 2936
            #   Should be used early as will only affect following --Var usage
227 dpurdie 2937
            #
2938
            push @var_opts, "--notag";
2939
            next;
2940
        }
2941
 
2942
        if ( $arg =~ /^--NoWarn$/ )
2943
        {
2944
            #
2945
            #   Supress warnings - No prequisites found
2946
            #   This is acceptable, but normally a tool should take an input
2947
            #   and create some output from it.
2948
            #
2949
            $no_warn = 1;
2950
            next;
2951
        }
2952
 
2953
        if ( $arg =~ /^--NoGenerate$/ )
2954
        {
2955
            #
2956
            #   Tool does generate a definable output
2957
            #   Should only be used internally
2958
            #
2959
            #   Need to create a dummy name for the rule
2960
            #   Use a base name and a number
2961
            #
2962
            my $dummy_target = 'generate_files_' . $NoGenIndex;
2963
            UniquePush (\@gen_files, $dummy_target );
2964
            UniquePush (\@GENERATED, $dummy_target);
2965
            next;
2966
        }
2967
 
2968
        if ( $arg =~ /^--UnknownPreq/ )
2969
        {
2970
            #
2971
            #   Indicate that the prequisites are not known, or too complex to
2972
            #   describe. ie: All files in a directory. May be used by packaging
2973
            #   tools.
2974
            #   The recipe will be run EVERY time we want to use the target.
2975
            #
2976
            $preq_unknown = 1;
2977
            $no_warn = 1;
2978
            next;
2979
        }
2980
 
2981
        if ( $arg =~ /^--AutoGenerate/ )
2982
        {
2983
            #
2984
            #   Determine when to run the tool based on the types of files that
2985
            #   are generated. Existance of a source file will force the tool
2986
            #   to be run during the 'generate' phase, othewise the tool will be run
2987
            #   when the generated components are required.
2988
            #
2989
            $gtype = 2;
261 dpurdie 2990
            Warning ("AutoGenerate MUST occur before options that declare generation of files",
2991
                     "Have seen:", @genreq_seen)
2992
                if (@genreq_seen);
227 dpurdie 2993
            next;
2994
        }
2995
 
2996
        if ( $arg =~ /^--Prereq=(.*)/ )
2997
        {
2998
            #
2999
            #   Specify a prerequisite file, that is not a part of the command line
3000
            #   Simply add the files to the list of preq files
3001
            #
3002
            my $fn = LocatePreReq ($1);
3003
            UniquePush ( \@preq_files, $fn );
3004
            Debug( "GenerateFiles: ExtraPrereq: $fn" );
3005
            next;
3006
        }
3007
 
3008
        if ( $arg =~ /^--Created(.*)=(.*)/ )
3009
        {
3010
            #
3011
            #   Specify a generated file, that is not a part of the command line
3012
            #   Add the files to the list of generated files
3013
            #
3014
            my $type = $1;
3015
            my $fn = $2;
3016
 
343 dpurdie 3017
            #
3018
            #   Append object suffix to CreatedObject
3019
            #
227 dpurdie 3020
            $fn .= '.' . $::o
3021
                if ( $type =~ m/Object/ );
3022
 
343 dpurdie 3023
            #
3024
            #   If the files is 'created' in a subdir, then add the dir
3025
            #   as a prerequisite.
3026
            #
3027
            if ( $type =~ m/Prog/ ) {
3028
                $fn = "\$(BINDIR)/$fn";
3029
                UniquePush (\@preq_files, '$(GBE_BINDIR)');
3030
 
3031
            } elsif ( $type !~ m/Common/ ) {
3032
                $fn = "\$(OBJDIR)/$fn";
3033
                UniquePush (\@preq_files, '$(GBE_OBJDIR)');
3034
            }
227 dpurdie 3035
 
3036
            #
3037
            #   Examine the file and see if it needs to be compiled
3038
            #   Add to the list of source files
3039
            #
261 dpurdie 3040
            push @genreq_seen, $arg;
303 dpurdie 3041
            if ( UniquePush (\@gen_files, $fn) )
3042
            {
3043
                if ( GenerateSrcFile ( $gtype, $fn  ) && $gtype == 2 )
3044
                {
3045
                    push @has_source, $fn;
3046
                }
3047
            }
227 dpurdie 3048
            Debug( "GenerateFiles: ExtraCreated: $fn" );
3049
            next;
3050
        }
3051
 
3052
        if ( $arg =~ /^--Clean($|=(.*))/ )
3053
        {
3054
            #
3055
            #   Detect Clean option
3056
            #
3057
            $clean_tag = $2 ? $2 : '-clean';
3058
 
3059
            #
3060
            #   Shell command with a --Clean will only
3061
            #   be run during a clean phase. They should not have any prereq
3062
            #   and should not generate any files, so simplify the interface.
3063
            #
3064
            push @args, '--NoWarn', '--NoGenerate'
3065
                if ( $shell_cmds );
3066
 
3067
            next;
3068
        }
3069
 
3070
        if ( $arg =~ /^--Text=(.*)/ )
3071
        {
3072
            #
3073
            #   Display this text when executing commands
3074
            #
3075
            $text = $1;
3076
            next;
3077
        }
3078
 
3079
 
3080
        #   Not an option. Must be an argument to the tool/program
3081
        #   Process the tool arguments and extract file information
3082
        #   Extract all fields of the form:
3083
        #           --xxxxx(yyyyyy[,zzzzz])
3084
        #           --xxxxx{yyyyyyy}
3085
        #           --xxxxx[yyyyyyy] to allow embedded brackets
3086
        #
3087
        while ( $arg =~ m/--(\w+)               # --CommandWord         $1
3088
                                (               # Just for grouping
3089
                                \((.*?)\)   |   # Stuff like (yyyyy)    $3
3090
                                {(.*?)}     |   # or    like {yyyyy}    $4
3091
                                \[(.*?)\]       # or    like [yyyyy]    $5
3092
                                )/x )           # Allow comments and whitespace
3093
        {
3094
            my $cmd = $1;                       # The command
3095
            my $ufn = $3 || $4 || $5;           # User filename + options
3096
            my $mb = $-[0];                     # Match begin offset
3097
            my $me = $+[0];                     # Match end
3098
            my $flags = '';                     # Optional flags ( --dir or --file )
3099
            my $raw_arg = $ufn;                 # Raw arguments
6387 dpurdie 3100
            my $all = substr( $arg, $mb, $me - $mb ); # All of match. Avoid use of $&
343 dpurdie 3101
            my $is_path = 1;
285 dpurdie 3102
 
227 dpurdie 3103
 
3104
            Error ("GenerateFiles. Empty element not allowed: $all")
3105
                unless ( defined($ufn) );
3106
 
3107
            $ufn =~ s/\s+$//;
3108
            $ufn =~ s/^\s+//;
3109
            $ufn =~ s~//~/~g;                   # Remove multiple /
3110
            if ( $ufn =~ m/(.*?),(.*)/ )        # Extract out any flags
3111
            {
3112
                $ufn = $1;
3113
                $flags = $2;
3114
            }
3115
 
3116
            my $fn = $ufn ;                     # Replacement filename
343 dpurdie 3117
            my $fnp = '';                       # Prefix to $fn
227 dpurdie 3118
            Error ("GenerateFiles. Empty element not allowed: $all" )
3119
                if ( length ($ufn) <= 0 );
3120
 
3121
            #
3122
            #   Process found user command
3123
            #
3124
            if ( $cmd =~ /^Generated/ )
3125
            {
3126
                my $use_dir = "";
343 dpurdie 3127
 
227 dpurdie 3128
                #
3129
                #   Generated filename
3130
                #       Determine the target directory
3131
                #       Determine the full name of the file.
3132
                #       Flag the file as generated
3133
                #
3134
                if ( $cmd =~ /Prog/ )
3135
                {
3136
                    #
3137
                    #   Generated Prog are generated in the BIN directory
3138
                    #   Ensure the directory exists by using its symbolic name
3139
                    #   as a prerequisite.
3140
                    #
343 dpurdie 3141
                    $use_dir = '$(BINDIR)';
3142
                    UniquePush (\@preq_files, '$(GBE_BINDIR)');
227 dpurdie 3143
                }
3144
                elsif ( $cmd !~ /Common/ )
3145
                {
3146
                    #
3147
                    #   Files that are not Common are generated in the
3148
                    #   object directory. This directory must exist, so it
3149
                    #   symbolic name GBE_OBJDIR is made a prerequisite too.
3150
                    #
3151
                    #   If the file is a header file, then add the directory
3152
                    #   to the include search path too.
3153
                    #
343 dpurdie 3154
                    $use_dir = '$(OBJDIR)';
3155
                    UniquePush (\@preq_files, '$(GBE_OBJDIR)');
3156
                    AddIncDir( $platforms , '$(OBJDIR)', '--NoWarn' )
227 dpurdie 3157
                        if ( $ScmSourceTypes{ StripFile($fn) } && $ScmSourceTypes{ StripFile($fn) } eq ".h" );
3158
                }
3159
 
3160
 
3161
                #
3162
                #   Append a toolset specfic object file name suffix
3163
                #   for Object files only
3164
                #
3165
                $fn .= ".$::o"
3166
                    if ( $cmd =~ /Object/ );
3167
 
3168
                #
3169
                #   Merge directory and filename parts
3170
                #
3171
                $fn = $use_dir . ( $use_dir ? "/" : ""  ) . $fn;
3172
 
3173
                #
3174
                #   Save for later user
3175
                #   Flag the file as a generated file
3176
                #
261 dpurdie 3177
                push @genreq_seen, $cmd;
303 dpurdie 3178
                if ( UniquePush (\@gen_files, $fn) )
3179
                {
5878 dpurdie 3180
                    if ($SRCS{ StripDir( $fn ) })
303 dpurdie 3181
                    {
5878 dpurdie 3182
                        abtWarning(1,"GenerateFiles. Generated File also a Src file: $fn");
303 dpurdie 3183
                    }
5878 dpurdie 3184
                    elsif ( GenerateSrcFile ( $gtype, $fn  ) )
3185
                    {
3186
                        push ( @has_source, $fn ) if ($gtype == 2);
3187
                    }
303 dpurdie 3188
                }
227 dpurdie 3189
 
3190
                #
3191
                #   Use the directory or the full name
3192
                #   If using the directory then ensure that we have a name
3193
                #   even if its "."
3194
                #
3195
                $fn = ($use_dir) ? "$use_dir" : "."
3196
                    if ( $cmd =~ /Directory/ );
3197
 
3198
                Debug( "GenerateFiles: Generate: $fn" );
3199
 
3200
            }
3201
            elsif ( $cmd =~ /^Prereq/ )
3202
            {
3203
                #
3204
                #   Prerequisite filename
3205
                #       Resolve the full name of the file. It may be known
3206
                #       as a source file (possibly generated) or it may be
3207
                #       located in a known source directory
3208
                #
3209
                $fn = LocatePreReq ($ufn);
3210
                UniquePush (\@preq_files, $fn);
3211
 
3212
                Debug( "GenerateFiles: Prereq: $fn" );
3213
 
3214
            }
3215
            elsif ( $cmd =~ /^PackageBase/ )
3216
            {
3217
                $fn = GetPackageBase( "GenerateFiles", $raw_arg );
3218
                UniquePush (\@preq_files, $fn);
3219
            }
3220
            elsif ( $cmd =~ /^PackageInfo/ )
3221
            {
3222
                $fn = GetPackageInfo( "GenerateFiles", $raw_arg );
3223
            }
3224
            elsif ( $cmd =~ /^Var/ )
3225
            {
343 dpurdie 3226
                ($fnp, $fn, $is_path) = ExpandGenVar( "GenerateFiles", $raw_arg, @var_opts );
227 dpurdie 3227
                $flags = '';
343 dpurdie 3228
                if ( $raw_arg eq 'ObjDir' ) {
3229
                    UniquePush (\@preq_files, '$(GBE_OBJDIR)');
3230
                } elsif ( $raw_arg eq 'BinDir' ) {
3231
                    UniquePush (\@preq_files, '$(GBE_BINDIR)');
3232
                } elsif ( $raw_arg eq 'LibDir' ) {
3233
                    UniquePush (\@preq_files, '$(GBE_LIBDIR)');
3234
                }
227 dpurdie 3235
            }
3236
            else
3237
            {
3238
                Warning ("GenerateFiles: Unknown replacement command: $cmd");
3239
                $fn = $ufn;
3240
            }
3241
 
3242
            #
3243
            #   Process path modification flags
3244
            #
3245
            $fn = ProcessPathName( $fn, $flags );
3246
 
3247
            #
3248
            #   Minor kludge under windows. Ensure directores have a "\" sep
3249
            #   Unless the user has specified a straight shell command
3250
            #
5986 dpurdie 3251
            $fn = "\$(subst /,\$(dirsep),$fn)"
343 dpurdie 3252
                if ( $is_path && $::ScmHost eq "WIN" && ! defined($shell_script) );
227 dpurdie 3253
 
3254
            #
343 dpurdie 3255
            #   Prepend any $fn Prefix
3256
            #   This will be a tag and is not subject to path processing
3257
            #
3258
            $fn = $fnp . $fn;
3259
 
3260
            #
227 dpurdie 3261
            #   Replace the found string with the real name of the file
3262
            #   Note: 4 argument version of substr is not always available
3263
            #         so we must do it the hard way
3264
            #               substr( $arg, $mb, $me - $mb, $fn);
3265
            #
3266
            $arg = substr( $arg, 0, $mb ) . $fn . substr( $arg, $me );
3267
 
3268
            Debug2( "GenerateFiles: subs: $all -> $fn" );
3269
        }
3270
 
3271
        #
3272
        #   Save the tool arguments in an array
3273
        #
3274
        push @tool_args, $arg;
3275
    }
3276
 
3277
 
3278
    #
5867 dpurdie 3279
    #   Sanity test. Ensure that some file have been marked as generated
227 dpurdie 3280
    #                Warn if no prerequisites found
3281
    #
303 dpurdie 3282
    Warning( "GenerateFiles. --AutoGenerate option has no effect",
3283
             "The following files are 'source' files",  @has_source ) if ( @has_source );
227 dpurdie 3284
    Warning( "No Prerequisite files found in $tool",@tool_args) unless ( $no_warn || $#preq_files >= 0 );
3285
    Error  ( "No generated files found in $tool",@tool_args) unless ($#gen_files >= 0);
3286
 
3287
 
3288
    #
3289
    #   Save information
3290
    #   Will be used to create makefile statements later
3291
    #
3292
    my %gen_data;
3293
 
3294
    $gen_data{'index'}      = $NoGenIndex++;
3295
    $gen_data{'shell'}      = $shell_cmds;
3296
    $gen_data{'gen'}        = \@gen_files;
3297
    $gen_data{'preq'}       = \@preq_files;
3298
    $gen_data{'tool'}       = $tool;
3299
    $gen_data{'toolargs'}   = \@tool_args;
3300
    $gen_data{'clean'}      = $clean_tag;
3301
    $gen_data{'text'}       = $text || $gen_files[0];
3302
    $gen_data{'preq_sus'}   = 1 if ( $preq_unknown );
263 dpurdie 3303
    $gen_data{'predelete'}  = 1 if ( $predelete );
227 dpurdie 3304
 
3305
    push(@GENERATE_FILES, \%gen_data);
6387 dpurdie 3306
#DebugDumpData("GenerateFiles", \%gen_data);
227 dpurdie 3307
    Debug2( "GenerateFiles: cmd: $tool @tool_args" );
3308
}
3309
 
3310
#-------------------------------------------------------------------------------
3311
# Function        : MakePerlModule
3312
#
3313
# Description     : Build Perl Module(s) using the Perl Build System
3314
#                   This is a thin wrapper around a specialised script
3315
#
3316
#                   The user can do the same job with correct use of
3317
#                   a GenerateFiles, but this is a lot tidier.
3318
#
3319
# Inputs          : $1      - platform specifier '*' (comma delemitered)
3320
#                   $*      - Paths to Perl Modules[,command options]
3321
#                             Options to the BuildPerl script
3322
#
3323
# Returns         :
3324
#
3325
sub MakePerlModule
3326
{
3327
    my ( $platforms, @args) = @_;
3328
 
3329
    return if ( ! ActivePlatform($platforms) );
3330
 
3331
    Debug2( "MakePerlModule:($platforms, @args)" );
3332
    my @opts;
3333
 
3334
    #
3335
    #   Extract options from paths to Perl Packages
3336
    #   Package names do not start with a '-'
3337
    #
3338
    foreach my $arg ( @args )
3339
    {
3340
        if ( $arg =~ /^-/ ) {
3341
            push @opts, $arg;
3342
 
3343
        } else {
3344
            #
3345
            #   Perl Package Directory Name
3346
            #   This may also contain embedded command to the Make command
3347
            #   These will be seperated with a comma
3348
            #       ie: module,-options=fred
3349
            #
3350
            my ($name,$options) = split( ',', $arg );
3351
            push @opts, "-PerlPackage=$arg";
3352
            push @opts, "--Prereq=$name/Makefile.PL";
3353
        }
3354
    }
3355
 
3356
    #
3357
    #   Invoke GenerateFiles with a bunch of additional arguments
3358
    #
3359
    GenerateFiles ($platforms, "--Tool=jats_buildperl.pl",
3360
                          '--Var(MachType)',                        # Build Machine type
3361
                          '--Var(PackageDir)',                      # Package dir
3362
                          '--NoGenerate',                           # Don't know the output
3363
                          '--Text=Make Perl Module',                # Pretty print
3364
                          '--NoWarn',
3365
                          '--Clean=-clean_build',                   # Jats clean support
3366
                          '--NoVarTag',                             # No more Tags
3367
                          @opts,
3368
                          );
3369
}
3370
 
3371
#-------------------------------------------------------------------------------
3372
# Function        : MakeLinuxDriver
3373
#
3374
# Description     : Build a Linux Device Driver using the Linux Device Driver
3375
#                   Build System
3376
#                   This is a thin wrapper around a specialised script
3377
#
3378
#                   The user can do the same job with correct use of
3379
#                   a GenerateFiles, but this is a lot tidier.
3380
#
3381
# Inputs          : $1      - platform specifier '*' (comma delemitered)
3382
#                   $2      - name of the driver. No extension
3383
#                   $*      - Driver sources
3384
#                             Options to the script
3385
#
3386
# Returns         :
3387
#
3388
sub MakeLinuxDriver
3389
{
3390
    my ( $platforms, $driver_name, @args) = @_;
3391
 
3392
    return if ( ! ActivePlatform($platforms) );
3393
 
285 dpurdie 3394
    Error ("No driver name specified") unless ( $driver_name );
227 dpurdie 3395
    Debug2( "MakeLinuxDriver:($platforms, $driver_name ,@args)" );
3396
    my @srcs;
3397
    my @opts;
3398
 
3399
    #
3400
    #   Extract options from source files
3401
    #   Package names do not start with a '-'
3402
    #
3403
    foreach my $arg ( @args )
3404
    {
3405
         if ( $arg =~ /^--Define=(.)/ ) {
3406
            push @opts, $arg;
5672 dpurdie 3407
 
3408
         } elsif ( $arg =~ /^--ExternalModule=(.)/ ) {
3409
               push @opts, $arg;
227 dpurdie 3410
 
3411
         } elsif ( $arg =~ /^-/ ) {
3412
            push @opts, $arg;
3413
            Warning ("MakeLinuxDriver: Unknown option: $arg. Passed to script");
3414
 
3415
        } else {
3416
            push @srcs, $arg;
3417
            push @opts, "--Prereq=$arg";
3418
        }
3419
    }
3420
 
3421
    #
3422
    #   Cleanup the drive name
3423
    #
3424
    $driver_name =~ s~\.ko$~~;
3425
 
3426
    #
3427
    #   Remove the specified sources from the list of object files
3428
    #   that will be build. This will ensure that some internal rules are
3429
    #   not generated.
3430
    #
3431
    foreach ( @srcs )
3432
    {
3433
        my $file = StripExt(StripDir( $_ ));
3434
        delete $OBJSOURCE{ $file };
3435
        @OBJS = grep(!/^$file$/, @OBJS);
3436
    }
3437
 
3438
    #
3439
    #   Invoke GenerateFiles with a bunch of additional arguments
3440
    #   At runtime the include directories will be added as
3441
    #   absolute paths
3442
    #
3443
    GenerateFiles ($platforms, "--Tool=jats_buildlinux.pl",
3444
                    "-Output=--GeneratedProg($driver_name.ko)",
3445
                    "-Driver=$driver_name",
3446
                    "-GccPath=\$(GCC_CC)",
3447
                    "-Arch=\$(HOST_CPU)",
3448
                    "-LeaveTmp=\$(LEAVETMP)",
3449
                    "-Verbose=\$(CC_PRE)",
3450
                    "-Type=\$(GBE_TYPE)",
3451
                    "-Platform=\$(GBE_PLATFORM)",
5672 dpurdie 3452
                    "--Var(LocalBinDir)",
227 dpurdie 3453
                    '$(patsubst %,-Incdir=%,$(INCDIRS))',
5672 dpurdie 3454
                    '--Clean',
227 dpurdie 3455
                    @opts,
3456
                    @srcs
3457
                    );
3458
}
3459
 
3460
#-------------------------------------------------------------------------------
3461
# Function        : GetPackageBase
3462
#
3463
# Description     : Helper routine
3464
#                   Given a package name, determine the base address of the
3465
#                   package
3466
#
3467
# Inputs          : $dname         - Directive name     (Reporting)
3468
#                   $name          - Required package
3469
#                                    Allows two forms:
3470
#                                       package_name
3471
#                                       package_name,ext
3472
#
3473
# Returns         : Path to the directory in which the files are installed
3474
#                   This may be the interface directory
3475
#
3476
sub GetPackageBase
3477
{
3478
    my ($dname, $fname) = @_;
3479
    my $pkg;
3480
    my ($name, $ext) = split(',', $fname);
3481
 
3482
    $pkg = GetPackageEntry( $name, $ext );
3483
    Error ("$dname: Package not found: $fname") unless ( $pkg );
3484
 
3485
    #
3486
    #   If a BuildPkgArchive then use the interface directory
3487
    #
3488
    return ( $pkg->{'TYPE'} eq 'link' ) ? $pkg->{'ROOT'} : '$(INTERFACEDIR)';
3489
}
3490
 
3491
#-------------------------------------------------------------------------------
3492
# Function        : GetPackageInfo
3493
#
3494
# Description     : Helper routine
3495
#                   Given a package name, return some information about the package
3496
#                   Only one information item is allowed with each call
3497
#
3498
# Inputs          : $dname         - Directive name     (Reporting)
3499
#                   $name          - Required package
3500
#                                    Allows two forms:
3501
#                                       package_name
3502
#                                       package_name,ext
3503
#                                    Selector
3504
#                                       --path
3505
#                                       --version
3506
#                                       --fullversion
3507
#                                       --project
3508
#
3509
# Returns         : Package information
3510
my %GetPackageInfo = qw(path ROOT
3511
                        version DVERSION
3512
                        fullversion VERSION
3513
                        project DPROJ);
3514
sub GetPackageInfo
3515
{
3516
    my ($dname, $args) = @_;
3517
    my $pkg;
3518
    my $name;
3519
    my $ext;
3520
    my $info;
3521
 
363 dpurdie 3522
    #
3523
    #   Split up the arguments
3524
    #       Options start with '--'
3525
    #   First non-option is the package name
3526
    #   2nd non-option is the packag extension
3527
    #
3528
    #   Only one option allowed
3529
    #       Convert it into a known package info item
3530
    #
3531
    #
227 dpurdie 3532
    foreach ( split(',', $args) )
3533
    {
3534
        if ( m/^--(.*)/ ) {
3535
            Error( "$dname: Too many info requests: $args") if ( $info );
3536
            $info = $GetPackageInfo{$1};
3537
            Error( "$dname: Unknown info type: $_") unless ($info);
363 dpurdie 3538
 
227 dpurdie 3539
        } elsif ( $ext ) {
3540
            Error("$dname: Too many names: $args");
363 dpurdie 3541
 
227 dpurdie 3542
        } elsif ( $name ) {
3543
            $ext = $_;
363 dpurdie 3544
 
227 dpurdie 3545
        } else {
3546
            $name = $_;
3547
        }
3548
    }
3549
 
3550
    $pkg = GetPackageEntry( $name, $ext );
3551
    Error ("$dname: Package not found: $args") unless ( $pkg );
3552
 
3553
    #
3554
    #   If a BuildPkgArchive then use the interface directory
363 dpurdie 3555
    #   Default data item - path to the package
227 dpurdie 3556
    #
363 dpurdie 3557
    $info = 'ROOT' unless ( $info );
3558
    if ( $info eq 'ROOT' &&  $pkg->{'TYPE'} ne 'link' )
227 dpurdie 3559
    {
3560
        return ( '$(INTERFACEDIR)');
3561
    }
363 dpurdie 3562
 
227 dpurdie 3563
    return ( $pkg->{$info} );
3564
}
3565
 
3566
#-------------------------------------------------------------------------------
3567
# Function        : GetPackageEntry
3568
#
3569
# Description     : Return the package class pointer given a package name
3570
#
3571
# Inputs          : $name          - Required package
3572
#                   $ext           - Option package extension
3573
#
3574
# Returns         : Class pointer
3575
#
3576
sub GetPackageEntry
3577
{
3578
    my ($name, $ext) = @_;
3579
    $ext = '' unless ( $ext );
3580
 
3581
    for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} })
3582
    {
3583
        next unless ( $entry->{'NAME'} eq $name );
3584
        next if ( $ext && $entry->{'DPROJ'} ne $ext );
3585
        return $entry;
3586
    }
285 dpurdie 3587
    return;
227 dpurdie 3588
}
3589
 
3590
#-------------------------------------------------------------------------------
3591
# Function        : ExpandGenVar
3592
#
3593
# Description     : Expand a known variable for the Generate Files option
3594
#
3595
# Inputs          : $dname         - Directive name     (Reporting)
3596
#                   $arg           - Raw argument
3597
#                                    This of the form of
3598
#                                       Tag[,--option]+
3599
#                                    Tags are specified in %ExpandGenVarConvert
3600
#
3601
#                                   Options are:
3602
#                                       --tag
3603
#                                       --notag
3604
#                                       --tag=<SomeTag>
3605
#                                       --absdrive
3606
#                                       --abspath
285 dpurdie 3607
#                                       --default=text
343 dpurdie 3608
#                                       --allownone
227 dpurdie 3609
#                                   Not all options are avalaible on all variables
3610
#                   @opts           - Options
3611
#                                       --notag     - Default is --notag
3612
#
343 dpurdie 3613
# Returns         : Tag             - Any tag component of the expansion
3614
#                   Path/Value      - Path/Value of the component
3615
#                   is_path         - Above is a path
3616
#                   is_abs          - Path is absolute
227 dpurdie 3617
#
3618
 
3619
#
3620
#   Create a Hash to simplify the process of converting Var names
343 dpurdie 3621
#   into makefile variables. There are two data items, separated by a comma.
3622
#       The first is the runtime expansion value
3623
#       The second describes the first:
3624
#           NotPresent  - Expansion is not a path
3625
#           '-'         - Expansion is a path and is relative to CWD
3626
#           '+'         - Expansion is a path and is absolute
227 dpurdie 3627
#
3628
my %ExpandGenVarConvert = (
3629
    'BuildName'         => '$(GBE_PBASE)',
3630
    'BuildVersion'      => '$(BUILDVER)',
3631
    'BuildVersionNum'   => '$(BUILDVERNUM)',
3632
 
3633
    'PackageDir'        => '$(PKGDIR),+',
3634
    'PackagePkgDir'     => '$(PKGDIR)/pkg/pkg.$(GBE_PLATFORM),+',
3635
    'PackageIncDir'     => '$(INCDIR_PKG),+',
6133 dpurdie 3636
    'PackageIncPlatDir' => '$(INCDIR_PKG)/$(GBE_PLATFORM),+',
227 dpurdie 3637
    'PackageLibDir'     => '$(LIBDIR_PKG)/$(GBE_PLATFORM),+',
3638
    'PackageBinDir'     => '$(BINDIR_PKG)/$(GBE_PLATFORM)$(GBE_TYPE),+',
3639
 
3640
    'PackageToolDir'    => '$(PKGDIR)/tools,+',
3641
    'PackageToolBin'    => '$(PKGDIR)/tools/bin/$(GBE_HOSTMACH),+',
3642
    'PackageToolScript' => '$(PKGDIR)/tools/scripts,+',
3643
 
3644
    'LibDir'            => '$(LIBDIR),+',
3645
    'BinDir'            => '$(BINDIR),+',
3646
    'ObjDir'            => '$(OBJDIR),+',
3647
 
3648
    'InterfaceDir'      => '$(INTERFACEDIR),+',
3649
    'InterfaceIncDir'   => '$(INCDIR_INTERFACE),+',
3650
    'InterfaceLibDir'   => '$(LIBDIR_INTERFACE)/$(GBE_PLATFORM),+',
3651
    'InterfaceBinDir'   => '$(BINDIR_INTERFACE)/$(GBE_PLATFORM)$(GBE_TYPE),+',
3652
 
3653
    'LocalDir'          => '$(LOCALDIR),+',
3654
    'LocalIncDir'       => '$(INCDIR_LOCAL),+',
3655
    'LocalLibDir'       => '$(LIBDIR_LOCAL)/$(GBE_PLATFORM),+',
3656
    'LocalBinDir'       => '$(BINDIR_LOCAL)/$(GBE_PLATFORM)$(GBE_TYPE),+',
3657
 
3658
    'Platform'          => '$(GBE_PLATFORM)',
3659
    'Product'           => '$(GBE_PRODUCT)',
3660
    'Target'            => '$(GBE_TARGET)',
3661
 
3662
    'Type'              => '$(GBE_TYPE)',
3663
    'Arch'              => '$(HOST_CPU)',
3664
    'Architecture'      => '$(HOST_CPU)',
3665
    'MachType'          => '$(GBE_HOSTMACH)',
3666
    'BuildRoot'         => '$(GBE_ROOT),+',
3667
 
3668
 
3669
    'Verbose'           => '$(CC_PRE)',
3670
    'LeaveTmp'          => '$(LEAVETMP)',
329 dpurdie 3671
    'Cwd'               => '$(CURDIR),-',
227 dpurdie 3672
 
6133 dpurdie 3673
    # Generated when used
227 dpurdie 3674
    'CompilerPath'      => '$(SCM_COMPILERPATH)',
3967 dpurdie 3675
    'PkgArch'           => '$(PACKAGE_ARCH)',
6133 dpurdie 3676
 
3677
    'Native'            => '0',
3678
    'Toolset'           => '0',
3679
 
227 dpurdie 3680
    );
3681
 
3682
sub ExpandGenVar
3683
{
3684
    my ($dname, $args, @uopts) = @_;
3685
    my $expansion;
3686
    my $prefix='';
3687
    my ($tag, @opts) = split('\s*,\s*', $args);
3688
    my $no_prefix;
285 dpurdie 3689
    my $default_value;
3690
    my $allow_none;
329 dpurdie 3691
    my $is_abs = 0;
227 dpurdie 3692
 
285 dpurdie 3693
    #
3694
    #   Parse options lists
3695
    #       Options provided by the caller
3696
    #       Options embedded in the argument
227 dpurdie 3697
    foreach ( @uopts )
3698
    {
3699
        if ( m/^--notag$/ ) {
3700
            $no_prefix = 1;
3701
        } else{
3702
            Error ("$dname: Unknown option: $_")
3703
        }
3704
    }
3705
 
285 dpurdie 3706
    foreach ( @opts )
3707
    {
3708
        if ( m/^--default=(.+)/i ) {
3709
            $default_value = $1;
3710
        } elsif ( m/^--allownone$/i ) {
3711
            $allow_none = 1;
3712
        }
3713
    }
3714
 
227 dpurdie 3715
    #
3716
    #   Perform run-time update on the %ExpandGenVarConvert
3717
    #   Most of it can be initialised at startup - but not all of it.
3718
    #
3719
    $ExpandGenVarConvert{CompilerPath} = undef unless $::ScmToolsetCompilerPath;
3720
    $ExpandGenVarConvert{Product}      = '$(GBE_PLATFORM)' unless $ScmProduct;
3721
 
6133 dpurdie 3722
    $ExpandGenVarConvert{Native}      = '1'  if isAnAlias ('NATIVE');
3723
    $ExpandGenVarConvert{Toolset}     = '1'  if isAnAlias ('TOOLSET');
3724
 
3725
 
227 dpurdie 3726
    #
3727
    #   Look up a hash of conversions
3728
    #   Could allow for a code ref, but not needed yet
3729
    #
3730
    Error ("$dname: Unknown expansion --Var($tag)")
3731
        unless ( exists $ExpandGenVarConvert{$tag} );
3732
 
285 dpurdie 3733
    #
3734
    #   Handle undefined expansions
3735
    #   Only 'CompilerPath', but it can be a pain in user land
3736
    #
3737
    $expansion = $ExpandGenVarConvert{$tag};
3738
    unless ( defined $expansion  )
3739
    {
3740
        return '' if ( $allow_none );
3741
        $expansion = $default_value;
3742
        Error ("$dname: Expansion --Var($tag) not be supported by toolset: $ScmToolset")
3743
            unless ( $expansion );
3744
    }
227 dpurdie 3745
 
285 dpurdie 3746
 
227 dpurdie 3747
    ($expansion,my $is_path) = split (',', $expansion );
329 dpurdie 3748
    $is_abs = 1
3749
        if ($is_path && $is_path eq '-' );
227 dpurdie 3750
 
3751
    #
3752
    #   Process options
3753
    #   Assume that a tag will be provided
3754
    #
3755
    $prefix =  $no_prefix ? '' : "-$tag=";
3756
    foreach my $opt ( @opts )
3757
    {
3758
        if ( $opt =~ /^--tag=(.*)/i ) {
3759
            $prefix = "$1=";
3760
 
3761
        } elsif ( $opt =~ m/^--tag$/i ) {
3762
            $prefix = "-$tag=";
3763
 
3764
        } elsif ( $opt =~ m/^--notag/i ) {
3765
            $prefix = '';
3766
 
329 dpurdie 3767
        } elsif ( $is_path && !$is_abs && $opt =~ /--abspath|--absdrive/i ) {
227 dpurdie 3768
            $expansion = '$(CURDIR)/' . $expansion;
329 dpurdie 3769
            $is_abs = 1;
227 dpurdie 3770
 
285 dpurdie 3771
        } elsif ( $opt =~ m/^--default=(.+)/i ) {
3772
            # Already processed
3773
        } elsif ( $opt =~ m/^--allownone$/i ) {
3774
            # Already processed
227 dpurdie 3775
        } else {
3776
            Error ("$dname: Unsupported option($opt) for --Var(@_)");
3777
        }
3778
    }
3779
 
3780
    Debug ("ExpandGenVar: args $args --> $prefix$expansion");
343 dpurdie 3781
    return $prefix , $expansion, $is_path ? 1 : 0, $is_abs;
227 dpurdie 3782
 
3783
}
3784
 
3785
#-------------------------------------------------------------------------------
6133 dpurdie 3786
# Function        : isAnAlias 
3787
#
3788
# Description     : Internal Helper
3789
#                   Determine if this platform is an alias for ...
3790
#
3791
# Inputs          :  $target    - Test against this target
3792
#
3793
# Returns         :  True - Is an alais for $target.
3794
#
3795
sub isAnAlias
3796
{
3797
    my ($target) = @_;
3798
    if (exists ($::BUILDINFO{$ScmPlatform}{'USERALIAS'}) )
3799
    {
3800
        if ( grep /^$target$/, @{$::BUILDINFO{$ScmPlatform}{'USERALIAS'}} )
3801
        {
3802
                return 1;    
3803
        }
3804
 
3805
    }
3806
    if (exists ($::BUILDINFO{$ScmPlatform}{'ALIAS'}) )
3807
    {
3808
        if ( $target eq $::BUILDINFO{$ScmPlatform}{'ALIAS'} )
3809
        {
3810
                return 1;    
3811
        }
3812
    }
3813
 
3814
    return 0;
3815
}
3816
 
3817
#-------------------------------------------------------------------------------
227 dpurdie 3818
# Function        : ProcessPathName
3819
#
3820
# Description     : Massage a pathname according to a set of flags
3821
#
3822
# Inputs          : $fn         - Patchname to massage
3823
#                   $flags      - Flags in a string
3824
#                                   --dir       - only the directory part ( or a "." )
3825
#                                   --file      - only the file part
3826
#                                   --abspath   - Absolute path
3827
#                                   --absdrive  - Absolute path with drive letter(WIN)
3828
#
3829
# Returns         : Massaged pathname
3830
#
3831
sub ProcessPathName
3832
{
3833
    my ( $fn, $flags ) = @_;
3834
    #
3835
    #   Process flags
3836
    #       --dir           - only the directory part ( or a "." )
3837
    #       --file          - only the file part
3838
    #       --abspath       - Absolute path
3839
    #       --absdrive      - Absolute path with drive letter(WIN)
3840
    #
3841
    if ( $flags =~ /--dir/ )
3842
    {
3843
        $fn = '.'
3844
            unless ( $fn =~ s~/[^/]*$~~);
3845
    }
3846
 
3847
    if ( $flags =~ /--file/ )
3848
    {
3849
        $fn =~ s~.*/~~;
3850
    }
3851
 
3852
    if ( $flags =~ /--abspath/ )
3853
    {
3854
        $fn = AbsPath( $fn );
3855
    }
3856
    elsif ( $flags =~ /--absdrive/ )
3857
    {
3858
        $fn = AbsPath( $fn );
3859
        if ( $::ScmHost eq "WIN" )
3860
        {
3861
            $fn = $::CwdDrive . '/' . $fn
3862
                unless ( $fn =~ m~^\w:/~  );
3863
            $fn =~ s~//~/~g;
3864
        }
3865
    }
3866
 
3867
  return $fn;
3868
}
3869
 
3870
#-------------------------------------------------------------------------------
3871
# Function        : LocatePreReq
3872
#
3873
# Description     : Locate a file known to JATS
3874
#                   There are many places to search
3875
#                       1) Src files - specified with a Src directive
3876
#                       2) Scripts - specified with a script directive
3877
#                       3) Search - Files in the specified search path
3878
#                       4) Programs specified with a 'Prog' directive
3879
#
3880
#                   Should also look in other locations (Libs, SharedLibs)
3881
#                   Not done yet. May be issues of a name clash if a program
3882
#                   and a library have the same name.
3883
#
3884
# Inputs          : Name to locate
3885
#
3886
# Returns         : Full pathname of file
3887
#
3888
sub LocatePreReq
3889
{
3890
    my ( $name ) = @_;
3891
    Debug ("LocatePreReq:Looking for $name");
3892
    #
3893
    #   Try a Src file first
3894
    #
3895
    if ( exists $SRCS{ $name } )
3896
    {
3897
        return $SRCS{ $name };
3898
    }
3899
 
3900
    #
3901
    #   Try a script
3902
    #
3903
    if ( exists $SCRIPTS{ $name } )
3904
    {
3905
        return $SCRIPTS{ $name };
3906
    }
3907
 
3908
    #
3909
    #   Try a PROG
3910
    #
289 dpurdie 3911
    if ( my $pProg = $PROGS->Get($name) )
227 dpurdie 3912
    {
289 dpurdie 3913
        return $pProg->getPath();
227 dpurdie 3914
    }
3915
 
3916
    #
3917
    #   Try searching for the file
3918
    #   Uses Data from AddSrcDir
3919
    #
3920
    #   Done: last because it generates warning messages
3921
    #
3922
    return MakeSrcResolve( $name );
3923
}
3924
 
3925
#-------------------------------------------------------------------------------
3926
# Function        : ToolExtensionPaths
3927
#
3928
# Description     : Return a list of toolset extension directories
3929
#                   The data will have been discovered by the build process
3930
#                   and will have been saved for the makefile creation phase
3931
#
3932
# Inputs          : None
3933
#
3934
# Returns         : Return an ordered unique list
3935
#
3936
sub ToolExtensionPaths
3937
{
3938
    Debug( "ToolExtensionPaths:", @::BUILDTOOLSPATH );
3939
    return @::BUILDTOOLSPATH;
3940
}
3941
 
3942
#-------------------------------------------------------------------------------
3943
# Function        : ToolExtensionProgram
3944
#
3945
# Description     : Determine if the named program exists within the PATH
3946
#                   that also includes the toolset extension
3947
#
3948
# Inputs          : program             - Name of program
3949
#                   elist               - An array of possible program extensions
3950
#
4324 dpurdie 3951
# Returns         : Full path the to program or an empty elelent (not undef)
227 dpurdie 3952
#
3953
sub ToolExtensionProgram
3954
{
3955
    my ($program, @elist ) = @_;
3956
 
3957
    #
3958
    #   If elist is empty then insert a defined entry
3959
    #
3960
    push @elist, '' unless ( @elist );
3961
 
3962
    #
3963
    #   Scan all toolset directories
3964
    #   for the program
3965
    #
3966
    for my $dir ( ToolExtensionPaths() )
3967
    {
3968
        for my $ext ( @elist )
3969
        {
3970
            my $tool = "$dir/$program$ext";
4324 dpurdie 3971
            Debug( "ToolsetExtensionProgram: Look for: $tool" );
227 dpurdie 3972
 
3973
            return $tool if ( -f $tool );
3974
        }
3975
    }
3976
}
3977
 
3978
sub Define
3979
{
3980
    Debug2( "Define(@_)" );
3981
 
3982
    push( @DEFINES, @_ );
3983
}
3984
 
3985
 
3986
sub Defines
3987
{
3988
    my( $path, $script ) = @_;
3989
    my( $line );
3990
 
3991
    Debug2( "Defines($path, $script)" );
3992
 
3993
    $script = Exists( $path, $script, "Defines" );
271 dpurdie 3994
    push( @DEFINES, "# Defines from: $script" );
285 dpurdie 3995
    open( my $fh, '<', $script ) || Error( "Opening $script" );
3996
    while (<$fh>) {
227 dpurdie 3997
        $_ =~ s/\s*(\n|$)//;                    # kill trailing whitespace & nl
3998
        push( @DEFINES, $_ );
3999
    }
4000
    push( @ScmDepends, "$script" );             # makefile dependencies
285 dpurdie 4001
    close( $fh );
227 dpurdie 4002
}
271 dpurdie 4003
#-------------------------------------------------------------------------------
4004
# Function        : Rule
4005
#
4006
# Description     : Add a Rule and Recipe to the generated makefile
4007
#                   This is not encouraged as it has been misused to create
4008
#                   unreadable and unmaintainable makefiles.
4009
#
4010
#                   Rules will be added to the makefile after the rules and
4011
#                   recipes created by JATS directives
4012
#
4013
# Inputs          : $platform               - Platform predicate
4014
#                   @rule                   - Array of rules to add
4015
#
4016
# Returns         : 
4017
#
227 dpurdie 4018
sub Rule
4019
{
4020
    my( $platforms, @rule ) = @_;
4021
 
4022
    return if ( ! ActivePlatform($platforms) );
4023
 
4024
    push( @RULES, @rule );
4025
    Message("Rule directive used. Consider replacing with GenerateFiles");
4026
}
4027
 
271 dpurdie 4028
#-------------------------------------------------------------------------------
4029
# Function        : Rules
4030
#
4031
# Description     : Add a file of Rules and Recipes to the generated makefile
4032
#                   Used internally ONLY as there is no platform predicate
4033
#                   Similar to 'Rule()'
4034
#
4035
# Inputs          : $path                   - path to script
4036
#                   $script                 - File fo Rules
4037
#
4038
# Returns         : 
4039
#
227 dpurdie 4040
sub Rules
4041
{
4042
    my( $path, $script ) = @_;
4043
    my( $line );
4044
 
4045
    $script = Exists( $path, $script, "Rules" );
271 dpurdie 4046
    push( @RULES, "# Rules from: $script" );
285 dpurdie 4047
    open( my $fh, '<', $script ) || Error( "Opening $script" );
4048
    while (<$fh>) {
227 dpurdie 4049
        $_ =~ s/\s*(\n|$)//;                    # kill trailing whitespace & nl
4050
        push( @RULES, $_ );
4051
    }
4052
    push( @ScmDepends, "$script" );             # makefile dependencies
285 dpurdie 4053
    close( $fh );
227 dpurdie 4054
}
4055
 
271 dpurdie 4056
#-------------------------------------------------------------------------------
4057
# Function        : AddRule
4058
#
4059
# Description     : Inernal function
4060
#                   Add a line to the Rules area
4061
#
4062
# Inputs          : @elements                   - Array of lines to add
4063
#
4064
# Returns         : Nothing
4065
#
4066
sub AddRule
4067
{
4068
    push( @RULES, @_ );
4069
}
227 dpurdie 4070
 
271 dpurdie 4071
#-------------------------------------------------------------------------------
4072
# Function        : Src
4073
#
4074
# Description     : This directive is used to identify files to JATS
4075
#                   Once a file has been identified as a 'Source' file, then it
4076
#                   can be used by name, without the need to locate the file again.
4077
#                   This implies that filenames must be unique.
4078
#                   The directories cannot be used to make files of the same name
4079
#                   unqiue - this is not the JATS way
4080
#
4081
#                   Source files will be classified as one of:
4082
#                       c, c++, header, assembler or other
4083
#
4084
#
4085
# Inputs          : $platform               - Active Platform Predicate
4086
#                   @elements               - A list of files and options
4087
#
4088
#                   Valid options are:
4089
#                       --c                 - Specifies the type of file
4090
#                       --cpp
4091
#                       --h, --headers
4092
#                       --asm
4093
#                       --FromPackage       - Search packages for the file
4094
#                       --List=xxx          - Append file to a named list
4095
#                       --Depends=xxx       - Manually name a dependency
6387 dpurdie 4096
#                       --IgnoreDuplicates  - Ignore duplicates (mostly internal use)
271 dpurdie 4097
#
4098
#                   Options are processed before file elements
4099
#                   Thus options apply to all files in the list
4100
#
4101
# Returns         : Nothing
4102
#
227 dpurdie 4103
sub Src
4104
{
4105
    my( $platforms, @elements ) = @_;
6387 dpurdie 4106
    my( $type, @args, $source, $basename, $from_package, @lists, $ignoreDups );
227 dpurdie 4107
    my( @depends, @srcs );
4108
 
4109
    $platforms = '' unless ( $platforms );
4110
    Debug2( "Src($platforms, @elements)" );
4111
 
4112
    #
4113
    #   Ensure that there is a file within the list
4114
    #
4115
    Warning( "Src directive does not specify any files: Src($platforms, @elements)" )
4116
        unless (grep( /^[^-]/, @elements ) );
4117
 
4118
    return if ( ! ActivePlatform($platforms) );
4119
 
4120
    #
4121
    #   Remove spaces from both ends of the arguments.
4122
    #   It is easier to remove spaces now than to detect them later
4123
    #
4124
    foreach ( @elements )
4125
    {
4126
        s/^\s+//;
4127
        s/\s+$//;
4128
        s~//~/~g;                               # Remove multiple /
4129
    }
4130
 
4131
    #.. Collect arguments
4132
    #
4133
    $type = "";
4134
    foreach ( @elements )
4135
    {
4136
        if ( /^--c$/ )
4137
        {
4138
            Debug( "Src: --c" );
4139
            $type = ".c";
4140
        }
4141
        elsif ( /^--cpp$/ )
4142
        {
4143
            Debug( "Src: --cpp" );
4144
            $type = ".cc";
4145
        }
4146
        elsif ( /^--h$/ || /^--header$/ )
4147
        {
4148
            Debug( "Src: --h" );
4149
            $type = ".h";
4150
        }
4151
        elsif ( /^--asm$/ )
4152
        {
4153
            Debug( "Src: --asm" );
4154
            $type = ".asm";
4155
        }
6387 dpurdie 4156
        elsif ( /^--IgnoreDup/ )
4157
        {
4158
            $ignoreDups = 1;
4159
        }
227 dpurdie 4160
        elsif ( /^--FromPackage$/ )
4161
        {
4162
            $from_package = 1;
4163
        }
4164
        elsif ( /^--List=(.*)/ )
4165
        {
4166
            my $list_name = $1;
4167
            Error( "Bad list name: $list_name" )
4168
                unless ( $list_name =~ m/^[A-Za-z]\w+/ );
4169
            push @lists, $list_name;
4170
        }
4171
        elsif ( /^--Depends=(.*)/ )
4172
        {
4173
            foreach ( split( ',', $1) )
4174
            {
4175
                my $full = MakeSrcResolveExtended( $from_package, $_ );
4176
                push @depends, $full;
4177
            }
4178
        }
4179
        elsif ( /^-(.*)/ )
4180
        {
4181
            Debug( "Src: arg $_" );
4182
            push @args, $_;
4183
        }
4184
        else
4185
        {
4186
            push @srcs, $_;
4187
            Warning ("Src files contains a '\\' character: $_" ) if (m~\\~);
4188
        }
4189
    }
4190
 
4191
    #.. Push source file(s)
4192
    foreach ( @srcs )
4193
    {
4194
        if ( ! /^-(.*)/ )
4195
        {
4196
            $source = MakeSrcResolveExtended( $from_package, $_ );
4197
            $basename = StripDir( $source );
4198
            Debug( "Src: $_ -> $source=$basename (@args),(@depends)" );
4199
 
4200
            if ( $SRCS{ $basename } ) {
6387 dpurdie 4201
                Warning( "Duplicate src ignored '$source'") unless $ignoreDups;
227 dpurdie 4202
                next;
4203
            }
4204
            $SRCS{ $basename } = $source;
4205
 
4206
            HashJoin( \%SRC_ARGS, $;, $basename, @args )
4207
                if (@args);
4208
 
4209
            HashJoin( \%SRC_DEPEND, $;, $basename, @depends )
4210
                if ( @depends );
4211
 
4212
            $SRC_TYPE{ $basename } = $type
4213
                if ($type);
4214
 
4215
 
4216
            foreach (@lists) {
4217
                my $lname_short = "LIST_$_";
4218
                my $lname_full = "LIST_FULL_$_";
4219
 
4220
                no strict 'refs';
4221
 
4222
                push @$lname_short,$basename;
4223
                push @$lname_full ,$source;
4224
 
4225
                use strict 'refs';
4226
            }
4227
 
4228
            __AddSourceFile( 1, $source, "", $type );
4229
        }
4230
    }
4231
}
4232
 
6387 dpurdie 4233
#-------------------------------------------------------------------------------
4234
# Function        : AddToSrc 
4235
#
4236
# Description     : Internal function
4237
#                   Used by plugins and tools
4238
#                   
4239
#                   Will test if specified file is known to JATS, before
4240
#                   adding to the the list of known (Src) files 
4241
#
4242
# Inputs          : $platform
4243
#                   $file           - Only one file
4244
#                   @srcOpts        - Same as Src
4245
#
4246
# Returns         : True if any file can be found
4247
#                   Returns full path to the file    
4248
#
4249
sub AddToSrc
4250
{
4251
    my( $platforms, $file, @args ) = @_;
4252
    Debug2( "AddToSrc($platforms, $file, @args)" );
227 dpurdie 4253
 
6387 dpurdie 4254
    #
4255
    #   Process files
4256
    #
4257
    my $basename = StripDir( $file );
4258
    unless (exists $SRCS{$file} || exists  $SRCS{$basename} ) {
4259
        Src ('*', $file, @args);
4260
    }
4261
 
4262
    return $SRCS{$basename};
4263
}
4264
 
4265
 
227 dpurdie 4266
###############################################################################
4267
#  sub LibNameSplit
4268
#      Just a little help to deal with major/minor stuff for shared libs -
4269
#      given the name of the library as the argument, split out major and minor
4270
#      parts and return the basename, i.e name without major and minor and
4271
#      the pair of major and minor.
4272
###############################################################################
4273
 
4274
sub LibNameSplit
4275
{
4276
    my ( @bits ) = split('\.', $_[0]);
4277
    my ( $major, $minor );
4278
 
4279
    if ($#bits >= 1) {
4280
        $major = $bits[0]; $minor = $bits[1];
4281
    } elsif ($#bits >= 0) {
4282
        $major = $bits[0]; $minor = 0;
4283
    } else {
4284
        $major = 1; $minor = 0;
4285
    }
4286
    Debug( "LibName: $@_[0] ($major.$minor)" );
4287
    return ($major, $minor);
4288
}
4289
 
4290
#-------------------------------------------------------------------------------
4291
# Function        : Lib
4292
#
4293
# Description     : Generate a static library
4294
#
4295
# Inputs          : Platform specifier
4296
#                   Name of the library
4297
#                   Arguemnts ...
4298
#
4299
# Returns         :
4300
#
4301
sub Lib
4302
{
4303
    my( $platforms, $lib, @args ) = @_;
4304
    return if ( ! ActivePlatform($platforms) );
4305
 
4306
    Error ("Lib: Library name not defined") unless ( $lib );
4307
 
4308
    #
4309
    #   May be a shared library or a static library - for historic reasons
4310
    #   If the user has specified a --Shared then its a shared library
4311
    #
4312
    return SharedLib( @_ )
4313
        if ( grep (/^--Shared/, @args) );
4314
 
4315
    #
4316
    #   Does this toolset support libraries
4317
    #
4318
    Error ("Libraries are not supported") unless ( defined $::a );
4319
 
4320
    #.. Fully qualify library path for addition to library list.
4321
    $lib = "lib$lib"
4322
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4323
    Debug( "Lib: $lib" );
4324
 
4325
    #
289 dpurdie 4326
    #   Create a new object to describe the library
227 dpurdie 4327
    #   Ensure that only one such lib exists
289 dpurdie 4328
    #   Add the library to the list of static libraries
227 dpurdie 4329
    #
4330
    Error( "Library of the same name already defined: $lib" )
289 dpurdie 4331
        if ( $LIBS->Get($lib) );
4332
    $LIBS->NewAdd($lib);
227 dpurdie 4333
 
4334
    #
4335
    #   Process arguments
4336
    #
4337
    push( @LINTLIBS, $lib );
4338
    _LibArgs( $lib, @args );
4339
}
4340
 
4341
 
4342
#-------------------------------------------------------------------------------
4343
# Function        : SharedLib
4344
#
4345
# Description     : Generate a shared library
4346
#
4347
# Inputs          : Platform specifier
4348
#                   Name of the library
4349
#                   Arguemnts ...
4350
#
4351
# Returns         :
4352
#
4353
sub SharedLib
4354
{
4355
    my( $platforms, $lib, @args ) = @_;
4356
 
4357
    return if ( ! ActivePlatform($platforms) );
4358
 
4359
    Error ("SharedLib: Library name not defined") unless ( $lib );
4360
    Error ("Shared Libraries are not supported") unless ( defined $::so );
4361
 
4362
#.. Fully qualify library path for addition to library list.
4363
    $lib = "lib$lib"
4364
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4365
    Debug( "ShLib: $lib" );
4366
 
4367
    #
4368
    #   Ensure that only one such lib exists
4369
    #
289 dpurdie 4370
    Error( "Library of the same name already defined: $lib" )
4371
        if ( $SHLIBS->Get($lib) );
4372
    $SHLIBS->NewAdd($lib);
293 dpurdie 4373
 
227 dpurdie 4374
    #
4375
    #   If the user has not specified a --Shared parameter then provide one
4376
    #
4377
    push @args, "--Shared=Current"
4378
        unless ( grep (/^--Shared/, @args) );
4379
 
4380
    #
4381
    #   Process arguments
4382
    #
4383
    push( @LINTSHLIBS, $lib );
4384
    _SharedLibArgs( $lib, @args );
4385
}
4386
 
4387
 
4388
#-------------------------------------------------------------------------------
4389
# Function        : LibArgs
4390
#
4391
# Description     : Add arguments to an existing library directive
4392
#
4393
# Inputs          : Platform specifier
4394
#                   Name of the library
4395
#                   Arguemnts ...
4396
#
4397
# Returns         :
4398
#
4399
sub LibArgs
4400
{
4401
    my( $platforms, $lib, @args ) = @_;
4402
    return if ( ! ActivePlatform($platforms) );
4403
 
4404
#.. Fully qualify library path for addition to library list.
4405
    $lib = "lib$lib"
4406
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4407
    Debug( "LibArgs: $lib" );
4408
 
4409
    #
4410
    #   Process the arguments
4411
    #
4412
    _LibArgs( $lib, @args );
4413
}
4414
 
4415
 
4416
#-------------------------------------------------------------------------------
4417
# Function        : _LibArgs
4418
#
4419
# Description     : Process static library arguments
4420
#                   Internal use only
4421
#
4422
# Inputs          : Name of the library
4423
#                   Arguments to process
4424
#
4425
sub _LibArgs
4426
{
4427
    my( $lib, @elements) = @_;
4428
    my $obj;
4429
 
4430
    #
289 dpurdie 4431
    #   Ensure that only one such lib exists
4432
    #
4433
    my $libp = $LIBS->Get($lib);
4434
    Error("Library name not defined: $lib")
4435
        unless ( $libp );
4436
 
4437
    #
227 dpurdie 4438
    #   Process each element
4439
    #
4440
    foreach (@elements)
4441
    {
371 dpurdie 4442
        if ( /^\s+/ )
4443
        {
4444
            Error ("Argument cannot start with a space: '$_'");
4445
        }
227 dpurdie 4446
        if ( /^--Shared/ )
4447
        {
4448
            Error( "--Shared not valid for a static library" );
4449
        }
4450
 
4451
        if ( /^-l(.*)/ || /^--l(.*)/ || /^-L(.*)/ || /^--L(.*)/ )
4452
        {
4453
        #.. Target library specified - add to library list.
4454
        #
4455
            Warning( "$_ within non shared library specification" );
4456
            next;
4457
        }
4458
 
4459
        if ( /^--if(.*)/ )
4460
        {
4461
            Warning( "$_ within non shared library specification" );
4462
            next;
4463
        }
4464
 
4465
        if ( /^--(.*)/ )
4466
        {
4467
            Debug( "LibArgs: arg $_" );
4468
 
4469
            #.. Argument specified - add to argument list
4470
            #
289 dpurdie 4471
            $libp->addItem('ARGS', $_);
4472
 
227 dpurdie 4473
            next;
4474
        }
4475
 
369 dpurdie 4476
        if ( %::ScmToolsetProgSource )
227 dpurdie 4477
        {
4478
            #
4479
            #   Toolset provides support for some file types
4480
            #   to be passed directly to the librarian builder
4481
            #
4482
            my $ext  = StripFile($_);
4483
            if ( exists ($::ScmToolsetProgSource{$ext}) )
4484
            {
4485
                my $full_path = MakeSrcResolve ( $_ );
4486
                my $flag = $::ScmToolsetProgSource{$ext};
4487
                Debug( "LibArgs: src $_" );
289 dpurdie 4488
                $libp->addItem('ARGS', "$flag$full_path" );
227 dpurdie 4489
                next;
4490
            }
4491
        }
4492
 
4493
        if ( $::o )
4494
        {
4495
        #.. Object specified - add to object list.
4496
        #
4497
            $obj = _LibObject( "", $_ );
4498
 
4499
        #.. Add to object list.
4500
        #   Note:   Object path must be explicit as several
4501
        #           toolsets add additional objects.
4502
        #
289 dpurdie 4503
            $libp->addItem('OBJS', "\$(OBJDIR)/$obj" );
227 dpurdie 4504
            next;
4505
        }
4506
 
4507
        #
4508
        #   Don't know how to handle this type of argument
4509
        #
4510
        Error ("LibArgs: Don't know how to handle: $_" );
4511
    }
4512
}
4513
 
4514
 
4515
#-------------------------------------------------------------------------------
4516
# Function        : SharedLibArgs
4517
#
4518
# Description     : Add arguments to an existing shared library directive
4519
#
4520
# Inputs          : Platform specifier
4521
#                   Name of the library
4522
#                   Arguemnts ...
4523
#
4524
# Returns         :
4525
#
4526
sub SharedLibArgs
4527
{
4528
    my( $platforms, $lib, @args ) = @_;
4529
    return if ( ! ActivePlatform($platforms) );
4530
 
4531
#.. Fully qualify library path for addition to library list.
4532
    $lib = "lib$lib"
4533
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4534
    Debug( "ShLibArgs: $lib" );
4535
 
4536
    _SharedLibArgs( $lib, @args );
4537
}
4538
 
4539
 
4540
#-------------------------------------------------------------------------------
4541
# Function        : _SharedLibArgs
4542
#
4543
# Description     : Process shared library arguments
4544
#                   Internal use only
4545
#
4546
# Inputs          : Name of the library
4547
#                   Arguments to process
4548
#
4549
sub _SharedLibArgs
4550
{
4551
    my ( $lib, @elements) = @_;
4552
 
289 dpurdie 4553
    my $libp = $SHLIBS->Get($lib);
4554
    Error("Library name not defined: $lib")
4555
        unless ( $libp );
4556
 
227 dpurdie 4557
    #
289 dpurdie 4558
    #.. Collect --Shared arguments
339 dpurdie 4559
    #   Need to process this one first so that we have a version number
227 dpurdie 4560
    #
4561
    foreach (@elements)
4562
    {
371 dpurdie 4563
        if ( /^\s+/ )
4564
        {
4565
            Error ("Argument cannot start with a space: '$_'");
4566
        }
289 dpurdie 4567
        next unless ( /^--Shared/ );
4568
 
4569
        my $shared;
227 dpurdie 4570
        if ( /^--Shared$/ )
4571
        {
4572
        #.. Shared library, default library version 1.0
4573
        #
4574
            $shared = "1.0";
4575
        }
4576
        elsif ( /^--Shared=Current$/ )
4577
        {
4578
        #.. Shared library, using 'current' build version
4579
        #
4580
            $shared = $::ScmBuildVersion;
289 dpurdie 4581
            $shared = "1.0" if ($shared eq "");
227 dpurdie 4582
        }
4583
        elsif ( /^--Shared=(.*)/ )
4584
        {
4585
        #.. Shared library, specific version
4586
        #
4587
            my($M, $m) = LibNameSplit($1);
289 dpurdie 4588
            $shared = "$M.$m";
4589
        }
227 dpurdie 4590
 
289 dpurdie 4591
        #
4592
        #   Update the shared Names
4593
        #
4594
        if ( defined $shared )
4595
        {
227 dpurdie 4596
            Warning( "multiple --Shared arguments" )
339 dpurdie 4597
                if (exists $libp->{ VERSION });
227 dpurdie 4598
            Debug( "ShLibArgs: shared $_ ($shared)" );
289 dpurdie 4599
            $libp->{ VERSION } = $shared;
227 dpurdie 4600
        }
289 dpurdie 4601
        else
4602
        {
4603
            Error ("ShLibArgs: --Shared argument not understood");
4604
        }
227 dpurdie 4605
    }
4606
 
4607
 
4608
#.. Parse all of the object and argument entries.
4609
#
4610
    foreach (@elements)
4611
    {
289 dpurdie 4612
        next if ( /^--Shared(.*)/ );
227 dpurdie 4613
 
4614
        if ( /^[-]{1,2}([lL])(.*)/ )
4615
        {
4616
        #.. Target library specified - add to library list.
339 dpurdie 4617
        #   Support --L and -L and --l and -l
227 dpurdie 4618
        #
4619
            Debug( "ShLibArgs: lib  -$1$2" );
289 dpurdie 4620
            $libp->addItem('LIBS', "-$1$2" );
227 dpurdie 4621
            next;
4622
        }
4623
 
4624
        if ( /^--if(.*)/ )
4625
        {
4626
        #.. Library conditional - add to library list.
4627
        #
4628
            Debug( "ShLibArgs: cond $_" );
289 dpurdie 4629
            $libp->addItem('LIBS', $_);
227 dpurdie 4630
            next;
4631
        }
4632
 
339 dpurdie 4633
        if ( /^--SoName=(.*)/i )
4634
        {
4635
        #.. Specify the SoName of the library
4636
        #   Not supported by all toolsets
4637
        #
4638
            my $soMode = $1;
4639
            if ( !$ScmToolsetSoName )
4640
            {
4641
                Warning ("Toolset does not support --SoName. Option ignored");
4642
                next;
4643
            }
4644
 
4645
            Error ("SharedLib: $lib. Multiple --SoName arguments not allowed")
4646
                if ( $libp->{ SONAME } );
4647
 
4648
            my ($major, $minor, $patch, $build, $raw_patch) = SplitVersion($::ScmBuildVersionFull);
4649
            my $soname = '.';
4650
            if ( $soMode =~ m/Major/i ) {
4651
                $soname .= $major;
4652
            } elsif ( $soMode =~ m/^Minor/i ) {
4653
                $soname .= "$major.$minor";
4654
            } elsif ( $soMode =~ m/^Patch/i ) {
4655
                $soname .= "$major.$minor.$patch";
4656
            } elsif ( $soMode =~ m/^Build/i ) {
4657
                $soname .= "$major.$minor.$patch.$build";
4658
            } elsif ( $soMode =~ m/^Full/i ) {
4659
                $soname .= $libp->{ VERSION };
4660
            } elsif ( $soMode =~ m/^None/i ) {
4661
                $soname = '';
4662
            } elsif ( $soMode =~ m/^[0-9.]+$/ ) {
4663
                $soname .= $soMode;
4664
            } else {
4665
                Error ("Unknown --SoName mode: $soMode");
4666
            }
4667
            $libp->addItem('ARGS', '--SoNameSuffix=' . $soname);
4668
            $libp->{ SONAME } = 1;
4669
            next;
4670
        }
4671
 
227 dpurdie 4672
        if ( /^-(.*)/ )
4673
        {                           
4674
        #.. Argument specified - add to argument list
4675
        #
4676
            Debug( "ShLibArgs: arg  $_" );
289 dpurdie 4677
            $libp->addItem('ARGS', $_);
227 dpurdie 4678
            next;
4679
        }
4680
 
369 dpurdie 4681
        if ( %::ScmToolsetProgSource )
227 dpurdie 4682
        {
4683
            #
4684
            #   Toolset provides support for some file types
4685
            #   to be passed directly to the program builder
4686
            #
4687
            my $ext  = StripFile($_);
4688
            if ( exists ($::ScmToolsetProgSource{$ext}) )
4689
            {
4690
                my $full_path = MakeSrcResolve ( $_ );
4691
                my $flag = $::ScmToolsetProgSource{$ext};
4692
                Debug( "ShLibArgs: src $_" );
289 dpurdie 4693
                $libp->addItem('ARGS', "$flag$full_path");
227 dpurdie 4694
                next;
4695
            }
4696
        }
4697
 
4698
        if ( $::o )
4699
        {
4700
        #.. Object specified - add to object list.
4701
        #
4702
            my ($obj) = _LibObject( $lib, $_ );
4703
 
4704
        #.. Add to object list.
4705
        #   Note:   Object path must be explicit as several
4706
        #           toolsets add additional objects.
4707
        #
4708
            $SHOBJ_LIB{ $obj } = $lib;
289 dpurdie 4709
            $libp->addItem('OBJS', "\$(OBJDIR)/$obj");
227 dpurdie 4710
            next;
4711
        }
4712
 
4713
        #
4714
        #   Don't know how to handle this type of argument
4715
        #
4716
        Error ("SharedLib: Don't know how to handle: $_" );
4717
    }
4718
}
4719
 
4720
 
4721
#-------------------------------------------------------------------------------
4722
# Function        : _LibObject
4723
#
4724
# Description     : Process library object file
4725
#                   Common processing routine for static and shared library
4726
#                   Internal use only
4727
#
4728
# Inputs          : shared  - Name of the shared library is shared, if defined
4729
#                   fname   - Name of file
4730
#
4731
# Returns         : Name of the object file
4732
#
4733
sub _LibObject
4734
{
4735
    my ($shared, $fname) = @_;
4736
    my ($file, $ext, $obj, $srcfile, $delete_obj);
4737
 
4738
    #.. Object specified - add to object list.
4739
    #
4424 dpurdie 4740
    #   Want to handle several cases
4741
    #       Normal - User has provided the name of an object file (without the obj suffix)
4742
    #       Other  - User has provided the name of a source file
4743
    #                Need to perform implicit source file processing
4744
    #
4745
    #   The hard part is detecting the difference
4746
    #   Just can't use the existence of a '.' 
4747
    #
4748
    if ($OBJSOURCE{$fname}) {
4749
        $file = $fname;                             # Already know about this file
4750
        $ext = '';                                  # Don't need to split it
4751
    } else {
4752
        $file = StripDirExt($fname);                # file name, without extension or Dir
4753
        $ext  = StripFile($fname);                  # extension
4754
    }
227 dpurdie 4755
 
4756
    if ($shared) {
4757
        $obj = "$shared/$file";                 # library specific subdir
4758
    } else {
4759
        $obj = "$file";
4760
    }
4761
 
4762
    Debug( "LibObjs: obj [$shared]$fname ($file$ext)" );
4763
 
4764
    #.. Unqualified object name
4765
    #
4424 dpurdie 4766
    if ( $ext eq '' ) {
227 dpurdie 4767
        #
4768
        #   Object file not covered by a "Src" statement
4769
        #   Assume that it will be created
4770
        #
4424 dpurdie 4771
        unless ( $srcfile = $OBJSOURCE{$file} )
227 dpurdie 4772
        {
4773
            #
4424 dpurdie 4774
            #   If the object is "generated" then it will be in the
227 dpurdie 4775
            #   SRCS list
4776
            #
4777
            unless ( $srcfile = $SRCS{"$file.$::o"} )
4778
            {
4779
                Warning( "No source for object '$fname' ($file)" );
4780
            }
4781
        }
4782
        $delete_obj = 1;
4783
    }
4784
 
4785
    #.. Qualified object name (ie has extension)
4786
    #       Strip extension and resolve ...
4787
    #       Assume that the named file can be built into an object file
4788
    #
4789
    else
4790
    {
4791
        #.. Resolve
4792
        #
4793
        if ( !($srcfile = $OBJSOURCE{ "$file" }) )
4794
        {
4795
            $srcfile = MakeSrcResolve( $fname );
4796
            $SRCS{ $fname } = $srcfile;
4797
            __AddSourceFile( 0, $fname, $obj );
4798
            $delete_obj = 1;
4799
        }
4800
    }
4801
 
4802
    #.. Delete generated object file
4803
    #   Ensure that the object file is added to the delete list
4804
    #   Add it to the ToolsetObj deletion list as the main OBJ deleltion
4805
    #   list will aready have been processed
4806
    #
4807
    ToolsetObj( "\$(OBJDIR)/$obj" )
4808
        if ( $delete_obj );
4809
 
4810
 
4811
    #.. Shared library objects,
4812
    #       Must explicitly relate source and object, as shared libraries
4813
    #       objects are built within a library specific subdirs.
4814
    #
4815
    $OBJSOURCE{ $obj } = $srcfile
371 dpurdie 4816
        if ( $shared && defined $srcfile );
227 dpurdie 4817
 
4818
    return $obj;
4819
}
4820
 
4821
 
4822
# MergeLibrary
4823
#   Merge a list of libraries into one library
4824
#
4825
sub MergeLibrary
4826
{
4827
    my( $platforms, $lib, @elements ) = @_;
4828
 
4829
    return if ( ! ActivePlatform($platforms) );
4830
 
4831
 
4832
#.. Fully qualify library path for addition to library list.
4833
    $lib = "lib$lib"
4834
       if ( $ScmTargetHost eq "Unix" && $lib !~ m/^lib/);
4835
    Debug( "MergeLibrary: $lib" );
4836
 
289 dpurdie 4837
    #
4838
    #   Create a new object to describe the library
4839
    #   Ensure that only one such lib exists
4840
    #   Add the library to the list of static libraries
4841
    #
4842
    Error( "Merged Library of the same name already defined: $lib" )
4843
        if ( $MLIBS->Get($lib) );
4844
    my $libp = $MLIBS->NewAdd($lib);
4845
 
227 dpurdie 4846
#.. Parse all of the object and argument entries.
4847
#
4848
    foreach (@elements)
4849
    {
4850
        if ( /^--(.*)/ )
4851
        {
289 dpurdie 4852
            $libp->addItem('ARGS', $_);
227 dpurdie 4853
        }
4854
        else
4855
        {
4856
            my ($llib);
4857
 
4858
            #
4859
            #   Collect the source libraries
4860
            #   These must have been installed and will be in a known area
4861
            #   Create full names for the libaries
4862
            #
4863
            if ( $ScmTargetHost eq "Unix" ) {
4864
                $llib = "lib$_";                # Prefix "lib" ....
4865
                $lib =~ s/^liblib/lib/;         # @LIBS already has lib added
4866
            } else {
4867
                $llib = $_;
4868
            }
4869
 
4870
            Debug( "MergeLibrary: merge $llib" );
289 dpurdie 4871
            $libp->addItem('LIBS', $llib);
227 dpurdie 4872
        }
4873
    }
4874
}
4875
 
4876
#-------------------------------------------------------------------------------
4877
# Function        : Script
4878
#
4879
# Description     : Locate a script for test purposes
4880
#
4881
# Inputs          : $platforms      - Platform selector
4882
#                   $script         - A single script name
4883
#                   $execute        - Flag to indicate that the script is to
4884
#                                     marked as executable when used in a TestProg
4885
#                                     This flag is NOT used as the script will
4886
#                                     be forced executable
4887
#
4888
# Returns         : Nothing
4889
#
4890
sub Script
4891
{
4892
    my( $platforms, $script, $execute ) = @_;
4893
 
4894
    Debug2( "Script(@_)" );
4895
 
4896
    return if ( ! ActivePlatform($platforms) );
4897
 
4898
    #
4899
    #   Locate the script as a source file
4900
    #
4901
    my $file = MakeSrcResolve ( $script );
4902
    $script = StripDir( $file );
4903
    $SCRIPTS{ $script } = $file;
4904
}
4905
 
4906
#-------------------------------------------------------------------------------
4907
# Function        : RunTest
4908
#
4909
# Description     : Define a test to be run with the 'run_tests' and 'run_unit_tests'
4910
#
4911
# Inputs          : $platform       - Enabled for these platforms
4912
#                   $prog           - Program to run
4913
#                                     This SHOULD return a non-zero exit status
4914
#                                     on error. The program may be a 'TestProg'
4915
#                                     or a 'Script'.
4916
#                   @elements       - Options and test arguments
4917
#                                     Options are:
4778 dpurdie 4918
#                                       --Auto              - Non interactive unit test
4919
#                                       --Unit              - Same and --Auto
4920
#                                       --UtfFormat=nnn     - Specifies Automated Unit Test, 
4921
#                                                             results post processed with formatter
4781 dpurdie 4922
#                                       --UtfArg=nnn        - Argument passed into the UTF formatter    
4923
#                                       --Name=nnn          - Test Name.
5695 dpurdie 4924
#                                       --CopyIn=file       - A file to be copied into the test directory.
4925
#                                       --MaxTime=fff.ff[smhd] - Max Test Time. Default 30m
227 dpurdie 4926
#
4927
#                                     Non Options are passed to the test program.
4928
#                                     --PackageBase(xxx)    - Base of package
4929
#                                     --PackageInfo(xxx)    - Package information
4930
#                                     --File(xxx)           - Resolved name of file
4931
#                                     --Var(xxx)            - Expanded variable
4932
#                                     --Local(xxx)          - File within the local directory
4933
#
4778 dpurdie 4934
#                                     Toolset Framework support (ie NUNIT in csharp.pl)
4935
#                                       --FrameWork=name    - Name of framework
4936
#                                       --xxxx              - Args passed to framework constructor
4937
#
227 dpurdie 4938
# Returns         : Nothing
4939
#
4781 dpurdie 4940
my %RunTestNames;                       # Unique Name Tests
227 dpurdie 4941
sub RunTest
4942
{
4943
    my( $platforms, $prog, @elements ) = @_;
4944
    my $command = './';                 # program prefix / command
4945
    my $winprog = 1;                    # 1: Convert / -> \ (WIN32 only)
4946
    my $framework;
4947
    my @framework_opts;
4948
    my @copy = ();
4949
    my $auto;
4778 dpurdie 4950
    my $utfFormat;
4781 dpurdie 4951
    my @utfArgs;
4952
    my $utfName;
5695 dpurdie 4953
    my $maxTime;
227 dpurdie 4954
 
4955
    return if ( ! ActivePlatform($platforms) );
4956
 
4957
    #
4958
    #   Scan @elements and extract useful information
4959
    #   Need to process twice as some args will modify the
4960
    #   processing done later
4961
    #
4962
    my @args;
4963
    foreach ( @elements )
4964
    {
4965
        if ( m/^--FrameWork=(.+)/ ) {
4966
            $framework = $1;
4967
 
4968
        } elsif ( m/^--Auto/ || m/^--Unit/) {
4969
            $auto = 1;
4970
 
4781 dpurdie 4971
        } elsif ( m/^--Name=(.*)/) {
4972
            $utfName = $1;
4973
 
4974
            Error("Duplicate Test Name: $utfName")
4975
                if (exists $RunTestNames{$utfName} );
4976
            $RunTestNames{$utfName} = 1;
4977
 
4778 dpurdie 4978
        } elsif ( m/^--UtfFormat=(.*)/) {
4979
            $utfFormat = $1;
4980
 
4781 dpurdie 4981
        } elsif ( m/^--UtfArg=(.*)/) {
4982
            push @utfArgs, $1;
4983
 
5695 dpurdie 4984
        } elsif ( m/^--MaxTime=(.*)/) {
4985
            $maxTime = $1;
4986
            unless ($maxTime =~ m~^[0-9]*\.?[0-9]+[smhd]?$~) {
4987
                Error("MaxTime invalid: $maxTime");
4988
            }
4989
 
227 dpurdie 4990
        } elsif ( m/^--CopyIn=(.*)/ ) {
4991
            push @copy, MakeSrcResolve ( $1 );
4992
 
4993
        } elsif ( $framework && m/^--\w+=(.+)/ ) {
4994
            push @framework_opts, $_;
4995
 
4996
        } else {
4997
            push @args, $_;
4998
        }
4999
    }
5000
    @elements = @args;
5001
    @args = ();
5002
 
5003
    #
5004
    #   Determine the source of the test prog
4612 dpurdie 5005
    #   If using a plug-in framework, then we don't know
227 dpurdie 5006
    #   If not, then may be a script or a TESTPROGS
5007
    #
5008
 
5009
    unless ( $framework )
5010
    {
289 dpurdie 5011
        if ( $TESTPROGS->Get($prog) || $PROGS->Get($prog)  ) {
227 dpurdie 5012
            #
5013
            #   Append a suitable EXE suffix
5014
            #
289 dpurdie 5015
            $prog = GenProgName( $prog );
227 dpurdie 5016
 
5017
        } elsif ( exists $SCRIPTS{$prog} ) {
5018
            #
5019
            #   Script names are raw
5020
            #   Perl script are invoked directly
5021
            #
5022
            $command = "\$(GBE_PERL) -w "
5023
                if ( $prog =~ /\.pl$/ );
5024
 
5025
            #
5026
            #   Pass / to shells
5027
            #
5028
            $winprog = 0
5029
                unless ( $prog =~ m~\.bat$~ )
5030
 
5031
        } else {
5032
            Warning("RunTest program not known: $prog",
261 dpurdie 5033
                  "It is not a TestProg, Prog or a Script",
5034
                  "The test may fail" );
227 dpurdie 5035
        }
5036
    }
5037
 
5038
    #
5039
    #   Extract and process options
5040
    #
5041
    my @uargs = ();
5042
    my @preq_files;
5043
 
5044
    foreach my $arg (@elements) {
5045
        #
5046
        #   Process the tool arguments and extract file information
5047
        #   Extract all fields of the form:
5048
        #           --xxxxx(yyyyyy[,zzzzz])
5049
        #           --xxxxx{yyyyyyy}
5050
        #           --xxxxx[yyyyyyy] to allow embedded brackets
5051
        #
5052
        while ( $arg =~ m/--(\w+)               # --CommandWord         $1
5053
                                (               # Just for grouping
5054
                                \((.*?)\)   |   # Stuff like (yyyyy)    $3
5055
                                {(.*?)}     |   # or    like {yyyyy}    $4
5056
                                \[(.*?)\]       # or    like [yyyyy]    $5
5057
                                )/x )           # Allow comments and whitespace
5058
        {
5059
            my $cmd = $1;                       # The command
5060
            my $ufn = $3 || $4 || $5;           # User filename + options
5061
            my $mb = $-[0];                     # Match begin offset
5062
            my $me = $+[0];                     # Match end
5063
            my $flags = '';                     # Optional flags ( --dir or --file )
5064
            my $raw_arg = $ufn;                 # Raw arguments
6387 dpurdie 5065
            my $all = substr( $arg, $mb, $me - $mb ); # All of match. Avoid use of $&
329 dpurdie 5066
            my $is_abs;
5067
            my $is_path = 1;
227 dpurdie 5068
 
5069
            Error ("RunTest. Empty element not allowed: $all")
5070
                unless ( defined($ufn) );
5071
 
5072
            $ufn =~ s/\s+$//;
5073
            $ufn =~ s~//~/~g;                   # Remove multiple /
5074
            if ( $ufn =~ m/(.*?),(.*)/ )        # Extract out any flags
5075
            {
5076
                $ufn = $1;
5077
                $flags = $2;
5078
            }
5079
 
5080
            my $fn = $ufn ;                     # Replacement filename
343 dpurdie 5081
            my $fnp = '';                       # Prefix to $fn
227 dpurdie 5082
            Error ("RunTest. Empty element not allowed: $all" )
5083
                if ( length ($ufn) <= 0 );
5084
 
5085
            #
5086
            #   Process found user command
5087
            #
5088
            if ( $cmd =~ /^File/ )
5089
            {
5090
                #
5091
                #   Prerequisite filename
5092
                #       Resolve the full name of the file. It may be known
5093
                #       as a source file (possibly generated) or it may be
5094
                #       located in a known source directory
5095
                #
5096
                $fn = MakeSrcResolve ( $ufn );
5097
                UniquePush (\@preq_files, $fn);
5098
 
5099
                Debug( "RunTest: Prereq: $fn" );
5100
 
5101
            }
5102
            elsif ( $cmd =~ /^PackageBase/ )
5103
            {
5104
                $fn = GetPackageBase( "RunTest", $raw_arg );
5105
                UniquePush (\@preq_files, $fn);
5106
            }
5107
            elsif ( $cmd =~ /^PackageInfo/ )
5108
            {
5109
                $fn = GetPackageInfo( "RunTest", $raw_arg );
5110
            }
5111
            elsif ( $cmd =~ /^Var/ )
5112
            {
343 dpurdie 5113
                ($fnp, $fn, $is_path, $is_abs) = ExpandGenVar( "RunTest", $raw_arg );
227 dpurdie 5114
                $flags = '';
5115
            }
5116
            elsif ( $cmd =~ /^Local/ )
5117
            {
5118
                $fn = '$(LOCALDIR)/' . $ufn ;
5119
                UniquePush (\@preq_files, $fn);
5120
            }
6387 dpurdie 5121
            elsif ( $cmd =~ /^Dir/ )
5122
            {
5123
                # Item is a directory.
5124
                # Must be massaged so that it will be correct within the context
5125
                # Modified path is simply added to the command line
5126
                # 
5127
                $fn = $ufn;
5128
                unless (-d $fn) {
5129
                    if (-f $fn) {
5130
                        Warning ("Not a directory. Its a file: $arg") ;
5131
                    } else {
5132
                        Warning ("Directory not found: $arg");
5133
                    }
5134
                }
5135
            }
227 dpurdie 5136
            else
5137
            {
5138
                Warning ("RunTest: Unknown replacement command: $cmd");
5139
                $fn = $ufn;
5140
            }
5141
 
5142
            #
5143
            #   Process path modification flags
5144
            #       --dir           - only the directory part ( or a "." )
5145
            #       --file          - only the file part
5146
            #       --abspath       - Absolute path
5147
            #       --absdrive      - Absolute path with drive letter(WIN)
5148
            #
5149
            $fn = ProcessPathName( $fn, $flags );
5150
 
5151
            #
5152
            #   The program is going to be executed within a subdirectory
5153
            #   so add one more level of indirection to the path, but only if
5154
            #   the path is relative
5155
            #
329 dpurdie 5156
            if ( $is_path && ! $is_abs )
227 dpurdie 5157
            {
329 dpurdie 5158
                unless ( $fn =~ m~^/|^\w:/~  )
5159
                {
5160
                    $fn = '../' . $fn
5161
                        unless( $fn =~ s~=~=../~ );
5162
                    $fn =~ s~/.$~~;
5163
                }
227 dpurdie 5164
            }
5165
 
5166
            #
5167
            #   Minor kludge under windows. Ensure directores have a "\" sep
5168
            #   Unless the user has specified a straight shell command
5169
            #
5986 dpurdie 5170
            $fn = "\$(subst /,\$(dirsep),$fn)"
227 dpurdie 5171
                if ( $::ScmHost eq "WIN" && $winprog );
5172
 
5173
            #
343 dpurdie 5174
            #   Prepend any $fn Prefix
5175
            #   This will be a tag and is not subject to path processing
5176
            #
5177
            $fn = $fnp . $fn;
5178
 
5179
            #
227 dpurdie 5180
            #   Replace the found string with the real name of the file
5181
            #   Note: 4 argument version of substr is not always available
5182
            #         so we must do it the hard way
5183
            #               substr( $arg, $mb, $me - $mb, $fn);
5184
            #
5185
            $arg = substr( $arg, 0, $mb ) . $fn . substr( $arg, $me );
5186
 
5187
            Debug2( "RunTest: subs: $all -> $fn" );
5188
        }
5189
        push(@uargs, "'$arg'");
5190
    }
5191
 
5192
    #
5193
    #   Create the test entry
5194
    #   This is a structure that will be placed in an array
5195
    #   The array preserves order and uniqness
5196
    #
5197
    my %test_entry;
5198
    $test_entry{'framework'}= $framework if ( $framework );
5199
    $test_entry{'framework_opts'}= \@framework_opts if ( $framework );
5200
    $test_entry{'command'}  = $command . $prog unless ( $framework);
5201
 
5202
    $test_entry{'prog'}     = $prog;
5203
    $test_entry{'copyprog'} = 1;
5204
    $test_entry{'args'}     = \@uargs;
5205
    $test_entry{'auto'}     = $auto if ( $auto );
4778 dpurdie 5206
    $test_entry{'utfformat'}= $utfFormat if ( $utfFormat );
4781 dpurdie 5207
    $test_entry{'utfargs'}  = \@utfArgs;
5208
    $test_entry{'utfname'}  = $utfName;
5695 dpurdie 5209
    $test_entry{'maxtime'}  = $maxTime if ($maxTime);
227 dpurdie 5210
    $test_entry{'copyin'}   = \@copy;
5211
    $test_entry{'copyonce'} = ();
5212
    $test_entry{'preq'}     = \@preq_files;
5213
    $test_entry{'testdir'}  = 'BINDIR';
5214
 
5215
    push ( @TESTS_TO_RUN, \%test_entry );
5216
 
5217
    #
5218
    #   Flag Auto Run processing required
5219
    #
4501 dpurdie 5220
    $TESTS_TO_RUN = 1;
227 dpurdie 5221
    $TESTS_TO_AUTORUN = 1 if ( $auto );
5222
}
5223
 
5224
 
5225
sub TestProg
5226
{
5227
    my( $platforms, $prog, @elements ) = @_;
5228
 
5229
    Debug2( "TestProg($platforms, $prog, @elements)" );
5230
 
5231
    return if ( ! ActivePlatform($platforms) );
5232
 
5233
    Error ("TestProg: Program name not defined") unless ( $prog );
5234
    Error ("Programs are not supported") unless ( defined $::exe );
5235
 
289 dpurdie 5236
    #
5237
    #   Create a new Prog object, or retrieve any existing one
5238
    #
5239
    my $pProg = $TESTPROGS->Get($prog);
5240
    $pProg = $TESTPROGS->NewAdd($prog)
5241
        unless ( $pProg );
227 dpurdie 5242
 
5243
#.. Parse all of the object, library and argument entries
5244
    Debug( "TestProg: $prog" );
5245
    foreach (@elements)
5246
    {
5247
        if ( /^[-]{1,2}([lL])(.*)/ )
5248
        {
5249
        #.. Target Library specified - add to library list.
5250
        #  
5251
            Debug( "TestProg: lib  -$1$2" );
289 dpurdie 5252
            $pProg->addItem('LIBS', "-$1$2");
227 dpurdie 5253
            next;
5254
        }
5255
 
5256
        if ( /^--if(.*)/ )
5257
        {
5258
        #.. Library conditional - add to library list.
5259
        #
5260
            Debug( "TestProg: cond $_" );
289 dpurdie 5261
            $pProg->addItem('LIBS', $_);
227 dpurdie 5262
            next;
5263
        }
5264
 
5265
        if ( /^-(.*)/ )
5266
        {
5267
        #.. Argument specified - add to argument list
5268
        #
5269
            Debug( "TestProg: arg $_" );
289 dpurdie 5270
            $pProg->addItem('ARGS', $_);
227 dpurdie 5271
            next;
5272
        }
5273
 
369 dpurdie 5274
        if ( %::ScmToolsetProgSource )
227 dpurdie 5275
        {
5276
            #
5277
            #   Toolset provides support for some file types
5278
            #   to be passed directly to the program builder
5279
            #
5280
            my $ext  = StripFile($_);
5281
            if ( exists ($::ScmToolsetProgSource{$ext}) )
5282
            {
5283
                my $full_path = MakeSrcResolve ( $_ );
5284
                my $flag = $::ScmToolsetProgSource{$ext};
5285
                Debug( "TestProg: src $_" );
289 dpurdie 5286
                $pProg->addItem('ARGS', "$flag$full_path");
227 dpurdie 5287
                next;
5288
            }
5289
        }
5290
 
5291
        if ( $::o )
5292
        {
5293
        #.. Object specified - add to object list.
5294
        #
5295
            my $obj = _LibObject( "", $_ );
5296
 
5297
        #.. Add to program object list.
289 dpurdie 5298
            $pProg->addItem('OBJS', "\$(OBJDIR)/$obj");
227 dpurdie 5299
            next;
5300
        }
5301
 
5302
        #
5303
        #   Don't know how to handle this type of argument
5304
        #
5305
        Error ("TestProg: Don't know how to handle: $_" );
5306
    }
5307
}
5308
 
5309
 
5310
sub Prog
5311
{
5312
    my( $platforms, $prog, @elements ) = @_;
5313
 
5314
    Debug2( "Prog($platforms, $prog, @elements)" );
5315
 
5316
    return if ( ! ActivePlatform($platforms) );
5317
 
5318
    Error ("Prog: Program name not defined") unless ( $prog );
5319
    Error ("Programs are not supported") unless ( defined $::exe );
5320
 
289 dpurdie 5321
    #
5322
    #   Create a new Prog object, or retrieve any existing one
5323
    #
5324
    my $pProg = $PROGS->Get($prog);
5325
    $pProg = $PROGS->NewAdd($prog)
5326
        unless ( $pProg );
227 dpurdie 5327
 
5328
#.. Parse all of the object, library and argument entries
5329
    Debug( "Prog: $prog" );
5330
    foreach (@elements)
5331
    {
5332
        if ( /^[-]{1,2}([lL])(.*)/ )
5333
        {
5334
        #.. Target Library specified - add to library list.
5335
        #  
5336
            Debug( "Prog: lib  -$1$2" );
289 dpurdie 5337
            $pProg->addItem('LIBS', "-$1$2");
227 dpurdie 5338
            next;
5339
        }
5340
 
5341
        if ( /^--if(.*)/ )
5342
        {
5343
        #.. Library conditional - add to library list.
5344
        #
5345
            Debug( "Prog: cond $_" );
289 dpurdie 5346
            $pProg->addItem('LIBS', $_);
227 dpurdie 5347
            next;
5348
        }
5349
 
5350
        if ( /^-(.*)/ )
5351
        {
5352
        #.. Argument specified - add to argument list
5353
        #
5354
            Debug( "Prog: arg $_" );
289 dpurdie 5355
            $pProg->addItem('ARGS', $_);
227 dpurdie 5356
            next;
5357
        }
5358
 
369 dpurdie 5359
        if ( %::ScmToolsetProgSource )
227 dpurdie 5360
        {
5361
            #
5362
            #   Toolset provides support for some file types
5363
            #   to be passed directly to the program builder
5364
            #
5365
            my $ext  = StripFile($_);
5366
            if ( exists ($::ScmToolsetProgSource{$ext}) )
5367
            {
5368
                my $full_path = MakeSrcResolve ( $_ );
5369
                my $flag = $::ScmToolsetProgSource{$ext};
5370
                Debug( "Prog: src $_" );
289 dpurdie 5371
                $pProg->addItem('ARGS', "$flag$full_path");
227 dpurdie 5372
                next;
5373
            }
5374
        }
5375
 
5376
        if ( $::o )
5377
        {
5378
        #.. Object specified - add to object list.
5379
        #
5380
            my $obj = _LibObject( "", $_ );
5381
 
5382
        #.. Add to program object list.
289 dpurdie 5383
            $pProg->addItem('OBJS', "\$(OBJDIR)/$obj");
227 dpurdie 5384
            next;
5385
        }
5386
 
5387
        #
5388
        #   Don't know how to handle this type of argument
5389
        #
5390
        Error ("Prog: Don't know how to handle: $_" );
5391
    }
5392
}
5393
 
5394
#-------------------------------------------------------------------------------
5395
# Function        : ProgAddExtra
5396
#
5397
# Description     : This (internal) function allows a toolset to list additional
5398
#                   binaries as a part of a program. This will ensure that the
5399
#                   binaries are generated in the 'make_prog' phase with the main
5400
#                   program.
5401
#
5402
#                   The files are not listed for packaging, by this function
5403
#
5404
#                   The function does not ensure that the files are not already
5405
#                   listed as a @PROG ( as @PROGS is not fully resolved at this point )
5406
#
5407
# Inputs          :     $name               - Tag name of program being built
5408
#                                             Not used (yet)
5409
#                       $prog               - Fully resolved path to a file
5410
#
5411
# Returns         : Nothing
5412
#
5413
sub ProgAddExtra
5414
{
5415
    my ($name, $prog) = @_;
5416
    Debug2( "ProgAddExtra($name: $prog)" );
5417
 
5418
    UniquePush(\@PROGS_EXTRA, $prog);
5419
}
5420
 
4261 dpurdie 5421
our %PROJECTS;                          # Project information
5422
my  @PROJECTS_ORDER;
227 dpurdie 5423
#-------------------------------------------------------------------------------
4261 dpurdie 5424
# Function        : MakeProjectName 
5425
#
5426
# Description     : Create a uniq project name
5427
#
5428
# Inputs          : srcPath 
5429
#
5430
# Returns         : A unique project name 
5431
#
5432
sub MakeProjectName
5433
{
5434
    my ($srcPath) = @_;
5435
    my $suffix = "";
5436
    my $index = 1;
5437
 
5438
    my $proj = StripDir( $srcPath );
5439
    while (exists $PROJECTS{$proj . $suffix})
5440
    {
5441
        $suffix = '.' . $index++;
5442
    }
5443
    return $proj . $suffix; 
5444
}
5445
 
5446
#-------------------------------------------------------------------------------
227 dpurdie 5447
# Function        : MakeProject
5448
#
5449
# Description     : A nasty directive that is intended to build a Microsoft
5450
#                   project for WINCE, WIN32 and .NET builds.
5451
#
5452
#                   There are many constraints:
5453
#                       Cannot be mixed with multi-platform builds
5454
#                       Some parameters are tool specific
5455
#
267 dpurdie 5456
#                   Allow programs to be Installed as well as Packaged
5457
#                   The 'Progect' is treated' as a program and it doesn't work
5458
#                   to well if we Install libraries.
227 dpurdie 5459
#
267 dpurdie 5460
#                   Only Reason to Install Programs is to allow the Cab Maker
5461
#                   to locate them.
5462
#
227 dpurdie 5463
# Inputs          : Platform        - Active platform
5464
#                   Project         - Project Name with extension
5465
#                   Options         - Many options
5466
#
5467
# Returns         :
5468
#
5469
sub MakeProject
5470
{
5471
    my( $platforms, $proj, @elements ) = @_;
5472
 
5473
    Debug2( "MakeProject($platforms, $proj, @elements)" );
5474
 
5475
    return if ( ! ActivePlatform($platforms) );
5476
 
5477
    #
5478
    #   Sanity test
5479
    #
5480
    Error ("MakeProject: Project name not defined") unless ( $proj );
5481
 
5482
    #
5483
    #   Take the project name and convert it into a full path
4261 dpurdie 5484
    #   Need to create a uniq project name - allowing for multiple uses
227 dpurdie 5485
    #
5486
    my $project = MakeSrcResolve ( $proj );
4261 dpurdie 5487
    $proj = MakeProjectName($project);
5488
 
237 dpurdie 5489
    Error ("Project File Not found: $project") unless ( -f $project );
227 dpurdie 5490
 
5491
    my $basedir = StripFileExt( $project );
5492
 
5493
    #
5494
    #   Collect user arguments
5495
    #   They are all processed within the toolset
5496
    #
5497
    my @tool_options;
5411 dpurdie 5498
    my $unit_tests;
5499
    my $auto_tests;
227 dpurdie 5500
    foreach ( @elements )
5501
    {
5502
        if ( m/^--Debug/ ) {
5503
            $PROJECTS{$proj}{'Debug'} = 1;
5504
 
5505
        } elsif ( m/^--Prod/ ) {
5506
            $PROJECTS{$proj}{'Prod'} = 1;
5507
 
267 dpurdie 5508
        } elsif ( m/^--(Package|Install)ProgDebug=(.*)/ ) {
5509
            _PackageFromProject( $1, $proj, $basedir,'Prog', 'D', $2 );
227 dpurdie 5510
 
267 dpurdie 5511
        } elsif ( m/^--(Package|Install)Prog(Prod)*=(.*)/ ) {
5512
            _PackageFromProject( $1, $proj, $basedir, 'Prog', 'P', $3 );
227 dpurdie 5513
 
267 dpurdie 5514
        } elsif ( m/^--(Package)LibDebug=(.*)/ ) {
5515
            _PackageFromProject( $1, $proj, $basedir, 'Lib', 'D', $2 );
227 dpurdie 5516
 
267 dpurdie 5517
        } elsif ( m/^--(Package)Lib(Prod)*=(.*)/ ) {
5518
            _PackageFromProject( $1, $proj, $basedir, 'Lib', 'P', $3 );
227 dpurdie 5519
 
267 dpurdie 5520
        } elsif ( m/^--(Package)SharedLibDebug=(.*)/ ) {
5521
            _PackageFromProject( $1, $proj, $basedir, 'Lib', 'D', $2 );
227 dpurdie 5522
 
267 dpurdie 5523
        } elsif ( m/^--(Package)SharedLib(Prod)*=(.*)/ ) {
5524
            _PackageFromProject( $1, $proj, $basedir, 'Lib', 'P', $3 );
227 dpurdie 5525
 
267 dpurdie 5526
        } elsif ( m/^--(Package)Hdr=(.*)/ ) {
5527
            _PackageFromProject( $1, $proj, $basedir, 'Hdr', undef, $2 );
227 dpurdie 5528
 
267 dpurdie 5529
        } elsif ( m/^--(Package)File=(.*)/ ) {
5530
            _PackageFromProject( $1, $proj, $basedir, 'File', undef, $2 );
227 dpurdie 5531
 
267 dpurdie 5532
        } elsif ( m/^--(Package)Tool(Prod)*=(.*)/ ) {
5533
            _PackageFromProject( $1, $proj, $basedir, 'Tool', 'P', $3 );
241 dpurdie 5534
 
267 dpurdie 5535
        } elsif ( m/^--(Package)ToolDebug=(.*)/ ) {
5536
            _PackageFromProject( $1, $proj, $basedir, 'Tool', 'D', $2 );
241 dpurdie 5537
 
267 dpurdie 5538
        } elsif ( m/^--(Package|Install)/ ) {
5539
            Error("MakeProject. Unknown $1 option: $_");
227 dpurdie 5540
 
5411 dpurdie 5541
        } elsif ( m/^--UnitTest/ ) {
5542
            $unit_tests = 1;
5543
 
5544
        } elsif ( m/^--AutoTest/ ) {
5545
            $auto_tests = 1;
5546
 
227 dpurdie 5547
        } else {
5548
            push @tool_options, $_;
5549
        }
5550
    }
5551
 
5552
    #
6353 dpurdie 5553
    #   Validate some of the arguments
5554
    #   Ensure has not specified both --Prod and --Debug
5555
    #
5556
    Error ("Makeproject. Conflicting options --Debug and --Prod" )
5557
        if ( $PROJECTS{$proj}{'Debug'}  && $PROJECTS{$proj}{'Prod'} );
5558
 
5559
    #   Ensure that global --OnlyProd/Debug don't prevent builds
5560
    $PROJECTS{$proj}{'Debug'} = 1 if ($ScmBuildType eq 'D');
5561
    $PROJECTS{$proj}{'Prod'} = 1 if ($ScmBuildType eq 'P');
5562
    Error ("Makeproject. Global and Local options --Debug and --Prod prevent project being built" )
5563
        if ( $PROJECTS{$proj}{'Debug'}  && $PROJECTS{$proj}{'Prod'} );
5564
 
5565
    #
227 dpurdie 5566
    #   Save the information
5567
    #
5568
    $PROJECTS{$proj}{'options'} = \@tool_options;
5569
    $PROJECTS{$proj}{'name'} = $proj;
5570
    $PROJECTS{$proj}{'project'} = $project;
5571
    $PROJECTS{$proj}{'basedir'} = $basedir;
5411 dpurdie 5572
    $PROJECTS{$proj}{'unittest'} = $unit_tests if ( $unit_tests );
5573
    $PROJECTS{$proj}{'autotest'} = $auto_tests if ( $auto_tests );
227 dpurdie 5574
    UniquePush (\@PROJECTS_ORDER, $proj);
5575
 
5576
}
5577
 
5578
#-------------------------------------------------------------------------------
5579
# Function        : _PackageFromProject
5580
#
5581
# Description     : Save Packaged data from the project
5582
#
267 dpurdie 5583
# Inputs          : $tgt        - Install or Package
5584
#                   $proj       - Name of the project
227 dpurdie 5585
#                   $base       - Base directory of files
5586
#                   $etype      - Type of Package (Progs, Libs, ... )
5587
#                   $type       - Debug or Production or both
5588
#                   $items      - Item to add. It may be comma seperated
5589
#
267 dpurdie 5590
my %PackageToData = ( 'Package' =>
5591
                        { 'Hdr'   => \%PACKAGE_HDRS,
5592
                          'Lib'   => \%PACKAGE_LIBS,
5593
                          'Prog'  => \%PACKAGE_PROGS,
5594
                          'File'  => \%PACKAGE_FILES,
5595
                          'Tool'  => \%PACKAGE_FILES,
5596
                          '_BASE' => 'PBase',
5597
                        },
5598
                      'Install' =>
5599
                        { 'Hdr'   => \%INSTALL_HDRS,
5600
                          'Lib'   => \%INSTALL_LIBS,
5601
                          'Prog'  => \%INSTALL_PROGS,
5602
                          'File'  => undef,
5603
                          'Tool'  => undef,
5604
                          '_BASE' => 'IBase',
5605
                        },
227 dpurdie 5606
                    );
5607
 
5608
sub _PackageFromProject
5609
{
267 dpurdie 5610
    my( $tgt, $proj, $base, $etype, $type, $items ) = @_;
227 dpurdie 5611
    my $subdir = '';
5612
 
5613
    #
267 dpurdie 5614
    #   Sanity test
5615
    #
5616
    $type = '' unless ( $type );
5617
    Error ("INTERNAL. Bad packaging option: $tgt")   unless ( exists $PackageToData{$tgt} );
5618
    Error ("INTERNAL. Bad packaging option: $etype") unless ( exists $PackageToData{$tgt}{$etype} );
5619
    Error ("Unsupported packaging combination: $tgt$etype$type=$items") unless ( defined $PackageToData{$tgt}{$etype} );
5620
 
5621
    #
5622
    #   Determine the index into the 'PackageInfo' structure
5623
    #   This provides the symbolic name for the target package path
5624
    #   for Package or Install
5625
    #
5626
    #   The key '_BASE' is internal. Used only to provide this information
5627
    #
5628
    my $tbase = $PackageToData{$tgt}{'_BASE'};
5629
 
5630
    #
227 dpurdie 5631
    #   Process options
5632
    #
5633
    foreach my $item ( split (/,/, $items ) )
5634
    {
5635
        next unless ( $item =~ m/^--/ );
5636
        if ( $item =~ m/^--Subdir=(.*)/ )
5637
        {
5638
            $subdir = '/' . $1;
5639
            $subdir =~ s~//~/~g;
5640
            $subdir =~ s~/$~~g;
5641
        }
5642
        else
5643
        {
5644
            Warning( "MakeProject: Unknown packaging option ignored: $_" );
5645
        }
5646
    }
5647
 
5648
    #
5649
    #   Process files
5650
    #
5651
    foreach my $item ( split (/,/, $items ) )
5652
    {
5653
        next if ( $item =~ m/^--/ );
5654
 
267 dpurdie 5655
        my $tdir = $PackageInfo{$etype}{$tbase} . $PackageInfo{$etype}{'Dir'} . $subdir ;
227 dpurdie 5656
        my $fname = StripDir( $item );
5657
        my $target = $tdir . '/' . $fname;
5658
 
5659
        $item = "$base/$item" if ( $base );
5660
 
5661
        #
5662
        #   Do not use $(GBE_TYPE) in the target name
5663
        #   The existing package mechanism does not handle different
5664
        #   production and debug file naming mechanism, whereas the project
5665
        #   must. Convert $(GBE_TYPE) into P or D to ensure uniquness
5666
        #
5667
        $target =~ s~\$\(GBE_TYPE\)~$type~ if ($type);
5668
 
5669
        #
5670
        #   Create a PACKAGE entry suitable for processing by the normal packaging
5671
        #   routines. This is complicated because the Projects do not adhere to
267 dpurdie 5672
        #   the JATS file name conventions
227 dpurdie 5673
        #
5674
        my %package_entry;
5675
        $package_entry{'src'}   = $item;
5676
        $package_entry{'dir'}   = $tdir;
267 dpurdie 5677
        $package_entry{'set'}   = 'ALL' if ($tgt eq 'Package');
227 dpurdie 5678
        $package_entry{'type'}  = $type if ($type);
5679
 
267 dpurdie 5680
        $PackageToData{$tgt}{$etype}->{$target} = {%package_entry};
227 dpurdie 5681
    }
5682
}
5683
 
5684
#-------------------------------------------------------------------------------
5685
# Function        : MakeAnt
5686
#
5687
# Description     : A nasty directive to create JAR files via ANT
5688
#                   There are several limitations
5689
#                   This is closely related to the MakeProject directive
5690
#
5691
#
5692
# Inputs          : Platform            - Active platform
5693
#                   buildfile           - Name of the build.xml file
5694
#                   Options             - A few options
5695
#                                         --Jar=file
5696
#                                               Generated JAR file(s)
5697
#                                         --GeneratedFile=file
5698
#                                               Other generated files
5699
#                                               Used to flag JNI that must
5700
#                                               Occur early
5701
#                                          --AutoTest=<name>
5702
#                                               Supports unitAutomated unit test
5703
#                                               by calling build target <name>
5704
#                                          --UnitTest=<name>
5705
#                                               Supports unit test
5706
#                                               by calling build target <name>
5707
#                                          --PackageBase
5708
#                                               Provides path to base of all packages
6294 dpurdie 5709
#                                          --AllPackages
5710
#                                               Provide paths to both LinkPkgArchive and BuildPkgArchive
227 dpurdie 5711
#
5712
# Returns         :
5713
#
5714
our %JAR_FILES;
5715
sub MakeAnt
5716
{
5717
    my( $platforms, $proj, @elements ) = @_;
5718
 
5719
    Debug2( "MakeAnt($platforms, $proj, @elements)" );
5720
 
5721
    return if ( ! ActivePlatform($platforms) );
5722
 
5723
    #
5724
    #   Sanity test
5725
    #
5726
    Error ("MakeAnt: build.xml name not defined") unless ( $proj );
5727
 
5728
    #
5729
    #   Take the project name and convert it into a full path
5730
    #
5731
    my $project;
5732
    $project = MakeSrcResolve ( $proj );
4261 dpurdie 5733
    $proj = MakeProjectName($project);
237 dpurdie 5734
    Error ("Build File Not found: $project") unless ( -f $project );
227 dpurdie 5735
 
5736
    my $basedir = StripFileExt( $project );
5737
 
5738
    #
5739
    #   Collect user arguments
5740
    #   They are all processed within the toolset
5741
    #
5742
    my @tool_options;
5743
    my @generated;
5744
    my $unit_tests;
5745
    my $auto_tests;
5746
    my $package_base;
6294 dpurdie 5747
    my $allPackages;
227 dpurdie 5748
 
5749
    foreach ( @elements )
5750
    {
5751
        if ( m/^--Debug/ ) {
5752
            $PROJECTS{$proj}{'Debug'} = 1;
5753
 
5754
        } elsif ( m/^--Prod/ ) {
5755
            $PROJECTS{$proj}{'Prod'} = 1;
5756
 
5757
        } elsif ( m/^--Jar=(.*)/ ) {
5758
            my $tgt = $1;
5759
               $tgt = "$basedir/$tgt" if ( $basedir );
5760
            my $fn = StripDir( $1 );
5761
            $JAR_FILES{$fn} = $tgt;
5762
            GenerateSrcFile( 0, $tgt );
5763
 
5764
        } elsif ( m/^--GeneratedFile=(.*)/ ) {
5765
            my $tgt = $1;
5766
            $tgt = "$basedir/$tgt" if ( $basedir );
5767
            push @generated, $tgt;
5768
            GenerateSrcFile( 2, $tgt );
5769
 
5770
        } elsif ( m/^--UnitTest=(.*)/ ) {
5771
            $unit_tests = $1
5772
 
5773
        } elsif ( m/^--AutoTest=(.*)/ ) {
5774
            $auto_tests = $1
5775
 
5776
        } elsif ( m/^--PackageBase/ ) {
5777
            $package_base = 1;
5778
 
6294 dpurdie 5779
        } elsif ( m/^--AllPackages/i ) {
5780
            $allPackages = 1;
227 dpurdie 5781
 
5782
        } elsif ( m/^--/ ) {
5783
            Error("MakeAnt. Unknown option ignored: $_");
5784
 
5785
        } else {
5786
            push @tool_options, $_;
5787
        }
5788
    }
5789
 
5790
    #
5791
    #   Extend option arguments to include the base dir of packages
5792
    #   Create definitions of the form PACKAGE_<name>
5793
    #
6294 dpurdie 5794
    for my $entry (getPackageList())
227 dpurdie 5795
    {
6294 dpurdie 5796
        my $pkgType = $entry->getType();
5797
        next if $pkgType eq 'interface'  ;
5798
        next unless ( ( $pkgType eq 'link') || $allPackages);
5799
        my $dir = $entry->getBase(2);
5800
        my $name = $entry->getName();
227 dpurdie 5801
        unless ( $package_base )
5802
        {
5803
            $dir .= '/jar';
5804
            next unless ( -d $dir );
5805
        }
6294 dpurdie 5806
        push @tool_options, "-DPACKAGE_$name=\$(call myabspath,$dir)";
227 dpurdie 5807
    }
5808
    #
5809
    #   Extend options to include the base dir of the created package
5810
    #   Allows careful use for direct packaging of artifacts
5811
    #
6294 dpurdie 5812
    push @tool_options, '-DPACKAGEDIR=$(call myabspath,$(PKGDIR))';
227 dpurdie 5813
 
5814
    #
5815
    #   Save the information
5816
    #
5817
    $PROJECTS{$proj}{'options'} = \@tool_options;
5818
    $PROJECTS{$proj}{'generated'} = \@generated if ( @generated );
5819
    $PROJECTS{$proj}{'name'}    = $proj;
5820
    $PROJECTS{$proj}{'project'} = $project;
5821
    $PROJECTS{$proj}{'basedir'} = $basedir;
5822
    $PROJECTS{$proj}{'type'}    = 'ant';
5823
    $PROJECTS{$proj}{'unittest'} = $unit_tests if ( $unit_tests );
5824
    $PROJECTS{$proj}{'autotest'} = $auto_tests if ( $auto_tests );
5825
    UniquePush (\@PROJECTS_ORDER, $proj);
5826
 
5827
    $TESTS_TO_AUTORUN = 1 if ( $auto_tests );
4501 dpurdie 5828
    $TESTS_TO_RUN     = 1 if ( $unit_tests || $auto_tests );
227 dpurdie 5829
 
5830
    #
5831
    #   Validate some of the arguments
5832
    #
5833
    Error ("MakeAnt. Conflicting options --Debug and --Prod" )
5834
        if ( $PROJECTS{$proj}{'Debug'}  && $PROJECTS{$proj}{'Prod'} );
5835
}
5836
 
5837
###############################################################################
5838
#
5839
#   Installation/Packaging util functions
5840
#
5841
#-------------------------------------------------------------------------------
5842
# Function        : __TargetDir
5843
#
5844
# Description     : Internal function to process common arguments for
5845
#                   the PackageXxx directives
5846
#
5847
# Inputs          : flags           - Indicate how to handle this argument
5848
#                   base            - Base directory for this type of package
5849
#                   argument        - Argument to process
5850
#                   pdir            - Reference to resultant directory
5851
#                   ptype           - Reference to resultant type (P or D)(optional)
5852
#
5853
# Returns         : 0               - Agument not consumed
5854
#                   1               - Argument consumed
5855
#                   2               - Skip this directive
5856
#
5857
my $T_TYPE  = 0x0001;                           # Postfix GBE_TYPE
5858
my $T_PKG   = 0x0002;                           # Special --Dir handling
5859
my $T_MACH  = 0x0004;                           # Allow --Machine too
5860
my $T_GBE   = 0x0008;                           # Allow --Gbe too
5861
my $T_FILE  = 0x0010;                           # Suffix or prefix subdir
5862
 
5863
sub __TargetDir
5864
{
5865
    my( $flags, $base, $argument, $pdir, $ptype ) = @_;
5866
    my $dir  = "";
5867
    my $consumed = 0;
5868
 
5869
    #
5870
    #   Generate basic parts
5871
    #   Note Product will default to Platform
5872
    #
5873
    my $str_platform = '$(GBE_PLATFORM)';
5874
    my $str_product = $ScmProduct ? '$(GBE_PRODUCT)' : '$(GBE_PLATFORM)';
5875
    my $str_target = '$(GBE_TARGET)';
5876
    my $str_common = '$(GBE_OS_COMMON)';
5877
 
5878
    my $str_common_avail = 0;
5879
       $str_common_avail = 1 if ( exists( $::BUILDINFO{$ScmPlatform}{OS_COMMON} ));
5880
 
5881
 
5882
    #
5883
    #   Add requested suffix
5884
    #
5885
    if ($flags & $T_TYPE)
5886
    {
5887
        $str_platform .= '$(GBE_TYPE)';
5888
        $str_product  .= '$(GBE_TYPE)';
5889
        $str_target   .= '$(GBE_TYPE)';
5890
        $str_common   .= '$(GBE_TYPE)';
5891
    }
5892
 
5893
    #
5894
    #   Process the argument
5895
    #
5896
    $_ = $argument;
5897
    if ( /^--Debug/ ) {                         # In the Debug build only
5898
        if ( $ptype ) {
5899
            $$ptype = "D";
5900
            $consumed = 1;
5901
        }
5902
 
5903
    } elsif ( /^--Prod$/ || /^--Production$/ ) { # In the Production build only
5904
        if ( $ptype ) {
5905
            $$ptype = "P";
5906
            $consumed = 1;
5907
        }
5908
 
5909
    } elsif (/^--Prefix=(.*)/) {                # Prefix with subdir
5910
        $dir = "$base/$1";
5911
 
5912
    } elsif (/^--Subdir=(.*)/) {                # same as 'prefix'
5913
        $dir = "$base/$1";
5914
 
5915
    } elsif (/^--Platform$/) {                  # Platform installation
5916
        $dir = "$base/$str_platform";
5917
 
5918
    } elsif (/^--Platform=(.*?),(.*)/) {        # prefix and suffix with platform specific subdir
5919
        $dir = "$base/$1/$str_platform/$2";
5920
 
5921
    } elsif (/^--Platform=(.*)/) {              # prefix with platform specific subdir
5922
        if ($flags & $T_FILE) {
5923
            $dir = "$base/$1/$str_platform";
5924
        } else {
5925
            $dir = "$base/$str_platform/$1";
5926
        }
5927
 
5928
    } elsif (/^--Product$/) {                   # Product installation
5929
        $dir = "$base/$str_product";
5930
 
5931
    } elsif (/^--Product=(.*?),(.*)/) {         # prefix and suffix with product specific subdir
5932
        $dir = "$base/$1/$str_product/$2";
5933
 
5934
    } elsif (/^--Product=(.*)/) {               # prefix with product specific subdir
5935
        if ($flags & $T_FILE) {
5936
            $dir = "$base/$1/$str_product";
5937
        } else {
5938
            $dir = "$base/$str_product/$1";
5939
        }
5940
 
5941
    } elsif (/^--Target$/) {                    # Target installation
5942
        $dir = "$base/$str_target";
5943
 
5944
    } elsif (/^--Target=(.*?),(.*)/) {          # prefix and suffix with target specific subdir
5945
        $dir = "$base/$1/$str_target/$2";
5946
 
5947
    } elsif (/^--Target=(.*)/) {                # prefix with target specific subdir
5948
        if ($flags & $T_FILE) {
5949
            $dir = "$base/$1/$str_target";
5950
        } else {
5951
            $dir = "$base/$str_target/$1";
5952
        }
5953
 
5954
    } elsif (/^--OsCommon/) {
5955
 
5956
        unless ( $str_common_avail ) {
5957
            Warning("Packaging option --OsCommon not supported on this platform($ScmPlatform). Directive skipped");
5958
            $consumed = 2;
5959
 
5960
        } elsif (/^--OsCommon$/) {                  # OS installation
5961
            $dir = "$base/$str_common";
5962
 
5963
        } elsif (/^--OsCommon=(.*?),(.*)/) {        # prefix and suffix with target specific subdir
5964
            $dir = "$base/$1/$str_common/$2";
5965
 
5966
        } elsif (/^--OsCommon=(.*)/) {              # prefix with target specific subdir
5967
            if ($flags & $T_FILE) {
5968
                $dir = "$base/$1/$str_common";
5969
            } else {
5970
                $dir = "$base/$str_common/$1";
5971
            }
5972
        }
5973
 
5974
    } elsif (/^--Derived=(.*?),(.*?),(.*)/) {   # Derived target + prefix + subdir
5975
        $dir = "$base/$2/$1_$str_platform/$3";
5976
 
5977
    } elsif (/^--Derived=(.*?),(.*)/) {         # Derived target + subdir
5978
        if ($flags & $T_FILE) {
5979
            $dir = "$base/$2/$1_$str_platform";
5980
        } else {
5981
            $dir = "$base/$1_$str_platform/$2";
5982
        }
5983
 
5984
    } elsif (/^--Derived=(.*)/) {               # Derived target
5985
        $dir = "$base/$1_$str_platform";
5986
 
5987
    } elsif ($flags & $T_MACH && /^--Machine(([=])(.*))?$/) {   # Allow Machine and Machine=xxx specfic target
5988
        #
5989
        #   Special: Append machine type to user dir
5990
        #            Intended to create tools/bin/win32 and tools/bin/sparc directories
5991
        my $path = ( defined( $3) ) ? "/$3" : "";
5992
        $dir = "$base$path/\$(GBE_HOSTMACH)";
5993
 
5994
    } elsif ($flags & $T_GBE && /^--Gbe(([=])(.*))?$/) {   # Allow Gbe and Gbe=xxx specfic target
5995
        my $path = ( defined( $3) ) ? "/$3" : "";
5996
        $dir = "$base/gbe$path";
5997
 
5998
    } elsif (/^--Dir=(.*)/) {                   # prefix with target specific subdir
5999
        Error ('Packaging directive with --Dir option does not specify a directory.',
6000
               'Possible bad use of option of the form:--Dir=$xxx',
6001
               'Note: Use of package.pl and this construct is deprecated') unless ( $1 );
241 dpurdie 6002
        my $udir = $1;
6003
 
6004
        #
6005
        #   Remove leading ./
6006
        #   Check for leading ../
5568 dpurdie 6007
        #   
6008
        #   Remove any stupid path manipulation elements
6009
        #   
5827 dpurdie 6010
        if ($udir =~ s~^([./]*/)~~)
6011
        {
6012
            Warning("Packaging directive with --Dir option contains path manipulation elements (removed)", "Option: $_");
6013
        }
241 dpurdie 6014
 
227 dpurdie 6015
        if ($flags & $T_PKG) {
241 dpurdie 6016
            $dir = __PkgDir( $udir );
227 dpurdie 6017
        } else {
6387 dpurdie 6018
            $dir = $base . "/" . $udir;
227 dpurdie 6019
        }
6020
    }
6021
 
6022
    return ($consumed) if ($dir eq "");
6023
    $dir =~ s~//~/~g;
6024
    $dir =~ s~/$~~;
6025
    $$pdir = $dir;
6026
    return (1);
6027
}
6028
 
6029
 
6030
#   __PkgDir ---
6031
#       Convert --Dir Package directives, removing leading subdir if
6032
#       matching the global $Pbase value.
6033
#
6034
#       Required as PKGDIR has the value 'GBE_ROOT/pkg/$Pbase'.
6035
#       Required to maintain compatability with older (package.pl) constructs
6036
#..
6037
 
6038
sub __PkgDir
6039
{
6040
    my( $dir ) = @_;
6041
    my $org = $dir;
6042
 
245 dpurdie 6043
    $dir =~ s~^\Q$::Pbase\E[/]?~~;
227 dpurdie 6044
    Debug2( "  PkgDir: converted \"$org\" to \"$dir\"" );
6045
 
6046
    $dir = "\$(PKGDIR)/$dir";
6047
    return $dir;
6048
}
6049
 
6050
 
6051
#   getMajorMinor ---
6052
#       Just a little help to deal with major/minor stuff for shared libs -
6053
#       given the name of the library as the argument, split out major and
6054
#       minor parts and return the basename, i.e name without major and minor
6055
#       and the pair of major and minor.
6056
#..
6057
 
285 dpurdie 6058
sub getMajorMinor
227 dpurdie 6059
{
6060
    my @bits = split ('\.', $_[0]);
6061
    my $stop;
6062
    my $major;
6063
    my $minor;
6064
 
6065
    if ( $#bits > 2 )
6066
    {
6067
        $stop = $#bits - 2;
6068
        $major = $bits[$#bits-1];
6069
        $minor = $bits[$#bits];
6070
    }
6071
    elsif ($#bits > 1)
6072
    {
6073
        $stop = $#bits-1;
6074
        $major = $bits[$#bits];
6075
        $minor=0;
6076
    }
6077
    else
6078
    {
6079
        $stop = $#bits; $major = 1; $minor = 0;
6080
    }
6081
 
6082
    my $base = $bits[0];
6083
    for ( my $i=1; $i <= $stop; $i++ ) {
6084
        $base = join ('.', $base, $bits[$i]);
6085
    }
6086
 
6087
    return ($base, $major, $minor);
6088
}
6089
 
6090
###############################################################################
6091
#
6092
#   Installation
6093
#
6094
 
6095
sub InstallHdr
6096
{
6097
    my( $platforms, @elements ) = @_;
335 dpurdie 6098
    my( $base, $dir, $srcfile, $full, $strip, $package );
227 dpurdie 6099
    my( $len, $name, $basename );
6100
 
6101
    Debug2( "InstallHdr($platforms, @elements)" );
6102
 
6103
    return if ( ! ActivePlatform($platforms) );
6104
    Warning ("InstallHdr: Needs local directory specified in build.pl") unless ( $::ScmLocal );
6105
 
6106
#.. Arguments
6107
#
6108
    $base = $PackageInfo{'Hdr'}{'IBase'};       # Base of target
6109
    $dir = $base . $PackageInfo{'Hdr'}{'Dir'};  # Installation path (default)
335 dpurdie 6110
    $full = $strip = 0;
227 dpurdie 6111
 
285 dpurdie 6112
    foreach ( @elements )
227 dpurdie 6113
    {
6114
                                                # Standard targets
6115
        my $rv = __TargetDir(0, $base, $_, \$dir);
6116
        next if ( $rv == 1 );
6117
        return if ( $rv == 2 );
6118
 
6119
        if (/^--Full/) {                        # using full (resolved) path
6120
            $full = 1;
6121
 
6122
        } elsif (/^--Strip$/) {                 # Strip path from source files
6276 dpurdie 6123
            $strip = -1;
227 dpurdie 6124
 
6276 dpurdie 6125
        } elsif (/^--Strip=(\d+)$/) {           # Strip some f the path from source files
6126
            $strip = $1;
227 dpurdie 6127
                                                # Package
6128
        } elsif (/^--Package$/ || /^--Package=(.*)/) {
6129
            $package = 1;
6130
 
6131
        } elsif (/^--(.*)/) {
6132
            Message( "InstallHdr: unknown option $_ -- ignored\n" );
6133
        }
6134
    }
6135
 
6136
#.. Files
6137
#
285 dpurdie 6138
    foreach ( @elements )
227 dpurdie 6139
    {
6140
        my %package_entry;
6141
        if ( ! /^--(.*)/ )
6142
        {
6143
            $name = $_;
6144
            $basename = StripDir( $name );
335 dpurdie 6145
            if ( !($srcfile = $SRCS{ $basename }) ) {
6146
                $srcfile = $name;
6147
            }
6148
 
227 dpurdie 6149
            if ( $full )
6150
            {
335 dpurdie 6151
                my $subdir = StripFileExt($srcfile);
6152
                $subdir = $1
6153
                    if ( $subdir =~ m~^$ProjectBase/(.*)~ );
6154
                $dir .= '/' . $subdir;
6155
                $dir =~ s~//~/~g;
6156
                $dir =~ s~/./~/~g;
6157
                $dir =~ s~/$~~g;
6158
                $name = $basename;
227 dpurdie 6159
            }
6160
 
6276 dpurdie 6161
            $name = StripPath($name, $strip) if ($strip);
227 dpurdie 6162
 
6163
            Debug( "InstallHdr( $dir/$name, src: $srcfile, dest: $dir)" );
6164
 
6165
            $package_entry{'src'} = $srcfile;
6166
            $package_entry{'dir'} = StripFileExt( "$dir/$name" );
6167
            $INSTALL_HDRS{ "$dir/$name" } = {%package_entry};
6168
        }
6169
    }
6170
 
6171
#.. Package
6172
#
6173
    PackageHdr( @_ )                            # auto package
6174
        if ( $package );
6175
}
6176
 
6177
 
6178
sub InstallLib
6179
{
6180
    my( $platforms, @elements ) = @_;
6181
    my( $base, $dir, $package );
6182
    my( $lib, $strip );
289 dpurdie 6183
    my $org_lib;
227 dpurdie 6184
 
6185
    Debug2( "InstallLib($platforms, @elements)" );
6186
 
6187
    return if ( ! ActivePlatform($platforms) );
6188
    Warning ("InstallLib: Needs local directory specified in build.pl") unless ( $::ScmLocal );
6189
 
6190
#.. Arguments
6191
#
6192
    $base = $PackageInfo{'Lib'}{'IBase'};       # Base of target
6193
    $dir = $base . $PackageInfo{'Lib'}{'Dir'};  # Installation path (default)
6194
 
285 dpurdie 6195
    foreach ( @elements )
227 dpurdie 6196
    {
6197
                                                # Standard targets
6198
        my $rv = __TargetDir(0, $base, $_, \$dir);
6199
        next if ( $rv == 1 );
6200
        return if ( $rv == 2 );
6201
 
6202
        if (/^--Package$/ || /^--Package=(.*)/) {
6203
            $package = 1;
6204
 
6205
        } elsif (/^--Strip$/) {                 # Strip path from source files
6276 dpurdie 6206
            $strip = -1;
227 dpurdie 6207
 
6276 dpurdie 6208
        } elsif (/^--Strip=(\d+)$/) {           # Strip some f the path from source files
6209
            $strip = $1;
6210
 
227 dpurdie 6211
        } elsif (/^--(.*)/) {
6212
            Message( "InstallLib: unknown option $_ -- ignored\n" );
6213
        }
6214
    }
6215
 
6216
#.. Files
6217
#
285 dpurdie 6218
    foreach ( @elements )
227 dpurdie 6219
    {
6220
        my %package_entry;
6221
        if ( ! /^--(.*)/ )
6222
        {
6276 dpurdie 6223
            $_ = StripPath($_, $strip) if ($strip);
289 dpurdie 6224
            $org_lib = $_;                      # Original name
227 dpurdie 6225
 
6226
            if ( $ScmTargetHost eq "Unix" ) {
6227
                $lib = "lib$_";                 # Prefix "lib" ....
6228
                $lib =~ s/^liblib/lib/;         # @LIBS already has lib added
6229
            } else {
6230
                $lib = $_;
6231
            }
6232
 
289 dpurdie 6233
            if (  my $libp = $SHLIBS->Get($lib) )
227 dpurdie 6234
            {
6235
                Debug( "InstallLib( $dir/$lib\$(GBE_TYPE).$::so, " .
6236
                    "src: \$(LIBDIR)/$lib\$(GBE_TYPE).$::so, dest: $dir)" );
6237
 
6238
                #
6239
                #   Create a "placekeeper" entry within $INSTALL_SHLIBS
6240
                #   The exact format of the name of the shared library is
6241
                #   toolset specific. Create an entry to allow the toolset
6242
                #   to extend the packaging information when the shared library
6243
                #   recipe is constructed.
6244
                #
289 dpurdie 6245
                my $ver = $libp->{ VERSION };
227 dpurdie 6246
                my $name = "$dir/$lib.$ver.PlaceKeeper";
6247
 
6248
                $package_entry{'placekeeper'} = 1;
6249
                $package_entry{'version'} = $ver;
6250
                $package_entry{'lib'} = $lib;
6251
                $package_entry{'dir'} = $dir;
289 dpurdie 6252
 
6253
                push @{$SHLIB_INS{$lib}}, $name;
227 dpurdie 6254
                $INSTALL_SHLIBS{$name} = {%package_entry};
6255
            }
6256
 
289 dpurdie 6257
            #
6258
            #   Clean up the package_entry
6259
            #   Insert common items
6260
            #
6261
            %package_entry = ();
6262
            $package_entry{'lib'} = $lib;
6263
            $package_entry{'dir'} = $dir;
6264
 
321 dpurdie 6265
            if ( my $libfile = $SRCS{$org_lib} )
227 dpurdie 6266
            {
6267
                #
6268
                #   Allow the user to package a sourced file as a library
289 dpurdie 6269
                #   But must be the un-massaged name of the file.
227 dpurdie 6270
                #
289 dpurdie 6271
                $package_entry{'dst'} = "$dir/$org_lib";
6272
                $package_entry{'src'} = $libfile;
6273
            }
6274
            elsif ( $LIBS->Get($lib) )
6275
            {
6276
                #
6277
                #   Install a library known to the makefile
6278
                #
6279
                my $libp = $LIBS->Get($lib);
227 dpurdie 6280
 
289 dpurdie 6281
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
6282
                $package_entry{'src'}    = $libp->getPath();
227 dpurdie 6283
            }
289 dpurdie 6284
            elsif ( ! $SHLIBS->Get($lib) )
227 dpurdie 6285
            {
289 dpurdie 6286
                #
6287
                #   Not a known shared lib
6288
                #   Not a known static lib
6289
                #   Not a 'sourced' file
6290
                #   Assume the a static library has magically appeared
6291
                #   in the standard LIB directory. May have been placed there
6292
                #   by a 'rule'
6293
                #
6294
                my $libp = $LIBS->New($lib);
227 dpurdie 6295
 
289 dpurdie 6296
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
6297
                $package_entry{'src'}    = $libp->getPath();
6298
            }
227 dpurdie 6299
 
289 dpurdie 6300
            #
6301
            #   Add entry to various lists if required
6302
            #
6303
            PackageLib_AddEntry ('InstallLib', \%LIB_INS, \%INSTALL_LIBS, \%package_entry )
6304
                if ( exists $package_entry{'dst'} );
227 dpurdie 6305
        }
6306
    }
6307
 
6308
#.. Package
6309
#
6310
    PackageLib( @_ )                            # auto package
6311
        if ( $package );
6312
}
6313
 
6314
 
6315
sub InstallJar
6316
{
6317
    my( $platforms, @elements ) = @_;
6318
    my( $base, $dir, $package );
6319
    my( $jar );
6320
 
6321
    Debug2( "InstallJar($platforms, @elements)" );
6322
 
6323
    return if ( ! ActivePlatform($platforms) );
6324
    Warning ("InstallJar: Needs local directory specified in build.pl") unless ( $::ScmLocal );
6325
 
6326
#.. Arguments
6327
#
6328
    $base = $PackageInfo{'Jar'}{'IBase'};       # Base of target
6329
    $dir = $base . $PackageInfo{'Jar'}{'Dir'};  # Installation path (default)
6330
 
285 dpurdie 6331
    foreach ( @elements )
227 dpurdie 6332
    {
6333
                                                # Standard targets
6334
        my $rv = __TargetDir(0, $base, $_, \$dir);
6335
        next if ( $rv == 1 );
6336
        return if ( $rv == 2 );
6337
 
6338
        if (/^--Package$/ || /^--Package=(.*)/) {
6339
            $package = 1;
6340
 
6341
        } elsif (/^--(.*)/) {
6342
            Message( "InstallJar: unknown option $_ -- ignored\n" );
6343
        }
6344
    }
6345
 
6346
 
6347
#.. Files
6348
#
285 dpurdie 6349
    foreach ( @elements )
227 dpurdie 6350
    {
6351
        my %package_entry;
6352
        if ( ! /^--(.*)/ )
6353
        {
6354
            $jar = $_;
6355
            my $src;
6356
            my $dest;
6357
 
6358
            if ( $JAR_FILES{$jar} )
6359
            {
6360
                $src = $JAR_FILES{$jar};
6361
                $dest = $jar;
6362
            }
6363
            else
6364
            {
6365
                $src = "\$(CLSDIR)/$jar\$(GBE_TYPE).jar";
6366
                $dest = "$jar\$(GBE_TYPE).jar";
6367
            }
6368
 
6369
 
6370
            Debug( "InstallJar( $dir/$dest, " .
6371
                "src: $src, dest: $dir)" );
6372
 
6373
            $package_entry{'src'} = $src;
6374
            $package_entry{'dir'} = $dir;
6375
            $INSTALL_CLSS{ "$dir/$dest" } = {%package_entry};
6376
 
6377
        }
6378
    }
6379
 
6380
#.. Package
6381
#
6382
    PackageJar( @_ )                            # auto package
6383
        if ( $package );
6384
}
6385
 
6386
 
6387
sub InstallProg
6388
{
6389
    my( $platforms, @elements ) = @_;
6390
    my( $base, $dir, $package );
6391
    my( $prog );
6392
 
6393
    Debug2( "InstallProg($platforms, @elements)" );
6394
 
6395
    return if ( ! ActivePlatform($platforms) );
6396
    Warning ("InstallProg: Needs local directory specified in build.pl") unless ( $::ScmLocal );
6397
 
6398
#.. Arguments
6399
#
6400
    $base = $PackageInfo{'Prog'}{'IBase'};       # Base of target
6401
    $dir = $base . $PackageInfo{'Prog'}{'Dir'};  # Installation path (default)
6402
 
285 dpurdie 6403
    foreach ( @elements )
227 dpurdie 6404
    {
6405
                                                # Standard targets
6406
        my $rv = __TargetDir($T_TYPE, $base, $_, \$dir);
6407
        next if ( $rv == 1 );
6408
        return if ( $rv == 2 );
6409
 
6410
        if (/^--Package$/ || /^--Package=(.*)/) {
6411
            $package = 1;
6412
 
6413
        } elsif (/^--(.*)/) {
6414
            Message( "InstallProg: unknown option $_ -- ignored\n" );
6415
        }
6416
    }
6417
 
6418
#.. Files
6419
#
285 dpurdie 6420
    foreach ( @elements )
227 dpurdie 6421
    {
6422
        my %package_entry;
6423
        if ( ! /^--(.*)/ )
6424
        {
6425
            my $ext = "";
6426
            $prog = $_;
6427
 
6428
            #
6429
            #   If the named target is a program then append the correct
6430
            #   extension. Otherwise assume that the target is either a script
6431
            #   or a some other file - and don't append an extension
6432
            #
6433
            $ext = $::exe
289 dpurdie 6434
                if ( $PROGS->Get($prog) );
227 dpurdie 6435
 
6436
            #
6437
            #   A "file" that is specified with a "Src" directive may be
6438
            #   installed as though it were a program
6439
            #
6440
            my $progfile;
6441
            $progfile = "\$(BINDIR)/$prog$ext"
6442
                unless ( $progfile = $SRCS{$prog} );
6443
 
6444
            Debug( "InstallProg( $dir/$prog$ext, " .
6445
                 "src: $progfile, dest: $dir)" );
6446
 
6447
            push @{$PROG_INS{$prog}}, "$dir/$prog$ext";
6448
 
6449
            $package_entry{'src'} = $progfile;
6450
            $package_entry{'dir'} = $dir;
6451
            $INSTALL_PROGS{ "$dir/$prog$ext" } = {%package_entry};
6452
        }
6453
    }
6454
 
6455
#.. Package
6456
#
6457
    PackageProg( @_ )                           # auto package
6458
        if ( $package );
6459
}
6460
 
6276 dpurdie 6461
#-------------------------------------------------------------------------------
6462
# Function        : StripPath 
6463
#
6464
# Description     : Internal function to strip bits from a pathname
6465
#                   Will never strip the filename, even if asked to strip too much
6466
#
6467
# Inputs          : $name       - Name to process
6468
#                   $stripCount - Strip part
6469
#                                 <0 - strip all paths
6470
#                                 =0  - Do nothing
6471
#                                 >0 - Strip count
6472
#
6473
# Returns         : Processed name
6474
#
6475
sub StripPath
6476
{
6477
    my( $name, $stripCount) = @_;
227 dpurdie 6478
 
6276 dpurdie 6479
    if ($stripCount)
6480
    {
6481
        $name =~ s~\\~/~g;
6482
        $name =~ s~//~~g;
6483
 
6484
        my @items = split('/', $name);
6485
        if ($stripCount > 0)
6486
        {
6487
            my $len = scalar @items;
6488
            my $remove = $stripCount; 
6489
            if ($stripCount >= $len ) {
6490
                $remove = $len - 1;
6491
            }
6492
            splice @items, 0, $remove;
6493
            $name = join('/', @items);
6494
        }
6495
        else
6496
        {
6497
            $name = pop @items;
6498
        }
6499
    }
6500
    return $name;
6501
}
6502
 
6503
 
227 dpurdie 6504
###############################################################################
6505
#
6506
#   Packaging
6507
#
6508
sub PackageDist
6509
{
6510
    my( $name, @elements ) = @_;
6511
 
6512
    Debug2( "PackageDist($name, @elements)" );
6513
 
6514
    foreach ( @elements )
6515
    {
6516
    #.. Distribution sets
6517
    #
6518
        HashJoin( \%PACKAGE_DIST, $;, $name, "$_" );
6519
 
6520
    #.. Summary of distribution sets
6521
    #
267 dpurdie 6522
        $PACKAGE_SETS{ $_ }{'TAG'} = 1
6523
            if ( ! exists $PACKAGE_SETS{ $_ }{'TAG'} );
227 dpurdie 6524
    }
6525
}
6526
 
311 dpurdie 6527
#-------------------------------------------------------------------------------
6387 dpurdie 6528
# Function        : PackageDir 
6529
#                   InstallDir
6530
#
6531
# Description     : Directive to package an entire directory tree
6532
#                   Will package the contents of the directory without regard as to there content
6533
#                   
6534
#                   Differs from PackageFile (... --DirTree ) in that the process is dynamic
6535
#                   It will support the packaging of files that are generated
6536
#                   
6537
#                   NOT intended to support the JATS BIN and LIB structure
6538
#                   It knows nothing of these types of files
6539
#
6540
# Inputs          : platforms   - Active platform list
6541
#                   Options:    - Many from PackageFile
6542
#                       --DirTree=xxx   Source Tree [Mandatory]
6543
#                       --Subdir=yyy    Target [ Mandatory]
6544
#
6545
sub PackageDir { 
6546
    return if ( !$ScmPackage );                 # Packaging enabled ?
6547
    _PackageInstallDir('PackageDir', 'PBase', \@PACKAGE_DIRS, @_);
6548
    }
6549
 
6550
sub InstallDir { 
6551
    Warning ("InstallDir: Needs local directory specified in build.pl") unless ( $::ScmLocal );
6552
    _PackageInstallDir('InstallDir', 'IBase', \@INSTALL_DIRS, @_);
6553
    }
6554
 
6555
sub _PackageInstallDir
6556
{
6557
    my( $cmdName, $tbase, $dirRef, $platforms, @elements ) = @_;
6558
    my( $base, $dir, $path, $type );
6559
    my %data;
6560
 
6561
    Debug2( "$cmdName($platforms, @elements)" );
6562
 
6563
    return if ( ! ActivePlatform($platforms) );
6564
 
6565
#.. Arguments
6566
#
6567
    $base = $PackageInfo{'File'}{$tbase};           # Base of target
6568
    $dir = $base . $PackageInfo{'File'}{'Dir'};     # Installation path (default)
6569
 
6570
    foreach ( @elements )
6571
    {
6572
        my $rv = __TargetDir($T_MACH|$T_GBE|$T_FILE, $base, $_, \$dir, \$type);
6573
        next if ( $rv == 1 );
6574
        return if ( $rv == 2 );
6575
 
6576
        if (/^--Executable$/) {                  # Mark the file as executable
6577
            $data{exefile} = "X";
6578
 
6579
        } elsif (/^--PreserveSymlink/i) {        # Preserve symlink to local file
6580
            delete $data{noPreserveSymlink};
6581
 
6582
        } elsif (/^--NoPreserveSymlink/i) {      # Preserve symlink to local file
6583
            $data{noPreserveSymlink} = 1;
6584
 
6585
        } elsif ( /^--DirTree=(.*)/ ) {
6586
            Error("DirTree. Multiple directories not allowed.") if ( $data{dirTree} );
6587
            $data{dirTree} =  $1;
6588
 
6589
        } elsif ( /^--FilterOut=(.*)/ ) {
6590
            push @{$data{exclude}}, $1;
6591
 
6592
        } elsif ( /^--FilterIn=(.*)/ ) {
6593
            push @{$data{include}}, $1;
6594
 
6595
        } elsif ( /^--FilterOutRe=(.*)/ ) {
6596
            push @{$data{excludeRe}}, $1;
6597
 
6598
        } elsif ( /^--FilterInRe=(.*)/ ) {
6599
            push @{$data{includeRe}}, $1;
6600
 
6601
        } elsif ( /^--StripDir/ ) {
6602
            $data{strip_base} = 1;
6603
 
6604
        } elsif ( m/^--Recurse/ ) {
6605
            delete $data{noRecurse};
6606
 
6607
        } elsif ( m/^--NoRecurse/ ) {
6608
            $data{noRecurse} = 1;
6609
 
6610
        } elsif (/^--(.*)/) {
6611
            Message( "$cmdName: unknown option $_ -- ignored\n" );
6612
        }
6613
    }
6614
    Error("DirTree. No path specified") unless ( defined($data{dirTree}) && $data{dirTree} ne "" );
6615
    Debug2( "$cmdName. Raw DirTree: $data{dirTree}" );
6616
 
6617
    # Prevent the user from escaping from the current directory
6618
    Error("$cmdName. Absolute paths are not allowed",
6619
          "Directory: $data{dirTree}") if ( $data{dirTree} =~ m~^/~ || $data{dirTree} =~ m~^.\:~ );
6620
 
6621
    #
6622
    #   Convert the relative path to one that is truely relative to the current
6623
    #   directory. This may occur when the user uses $ProjectBase
6624
    #
6625
    my $abs_dir_tree = AbsPath($data{dirTree});
6626
    $data{dirTree} = RelPath($abs_dir_tree);
6627
 
6628
    #
6629
    #   Ensure that the user is not trying to escape the package
6630
    #   Don't allow the user to attempt to package the entire package either
6631
    #
6632
    #   Calculate the relative path from $ProjectBase to the target directory
6633
    #   It must not be above the $ProjectBase 
6634
    #
6635
    if ( $data{dirTree} =~ m~^\.\.~)
6636
    {
6637
        my $dirFromBase = RelPath($abs_dir_tree, AbsPath($ProjectBase));
6638
        Error("$cmdName. DirTree cannot extend outside current package.",
6639
              "Directory: $dirFromBase") if ( $dirFromBase =~ m~\.\.~ );
6640
        Error("$cmdName. DirTree cannot package entire package.",
6641
            "Directory: $dirFromBase") if ( $dirFromBase eq '.' );
6642
    }
6643
 
6644
    Debug( "$cmdName( $data{dirTree}");
6645
    $data{dir} = $dir;
6646
    $data{type} = $type if defined $type;
6647
    #DebugDumpData("$cmdName", \%data);
6648
    push @{$dirRef}, \%data;
6649
}
6650
 
6651
#-------------------------------------------------------------------------------
311 dpurdie 6652
# Function        : PackageFile
6653
#
6654
# Description     : Directive to package files
6655
#                   Not to be used to package libraries, executables, headers
6656
#                   as this should be done by specialised directives
6657
#
6658
#                   Use to package other files
6659
#                   Can package an entire tree (ugly)
6660
#
6661
# Inputs          : 
6662
#
6663
#
227 dpurdie 6664
sub PackageFile
6665
{
6666
    my( $platforms, @elements ) = @_;
335 dpurdie 6667
    my( $base, $dir, $full, $path, $dist, $strip, $exefile, $type );
227 dpurdie 6668
    my( $name, $basename, $len, $srcfile );
4257 dpurdie 6669
    my( $dir_tree, @dir_tree_exclude, @dir_tree_include, $strip_base, $strip_dots );
335 dpurdie 6670
    my $recurse = 1;
6133 dpurdie 6671
    my $preserveSymlink = 0;
227 dpurdie 6672
 
6673
    Debug2( "PackageFile($platforms, @elements)" );
6674
 
6675
    return if ( !$ScmPackage );                 # Packaging enabled ?
6676
    return if ( ! ActivePlatform($platforms) );
6677
 
6678
#.. Arguments
6679
#
6680
    $dist = "ALL";                                  # Default set (ALL)
6681
    $base = $PackageInfo{'File'}{'PBase'};          # Base of target
6682
    $dir = $base . $PackageInfo{'File'}{'Dir'};     # Installation path (default)
335 dpurdie 6683
    $full = 0;
227 dpurdie 6684
    $strip = 0;
341 dpurdie 6685
    $strip_base = 0;
4257 dpurdie 6686
    $strip_dots = 0;
227 dpurdie 6687
    $exefile = 0;
6688
 
285 dpurdie 6689
    foreach ( @elements )
227 dpurdie 6690
    {
6691
        my $rv = __TargetDir($T_PKG|$T_MACH|$T_GBE|$T_FILE, $base, $_, \$dir, \$type);
6692
        next if ( $rv == 1 );
6693
        return if ( $rv == 2 );
6694
 
6695
        if (/^--Full/) {                        # Using full (resolved) path
6696
            $full = 1;
6697
 
6698
        } elsif (/^--Set=(.*)/) {               # Distribution set
6699
            $dist = "$1";
6700
 
6701
        } elsif (/^--Package$/) {               # Package .. call by InstallFile
6702
        } elsif (/^--Package=(.*)/) {
6703
            $dist = "$1";
6704
 
6705
        } elsif (/^--Strip$/) {                 # Strip path from source files
6276 dpurdie 6706
            $strip = -1;
227 dpurdie 6707
 
6294 dpurdie 6708
        } elsif (/^--Strip=(\d+)$/) {           # Strip path from source files
6276 dpurdie 6709
            $strip = $1;
6710
 
227 dpurdie 6711
        } elsif (/^--Executable$/) {            # Mark the file as executable
6712
            $exefile = "X";
6713
 
6133 dpurdie 6714
        } elsif (/^--PreserveSymlink/i) {       # Preserve symlink to local file
6715
            $preserveSymlink = 1;
6716
 
227 dpurdie 6717
        } elsif ( /^--DirTree=(.*)/ ) {
6718
            Error("DirTree. Multiple directories not allowed.") if ( $dir_tree );
4163 dpurdie 6719
            $dir_tree =  $1;
4257 dpurdie 6720
            Error("DirTree. No path specified") unless ( defined($dir_tree) && $dir_tree ne "" );
227 dpurdie 6721
 
4163 dpurdie 6722
            # Prevent the user from escaping from the current directory
6723
            Error("DirTree. Absolute paths are not allowed",
6724
                  "Directory: $dir_tree") if ( $dir_tree =~ m~^/~ || $dir_tree =~ m~^.\:~ );
6725
 
6726
            #
6727
            #   Convert the relative path to one that is truely relative to the current
6728
            #   directory. This may occur when the user uses $ProjectBase
6729
            #
4257 dpurdie 6730
            my $abs_dir_tree = AbsPath($dir_tree);
6731
            $dir_tree = RelPath($abs_dir_tree);
6732
 
6733
            #
6734
            #   Ensure that the user is not trying to escape the package
4265 dpurdie 6735
            #   Don't allow the user to attempt to package the entire package either
4257 dpurdie 6736
            #
6737
            #   Calculate the relative path from $ProjectBase to the target directory
6738
            #   It must not be above the $ProjectBase 
6739
            #
4265 dpurdie 6740
            if ( $dir_tree =~ m~^\.\.~)
6741
            {
6742
                my $dirFromBase = RelPath($abs_dir_tree, AbsPath($ProjectBase));
6743
                Error("DirTree cannot extend outside current package.",
6744
                      "Directory: $dirFromBase") if ( $dirFromBase =~ m~\.\.~ );
6745
                Error("DirTree cannot package entire package.",
6746
                    "Directory: $dirFromBase") if ( $dirFromBase eq '.' );
6747
            }
4257 dpurdie 6748
 
4163 dpurdie 6749
            Debug2( "PackageFile. DirTree: $dir_tree" );
6750
 
227 dpurdie 6751
            Error("DirTree. Directory not found",
6752
                  "Directory: $dir_tree") unless  ( -d $dir_tree );
6753
 
4257 dpurdie 6754
            # If packaging a parent directory then force dot_stripping of the base directory
6755
            # strip_base will have precedence if both are active
6756
            if ( $dir_tree =~ m~\.\.~ )
6757
            {
6758
                $dir_tree =~ m~(\.\./)+~;
6759
                $strip_dots = length($1);
6760
            }
6761
 
227 dpurdie 6762
        } elsif ( /^--FilterOut=(.*)/ ) {
6763
            push @dir_tree_exclude, $1;
6764
 
6765
        } elsif ( /^--FilterIn=(.*)/ ) {
6766
            push @dir_tree_include, $1;
6767
 
6768
        } elsif ( /^--StripDir/ ) {
341 dpurdie 6769
            $strip_base = 1;
227 dpurdie 6770
 
335 dpurdie 6771
        } elsif ( m/^--Recurse/ ) {
6772
            $recurse = 1;
6773
 
6774
        } elsif ( m/^--NoRecurse/ ) {
6775
            $recurse = 0;
6776
 
227 dpurdie 6777
        } elsif (/^--(.*)/) {
6778
            Message( "PackageFile: unknown option $_ -- ignored\n" );
6779
        }
6780
    }
6781
 
6782
 
6783
    #.. DirTree expansion
6784
    #   Note: Uses REs, not simple globs
6785
    #         Use JatsLocateFiles to do the hard work
6786
    if ( $dir_tree )
6787
    {
335 dpurdie 6788
        my $search = JatsLocateFiles->new('FullPath' );
6789
        $search->recurse($recurse);
227 dpurdie 6790
        $search->filter_in_re ( $_ ) foreach ( @dir_tree_include );
6791
        $search->filter_out_re( $_ ) foreach ( @dir_tree_exclude );
1431 dpurdie 6792
        $search->filter_out_re( '/\.svn/' );
5848 dpurdie 6793
        $search->filter_out_re( '/\.git/' );
227 dpurdie 6794
        @elements = $search->search ( $dir_tree );
4257 dpurdie 6795
        if ($strip_base){
6796
            $strip_base = length( $dir_tree ) if ( $strip_base );
6797
        } elsif ($strip_dots) {
6798
            $strip_base = $strip_dots;
6799
        }
6403 dpurdie 6800
    } else {
6801
        $strip_base = 0;
227 dpurdie 6802
    }
6803
 
6804
#.. Files
6805
#
285 dpurdie 6806
    foreach ( @elements )
227 dpurdie 6807
    {
6808
        my %package_entry;
299 dpurdie 6809
        $name = $_;
6133 dpurdie 6810
        my $symlink;
299 dpurdie 6811
 
227 dpurdie 6812
        #
299 dpurdie 6813
        #   Trap special files
6814
        #       DPACKAGE - but only if we have a DPackageLibrary directive
6815
        #                  in the same makefile.
6816
        #
6817
        if ( m~^DPACKAGE$~ && $DPackageDirective ) {
6818
            $name = 'DPACKAGE.' . $::GBE_MACHTYPE;
6819
        }
6820
 
227 dpurdie 6821
        if ( ! /^--(.*)/ )
6822
        {
6823
            $basename = StripDir( $name );
335 dpurdie 6824
            if ( !($srcfile = $SRCS{ $basename }) ) {
6825
                $srcfile = $name;
6826
            }
6827
 
227 dpurdie 6828
            if ( $full )
6829
            {
335 dpurdie 6830
                my $subdir = StripFileExt($srcfile);
6831
                $subdir = $1
6832
                    if ( $subdir =~ m~^$ProjectBase/(.*)~ );
6833
                $dir .= '/' . $subdir;
6834
                $dir =~ s~//~/~g;
6835
                $dir =~ s~/./~/~g;
6836
                $dir =~ s~/$~~g;
6837
                $name = $basename;
227 dpurdie 6838
            }
6839
 
6276 dpurdie 6840
            $name = StripPath($name, $strip) if ($strip);
227 dpurdie 6841
 
341 dpurdie 6842
            if ( $strip_base )
6843
            {
6844
                $name = substr $name, $strip_base;
6845
                $name =~ s~^/~~;
6846
            }
6847
 
227 dpurdie 6848
            $dir =~ s~//~/~g;
6849
            $dir =~ s~/$~~;
6850
 
6851
            #
6133 dpurdie 6852
            #   Preserve Symlink
6853
            #
6854
            if ($preserveSymlink && -l $srcfile)
6855
            {
6856
                $symlink = 1;
6857
            }
6858
 
6859
            #
227 dpurdie 6860
            #   Sanity test the source filename
6861
            #   User may have misused an option
6862
            #
6387 dpurdie 6863
            if ( !$dir_tree && ( ( $srcfile =~ m/=/ ) || ( $srcfile =~ m/^-/ ) || ( $srcfile =~ m~/-~ ))  )
227 dpurdie 6864
            {
6865
               Warning ("PackageFile: Suspect source filename: $srcfile");
6866
            }
6867
 
6868
            Debug( "PackageFile( $dir/$name, " .
6869
                "src: $srcfile, dest: $dir, dist: $dist, exe: $exefile )" );
6870
 
6871
            $package_entry{'src'} = $srcfile;
6872
            $package_entry{'dir'} = StripFileExt( "$dir/$name" );
6873
            $package_entry{'set'} = $dist;
6874
            $package_entry{'exe'} = $exefile if $exefile;
6875
            $package_entry{'type'} = $type if ( $type );
6133 dpurdie 6876
            $package_entry{'symlink'} = 1 if ( $symlink );
227 dpurdie 6877
 
6878
            $PACKAGE_FILES{ "$dir/$name" } = {%package_entry};
6879
        }
6880
    }
6881
}
6882
 
6883
sub PackageHdr
6884
{
6885
    my( $platforms, @elements ) = @_;
335 dpurdie 6886
    my( $base, $dir, $full, $path, $dist, $strip );
227 dpurdie 6887
    my( $name, $basename, $len, $srcfile );
6888
 
6889
    Debug2( "PackageHdr($platforms, @elements)" );
6890
 
6891
    return if ( !$ScmPackage );                 # Packaging enabled ?
6892
    return if ( ! ActivePlatform($platforms) );
6893
 
6894
#.. Arguments
6895
#
6896
    $dist = "ALL";                                  # Default set (ALL)
6897
    $base = $PackageInfo{'Hdr'}{'PBase'};           # Base of target
6898
    $dir = $base . $PackageInfo{'Hdr'}{'Dir'};      # Installation path (default)
335 dpurdie 6899
    $full = 0;
227 dpurdie 6900
    $strip = 0;
6901
 
285 dpurdie 6902
    foreach ( @elements )
227 dpurdie 6903
    {
6904
        my $rv = __TargetDir($T_PKG, $base, $_, \$dir);
6905
        next if ( $rv == 1 );
6906
        return if ( $rv == 2 );
6907
 
6908
        if (/^--Full/) {                        # Using full (resolved) path
6909
            $full = 1;
6910
 
6911
        } elsif (/^--Set=(.*)/) {               # Distribution set
6912
            $dist = "$1";
6913
 
6914
        } elsif (/^--Package$/) {               # Package .. call by InstallHdr
6915
        } elsif (/^--Package=(.*)/) {
6916
            $dist = "$1";
6917
 
6918
        } elsif (/^--Strip$/) {                 # Strip path from source files
6276 dpurdie 6919
            $strip = -1;
227 dpurdie 6920
 
6276 dpurdie 6921
        } elsif (/^--Strip=(\d+)$/) {           # Strip some f the path from source files
6922
            $strip = $1;
6923
 
227 dpurdie 6924
        } elsif (/^--(.*)/) {
6925
            Message( "PackageHdr: unknown option $_ -- ignored\n" );
6926
        }
6927
    }
6928
 
6929
#.. Files
6930
#
285 dpurdie 6931
    foreach ( @elements )
227 dpurdie 6932
    {
6933
        my %package_entry;
6934
        if ( ! /^--(.*)/ )
6935
        {
5991 dpurdie 6936
            $name = $_;
227 dpurdie 6937
            $basename = StripDir( $name );
335 dpurdie 6938
            if ( !($srcfile = $SRCS{ $basename }) ) {
6939
                $srcfile = $name;
6940
            }
6941
 
227 dpurdie 6942
            if ( $full )
6943
            {
335 dpurdie 6944
                my $subdir = StripFileExt($srcfile);
6945
                $subdir = $1
6946
                    if ( $subdir =~ m~^$ProjectBase/(.*)~ );
6947
                $dir .= '/' . $subdir;
6948
                $dir =~ s~//~/~g;
6949
                $dir =~ s~/./~/~g;
6950
                $dir =~ s~/$~~g;
6951
                $name = $basename;
227 dpurdie 6952
            }
6953
 
6276 dpurdie 6954
            $name = StripPath($name, $strip) if ($strip);
227 dpurdie 6955
 
6956
            Debug( "PackageHdr( $dir/$name, " .
6957
                "src: $srcfile, dest: $dir, dist: $dist )" );
6958
 
6959
            $package_entry{'src'} = $srcfile;
6960
            $package_entry{'dir'} = StripFileExt( "$dir/$name" );
6961
            $package_entry{'set'} = $dist;
6962
 
6963
            $PACKAGE_HDRS{ "$dir/$name" } = {%package_entry};
6964
        }
6965
    }
6966
}
6967
 
6968
 
6969
sub PackageLib
6970
{
6971
    my( $platforms, @elements ) = @_;
6972
    my( $base, $dir, $dist, $type );
6973
    my( $lib, $org_lib, %extras, $strip );
6974
 
6975
    Debug2( "PackageLib($platforms, @elements)" );
6976
 
6977
    return if ( !$ScmPackage );                 # Packaging enabled ?
6978
    return if ( ! ActivePlatform($platforms) );
6979
 
6980
#.. Arguments
6981
#
6982
    $dist = "ALL";                              # Default set (ALL)
6983
    $base = $PackageInfo{'Lib'}{'PBase'};       # Base of target
6984
    $dir = $base . $PackageInfo{'Lib'}{'Dir'};  # Installation path (default)
6985
    $type = "";
6986
 
285 dpurdie 6987
    foreach ( @elements )
227 dpurdie 6988
    {
6989
                                                # Standard targets
6990
        my $rv = __TargetDir($T_PKG, $base, $_, \$dir, \$type);
6991
        next if ( $rv == 1 );
6992
        return if ( $rv == 2 );
6993
 
6994
        if (/^--Set=(.*)/) {                    # Distribution set(s)
6995
            $dist = "$1";
6996
 
6997
        } elsif (/^--Package$/) {               # Package .. call by PackageLib
6998
        } elsif (/^--Package=(.*)/) {
6999
            $dist = "$1";
7000
 
7001
        } elsif (/^--Extras=(.*)/) {            # Extras=[none, .. ,all]
7002
            foreach my $elem ( split( ',', $1 ) )
7003
            {
7004
                Error ("PackageLib: Unknown Extras mode: $elem")
7005
                    unless ( grep m/$elem/, qw(none stub map lint debug all) );
7006
                $extras{$elem} = 1;
7007
            }
7008
            %extras = () if ( $extras{'all'} );
7009
 
7010
        } elsif (/^--Strip$/) {                 # Strip path from source files
6276 dpurdie 7011
            $strip = -1;
227 dpurdie 7012
 
6276 dpurdie 7013
        } elsif (/^--Strip=(\d+)$/) {           # Strip some f the path from source files
7014
            $strip = $1;
7015
 
227 dpurdie 7016
        } elsif (/^--(.*)/) {
7017
            Message( "PackageLib: unknown option $_ -- ignored\n" );
7018
        }
7019
    }
7020
 
7021
#.. Files
7022
#
285 dpurdie 7023
    foreach ( @elements )
227 dpurdie 7024
    {
7025
        my %package_entry;
7026
        if ( ! /^--(.*)/ )
7027
        {
6276 dpurdie 7028
            $_ = StripPath($_, $strip) if ($strip);
227 dpurdie 7029
 
7030
            $org_lib = $_;                      # Original name
7031
            if ( $ScmTargetHost eq "Unix" ) {
7032
                $lib = "lib$_";                 # Prefix "lib" ....
7033
                $lib =~ s/^liblib/lib/;         # @LIBS already has lib added
7034
            } else {
7035
                $lib = $_;
7036
            }
7037
 
289 dpurdie 7038
            if (  my $libp = $SHLIBS->Get($lib) )
227 dpurdie 7039
            {
7040
                Debug( "PackageLib( $dir/$lib\$(GBE_TYPE).$::so, " .
7041
                    "src: \$(LIBDIR)/$lib\$(GBE_TYPE).$::so, dest: $dir, dist: $dist, type: $type )" );
7042
 
7043
                #
7044
                #   Create a "placekeeper" entry within $PACKAGE_SHLIBS
7045
                #   The exact format of the name of the shared library is
7046
                #   toolset specific. Create an entry to allow the toolset
7047
                #   to extend the packaging information when the shared library
7048
                #   recipe is constructed.
7049
                #
7050
                #
289 dpurdie 7051
                my $ver = $libp->{ VERSION };
227 dpurdie 7052
                my $name = "$dir/$lib.$ver.PlaceKeeper";
7053
 
7054
                $package_entry{'placekeeper'} = 1;
7055
                $package_entry{'version'} = $ver;
7056
                $package_entry{'lib'} = $lib;
7057
                $package_entry{'dir'} = $dir;
7058
                $package_entry{'set'} = $dist;
7059
                $package_entry{'type'} = $type if ( $type );
7060
                $package_entry{'extras'} = {%extras} if ( scalar %extras );
289 dpurdie 7061
 
7062
                push @{$SHLIB_PKG{$lib}}, $name;
227 dpurdie 7063
                $PACKAGE_SHLIBS{$name} = {%package_entry};
7064
            }
7065
 
289 dpurdie 7066
            #
7067
            #   Clean up the package_entry
7068
            #   Insert common items
7069
            #
7070
            %package_entry = ();
7071
            $package_entry{'lib'} = $lib;
7072
            $package_entry{'dir'} = $dir;
7073
            $package_entry{'set'} = $dist;
7074
            $package_entry{'extras'} = {%extras} if ( scalar %extras );
7075
            $package_entry{'type'} = $type if ( $type );
7076
 
227 dpurdie 7077
            if ( my $libfile = $SRCS{$org_lib} )
7078
            {
7079
                #
7080
                #   Allow the user to package a sourced file as a library
7081
                #   But must be the un-massaged name of the file.
7082
                #
5991 dpurdie 7083
                $package_entry{'dst'} = "$dir/$org_lib";
7084
                $package_entry{'src'} = $libfile;
289 dpurdie 7085
            }
7086
            elsif ( $LIBS->Get($lib) )
7087
            {
7088
                #
7089
                #   Package up a library known to the makefile
7090
                #
7091
                my $libp = $LIBS->Get($lib);
227 dpurdie 7092
 
289 dpurdie 7093
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
7094
                $package_entry{'src'}    = $libp->getPath();
227 dpurdie 7095
            }
289 dpurdie 7096
            elsif ( ! $SHLIBS->Get($lib) )
227 dpurdie 7097
            {
289 dpurdie 7098
                #
7099
                #   Not a known shared lib
7100
                #   Not a known static lib
7101
                #   Not a 'sourced' file
7102
                #   Assume the a static library has magically appeared
7103
                #   in the standard LIB directory. May have been placed there
7104
                #   by a 'rule'
7105
                #
7106
                my $libp = $LIBS->New($lib);
227 dpurdie 7107
 
289 dpurdie 7108
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
7109
                $package_entry{'src'}    = $libp->getPath();
7110
            }
227 dpurdie 7111
 
289 dpurdie 7112
            #
7113
            #   Add entry to various lists if required
7114
            #
7115
            PackageLib_AddEntry ('PackageLib', \%LIB_PKG, \%PACKAGE_LIBS, \%package_entry )
7116
                if ( exists $package_entry{'dst'} );
227 dpurdie 7117
        }
7118
    }
7119
}
7120
 
289 dpurdie 7121
#-------------------------------------------------------------------------------
7122
# Function        : PackageLib_AddEntry
7123
#
7124
# Description     : Helper function to add a package entry
7125
#                   to the lists
7126
#
7127
# Inputs          : $directive          - Directive name
7128
#                   $pList              - Ref to array list to maintain
7129
#                   $pHash              - Ref to hash to maintain
7130
#                   $pData              - Packaging Data
7131
#                                         Must Take a copy.
7132
#
7133
# Returns         : 
7134
#
227 dpurdie 7135
 
289 dpurdie 7136
sub PackageLib_AddEntry
7137
{
7138
    my ($directive, $pList, $pHash, $pData) = @_;
7139
 
7140
    my $lib = delete $pData->{'lib'};
7141
    my $dst = delete $pData->{'dst'};
7142
 
7143
    Error ("INTERNAL PackageLib_AddEntry: lib or dst not defined")
7144
        unless ( $lib && $dst );
7145
 
7146
    Debug( "$directive( ",$dst,
7147
            ", src: " ,$pData->{'src'},
7148
            ", dest: ",$pData->{'dir'},
7149
            ", dist: ",$pData->{'set'},
7150
            ", type: ",$pData->{'type'} || '',
7151
            " )" );
7152
 
7153
    push @{$pList->{$lib }}, $dst;
7154
    $pHash->{$dst } = {%$pData};
7155
}
7156
 
7157
 
227 dpurdie 7158
sub PackageProg
7159
{
7160
    my( $platforms, @elements ) = @_;
7161
    my( $base, $dir, $dist, $type );
7162
    my( $prog, %extras, $strip );
7163
 
7164
    Debug2( "PackageProg($platforms, @elements)" );
7165
 
7166
    return if ( !$ScmPackage );                 # Packaging enabled ?
7167
    return if ( ! ActivePlatform($platforms) );
7168
 
7169
#.. Arguments
7170
#
7171
    $dist = "ALL";                              # Default set (ALL)
7172
    $base = $PackageInfo{'Prog'}{'PBase'};       # Base of target
7173
    $dir = $base . $PackageInfo{'Prog'}{'Dir'};  # Installation path (default)
7174
    $type = "";
7175
 
285 dpurdie 7176
    foreach ( @elements )
227 dpurdie 7177
    {
7178
                                                # Standard targets
7179
        my $rv = __TargetDir($T_PKG|$T_TYPE, $base, $_, \$dir, \$type);
7180
        next if ( $rv == 1 );
7181
        return if ( $rv == 2 );
7182
 
7183
        if (/^--Set=(.*)/) {                    # Distribution set(s)
7184
            $dist = "$1";
7185
 
7186
        } elsif (/^--Package$/) {               # Package .. call by PackageLib
7187
        } elsif (/^--Package=(.*)/) {
7188
            $dist = "$1";
7189
 
7190
        } elsif (/^--Tool(([=])(.*))?$/) {      # Allow Tool and Tool=xxx specfic target
7191
            my $path = ( defined( $3) ) ? "/$3" : "";
261 dpurdie 7192
            $dir = "\$(PKGDIR)$path/\$(GBE_HOSTMACH)";
227 dpurdie 7193
 
7194
        } elsif (/^--Extras=(.*)/) {            # Extras=[none, .. ,all]
7195
            foreach my $elem ( split( ',', $1 ) )
7196
            {
7197
                Error ("PackageLib: Unknown Extras mode: $elem")
7198
                    unless ( grep m/$elem/, qw(none stub map lint debug all) );
7199
                $extras{$elem} = 1;
7200
            }
7201
            %extras = () if ( $extras{'all'} );
7202
 
7203
        } elsif (/^--Strip$/) {                 # Strip path from source files
6276 dpurdie 7204
            $strip = -1;
227 dpurdie 7205
 
6276 dpurdie 7206
        } elsif (/^--Strip=(\d+)$/) {           # Strip some f the path from source files
7207
            $strip = $1;
7208
 
227 dpurdie 7209
        } elsif (/^--(.*)/) {
7210
            Message( "PackageProg: unknown option $_ -- ignored\n" );
7211
        }
7212
    }
7213
 
7214
#.. Files
7215
#
285 dpurdie 7216
    foreach ( @elements )
227 dpurdie 7217
    {
7218
        my %package_entry;
7219
        if ( m~descpkg~ ) {
7220
            PackageFile($platforms, @elements);
7221
 
7222
        } elsif ( ! /^--(.*)/ ) {
6276 dpurdie 7223
            $_ = StripPath($_, $strip) if ($strip);
227 dpurdie 7224
 
7225
            my $ext = "";
7226
            $prog = $_;
7227
 
7228
            #
7229
            #   If the named target is a program then append the correct
7230
            #   extension. Otherwise assume that the target is either a script
7231
            #   or a some other file - and don't append an extension
7232
            #
7233
            #   A program may not have any object files, only libraries
7234
            #
7235
            $ext = $::exe
289 dpurdie 7236
                if ( $PROGS->Get($prog) );
227 dpurdie 7237
 
7238
            #
7239
            #   A "file" that is specified with a "Src" directive may be
7240
            #   installed as though it were a program
7241
            #
7242
            my $progfile;
387 dpurdie 7243
            if ( $progfile = $SRCS{$prog} )
7244
            {
5991 dpurdie 7245
                $progfile = $progfile;
7246
                $prog = $prog;
387 dpurdie 7247
            }
7248
            else
7249
            {
7250
                $progfile = "\$(BINDIR)/$prog$ext";
7251
            }
227 dpurdie 7252
 
7253
            Debug( "PackageProg( $dir/$prog$ext, " .
7254
                 "src: $progfile, dest: $dir, dist: $dist, type: $type )" );
7255
 
7256
            my $target = "$dir/$prog$ext";
7257
            push @{$PROG_PKG{$prog}}, $target;
7258
 
7259
            $package_entry{'src'}   = $progfile;
7260
            $package_entry{'dir'}   = $dir;
7261
            $package_entry{'set'}   = $dist;
7262
            $package_entry{'extras'}= {%extras} if ( scalar %extras );
7263
            $package_entry{'type'}  = $type if ( $type );
7264
 
7265
            $PACKAGE_PROGS{$target} = {%package_entry};
7266
        }
7267
    }
7268
}
7269
 
7270
 
7271
sub PackageJar
7272
{
7273
    my( $platforms, @elements ) = @_;
7274
    my( $base, $dir, $dist, $type );
7275
    my( $jar );
7276
 
7277
    Debug2( "PackageJar($platforms, @elements)" );
7278
 
7279
    return if ( !$ScmPackage );                 # Packaging enabled ?
7280
    return if ( ! ActivePlatform($platforms) );
7281
 
7282
#.. Arguments
7283
#
7284
    $dist = "ALL";                              # Default set (ALL)
7285
    $base = $PackageInfo{'Jar'}{'PBase'};       # Base of target
7286
    $dir = $base . $PackageInfo{'Jar'}{'Dir'};  # Installation path (default)
7287
    $type = "";
7288
 
285 dpurdie 7289
    foreach ( @elements )
227 dpurdie 7290
    {
7291
                                                # Standard targets
7292
        my $rv = __TargetDir($T_PKG, $base, $_, \$dir, \$type);
7293
        next if ( $rv == 1 );
7294
        return if ( $rv == 2 );
7295
 
7296
        if (/^--Set=(.*)/) {                    # Distribution set(s)
7297
            $dist = "$1";
7298
 
7299
        } elsif (/^--Package$/) {               # Package .. call by InstallJar
7300
        } elsif (/^--Package=(.*)/) {
7301
            $dist = "$1";
7302
 
7303
        } elsif (/^--(.*)/) {
7304
            Message( "PackageJar: unknown option $_ -- ignored\n" );
7305
        }
7306
    }
7307
 
7308
#.. Files
7309
#
285 dpurdie 7310
    foreach ( @elements )
227 dpurdie 7311
    {
7312
        my %package_entry;
7313
        if ( ! /^--(.*)/ )
7314
        {
7315
            $jar = $_;
7316
            my $src;
7317
            my $dest;
7318
 
7319
            if ( $JAR_FILES{$jar} )
7320
            {
7321
                $src = $JAR_FILES{$jar};
7322
                $dest = $jar;
7323
            }
7324
            else
7325
            {
7326
                $src = "\$(CLSDIR)/$jar\$(GBE_TYPE).jar";
7327
                $dest = "$jar\$(GBE_TYPE).jar";
7328
            }
7329
 
7330
 
7331
            Debug( "PackageJar( $dir/$dest, " .
7332
                "src: $src, dest: $dir, dist: $dist, type: $type )" );
7333
 
7334
            $package_entry{'src'} = $src;;
7335
            $package_entry{'dir'} = $dir;
7336
            $package_entry{'set'} = $dist;
7337
            $package_entry{'type'} = $type if ( $type );
7338
 
7339
            $PACKAGE_CLSS{ "$dir/$dest" } = {%package_entry};
7340
 
7341
        }
7342
    }
7343
}
7344
 
7345
#-------------------------------------------------------------------------------
7346
# Function        : PackageProgAddFiles         - Add files to a PackageProg
7347
#                   PackageLibAddFiles          - Add files to a PackageLib
7348
#                   PackageShlibAddFiles        - Add files to a PackageLib (shared lib)
7349
#                   PackageShlibAddLibFiles     - Add files to a PackageLib (shared lib)
7350
#                                                 Add static library files
7351
#
7352
# Description     : Add files to a Program package or installation
7353
#                   For use by Tool sets to allow additional files to be
7354
#                   packaged with a program.
7355
#
7356
#                   The files are only added if the named program is being
7357
#                   packaged and/or installed.
7358
#
7359
#
7360
# Inputs          : prog        - program identifier
7361
#                   file        - A file to be add
7362
#                   args        - Additional packageing arguments
7363
#
7364
# Returns         : Nothing
7365
#
7366
 
7367
sub PackageProgAddFiles
7368
{
7369
    Debug("PackageProgAddFiles");
7370
 
7371
    PackageAddFiles ( \%PACKAGE_PROGS, \%PACKAGE_PROGS, \%PROG_PKG, @_);
7372
    PackageAddFiles ( \%INSTALL_PROGS, \%INSTALL_PROGS, \%PROG_INS, @_);
7373
}
7374
 
7375
sub PackageLibAddFiles
7376
{
7377
    Debug("PackageLibAddFiles");
7378
 
7379
    PackageAddFiles ( \%PACKAGE_LIBS, \%PACKAGE_LIBS, \%LIB_PKG, @_ );
7380
    PackageAddFiles ( \%INSTALL_LIBS, \%INSTALL_LIBS, \%LIB_INS, @_ );
7381
}
7382
 
7383
sub PackageShlibAddFiles
7384
{
7385
    my ($prog, $file, @args) = @_;
7386
    Debug("PackageShlibAddFiles");
7387
 
7388
    PackageAddFiles ( \%INSTALL_SHLIBS, \%INSTALL_SHLIBS, \%SHLIB_INS, @_ );
7389
    PackageAddFiles ( \%PACKAGE_SHLIBS, \%PACKAGE_SHLIBS, \%SHLIB_PKG, @_ );
7390
 
7391
    #
7392
    #   These files become the target of the "make_install_shlib" operation unless:
7393
    #       Conditionally packaged files are not always created
7394
    #       RemoveOnly files are not always generated
7395
    #
7396
    my $no_add;
7397
    foreach ( @args )
7398
    {
4382 dpurdie 7399
        if ( m/^defined=/ or m/^RemoveOnly=/ or /NoTarget=/ )
227 dpurdie 7400
        {
7401
            $no_add = 1;
7402
            last;
7403
        }
7404
    }
7405
 
7406
    push (@SHLIB_TARGETS, $file ) unless $no_add;
7407
}
7408
 
7409
sub PackageShlibAddLibFiles
7410
{
7411
    Debug("PackageShlibAddLibFiles");
7412
 
7413
    PackageAddFiles ( \%PACKAGE_SHLIBS, \%PACKAGE_LIBS, \%SHLIB_PKG, @_ , 'Class=lib');
7414
    PackageAddFiles ( \%INSTALL_SHLIBS, \%INSTALL_LIBS, \%SHLIB_INS, @_ , 'Class=lib');
7415
}
7416
 
7417
#-------------------------------------------------------------------------------
7418
# Function        : PackageAddFiles
7419
#
7420
# Description     : Internal function to add files to the data structures that
7421
#                   describe a package or installation
7422
#
7423
#                   Use this function to package or install additional files with
7424
#                   the Progs and Libs
7425
#
7426
#                   ie: Add a LIB file to be packaged with a Shared Library
7427
#                   ie: Add a MAP file to be packaged with a program
7428
#
7429
# Inputs          : ref_spkg  - Reference to the hash that contains the package data
7430
#                   ref_dpkg  - Reference to the target package/install hash
7431
#                               Normally the same as ref_dpkg, but does allow
289 dpurdie 7432
#                               a static library to be added to a dynamic library
227 dpurdie 7433
#                               package.
7434
#                   ref_list  - Reference to a hash that may contain package keys to process
7435
#                   prog      - Key for index to above
7436
#                   file      - A file to be added
7437
#                   args      - Additional packaging arguments
7438
#
7439
# Returns         :
7440
#
7441
sub PackageAddFiles
7442
{
7443
    my ($ref_spkg, $ref_dpkg, $ref_list, $prog, $file, @args ) = @_;
7444
 
7445
    #
7446
    #   Process entry
7447
    #   The files may need to be added to multiple packages
7448
    #
7449
    Debug("PackageAddFiles: $file");
7450
 
7451
    return unless ( $ref_list->{$prog} );
7452
 
7453
    #
7454
    #   Parse arguments and extract the "Class=xxx" argument. This may be used
7455
    #   to limit the extra files piggybacked with the base file
7456
    #   All files without a class will be treated as base files
7457
    #
7458
    my $class;
7459
    foreach ( @args )
7460
    {
7461
        next unless ( m~^Class=(.*)$~ );
7462
        $class = $1 unless ( $1 eq 'none' );
7463
    }
7464
    Debug("PackageAddFiles: Class: ", $class || 'Default=None');
7465
 
7466
    foreach my $entry_key ( @{$ref_list->{$prog}} )
7467
    {
7468
        Debug("PackageAddFiles: Entry found: $entry_key");
7469
 
7470
        #
7471
        #   Copy of the template entry
7472
        #
7473
        my %package_entry = %{$ref_spkg->{$entry_key}};
7474
        Error ("INTERNAL: Expected entry in PACKAGE_ hash not found: $entry_key" )
7475
            unless ( %package_entry );
7476
 
7477
        #
7478
        #   Do not add the file if the user has limited the extra files added
7479
        #   to the packaging list and the current file is not in the class list
7480
        #
7481
        if ( $class && $package_entry{'extras'} )
7482
        {
7483
            next unless ( $package_entry{'extras'}{$class} );
7484
        }
7485
 
7486
        #
7487
        #   Create new entries for the file
7488
        #
7489
        $package_entry{'src'} = $file;
7490
        foreach ( @args )
7491
        {
7492
            m~^(.*)=(.*)$~;
7493
            $package_entry{$1} = $2;
7494
        }
7495
 
7496
        #
7497
        #   Clean out useless fields
7498
        #   Must remove the placekeeper marker to allow the entry to be visible
7499
        #
7500
        delete $package_entry{'placekeeper'};
7501
        delete $package_entry{'version'};
7502
        delete $package_entry{'lib'};
261 dpurdie 7503
#       delete $package_entry{'extras'};                   # Keep these
227 dpurdie 7504
        delete $package_entry{'Class'};
7505
 
7506
        #
7507
        #   Add the entry
7508
        #
7509
        #   Under some conditions is it possible to attempt to add the same named
7510
        #   file. This will result in a circular dependancy in the makefile
7511
        #
7512
        #   The condition is when merged libaries with PDBs (WINCE+WIN32) are merged
261 dpurdie 7513
        #   and the source for the merge is the "local directory.
227 dpurdie 7514
        #
7515
        #
7516
        my $dst = $package_entry{'dir'} ;
7517
        ( my $dfile = $file) =~ s~.*/~~;
7518
        Debug( "    added $dst/$dfile = $file" );
7519
 
7520
        $ref_dpkg->{"$dst/$dfile"} = {%package_entry}
7521
            unless ( "$dst/$dfile" eq "$file" );
7522
    }
7523
}
7524
 
7525
#-------------------------------------------------------------------------------
7526
# Function        : PackageProgRemoveFiles
7527
#
7528
# Description     : Flag a Packaged program to be not packaged
7529
#                   This mechanism is used to remove a program from packageing
7530
#                   under conditions where the toolset has generated a different
7531
#                   program.
7532
#
7533
#                   The entry is flagged as a placeholder
7534
#
7535
# Inputs          : prog        - Program to process
7536
#
7537
# Returns         : Nothing
7538
#
7539
sub PackageProgRemoveFiles
7540
{
7541
    my ($prog) = @_;
7542
    Verbose ("PackageProgRemoveFiles: $prog" );
7543
    return unless (exists($PROG_PKG{$prog}));
7544
 
7545
    #
7546
    #   Must lookup the TAG to locate the  required entry
7547
    #
7548
    my $tag = $PROG_PKG{$prog};
7549
    foreach my $entry ( @$tag )
7550
    {
7551
        Verbose("Do not package: $entry");
7552
        if ( exists $PACKAGE_PROGS{$entry} )
7553
        {
7554
            $PACKAGE_PROGS{$entry}{placekeeper} = 'ProgRemoved';
7555
        }
7556
    }
7557
}
7558
 
7559
#-------------------------------------------------------------------------------
7560
# Function        : DPackageLibrary
7561
#
7562
# Description     : Collect information to allow the generation of a DPACKAGE
299 dpurdie 7563
#                   file. This directive allows the generation of "Library"
227 dpurdie 7564
#                   directives within the final DPACKAGE
7565
#
7566
#                   This directive does generate the DPACKAGE file.
7567
#
7568
# Inputs          : platform    - This does not need to be an active platform
7569
#                                 it is simply passed to the DPACKAGE builder
7570
#
7571
#                   using       - The "using" target
7572
#
7573
#                   ...         - Arguments for the Library directive
7574
#
7575
# Returns         :
7576
#
7577
sub DPackageLibrary
7578
{
7579
    JatsDPackage::DPackageAdd ( @_ );
299 dpurdie 7580
    $DPackageDirective = 1;
227 dpurdie 7581
}
7582
 
7583
#-------------------------------------------------------------------------------
7584
# Function        : SetProjectBase
7585
#
7586
# Description     : Allows the user to modify the build's concept of the Base
7587
#                   of the build. By default the base is the same directory as
7588
#                   the build.pl file, but in some contorted environments it
7589
#                   is a great deal simpler to specify a differnt base.
7590
#
7591
#                   The use may use the variable $ProjectBase as a path
7592
#                   specifier to locate files and directories
7593
#
7594
#                   Both absolute and relative paths are supported
7595
#                   If the initial value of $ProjectBase is relative then
7596
#                   it will be maintained as a relative path.
7597
#
7598
# Inputs          : elements        path to base
7599
#                                   These may be:
7600
#                                       --Up=xx
7601
#                                       name
7602
#
7603
# Returns         : Nothing
7604
#
7605
 
7606
#
7607
#   Allow the user to modify the project base variable
7608
#
7609
sub SetProjectBase
7610
{
7611
    my $rip = 0;
7612
    my $path = "";
7613
    my $is_relative;
7614
 
7615
    Debug("ProjectBase Initial: $ProjectBase, @_");
7616
 
7617
    #
7618
    #   Ensure that the ProjectBase is in a "nice" form
7619
    #   1) No /./ bits
7620
    #   2) No trailing /
7621
    #   3) Not equal to .
7622
    #   4) No training /.
7623
    #   5) No //
7624
    #
7625
    $ProjectBase =~ s~/\./~/~g;
7626
    $ProjectBase =~ s~/$~~g;
7627
    $ProjectBase =~ s~^\.$~~g;
7628
    $ProjectBase =~ s~/\.$~~g;
7629
    $ProjectBase =~ s~//$~/~g;
7630
 
7631
    #
7632
    #   ProjectBase may be absolute or relative
7633
    #   Determine this before we mess with it
7634
    #
7635
    $is_relative = ($ProjectBase !~ m~^/~);
7636
 
7637
    #
7638
    #   Process each argument
7639
    #
7640
    foreach ( @_ )
7641
    {
7642
        if ( /^--Up=([0-9]*)/ ) {
7643
            $rip = $1;
7644
        } elsif ( /^--/ ) {
7645
            Warning( "SetProjectBase - unknown option \"$_\" - ignored" );
7646
        } else {
7647
            $path = $_;
7648
        }
7649
    }
7650
 
7651
    #
7652
    #   Process the UP requests
7653
    #   If the tail directory is a ".." then up is done by adding another ".."
7654
    #   If the tail directory is not a "..", then up is done by removing it
7655
    #
7656
    #   If we go past the start of the path then simply add ".."
7657
    #
7658
    while ( $rip-- > 0 )
7659
    {
7660
        Debug2("ProjectBase: $ProjectBase, Up: $rip, IsRel: $is_relative");
7661
 
7662
        #
7663
        #   If ending in a /.. or is exactly equal to ..
7664
        #   Then its a dot-dot and the way to go UP is to append another ..
7665
        #
7666
        if ( $ProjectBase =~ m~(/\.\.$)|(^\.\.$)~ )
7667
        {
7668
            $ProjectBase .= '/..';
7669
        }
7670
        else
7671
        {
7672
            #
7673
            #   Not a dot-dot ending
7674
            #   Attempt to remove the last directory of the form
7675
            #       /xxxxx
7676
            #   Where the leading / is optional
7677
            #   Note: Must have at least one character in the dirname
7678
            #         This prevents leading / from matching - which is needed
7679
            #
7680
            unless ($ProjectBase =~ s~/?[^/]+$~~)
7681
            {
7682
                #
7683
                #   Removal failed
7684
                #   If a relative path then we can keep on going up,
7685
                #   otherwise we are dead.
7686
                #
7687
                Error ("ProjectBase outside project") unless ($is_relative);
7688
                $ProjectBase = '..';
7689
            }
7690
 
7691
            #
7692
            #   Ensure that the leading / in an absolute path is not deleted
7693
            #
7694
            $ProjectBase = '/'
7695
                unless ( $is_relative || $ProjectBase );
7696
        }
7697
    }
7698
 
7699
    #
7700
    #   Append the user path
7701
    #
7702
    $ProjectBase .= '/' . $path if ( $path );
7703
    $ProjectBase = '.' unless ( $ProjectBase );
7704
    Debug("ProjectBase set to : $ProjectBase");
7705
 
7706
    #
7707
    #   Once upon a time I tried to convert paths that contained spaces into
7708
    #   short (mangled) names. This was not sucessful because:
7709
    #       1) Clearcase dynamic views do not support name mangling
7710
    #       2) Samba file system does not appear to support name mangling
7711
    #
7712
    #   Spaces in paths are not good for MAKE
7713
    #   Now I simple generate a message
7714
    #
7715
    Warning( "ProjectBase contains a space: $ProjectBase")
7716
        if ( $ProjectBase =~ m/ / );
7717
 
7718
    #
7719
    #   Sanity check
7720
    #   Absolute paths can be checked easily
7721
    #   Checking of relative paths does not appear to work
7722
    #   When I tested it chdir, opendir and stat would limit themselves
7723
    #   and drop into the root directory ( under windows )
7724
    #
7725
    #   Solution: Check the path does not extend beyond the file tree
7726
    #
7727
    my $distance = 1;
7728
    my $tpath = $ProjectBase;
7729
 
7730
    if ( $is_relative && $tpath ne '.' )
7731
    {
7732
        #
7733
        #   Build up the complete pathname by merging it with the
7734
        #   current directory. Then clean it up.
7735
        #
7736
        $tpath = $::Cwd . '/' . $ProjectBase;
7737
 
7738
        #
7739
        #   Scan the list of diretories and count the distance from the root
7740
        #   This should not be greater than zero for sanity
7741
        #   Note: Get an empty elemement from the split due to
7742
        #         the leading / of the ABS path
7743
        #
7744
        $distance = 0;
7745
        foreach (  split ('/', $tpath) )
7746
        {
7747
            if ( m~\.\.~ )
7748
            {
7749
                $distance--;
7750
            }
7751
            else
7752
            {
7753
                $distance++;
7754
            }
7755
        }
7756
    }
7757
 
7758
    #
7759
    #   Warn if not a valid directory
7760
    #
7761
    Warning( "ProjectBase is not a directory: $ProjectBase")
7762
        if ( $distance <= 0 || !  -d $tpath  );
7763
 
7764
    #
7765
    #   $ProjectBase will always be a valid directory, but if its the top
7766
    #   directory (/) and it is added to a path we will get //path
7767
    #   This is not good, so // will be removed later in the AddIncDir and
7768
    #   AddSrcDir commands where $ProjectBase is really used.
7769
    #
7770
    #   Alternatively we could set $ProjectBase to an empty string, but then
7771
    #   this may be confused with an empty relative directory
7772
    #
7773
    Debug("ProjectBase Final  : $ProjectBase");
7774
}
7775
 
7776
#-------------------------------------------------------------------------------
7777
# Function        : DeployPackage
7778
#
7779
# Description     : Generate a deployed package
7780
#                   This is a gateway to a different packaging system
7781
#
7782
#                  DeployPackage and PackageXxxxx directives are mutually
7783
#                  exclusive. Only one person can play in the package area.
7784
#
7785
# Inputs          : Platform Specifier
7786
#                   Package Name    (Optional)
7787
#                   Options
7788
#                       --Name : Base name of the package. The default is taken
7789
#                                from the build.pl file
7790
#                       --Dir  : Package directory
7791
#                                The default is based on the package name
7792
#
7793
# Returns         :
7794
#
7795
sub DeployPackage
7796
{
7797
    my( $platforms, @elements ) = @_;
7798
    my $dir;
7799
    my $name;
7800
 
267 dpurdie 7801
    #
7802
    #   Flag that this build creates a deployable package, even if its not
7803
    #   active on this platform.
7804
    #
7805
    $DEPLOYPACKAGE = 1;
7806
 
7807
 
227 dpurdie 7808
    Debug2( "DeployPackage($platforms, @elements)" );
7809
    return if ( ! ActivePlatform($platforms) );
7810
 
7811
    #
7812
    #   Only allow one use of this directive
7813
    #
7814
    Error("DeployPackage can only be used once" ) if ( %DEPLOYPACKAGE );
267 dpurdie 7815
    $DEPLOYPACKAGE = 2;
227 dpurdie 7816
 
7817
    #
7818
    #   Ensure that the deployment file is available
7819
    #
7820
    my $command_file = $ScmDeploymentPatch ? "deploypatch.pl" : "deployfile.pl";
7821
    Error("DeployPackage: $command_file not found") unless (-f "./$command_file");
7822
    #
7823
    #   Collect arguments
7824
    #
7825
    foreach (@elements )
7826
    {
7827
        if ( m/^--Dir=(.*)/ ) {
7828
            Error ("DeployPackage: Package directory defined multiple times") if $dir;
7829
            $dir = $1;
7830
 
7831
        } elsif ( m/^--Name=(.*)/ ) {
7832
            Error ("DeployPackage: Package name defined multiple times") if $name;
7833
            $name = $1;
7834
 
7835
        } elsif ( m/^--/ ) {
7836
            Warning( "DeployPackage: Unknown option ignored: $_");
7837
 
7838
        } else {
7839
            Error ("DeployPackage: Package name defined multiple times") if $name;
7840
            $name = $_;
7841
 
7842
        }
7843
    }
7844
 
7845
    $name = $::ScmBuildPackage unless ( $name );
7846
 
7847
    #
7848
    #   Save the deployment data
7849
    #
7850
    $dir = lc($name) unless ( $dir );
7851
    $DEPLOYPACKAGE{'name'} = $name;
7852
    $DEPLOYPACKAGE{'dir'} = $dir;
7853
    $DEPLOYPACKAGE{'cmdfile'} = $command_file;
7854
 
7855
    #
7856
    #   Flag that toolset tests should be supressed
7857
    #   The Deploy world does not really use the full makefiles and if the
7858
    #   compilers are not installed will not be able to create deployment
7859
    #   packages
7860
    #
7861
    $ScmNoToolsTest = 1;
7862
}
7863
 
7864
 
7865
###############################################################################
7866
###############################################################################
7867
# Private function section.
7868
#       The following functions are used INTERNALLY by makelib.pl2.
7869
###############################################################################
7870
 
7871
###############################################################################
7872
#   A collection of functions to write to the MAKEFILE handle
7873
#
7874
#   MakeHeader          - Write a nice section header
7875
#   MakeNewLine         - Print a new line
7876
#   MakePrint           - Print a line ( without trailing \n)
7877
#   MakeQuote           - Escape \ and " character, then print a line
7878
#   MakePrintList       - Print an array
7879
#   MakeEntry           - Complex line printer
7880
#   MakePadded          - Padded line printer (internal)
7881
#   PadToPosn           - Calc space+tabs to tabstop (internal)
7882
#   MakeEntry3          - Complex Line Printer
7883
#   MakeDefEntry        - Print a definition line (Production + Debug support)
7884
#   MakeIfDefEntry      - Print ifdef entry
261 dpurdie 7885
#   MakeIfnDefEntry     - Print ifndef entry
7886
#   MakeIfZeroEntry     - Print ifeq entry
227 dpurdie 7887
#
7888
###############################################################################
7889
 
7890
sub MakeHeader
7891
{
7892
    my ($text, @rest) = @_;
7893
    my $length = length ($text);
7894
 
7895
    print MAKEFILE "\n";
7896
    print MAKEFILE "#--------- $text ", '-' x (80 - 12 - $length)  ,"\n";
7897
    print MAKEFILE "#    $_\n" foreach  ( @rest ) ;
7898
    print MAKEFILE "#\n";
7899
}
7900
 
7901
sub MakeNewLine         # Print a newline to the current 'Makefile'
7902
{
7903
    print MAKEFILE "\n";
7904
}
7905
 
7906
sub MakePrint           # Print to the current 'Makefile'
7907
{
7908
    print MAKEFILE @_
7909
        if ( defined $_[0] );
7910
}
7911
 
7912
sub MakeQuote           # Quote a makefile text line
7913
{
7914
    my( $line ) = @_;
7915
    $line =~ s/\\/\\\\/g;                       # quote all '\' characters
7916
    $line =~ s/"/\\"/g;                         # Then quote '"' characters
255 dpurdie 7917
    $line =~ s/=#/=\\#/g;                       # Then quote '=#' sequence
227 dpurdie 7918
    print MAKEFILE $line;
7919
}
7920
 
7921
sub MakePrintList
7922
{
7923
    print MAKEFILE $_ . "\n" foreach (@{$_[0]});
7924
}
7925
 
2429 dpurdie 7926
sub QuoteArray
7927
{
7928
    my $quote = "'";
7929
    if ( @_ ) {
7930
        return ($quote . join("$quote $quote", @_) . $quote);
7931
    }
7932
    return '';
7933
}
227 dpurdie 7934
 
7935
#-------------------------------------------------------------------------------
7936
# Function        : MakeEntry
7937
#
7938
# Description     : Build a entry based on the element list
7939
#                   Creates text of the form
7940
#                       $(BINDIR)/prog.exe: object1.obj \
7941
#                                           object2.obj
7942
#
7943
#
7944
# Inputs          : $prelim         - Preamble (one-off)
7945
#                   $postlim        - Postamble (one-off)
7946
#                   $prefix         - Pefix (to each element of array)
7947
#                   $postfix        - Postfix (to each element of array )
7948
#                   @elements       - Array of element to wrap
7949
#
7950
# Returns         :   1 Always
7951
#
7952
# Notes:
7953
#       The above description means that the following entry format is
7954
#       produced:
7955
#
7956
#           <preliminary><prefix><variant1><prefix><variant2>...<final>
7957
#
7958
#       With judicious use of newline and tab characters, a target
7959
#       and dependency list along with the command(s) to build the
7960
#       target can be constructed.
7961
#
7962
sub MakeEntry
7963
{
7964
    my( $prelim, $postlim, $prefix, $postfix, @elements ) = @_;
7965
 
7966
    MakePrint $prelim;
7967
    MakePrint "${prefix}${_}${postfix}" foreach ( @elements );
7968
    MakePrint $postlim if ($postlim);
7969
    return 1;
7970
}
7971
 
7972
#-------------------------------------------------------------------------------
7973
# Function        : MakePadded
7974
#
7975
# Description     : Generate aligned output of the form
7976
#                       Prefix_text           Aligned_text
7977
#                   where the aligned text is at a specified TAB boundary
7978
#
7979
# Inputs          : $align      - Tab stop (One tab = 8 chars)
7980
#                   $prefix     - Text to print before alignment occurs
7981
#                   @line       - Remainder of the line
7982
#
7983
sub MakePadded          # Print to the current 'Makefile', tab aligning
7984
{
7985
    my( $align, $prefix, @line ) = @_;
7986
 
7987
    my $strlen = length( $prefix );
7988
    my $pad = PadToPosn( $strlen, $align * 8 );
7989
 
7990
    print MAKEFILE $prefix . $pad;
7991
    print MAKEFILE @line;
7992
}
7993
 
7994
#-------------------------------------------------------------------------------
7995
# Function        : PadToPosn
7996
#
7997
# Description     : Given that we are at $startposn return a tab and space
7998
#                   string to place us at $endposn
7999
#
8000
sub PadToPosn
8001
{
8002
    my ($startposn, $endposn ) = @_;
8003
 
8004
 
8005
    #
8006
    #   Case where we are already too far into the line
8007
    #
8008
    return ( ' ' )if ( $endposn <= $startposn );
8009
 
8010
    my $tcount = 0;
8011
    my $scount = 0;
8012
 
8013
    while ( $startposn < $endposn )
8014
    {
8015
        $tcount ++;
8016
        $startposn = ($startposn >> 3) * 8 + 8;
8017
 
8018
        my $delta = $endposn - $startposn;
8019
        if ( $delta < 8 )
8020
        {
8021
            $scount = $delta;
8022
            last;
8023
        }
8024
 
8025
    }
8026
    return ( "\t" x $tcount .  ' ' x $scount );
8027
}
8028
 
8029
#-------------------------------------------------------------------------------
8030
# Function        : MakeEntry3
8031
#
8032
# Description     : Build a makefile entry based on the element list, tab aligned
8033
#                   Can creat text of the form:
8034
#                       TAG = NAME0 \       TAG : NAME0 \ 
8035
#                             NAME1               NAME1
8036
#
8037
#
8038
# Inputs          : $prelim             - Preliminary text
8039
#                   $presep             - Preliminary seperator
8040
#                   $elem_ref           - Either a single name or a reference to
8041
#                                         and array of names, or a hash.
8042
#
8043
# Returns         : Writes directly to the Makefile
8044
#
8045
sub MakeEntry3
8046
{
8047
    my( $prelim, $presep, $elem_ref ) = @_;
8048
 
8049
    #
8050
    #   The prelim may have some "\n" characters at the start
8051
    #   These simplify formatting, but mess up the nice formatting
8052
    #
8053
    if ($prelim =~ m~(^\n+)(.*)~ )
8054
    {
8055
        MakePrint $1;
8056
        $prelim = $2;
8057
    }
8058
 
8059
    #
8060
    #   Print the definition and the sep with nice padding
8061
    #
8062
    MakePadded ( 3, $prelim, $presep );
8063
    my $leadin = ' ';
8064
 
8065
    #
8066
    #   If a HASH reference then use a sorted list of keys from the hash.
8067
    #
8068
    if ( ref ($elem_ref) eq "HASH" )
8069
    {
8070
        my @hash_list;
8071
        @hash_list = sort keys ( %{$elem_ref} );
8072
        $elem_ref = \@hash_list;
8073
    }
8074
 
8075
    #
8076
    #   If the list is only one element long, then create a simple form
8077
    #   If the list is not an array ref, then treat it as a single element
8078
    #
8079
    if ( ref ($elem_ref) eq "ARRAY" )
8080
    {
8081
        my $line = 0;
8082
        foreach my $element ( @$elem_ref )
8083
        {
8084
            print MAKEFILE $leadin . $element;
8085
            $leadin = " \\\n" . PadToPosn(0,24 + length( $presep ) + 1 ) unless ($line++);
8086
        }
8087
    }
8088
    elsif ( defined $elem_ref )
8089
    {
8090
            print MAKEFILE $leadin . $elem_ref;
8091
    }
8092
    MakeNewLine();
8093
    return 1;
8094
}
8095
 
8096
#-------------------------------------------------------------------------------
8097
# Function        : MakeDefEntry
8098
#
8099
# Description     : Make a definition entry of the form
8100
#
8101
#                       TAG = NAME0 \
8102
#                             NAME1
8103
#
8104
#                   Support a list of definitions that will always be created
8105
#                   as well as a production and a debug list.
8106
#
8107
#                   Will always generate the "TAG = " string, even if the list
8108
#                   is empty.
8109
#
8110
#                   Will supress the TAG if there is no data if the FIRST opr starts with a '+'
8111
#
8112
# Inputs          : TAG         - Text tag to create
8113
#                   FIRST       - First assignement opr. = or +=
8114
#                   ALL_LIST    - A reference to a list of names to assign
8115
#                                 or a single name.
8116
#                   PROD_LIST   - Optional list to extend the definition with for a production build
8117
#                   DEBUG_LIST  - Optional list to extend the definition with for a debug build
8118
#
8119
# Returns         : Nothing
8120
#
8121
 
8122
sub MakeDefEntry
8123
{
8124
    my( $tag, $assign, $all, $prod, $debug ) = @_;
8125
 
8126
    #
8127
    #   Do not generate anything if the $opr is "+=" and there is no data
8128
    #   to output. ie: Supress empty TAG += statements
8129
    #
8130
    return if ( $assign =~ m/\+/ && ( ref($all) && ! defined $all->[0] ) );
8131
 
8132
    #
8133
    #   TAG for all entries
8134
    #
8135
    MakeEntry3( $tag, $assign, $all );
8136
 
8137
 
8138
    #
8139
    #   TAGs for PROD build
8140
    #   TAGs for DEBUG build
8141
    #
8142
    if ( defined $prod && defined $prod->[0] )
8143
    {
8144
        print MAKEFILE 'ifeq "$(DEBUG)" "0"' . "\n";
8145
        MakeEntry3( $tag, "+=", $prod );
267 dpurdie 8146
        print MAKEFILE 'endif' . "\n";
227 dpurdie 8147
    }
8148
 
8149
    if ( defined $debug && defined $debug->[0] )
8150
    {
8151
        print MAKEFILE 'ifeq "$(DEBUG)" "1"' . "\n";
8152
        MakeEntry3( $tag, "+=", $debug );
267 dpurdie 8153
        print MAKEFILE 'endif' . "\n";
227 dpurdie 8154
    }
8155
 
8156
}
8157
 
8158
sub MakeIfDefEntry
8159
{
8160
    my( $iftag, @rest ) = @_;
8161
 
8162
    print MAKEFILE "ifdef $iftag\n";
8163
    MakeDefEntry (@rest);
8164
    print MAKEFILE "endif\n\n";
8165
}
8166
 
8167
sub MakeIfnDefEntry
8168
{
8169
    my( $iftag, @rest ) = @_;
8170
 
8171
    print MAKEFILE "ifndef $iftag\n";
8172
    MakeDefEntry (@rest);
8173
    print MAKEFILE "endif\n\n";
8174
}
8175
 
261 dpurdie 8176
sub MakeIfZeroEntry
8177
{
8178
    my( $iftag, @rest ) = @_;
8179
 
8180
    print MAKEFILE "ifeq (\$($iftag),0)\n";
8181
    MakeDefEntry (@rest);
8182
    print MAKEFILE "endif\n\n";
8183
}
8184
 
227 dpurdie 8185
#-------------------------------------------------------------------------------
8186
# Function        : CreateNameList
8187
#
8188
# Description     : Create a list of names by adding a prefix and suffix to a
8189
#                   list of items. This is used to add a directory prefix and a
8190
#                   file suffix to a list of files.
8191
#
8192
# Inputs          : $prefix             ie: '$(OBJDIR)/'
8193
#                   $suffix             ie: '.obj'
8194
#                   $elem_ref           ie: A list of files ( passed be ref )
8195
#                                           If a Hash then its sorted keys is used
8196
#
8197
# Returns         : A ref to the resulting list
8198
#
8199
sub CreateNameList
8200
{
8201
    my( $prefix, $suffix, $elem_ref ) = @_;
8202
    my @result;
8203
 
8204
    if ( ref ($elem_ref) eq "HASH" )
8205
    {
8206
        my @hash_list;
8207
        @hash_list = sort keys ( %{$elem_ref} );
8208
        $elem_ref = \@hash_list;
8209
    }
8210
 
8211
    foreach  ( @$elem_ref )
8212
    {
8213
        push @result, $prefix . $_ . $suffix;
8214
    }
8215
    return \@result;
8216
}
8217
 
8218
#-------------------------------------------------------------------------------
8219
# Function        : ListGeneratedProjects
8220
#
8221
# Description     : Return a list of generated/nongenerated projects
8222
#                   Used in conjunction with CreateNameList
8223
#
8224
# Inputs          : $type       - TRUE : Generated
8225
#                                 FALSE: Not Generated
8226
#
8227
# Returns         : A reference to a list of projects
8228
#                   undef will be retuend if there are no projects
8229
#
8230
sub ListGeneratedProjects
8231
{
8232
    my ($type) = @_;
8233
    my @list;
8234
    foreach my $project ( @PROJECTS_ORDER )
8235
    {
8236
        if ( exists($PROJECTS{$project}->{'generated'}) xor $type )
8237
        {
8238
            push @list, $project;
8239
        }
8240
    }
8241
    return @list ? \@list : undef;
8242
}
8243
 
8244
#-------------------------------------------------------------------------------
8245
# Function        : ListCleanGenerated
8246
#
8247
# Description     : return a list of generated targets that have 'clean'
8248
#                   operations. This is used in conjunction with CreateNameList
8249
#
8250
# Inputs          : None
8251
#
8252
# Returns         : A list of project indexes, that can be cleaned
8253
#
8254
sub ListCleanGenerated
8255
{
8256
    my @list;
8257
    foreach my $i ( @GENERATE_FILES )
8258
    {
8259
        push @list, $i->{'index'}
8260
            if ( $i->{'clean'} );
8261
    }
8262
    return \@list;
8263
}
8264
 
251 dpurdie 8265
#-------------------------------------------------------------------------------
8266
# Function        : MakeResolve
8267
#
8268
# Description     : Internal Function
8269
#                   Locate a source file by examining a list of directories
8270
#
8271
#                   Don't use directly
8272
#                   Use MakeSrcResolve or MakeSrcResolveExtended
8273
#
8274
# Inputs          : $dirs           - Ref to an array of directories to scan
8275
#                   $source         - File to locate
8276
#
8277
# Returns         : Resolved path to the file
8278
#                   Will warn if multiple instances of the file are found
8279
#
227 dpurdie 8280
sub MakeResolve
8281
{
8282
    my( $dirs, $source ) = @_;
285 dpurdie 8283
    my( $first, $count );
227 dpurdie 8284
 
237 dpurdie 8285
    #
8286
    #   If the path contains a '$' then its assumed to be
8287
    #   a variable name in the path. Just assume that it exists
8288
    #
8289
    return $source if ( $source =~ m#\$# );
8290
 
8291
    #
8292
    #   If the path is absolute or contains a leading ., then don't search
8293
    #   Warn if it can't be found
8294
    #
8295
    if ( $source =~ m#^(/|\.)# )
8296
    {
8297
        Warning( "Unable to resolve '$source' path" ) unless -f $source;
8298
        return $source;
227 dpurdie 8299
    }
8300
 
6276 dpurdie 8301
    my @found;
8302
    # Search the local path first
8303
    push (@found, $source ) if -f ($source);
237 dpurdie 8304
 
285 dpurdie 8305
    foreach my $dir (@$dirs)
227 dpurdie 8306
    {
331 dpurdie 8307
        next if ( $dir eq '.' );
6276 dpurdie 8308
        my $temp = $dir . '/' . $source;
227 dpurdie 8309
        Debug2( "MakeResolve: Looking in: $temp" );
6276 dpurdie 8310
        push (@found, $temp) if (-f $temp);
227 dpurdie 8311
    }
8312
 
6276 dpurdie 8313
    Warning( "Unable to resolve path to '$source'" ) unless $found[0];
8314
    if (scalar @found > 1)
8315
    {
8316
        Warning("Duplicates for '$source'. Using the first", @found);
227 dpurdie 8317
    }
6276 dpurdie 8318
 
8319
    return $found[0] || "";
227 dpurdie 8320
}
8321
 
251 dpurdie 8322
#-------------------------------------------------------------------------------
8323
# Function        : MakeSrcResolve
8324
#
8325
# Description     : Locate a source file by examining the list of source
8326
#                   directories. There are a few frills
8327
#
8328
#                   Look for a source file in
8329
#                       1) %::BUILD_KNOWNFILES
8330
#                       2) %SRCS
8331
#                       3) Dirs specified by the array @SRCSDIRS
8332
#
8333
# Inputs          : Name of a file to resolve
8334
#
8335
# Returns         : Resolved path.
283 dpurdie 8336
#                   Input file - if not found at all
251 dpurdie 8337
#
227 dpurdie 8338
sub MakeSrcResolve
8339
{
8340
    my ($name) = @_;
8341
    my $file;
8342
 
251 dpurdie 8343
    if ( exists ( $::BUILD_KNOWNFILES{$name} ) ) {
8344
        #
8345
        #   The Known Files list is relative to ScmRoot
8346
        #   This must be included in the full path
8347
        #
8348
        $file = $ScmRoot . '/' . $::BUILD_KNOWNFILES{$name};
8349
 
8350
    } elsif ( exists $SRCS{$name} ) {
8351
        $file = $SRCS{$name};
8352
 
8353
    } else {
8354
        $file = MakeResolve( \@SRCDIRS, @_ )
8355
    }
227 dpurdie 8356
    return $file;
8357
}
8358
 
8359
 
8360
# MakeSrcResolveExtended
8361
#   from_global = 0 : Search user specified directories
8362
#               = 1 : Search LinkPkgArchive list
8363
#
8364
our @PkgSrcDirList;
8365
sub MakeSrcResolveExtended
8366
{
8367
    my ( $from_global, $file ) = @_;
8368
 
8369
    #
8370
    #   Simple Case. Resolve source from known source directories
8371
    #
8372
    #
8373
    return MakeSrcResolve( $file )
8374
        unless ( $from_global );
8375
 
8376
    #
8377
    #   Not so simple Case
8378
    #   Resolve the source from the imported packages
8379
    #
8380
    #   Create a list of directores to search, but only the first time
311 dpurdie 8381
    #       - Interface directories - from BuildPkgArchive
227 dpurdie 8382
    #       - LnkPkgArchive directories
8383
    #         Using target,product,platform include directories
8384
    #
8385
    unless ( @PkgSrcDirList )
8386
    {
8387
        for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} })
8388
        {
311 dpurdie 8389
            next if ( $entry->{'TYPE'} eq 'build' ); # Ignore BuildPkgArchives
8390
 
227 dpurdie 8391
            for (@{$entry->{'PINCDIRS'}}, @{$entry->{'THXDIRS'}}, '' )
8392
            {
8393
                my $dir = $entry->{'ROOT'} . "/" . $_ ;
8394
                $dir =~ s~//~/~g;
8395
                $dir =~ s~/$~~;
311 dpurdie 8396
                push ( @PkgSrcDirList, $dir );
227 dpurdie 8397
            }
8398
        }
311 dpurdie 8399
    }
227 dpurdie 8400
 
8401
    return MakeResolve( \@PkgSrcDirList, $file );
8402
}
8403
 
8404
#-------------------------------------------------------------------------------
8405
# Function        : GetPackageRoot
8406
#
8407
# Description     : Determine the root directory for a given package
8408
#                   This routine is intended for non-standard JATS scripts that
8409
#                   access package contents directly
8410
#
8411
#                   Note: This routine does not attempt to handle multiple
8412
#                         instances of a package ( sysbasetypes ).
8413
#
8414
# Inputs          : $pname          - Name of the package
8415
#
8416
# Returns         :
8417
#
8418
sub GetPackageRoot
8419
{
8420
    my( $pname ) = @_;
8421
    Debug( "GetPackageRoot(@_)" );
8422
 
8423
    my $result = undef;
8424
    my $pkg = GetPackageEntry( $pname );
8425
    if ( $pkg )
8426
    {
8427
        $result = $pkg->{'ROOT'};
8428
        Debug( "GetPackageRoot: $result" );
8429
    }
8430
 
8431
    return $result;
8432
}
8433
 
8434
#-------------------------------------------------------------------------------
8435
# Function        : ActiveProject
8436
#
8437
# Description     : Determine if the specified project is currenly 'active'
8438
#
345 dpurdie 8439
# Inputs          : $project            - one or more project names separated
8440
#                                         by either a comma or a colon
227 dpurdie 8441
#
8442
# Returns         : TRUE    if the project is active
8443
#
8444
sub ActiveProject
8445
{
8446
    my ($project) = @_;
345 dpurdie 8447
    foreach (  split( '\s*[:,]\s*', $project ) )
227 dpurdie 8448
    {
8449
        return 1
8450
            if ( $_ eq $::ScmBuildProject );
8451
    }
8452
    return 0;
8453
}
8454
 
345 dpurdie 8455
#-------------------------------------------------------------------------------
8456
# Function        : ActiveDefine
8457
#
8458
# Description     : Determine if the specified definition is currenly 'active'
8459
#
8460
# Inputs          : $defs               - one or more variable names separated
8461
#                                         by either a comma or a colon
8462
#
8463
# Returns         : TRUE    if any of the definitions are known
8464
#
8465
sub ActiveDefine
8466
{
8467
    my ($defs) = @_;
8468
    no strict 'refs';
8469
    foreach (  split( '\s*[:,]\s*', $defs ) )
8470
    {
8471
        return 1
4455 dpurdie 8472
            if ( defined( $$_ ) || ( @$_ ) );
345 dpurdie 8473
    }
8474
    use strict 'refs';
8475
    return 0;
8476
}
227 dpurdie 8477
 
8478
#-------------------------------------------------------------------------------
345 dpurdie 8479
# Function        : ActiveMachType
8480
#
8481
# Description     : Determine if the specified MachType is currenly 'active'
8482
#
8483
# Inputs          : $mtype              - one or more machine names separated
8484
#                                         by either a comma or a colon
8485
#
8486
# Returns         : TRUE    if any of the current MachType is in the list
8487
#
8488
sub ActiveMachType
8489
{
8490
    my ($mtype) = @_;
8491
    foreach (  split( '\s*[:,]\s*', $mtype ) )
8492
    {
8493
        return 1
8494
            if ( uc($_) eq uc($::GBE_MACHTYPE) );
8495
    }
8496
    return 0;
8497
}
8498
 
8499
#-------------------------------------------------------------------------------
6133 dpurdie 8500
# Function        : ActiveAlias
8501
#
8502
# Description     : Determine if the specified Alias is currenly 'active'
8503
#
8504
# Inputs          : $mtype              - one or more alias names separated
8505
#                                         by either a comma or a colon
8506
#
8507
# Returns         : TRUE    if any of the current Aliases is in the list
8508
#
8509
sub ActiveAlias
8510
{
8511
    my ($mtype) = @_;
8512
    foreach (  split( '\s*[:,]\s*', $mtype ) )
8513
    {
8514
        return 1
8515
            if ( isAnAlias( uc($_) ) );
8516
    }
8517
    return 0;
8518
}
8519
 
8520
 
8521
#-------------------------------------------------------------------------------
227 dpurdie 8522
# Function        : ActivePlatform
8523
#
8524
# Description     : Determine if the specified platform is currently 'active'
8525
#                   This is used by all user directives in order to determine
8526
#                   if the directive should be ignored for the current platform
8527
#
8528
# Inputs          : $platform_spec      - A platform specifier
8529
#                                         This is a bit complex.
8530
#
241 dpurdie 8531
#                   Format of platform_spec. One or more of
8532
#                       PlatformName
8533
#                       AliasName
6133 dpurdie 8534
#                       TargetName[,--Target]
345 dpurdie 8535
#                   Special Options (Must all be True)
8536
#                       --Project=ProjectName[:ProjectName]+
8537
#                       --Defined=SomeValue[:SomeValue]+
6133 dpurdie 8538
#                       --MachType=SomeMachType[:SomeMachType]+
8539
#                       --Alias=SomeAlias[:SomeAlias]+
8540
#                   Some shortcuts
8541
#                       '*'     ==> Always true
8542
#
345 dpurdie 8543
#                   Each can be prefixed with a '!' to negate the test
6133 dpurdie 8544
#                   
8545
#                   PlatformNames are either additive or negative(prefixed with !)
8546
#                       Order is not important                   
8547
#                       All additive names are accumulated before the negative items are considered.
8548
#                           ie: aa,!bb => !bb,aa
8549
#                       If only negative names are provided then JATS assumes a leading '*'
8550
#                           ie: !aaa => *,!aaa
8551
#                   
241 dpurdie 8552
#                   Valid options are:
271 dpurdie 8553
#                       --Target        - indicates that the platform is a 'target'
241 dpurdie 8554
#
8555
# Returns         : TRUE if the platform spec is satisfied
8556
#
227 dpurdie 8557
sub ActivePlatform
8558
{
8559
    my( $platform_spec ) = @_;
8560
    my( @platforms, $scmplatform, $platform );
6133 dpurdie 8561
    my( %arguments, @args );
241 dpurdie 8562
    my @plist;
227 dpurdie 8563
 
241 dpurdie 8564
    #
8565
    #   Short circuit check
6133 dpurdie 8566
    #       '*' is used so often that it pays to check it first
241 dpurdie 8567
    #
8568
    if ( $platform_spec eq '*' )
8569
    {
8570
        Debug3( " ActivePlatform(@_) = TRUE" );
8571
        return 1;
8572
    }
227 dpurdie 8573
 
241 dpurdie 8574
    #
8575
    #   Platform specifier may be a comma seperated list
8576
    #   ie:  WIN32,MOS,XXX
8577
    #   Extract non-platform arguments
279 dpurdie 8578
    #   Process to yield a dummy platform of '0' or '1' - these will be seen later
241 dpurdie 8579
    #
8580
    foreach ( split( '\s*,\s*', $platform_spec ) )
8581
    {
345 dpurdie 8582
        my ($result, $not);
8583
        if ( m~^(!?)--Project=(.+)~ ) {
325 dpurdie 8584
            $not = $1;
345 dpurdie 8585
            $result = ActiveProject($2);
277 dpurdie 8586
 
345 dpurdie 8587
        } elsif ( m~^(!?)--Defined=(.+)~ ) {
325 dpurdie 8588
            $not = $1;
345 dpurdie 8589
            $result = ActiveDefine($2);
241 dpurdie 8590
 
345 dpurdie 8591
        } elsif ( m~^(!?)--MachType=(.+)~ ) {
325 dpurdie 8592
            $not = $1;
345 dpurdie 8593
            $result = ActiveMachType($2);
8594
 
6133 dpurdie 8595
        } elsif ( m~^(!?)--Alias=(.+)~ ) {
8596
            $not = $1;
8597
            $result = ActiveAlias($2);
8598
 
325 dpurdie 8599
        } else {
8600
            #
8601
            #   Must be a platform argument
8602
            #   Add to a list
8603
            #
8604
            push @platforms, $_;
241 dpurdie 8605
            next;
8606
        }
8607
 
8608
        #
325 dpurdie 8609
        #   Continue processing non-platform arguments
345 dpurdie 8610
        #   Each one must be TRUE, allowing for negation.
241 dpurdie 8611
        #
325 dpurdie 8612
        $result = $result ? 1 : 0;
345 dpurdie 8613
        $result = ! $result if ( $not );
8614
        return 0 unless ( $result );
241 dpurdie 8615
    }
8616
 
4128 dpurdie 8617
    #
8618
    #   If we have no platforms then the test was purely non-platform arguments.
8619
    #
6133 dpurdie 8620
    if ($platform_spec ne '' && ! @platforms) {
8621
        Debug3( " ActivePlatform(@_ == $ScmPlatform) = TRUE" );
4128 dpurdie 8622
        return 1;
8623
    }
8624
 
6133 dpurdie 8625
    unless (@platforms) {
8626
        Debug3( " ActivePlatform(@_ == $ScmPlatform) = FALSE" );
8627
        return 0;
8628
    }
8629
 
8630
 
241 dpurdie 8631
    #   Platform specified may be an Alias
8632
    #   Perform alias expansion
8633
    #
8634
    @platforms = ExpandPlatforms( @platforms );         # aliasing
227 dpurdie 8635
    Debug3( " ActivePlatform(@_)" );
6198 dpurdie 8636
#    Debug0( " Platforms(@platforms)" );
227 dpurdie 8637
 
8638
#.. Arguments
241 dpurdie 8639
#   At this point we have a list of platforms and arguments
8640
#   Build up a hash of arguments for each platform being parsed
227 dpurdie 8641
#   Multiple arguments can follow a platform name
241 dpurdie 8642
#   Arguments apply to the preceeding platform name
227 dpurdie 8643
#
241 dpurdie 8644
    $platform = undef;
227 dpurdie 8645
    foreach ( @platforms )
8646
    {
241 dpurdie 8647
        if ( /^--Target/ ) {                     # Arguments
8648
            if ( $platform ) {
8649
                $arguments{$platform}{'Target'} = 1;
8650
            } else {
317 dpurdie 8651
                Warning ("No Platform preceding platform option: $_");
241 dpurdie 8652
            }
8653
 
305 dpurdie 8654
        } elsif ( /^--Only(Prod)|(Debug)/ || /--board=/ ) {
273 dpurdie 8655
            # Known arguments
305 dpurdie 8656
            # Bit of a kludge. Must be a better way
273 dpurdie 8657
 
241 dpurdie 8658
        } elsif ( /^--/ ) {
8659
            Warning ("Unknown platform option: $_");
8660
 
227 dpurdie 8661
        } else {                                # Target
8662
            $platform = $_;
241 dpurdie 8663
            push @plist, $platform;
227 dpurdie 8664
        }
8665
    }
8666
 
241 dpurdie 8667
#.. Scan the expression
227 dpurdie 8668
#
6198 dpurdie 8669
    $scmplatform = uc( $ScmPlatform );              # current platform
6133 dpurdie 8670
    my @add;
8671
    my @remove;
8672
    foreach ( @plist ) {
6198 dpurdie 8673
        my $platform = uc( Trim( $_ ) );            # trim white and convert case
6133 dpurdie 8674
        my $pname = $platform;
8675
        my $invert = 0;
8676
        if (substr($platform, 0, 1) eq '!') {
8677
            $invert = 1;
8678
            $pname = substr($platform, 1)
8679
        }
325 dpurdie 8680
 
227 dpurdie 8681
        #
241 dpurdie 8682
        #   Determine filter comparison
6133 dpurdie 8683
        #       Either a Platform or a Target
241 dpurdie 8684
        #
6133 dpurdie 8685
        if ( $arguments{$platform}{'Target'} ) {
8686
            $pname = $scmplatform if ($pname eq  uc( $ScmTarget ));
227 dpurdie 8687
        }
241 dpurdie 8688
 
6133 dpurdie 8689
        #
8690
        #   Catch some historically bad practices
8691
        #
8692
        $pname = $scmplatform if ( $pname eq '*'  || $pname eq '1' ); 
227 dpurdie 8693
 
6133 dpurdie 8694
        Debug3( "   Platform=$platform, PName=$pname" );
8695
 
227 dpurdie 8696
        #
8697
        #   Examine platform names
6133 dpurdie 8698
        #   Allow negation (removal) of the name
227 dpurdie 8699
        #
6133 dpurdie 8700
        if ( substr($platform, 0, 1) eq '!' )  {
8701
            push @remove, $pname; 
8702
        } else {
8703
            push @add, $pname; 
227 dpurdie 8704
        }
8705
    }
8706
 
241 dpurdie 8707
    #
6133 dpurdie 8708
    #   Build complete list of allowed platforms
8709
    #       Process additive rules before removal rules
8710
    #       If there are no additive rules, then assume all protaforms
241 dpurdie 8711
    #
6133 dpurdie 8712
    my %calcList;
8713
    @add = @::BUILDPLATFORMS unless @add;
6204 dpurdie 8714
    $calcList{uc $_} = 1 foreach (@add);
8715
    delete $calcList{uc $_} foreach (@remove);
6133 dpurdie 8716
#DebugDumpData("Add", \@add);
8717
#DebugDumpData("Remove", \@remove);
8718
#DebugDumpData("calcList", \%calcList);
241 dpurdie 8719
 
8720
    #
6133 dpurdie 8721
    #   If the current build target is left in the platform list, then we are building for it
8722
    #   
6198 dpurdie 8723
    if (exists $calcList{$scmplatform}) {
227 dpurdie 8724
        Debug3( " ActivePlatform(@_ == $ScmPlatform) = TRUE" );
8725
        return 1;
8726
    }
241 dpurdie 8727
 
227 dpurdie 8728
    Debug3( " ActivePlatform(@_ == $ScmPlatform) = FALSE" );
8729
    return 0;
8730
}
8731
 
8732
#-------------------------------------------------------------------------------
321 dpurdie 8733
# Function        : If
8734
#
8735
# Description     : Function for embedding arguments in directives
8736
#                   To be used within another directive
8737
#                   ie:
8738
#                       AnyDirective ('*',  arg1, arg2, ...
8739
#                                           If (SomePlatform, arg1, .. ,argn))
8740
#
8741
# Inputs          : $platform               - Active Platform speciifier
8742
#                   @args                   - Args
8743
#
8744
# Returns         : @args or nothing
8745
#
8746
sub  If
8747
{
8748
    my $platform = shift;
8749
    return @_
8750
        if ( ActivePlatform( $platform ));
8751
    return;
8752
}
8753
 
8754
#-------------------------------------------------------------------------------
227 dpurdie 8755
# Function        : RegisterMakefileGenerate
8756
#
8757
# Description     : Register a function to be called at the start of the
8758
#                   makefile generation process
8759
#
8760
# Inputs          : $fname      - Name of the function
8761
#                   $args       - Function Arguments
8762
#
8763
# Returns         : Nothing
8764
#
8765
our @MF_Generators;
8766
sub RegisterMakefileGenerate
8767
{
8768
   my ($fref) = @_;
8769
   my $rtype = ref($fref) || 'not a reference';
8770
 
8771
   Error ("RegisterMakefileGenerate called incorrectly",
8772
          "First argument MUST be a code reference",
8773
          "It is a $rtype"
8774
          ) unless ( $rtype eq 'CODE' );
8775
 
8776
   #
8777
   #    Save the arguments by reference in an array
8778
   #    The array will be processed later
8779
   #
8780
   push @MF_Generators, \@_;
8781
}
8782
 
8783
#-------------------------------------------------------------------------------
271 dpurdie 8784
# Function        : RegisterSrcHook
8785
#
8786
# Description     : Register a function to be called when a source file is
8787
#                   declared
8788
#
8789
# Inputs          : $ext        - Extension of interest
8790
#                                 '*' will be used by all
8791
#                   $fname      - Name of the function
8792
#                   $args       - Function Arguments
8793
#
8794
# Returns         : Nothing
8795
#
8796
sub RegisterSrcHook
8797
{
8798
    my $ext = shift;
8799
    my ($fref) = @_;
8800
    my $rtype = ref($fref) || 'not a reference';
8801
 
8802
    Error ("RegisterSrcHook called incorrectly",
8803
           "Second argument MUST be a code reference",
8804
           "It is a $rtype"
8805
           ) unless ( $rtype eq 'CODE' );
8806
 
8807
    #
8808
    #    Save the arguments by reference in an array
8809
    #    The array will be processed later
8810
    #
8811
    push @{$MF_RegisterSrcHooks{$ext}}, \@_;
8812
}
8813
 
8814
 
8815
#-------------------------------------------------------------------------------
227 dpurdie 8816
# Function        : MakefileHeader
8817
#
8818
# Description:    : Generate a "standard" makefile header.
8819
#
8820
#..
8821
 
8822
sub MakefileHeader
8823
{
8824
    my ($file, $desc, $by, @trailing) = @_;
8825
    my ($diff);
8826
 
8827
    $diff = 0 if (($diff = ((80-5) - length($desc))) < 0);
8828
    $desc .= ' ' . ('-' x $diff);
8829
 
8830
    print $file <<EOF;
8831
#-- $desc
8832
#
8833
#                   -- Please do not edit this file. --
8834
#
8835
#       To do so may result in a system failure, in additional to any
8836
#       changes made shall be overwritten.
8837
#
8838
# Created by $by
8839
#         on $::CurrentTime
8840
#
8841
EOF
8842
    #
8843
    #   Print out the trailer
8844
    #   This is an array. Place each entry on a new line
8845
    #
8846
    print $file $_ . "\n" for ( @trailing );
8847
}
8848
 
8849
###############################################################################
8850
# MakeFileGenerate:
8851
#       This subroutine does all of the actual make file generation based
8852
#       on information provided in the calls to the various public
8853
#       interface routines.
8854
#
8855
# Inputs:
8856
#
8857
# Returns:
8858
###############################################################################
8859
 
8860
my $MakefileGenerate_once = 0;
8861
sub MakefileGenerate
8862
{
8863
    my $Makefile = "$ScmPlatform.mk";
8864
    Debug( "MakefileGenerate: $Makefile" );
8865
 
8866
    #
8867
    #   Nasty things happen when we generate a makefile twice
8868
    #   Just warn the user and do nothing
8869
    #   If its in the common makefile.pl then just ignore it
8870
    #
8871
    if ( $ScmProcessingRootMake )
8872
    {
8873
        Warning ("MakefileGenerate directive is not allowed in common makefile.pl");
8874
        return;
8875
    }
8876
 
8877
    if ( $MakefileGenerate_once )
8878
    {
8879
        Warning ("MakefileGenerate should only be called once.",
8880
                 "Dir: $::Cwd");
8881
        return;
8882
    }
8883
    $MakefileGenerate_once = 1;
8884
 
8885
    #
8886
    #   Invoke all registered Makefile Generator functions
8887
    #   These allow clever directives to collect information to be
8888
    #   processed before the makefiles are created
8889
    #
8890
    while ( @MF_Generators )
8891
    {
8892
        Debug( "MakefileGenerate: Invoke RegisterMakefileGenerate function" );
8893
        my ($fname, @args) = @{shift @MF_Generators};
8894
        &$fname ( @args );
8895
    }
8896
 
8897
    #
8898
    #   Allow the toolset the opportunity to process all the collected data
8899
    #   before the makefile is created. This is optional
8900
    #
8901
    my( $if ) = MakeIf::Factory();              # build interface
8902
    $if->Preprocess();
8903
 
8904
    #
343 dpurdie 8905
    #   If we have supressed the Toolset use, then we need to sanity test
8906
    #   the use of the toolset
8907
    #
8908
    if ( $ScmNoToolsTest )
8909
    {
8910
        ReportError ("Building programs not supported with --NoToolset") if ( @PROGS || @TESTPROGS );
8911
        ReportError ("Building libraries not supported with --NoToolset") if ( @LIBS || @MLIBS || @SHLIBS );
8912
        ReportError ("Building projects not supported with --NoToolset") if ( %PROJECTS );
8913
        ErrorDoExit();
8914
    }
8915
 
8916
    #
227 dpurdie 8917
    #   Auto package the 'descpkg' file
8918
    #   If this makefile packages any files, then it can also package the descpkg file
8919
    #   The descpkg will be piggybacked into all makefiles that do a package
8920
    #
8921
    if ( %PACKAGE_FILES || %PACKAGE_HDRS || %PACKAGE_CLSS || %PACKAGE_LIBS
6387 dpurdie 8922
                        || %PACKAGE_SHLIBS || %PACKAGE_PROGS || @PACKAGE_DIRS )
227 dpurdie 8923
    {
251 dpurdie 8924
        Src ('*', 'descpkg') unless ($SRCS{ descpkg });
8925
        PackageFile ('*', 'descpkg');
227 dpurdie 8926
    }
8927
 
8928
    #
8929
    #   Some toolsets NEED a relative root
261 dpurdie 8930
    #   Note: At the moment ScmRoot is relative anyway, thus this code
8931
    #         does nothing
227 dpurdie 8932
    #
8933
    my $gbe_root = $::ScmRoot;
8934
    if ( $::UseRelativeRoot )
8935
    {
8936
        $gbe_root =  RelPath( $::ScmRoot );
8937
    }
8938
 
8939
    #
8940
    #   Now start to create the makefile
8941
    #
6133 dpurdie 8942
    ToolsetFiles::AddFile($Makefile);
285 dpurdie 8943
    open( MAKEFILE, '>', $Makefile ) || Error( "Cannot create $Makefile" );
227 dpurdie 8944
    ::MakefileHeader( *MAKEFILE,
8945
                      'Auto-generated Platform Dependent Makefile',
8946
                      "$ScmMakelib (version $ScmVersion)",
6177 dpurdie 8947
                      "# COPYRIGHT - VIX IP PTY LTD (\"VIX\"). ALL RIGHTS RESERVED.",
227 dpurdie 8948
                      '#',
8949
                      "# Located in $::Cwd",
8950
                      "# Platform $::ScmPlatform",
8951
                      '#' . ('-' x 79),
8952
                      );
8953
 
8954
    #
8955
    #   Ensure that some essential variables are set
8956
    #
8957
    print MAKEFILE <<EOF;
8958
#
8959
#   Validate essential environment variables
8960
#
8961
ifndef GBE_BIN
8962
    \$(error ERROR: GBE_BIN is not available)
8963
endif
8964
ifndef GBE_PERL
8965
    \$(error ERROR: GBE_PERL is not available)
8966
endif
8967
ifndef DEBUG
8968
    \$(error ERROR: DEBUG is not defined)
8969
endif
8970
EOF
8971
 
8972
 
8973
    print MAKEFILE <<EOF;
8974
 
8975
#
8976
#   Basic definitions
8977
#
343 dpurdie 8978
GBE_ROOT      := $gbe_root
8979
GBE_ROOT_ABS  := \$(abspath \$(GBE_ROOT))
8980
GBE_HOST      := $::ScmHost
8981
GBE_HOSTMACH  := $::GBE_MACHTYPE
8982
GBE_TARGET    := $::ScmTarget
8983
GBE_MACHTYPE  := $::ScmMachType
8984
GBE_PLATFORM  := $::ScmPlatform
8985
GBE_PBASE     := $::Pbase
8986
GBE_TYPE      := \$(if \$(findstring 1,\$(DEBUG)),D,P)
227 dpurdie 8987
EOF
8988
 
343 dpurdie 8989
MakePrint( "GBE_ARGS      := @ScmPlatformArgs\n" )
227 dpurdie 8990
    if ( scalar @ScmPlatformArgs );
8991
 
343 dpurdie 8992
MakePrint( "GBE_PRODUCT   := $ScmProduct\n" )
227 dpurdie 8993
    if ( $ScmProduct ne "" );
8994
 
343 dpurdie 8995
MakePrint( "GBE_OS_COMMON := $::BUILDINFO{$ScmPlatform}{OS_COMMON}\n" )
227 dpurdie 8996
    if ( exists($::BUILDINFO{$ScmPlatform}{OS_COMMON}) );
8997
 
8998
    print MAKEFILE <<EOF;
8999
 
9000
SHELL           := \$(GBE_BIN)/sh
9001
SHELLARGS       :=
9002
EXTENDED_LINE   := \$(GBE_BIN)/extend.lst
9003
export EXTENDED_LINE MAKE
9004
 
343 dpurdie 9005
MFLAGS           := --no-print --warn -r
9006
BUILDNAME        := $::ScmBuildName
9007
BUILDVER         := $::ScmBuildVersionFull
9008
BUILDVERNUM      := $::ScmBuildVersion
227 dpurdie 9009
BUILDPREVIOUSVER := $::ScmBuildPreviousVersion
343 dpurdie 9010
DEPLOYPATCH      := $ScmDeploymentPatch
9011
GBE_NOTOOLSTEST  := $ScmNoToolsTest
4781 dpurdie 9012
MAKEFILEUID      := $ScmMakeUid
9013
export MAKEFILEUID
227 dpurdie 9014
 
9015
#
9016
#   Ensure PWD is correctly set
9017
#
9018
PWD             := \$(CURDIR)
9019
export PWD
9020
 
261 dpurdie 9021
#
9022
#   NODEPEND    - Used to suppress generated dependency file checking
9023
#                 Mostly done in jmake.pl
9024
#   EXPERT      - Used to suppress dependency on this makefile
9025
#
9026
EOF
9027
 
285 dpurdie 9028
MakePrint( "EXPERT\t\t?= " . ($ScmExpert ? '1' : '0' ) . "\n" );
9029
MakePrint( "NODEPEND\t?= 0\n" );
261 dpurdie 9030
 
9031
print MAKEFILE <<EOF;
9032
 
9033
#
9034
#   SCM_MAKEFILE - The name of the file to depend upon
9035
#                  Supressed in EXPERT mode
9036
#
9037
ifneq (\$(EXPERT),0)
9038
SCM_MAKEFILE	:=
9039
else
9040
SCM_MAKEFILE	:= $Makefile
9041
endif
9042
EOF
9043
 
267 dpurdie 9044
#
9045
#   Setup the base directory for the packaging process
9046
#   When building a deployable package the base directory is changed to match
9047
#   that used by the deployment world. This is done so that the descpkg file
9048
#   can be created in the correct location
9049
#
9050
my  $PKGDIR = "pkg/$::Pbase";
9051
    $PKGDIR = "build/deploy" if ( $DEPLOYPACKAGE );
9052
Verbose("Setting PKGDIR: $PKGDIR");
9053
 
261 dpurdie 9054
print MAKEFILE <<EOF;
9055
 
227 dpurdie 9056
#--------- Targets -------------------------------------------------------------
9057
 
9058
.PHONY: 	default all build install package unpackage uninstall \\
9059
		clean unbuild clobber deploy
9060
 
373 dpurdie 9061
default:
227 dpurdie 9062
all:		install package deploy
9063
build:		make_init generate install_hdr depend make_lib \\
6387 dpurdie 9064
		install_lib make_install_shlib make_prog install_class install_dirs
227 dpurdie 9065
install:	build install_prog
6387 dpurdie 9066
package:	package_dirs package_files package_hdr package_lib package_shlib \\
9067
		package_prog package_class
227 dpurdie 9068
unpackage:	unpackage_class unpackage_prog unpackage_shlib \\
6387 dpurdie 9069
		unpackage_lib unpackage_hdr unpackage_files unpackage_dirs 
9070
uninstall:	uninstall_dirs uninstall_class uninstall_prog uninstall_shlib \\
227 dpurdie 9071
		uninstall_lib uninstall_hdr
9072
clean:		make_clean unmake_prog unmake_test unmake_lib unobj \\
261 dpurdie 9073
		undepend ungenerate rmlitter unmake_dir
227 dpurdie 9074
unbuild:	clean uninstall
9075
clobber:	unpackage unbuild
9076
deploy:		install run_deploy
9077
 
9078
#--------- Macros --------------------------------------------------------------
9079
 
9080
OBJDIR		= \$(GBE_PLATFORM)\$(GBE_TYPE).OBJ
9081
LIBDIR		= \$(GBE_PLATFORM).LIB
9082
BINDIR		= \$(GBE_PLATFORM)\$(GBE_TYPE).BIN
9083
CLSDIR		= classes\$(GBE_TYPE)
9084
 
267 dpurdie 9085
PKGDIR		= \$(GBE_ROOT)/$PKGDIR
227 dpurdie 9086
INCDIR_PKG	= \$(PKGDIR)/include
9087
LIBDIR_PKG	= \$(PKGDIR)/lib
9088
BINDIR_PKG	= \$(PKGDIR)/bin
9089
CLSDIR_PKG	= \$(PKGDIR)/classes
4996 dpurdie 9090
UTFDIR_PKG	= \$(GBE_ROOT_ABS)/$PKGDIR/utfResults
227 dpurdie 9091
 
9092
LOCALDIR	= \$(GBE_ROOT)/local
9093
INCDIR_LOCAL	= \$(LOCALDIR)/inc
9094
LIBDIR_LOCAL	= \$(LOCALDIR)/lib
9095
BINDIR_LOCAL	= \$(LOCALDIR)/bin
9096
CLSDIR_LOCAL	= \$(LOCALDIR)/classes
9097
BINDIR_LOCAL_PATH = \$(GBE_ROOT_ABS)/local/bin/\$(GBE_PLATFORM)\$(GBE_TYPE)
9098
 
9099
INTERFACEDIR	= \$(GBE_ROOT)/$ScmInterface
9100
INCDIR_INTERFACE= \$(INTERFACEDIR)/include
9101
LIBDIR_INTERFACE= \$(INTERFACEDIR)/lib
9102
BINDIR_INTERFACE= \$(INTERFACEDIR)/bin
9103
CLSDIR_INTERFACE= \$(INTERFACEDIR)/classes
9104
 
9105
.SUFFIXES:		# Delete the default suffixes
9106
 
9107
EOF
9108
 
9109
    MakePrintList( \@DEFINES );
9110
    MakeNewLine();
9111
 
9112
#-------------------------------------------------------------------------------
9113
#
9114
#
261 dpurdie 9115
    MakeHeader ("Defines, flags and file sets");
227 dpurdie 9116
 
9117
    # Flags
6177 dpurdie 9118
    foreach my $opt ( sort keys %ScmCompilerOpts )
261 dpurdie 9119
    {
9120
        MakeDefEntry ( $opt, "=", $ScmCompilerOpts{$opt} );
9121
    }
227 dpurdie 9122
 
261 dpurdie 9123
    MakeDefEntry( "CFLAGS",         "=", \@CFLAGS, \@CFLAGS_PROD, \@CFLAGS_DEBUG );
9124
    MakeDefEntry( "CLINTFLAGS",     "=", \@CLINTFLAGS, \@CLINTFLAGS_PROD, \@CLINTFLAGS_DEBUG );
9125
    MakeDefEntry( "CDEPENDFLAGS",   "=", \@CFLAGS, \@CFLAGS_PROD, \@CFLAGS_DEBUG );
9126
    MakeDefEntry( "CXXFLAGS",       "=", \@CXXFLAGS, \@CXXFLAGS_PROD, \@CXXFLAGS_DEBUG );
9127
    MakeDefEntry( "CXXLINTFLAGS",   "=", \@CXXLINTFLAGS, \@CXXLINTFLAGS_PROD, \@CXXLINTFLAGS_DEBUG );
9128
    MakeDefEntry( "CXXDEPENDFLAG",  "=", \@CXXFLAGS, \@CXXFLAGS_PROD, \@CXXFLAGS_DEBUG );
267 dpurdie 9129
    MakeDefEntry( "ASFLAGS",        "=", \@ASFLAGS, \@ASFLAGS_PROD, \@ASFLAGS_DEBUG );
9130
    MakeDefEntry( "LDFLAGS",        "=", \@LDFLAGS, \@LDFLAGS_PROD, \@LDFLAGS_DEBUG );
227 dpurdie 9131
 
9132
 
9133
#-------------------------------------------------------------------------------
9134
#   
9135
#
261 dpurdie 9136
    MakeHeader ("Tool Search Path",
9137
                "Extend the PATH seen by all the tools to include",
9138
                "The tools/bin directories discovered in Packages" );
9139
    my $put_PATH;
9140
    my $put_LD_LIBRARY_PATH;
9141
    for my $path ( ToolExtensionPaths() )
9142
    {
9143
        MakePrint( "PATH := $path$::ScmPathSep\$(PATH)\n" );
9144
        $put_PATH = 1;
227 dpurdie 9145
 
261 dpurdie 9146
        if ( $::ScmHost eq "Unix" )
9147
        {
227 dpurdie 9148
        MakePrint( "LD_LIBRARY_PATH ?= \n" );
9149
        MakePrint( "LD_LIBRARY_PATH := $path$::ScmPathSep\$(LD_LIBRARY_PATH)\n" );
261 dpurdie 9150
            $put_LD_LIBRARY_PATH =1;
9151
        }
227 dpurdie 9152
    }
9153
 
261 dpurdie 9154
    #   Export the appropriate environment variables
9155
    #   Note: Windows has an issue with PATH and Path
9156
    #         Haven't got to the bottom of it yet, but it would appear that DLL
9157
    #         searching uses Path and other stuff uses PATH. Not too sure how we
9158
    #         end up with two (or more in the environment)
9159
    #
9160
    #
9161
    if ( $put_LD_LIBRARY_PATH )
9162
    {
343 dpurdie 9163
        MakePrint( "export LD_LIBRARY_PATH\n" );
261 dpurdie 9164
    }
227 dpurdie 9165
 
261 dpurdie 9166
    if ( $put_PATH )
9167
    {
343 dpurdie 9168
        MakePrint( "Path := \$(PATH)\n" );
9169
        MakePrint( "export PATH Path\n" );
261 dpurdie 9170
    }
227 dpurdie 9171
 
9172
#-------------------------------------------------------------------------------
9173
#   
9174
#
261 dpurdie 9175
    MakeHeader ("Perl Module Search Path",
9176
                "Extend the PERL5LIB seen by invocations of perl");
227 dpurdie 9177
 
261 dpurdie 9178
    my $perl_module_found;
9179
    for my $path ( ToolExtensionPaths() )
227 dpurdie 9180
    {
6276 dpurdie 9181
        if (my @results =  glob( "$path/*.pm"))
261 dpurdie 9182
        {
6276 dpurdie 9183
            MakePrint( "PERL5LIB := $path$::ScmPathSep\$(PERL5LIB)\n" );
261 dpurdie 9184
            $perl_module_found = 1;
9185
        }
227 dpurdie 9186
    }
261 dpurdie 9187
    if ( $perl_module_found  )
9188
    {
227 dpurdie 9189
    MakePrint( "export PERL5LIB\n" );
261 dpurdie 9190
    }
227 dpurdie 9191
 
261 dpurdie 9192
#-------------------------------------------------------------------------------
227 dpurdie 9193
#   
9194
#
261 dpurdie 9195
    MakeHeader ("Include Search Paths",
367 dpurdie 9196
                "Package Include Paths for header files and libraries" );
227 dpurdie 9197
 
6177 dpurdie 9198
    MakeDefEntry( 'PINCDIRS'  , '=', '# includes');
9199
    MakeDefEntry( 'PINCDIRS_INTERFACE', '=', '# Interface includes');
9200
    MakeDefEntry( 'PINCDIRS_LOCAL', '=', '# Local includes');
9201
    MakeDefEntry( 'PLIBDIRS'  , '=', '# libraries');
9202
    MakeDefEntry( 'PLIBDIRS_INTERFACE', '=', '# Interface libraries');
9203
    MakeDefEntry( 'PLIBDIRS_LOCAL', '=', '# Local libraries');
367 dpurdie 9204
 
9205
    for my $package (@{$::ScmBuildPkgRules{$ScmPlatform} })
9206
    {
9207
        #
9208
        #   Skip the pseudo package that encapsulates the interface
9209
        #   directory. Currently the makefiles do this in a different
9210
        #   manner - to be resolved
9211
        #
9212
        #   Just comment out the lines so that the data is visible
9213
        #   Its a hint to make use of the data
9214
        #
9215
        my $prefix = '';
6177 dpurdie 9216
        my $suffix = '';
367 dpurdie 9217
        $prefix = '# ' if ( $package->{'TYPE'} eq 'build' );
9218
 
6177 dpurdie 9219
        #
9220
        #   The interface directory is a little bit different
9221
        #
9222
        my ($name,$base);
9223
        if ( $package->{'TYPE'} eq 'interface' ) {
9224
            $base = '$(INTERFACEDIR)';
9225
            $name = 'Interface Directory';
9226
            $suffix = '_INTERFACE';
9227
        } else {
9228
            $name = $package->{'NAME'} . '/' . $package->{'VERSION'};
9229
            $base = $package->{'ROOT'};
9230
        }
367 dpurdie 9231
 
1329 dpurdie 9232
        my @doc;
9233
        push (@doc, "From: $base");
9234
        push (@doc, 'BuildPkgArchive via Interface' )if $package->{'TYPE'} eq 'build' ;
367 dpurdie 9235
 
1329 dpurdie 9236
        MakeHeader ("Source: $name", @doc);
9237
 
367 dpurdie 9238
        #
9239
        #   List include and library directories
9240
        #   Note: Need the True Path for windows.
9241
        #       Some makefile functions (wildcard) only work as expected
9242
        #       if the case of the pathname is correct. Really only a problem
6177 dpurdie 9243
        #       with badly formed legacy packages where the Windows user
367 dpurdie 9244
        #       guessed at the package format.
9245
        #
9246
        #       The conversion to a TruePath is done when ScmBuildPkgRules
6177 dpurdie 9247
        #       is created. Create once, use many time.
367 dpurdie 9248
        #
6177 dpurdie 9249
        for my $type (qw (PINCDIRS PLIBDIRS) ) {
9250
            for my $path ( @{$package->{$type}} ) {
9251
                MakeDefEntry ( "$prefix$type$suffix", "+=", $base . $path);
367 dpurdie 9252
            }
9253
        }
9254
    }
9255
 
6177 dpurdie 9256
    #
9257
    #   Local Paths
9258
    #   These are a little bit special
9259
    #
9260
    MakeHeader ('Source: Local',  'From: Package Local');
9261
 
9262
    sub MakeLocalPaths 
9263
    {
9264
        my ($name, $root, $addRoot) = @_;
9265
        my @pathlist;
9266
 
9267
        foreach my $tag ( $ScmPlatform, $ScmProduct, $ScmTarget ) {
9268
            UniquePush( \@pathlist, "$root/$tag" ) if ( $tag );
9269
        }
9270
 
9271
        #   Add the root directory too
9272
        UniquePush( \@pathlist, $root) if $addRoot;
9273
 
9274
        MakeDefEntry ( $name , "+=", \@pathlist);
9275
    }
9276
 
9277
    MakeLocalPaths ( 'PINCDIRS_LOCAL', '$(INCDIR_LOCAL)', 1 );
9278
    MakeLocalPaths ( 'PLIBDIRS_LOCAL', '$(LIBDIR_LOCAL)', 0 );
9279
 
9280
 
367 dpurdie 9281
#-------------------------------------------------------------------------------
9282
#   
9283
#
9284
    MakeHeader ("Include Search Paths",
9285
                "Local Include Paths",
9286
                " LINKDIRS - Local include search path (short)",
9287
                " INCDIRS  - Include search path (complete)",
9288
                " NODEPDIRS - ",
9289
                " SRCDIRS - ",
9290
                " LIBDIRS - Library search path",
9291
 
9292
                );
9293
 
227 dpurdie 9294
    # Include search path
9295
    #
9296
    #   user-local
367 dpurdie 9297
    #   local
9298
    #   interface
9299
    #       BuildPkgArchive
9300
    #       LinkPkgArchive
227 dpurdie 9301
    #   user-global
9302
    #
9303
 
6177 dpurdie 9304
    MakeDefEntry ( "\nLINCDIRS",    "= ", \@L_INCDIRS );                    # .. Local
9305
    MakeDefEntry ( "LINCDIRS",      "+=", '$(PINCDIRS_LOCAL)');             # .. Sandbox local
9306
    MakeDefEntry ( "LINCDIRS",      "+=", '$(PINCDIRS_INTERFACE)');         # .. Sandbox interface
9307
    MakeDefEntry ( "LINCDIRS",      "+=", \@G_INCDIRS );                    # .. Global
227 dpurdie 9308
 
6177 dpurdie 9309
    MakeDefEntry ( "INCDIRS",  "= ", '$(LINCDIRS)' );                       # Local
9310
    MakeDefEntry ( "INCDIRS",  "+=", '$(PINCDIRS)' );                       # Package
9311
    MakeDefEntry ( "LINCDIRS", "+=", \@S_INCDIRS );                         # System
227 dpurdie 9312
 
9313
    # Source search path
9314
 
261 dpurdie 9315
    MakeDefEntry( "\nNODEPDIRS",        "=", \@NODEPDIRS );
227 dpurdie 9316
 
6177 dpurdie 9317
    MakeDefEntry( "\nSRCDIRS","= "  , [ @L_SRCDIRS, @G_SRCDIRS ] );         # Local
9318
    MakeDefEntry ( "SRCDIRS", "+=" , '$(PINCDIRS)' );                       # Package
9319
    MakeDefEntry ( "SRCDIRS", "+=" , \@S_INCDIRS );                         # System
227 dpurdie 9320
 
9321
    # Library search path
9322
    #
9323
    #   user-local
367 dpurdie 9324
    #   local
9325
    #   interface
9326
    #       BuildPkgArchive
9327
    #       LinkPkgArchive
227 dpurdie 9328
    #   user-global
6177 dpurdie 9329
    #   
9330
    #   Kludge Note:
9331
    #       The LIBDIRS path needs an element with a directory seperator in it
9332
    #       Needed by (broken) cmdfile o determine the file seperator to use
9333
    #       
227 dpurdie 9334
 
367 dpurdie 9335
    MakeDefEntry( "\nLIBDIRS",  "= ", '$(LIBDIR)' );                    # User Local
261 dpurdie 9336
    MakeDefEntry( "LIBDIRS",    "+=", \@L_LIBDIRS );                    # Local
6177 dpurdie 9337
    MakeDefEntry( "LIBDIRS",    "+=", '$(PLIBDIRS_LOCAL)' );            # Sandbox/local
9338
    MakeDefEntry( "LIBDIRS",    "+=", '$(PLIBDIRS_INTERFACE)' );        # Sandbox/interface
9339
    MakeDefEntry( "LIBDIRS",    "+=", '$(LIBDIR_INTERFACE)' );          # Kludge. See note above
261 dpurdie 9340
    MakeDefEntry( "LIBDIRS",    "+=", \@G_LIBDIRS );                    # Global
367 dpurdie 9341
    MakeDefEntry( "LIBDIRS",    "+=", '$(PLIBDIRS)' );                  # Package
261 dpurdie 9342
    MakeDefEntry( "LIBDIRS",    "+=", \@S_LIBDIRS );                    # System
227 dpurdie 9343
 
9344
#-------------------------------------------------------------------------------
9345
#
9346
#   Subdir creation and deletion
9347
#   Creation is done on the fly
9348
#   Deletion is done AFTER the toolset functions have been invoked to create the
9349
#   build artifacts so that the toolsets can create directories too
9350
 
9351
    MakeHeader ("Subdir creation");
9352
    CreateMkdirRules();
6177 dpurdie 9353
    MkdirRule( '$(OBJDIR)', 'OBJDIR', '--Extra=depend,depend.err' );    # Object build directory
2429 dpurdie 9354
    MkdirRule( '$(OBJDIR)/'.$_ ) foreach (@SHLIBS);                     # Shared library build directory
9355
    MkdirRule( '$(LIBDIR)', 'LIBDIR' );                                 # Library directory
9356
    MkdirRule( '$(BINDIR)', 'BINDIR' );                                 # Binary directory
227 dpurdie 9357
 
261 dpurdie 9358
    #
9359
    #   Create a directory for library merge tool to work within
9360
    #
9361
    MkdirRule( "\$(MLIBDIR)", 'MLIBDIR', '--Path=$(GBE_PLATFORM).MRG', '--RemoveAll' ) if (@MLIBS);
9362
 
227 dpurdie 9363
#-------------------------------------------------------------------------------
9364
#   Generate rules and recipes to create all the toolset specific parts
9365
#   This is done fairly early to allow the toolsets to extend various
9366
#   definitions that may be used later in the makefile construction
9367
#
9368
    MakeHeader ("Construct Programs");
9369
 
9370
    foreach my $i ( @PROGS )
9371
    {
289 dpurdie 9372
        my $pProg = $PROGS->Get($i);
9373
        my $pArgs = $pProg->getItems('ARGS');
9374
        my $pObjs = $pProg->getItems('OBJS');
9375
        my $pLibs = $pProg->getItems('LIBS');
227 dpurdie 9376
 
289 dpurdie 9377
        #
9378
        #   Create a list of program object files
9379
        #
9380
        push @PROGOBJS, @$pObjs;
227 dpurdie 9381
 
9382
        MakePrint( "#---- (${i})\n\n" );
9383
        if ( $ScmToolsetProgDependancies )
9384
        {
261 dpurdie 9385
            #
9386
            #   Original style Prog Interface
271 dpurdie 9387
            #   Write some dependency information here and some in the toolset
9388
            #   Problems:
9389
            #       1) Errors in library dependency generation will be
9390
            #          reported after all the object files have been created
9391
            #          Thus the error message and the make-stop are seperated
9392
            #          by many,many lines of output. This makes it difficult
9393
            #          to see the error.
261 dpurdie 9394
            #
271 dpurdie 9395
            #       2) Lack of Flexability
9396
            #
293 dpurdie 9397
            MakeEntry( "\$(BINDIR)/$i$::exe: ", "", "\\\n\t\t", ".$::o ", @$pObjs );
227 dpurdie 9398
        }
9399
        else
9400
        {
261 dpurdie 9401
            #
9402
            #   New Style Prog Interface
9403
            #   The toolset does it all
9404
            #
9405
            #   Flag the progam packaging as a placeholder.
9406
            #   The toolset will replace/update it.
9407
            #
227 dpurdie 9408
            PackageProgRemoveFiles( $i );
9409
        }
9410
 
289 dpurdie 9411
        $if->LD    ( $i, $pArgs, $pObjs, $pLibs );
9412
        $if->LDLINT( $i, $pArgs, $pObjs, $pLibs );
227 dpurdie 9413
    }
9414
 
9415
#-------------------------------------------------------------------------------
9416
#   
9417
#
9418
    MakeHeader ("Construct Test Programs");
289 dpurdie 9419
    foreach my $i ( @TESTPROGS )
227 dpurdie 9420
    {
289 dpurdie 9421
        my $pProg = $TESTPROGS->Get($i);
9422
        my $pArgs = $pProg->getItems('ARGS');
9423
        my $pObjs = $pProg->getItems('OBJS');
9424
        my $pLibs = $pProg->getItems('LIBS');
227 dpurdie 9425
 
289 dpurdie 9426
        #
9427
        #   Create a list of program object files
9428
        #
9429
        push @TESTPROGOBJS, @$pObjs;
9430
 
227 dpurdie 9431
        MakePrint( "#---- (${i})\n\n" );
9432
        if ( $ScmToolsetProgDependancies )
9433
        {
293 dpurdie 9434
            MakeEntry( "\$(BINDIR)/$i$::exe: ", "", "\\\n\t\t", ".$::o ", @$pObjs );
227 dpurdie 9435
        }
9436
        else
9437
        {
9438
            PackageProgRemoveFiles( $i );
9439
        }
9440
 
289 dpurdie 9441
        $if->LD    ( $i, $pArgs, $pObjs, $pLibs );
9442
        $if->LDLINT( $i, $pArgs, $pObjs, $pLibs );
227 dpurdie 9443
    }
9444
 
9445
#-------------------------------------------------------------------------------
9446
#
9447
#
9448
    MakeHeader ("Transfer Scripts to BINDIR");
9449
    foreach my $i ( sort ( values %SCRIPTS ))
9450
    {
9451
        my $tname = "\$(BINDIR)/" . StripDir( $i );
9452
 
9453
 
9454
        MakePrint( "$i:\t\tmakefile.pl\n" .
6177 dpurdie 9455
            "\t\$(XX_PRE)if [ ! -f \"$i\" ]; then echo 'Script [$i] not found'; exit 2; fi\n\n" );
227 dpurdie 9456
 
9457
        #
9458
        #   Create a rule to copy the script into the BIN directory
9459
        #   Mark the script as executable - It can't hurt and its there
9460
        #   to be run as part of a test.
9461
        #
9462
        MakePrint "$tname:\t\$(GBE_BINDIR) $i\n" .
9463
                  "\t\$(XX_PRE)\$(cp) -f $i $tname\n" .
9464
                  "\t\$(XX_PRE)\$(chmod) -f +wx $tname\n\n"
9465
    }
9466
 
9467
#-------------------------------------------------------------------------------
9468
#   
9469
#
9470
    MakeHeader ("Construct Libraries");
9471
    foreach my $i ( @LIBS )
9472
    {
289 dpurdie 9473
        my $pLib  = $LIBS->Get($i);
9474
        my $pArgs = $pLib->getItems('ARGS');
9475
        my $pObjs = $pLib->getItems('OBJS');
227 dpurdie 9476
 
363 dpurdie 9477
        unless ( $ScmToolsetNillLibSrc )
9478
        {
9479
            Error ("Library has no component objects: $i")
9480
                if ( scalar @$pObjs <= 0 );
9481
        }
299 dpurdie 9482
 
227 dpurdie 9483
        MakePrint "#---- (${i})\n\n";
289 dpurdie 9484
        $if->AR(     $i, $pArgs, $pObjs, $pLib);
9485
        $if->ARLINT( $i, $pArgs, $pObjs, $pLib );
227 dpurdie 9486
    }
9487
 
289 dpurdie 9488
#-------------------------------------------------------------------------------
9489
#   
9490
#
9491
    MakeHeader ("Construct Merged Libraries");
227 dpurdie 9492
    sub MlibEntry
9493
    {
289 dpurdie 9494
        my( $mlib, $plib, $pLibs ) = @_;
227 dpurdie 9495
        my @flib;
9496
 
289 dpurdie 9497
        MakePrint '$(LIBDIR)/' . GenLibName($mlib) . ":";
9498
        foreach my $lib ( @$pLibs )
227 dpurdie 9499
        {
289 dpurdie 9500
            #
9501
            #   Each library name may contains one embedded option which
9502
            #   specifies the source directory
9503
            #       libname[,--Option | BaseSubdir]
9504
            #
227 dpurdie 9505
            my ($slib, $sdir) = split( ',', $lib );
343 dpurdie 9506
            my $mode;
227 dpurdie 9507
 
9508
            #
283 dpurdie 9509
            #   By default the librares are pulled from LOCAL unless the
9510
            #   library is built in this directory, in which case it will
289 dpurdie 9511
            #   be used.
227 dpurdie 9512
            #
289 dpurdie 9513
            $sdir = ( $LIBS->Get($slib) ) ? '--Here' : '--Local'
9514
                unless ( $sdir );
227 dpurdie 9515
 
9516
            #
9517
            #   --Interface     - Pull library from the interface directory
9518
            #   --Local         - Pull library from the local directory
9519
            #   --SubDir=xxxx   - Pull library from specified subdirectory
283 dpurdie 9520
            #   --Here          - Pull from local directory if built locally
227 dpurdie 9521
            #   otherwise       - Pull library from specified subdirectory
9522
            #
9523
            if ($sdir eq '--Interface') {
9524
                $sdir = '$(LIBDIR_INTERFACE)/$(GBE_PLATFORM)';
9525
 
343 dpurdie 9526
 
9527
            } elsif ($sdir eq '--InterfacePlain') {
9528
                $sdir = '$(LIBDIR_INTERFACE)/$(GBE_PLATFORM)';
9529
                $mode = 1;
9530
 
227 dpurdie 9531
            } elsif ( $sdir eq '--Local') {
9532
                $sdir = $PackageInfo{'Lib'}{'IBase'} .  # Base of Installed libs
9533
                        $PackageInfo{'Lib'}{'Dir'};     # Default subdir
9534
 
9535
            } elsif ( $sdir =~ m~^--SubDir=(.*)~ ) {
9536
                $sdir = $1 . '/$(LIBDIR)';
9537
 
283 dpurdie 9538
            } elsif ( $sdir eq '--Here') {
9539
                $sdir = '$(LIBDIR)';
9540
 
227 dpurdie 9541
            } else {
9542
                $sdir .= '/$(LIBDIR)';
9543
            }
9544
 
343 dpurdie 9545
            MakePrint " \\\n\t\t${sdir}/" . GenLibName($slib, $mode);
227 dpurdie 9546
            push @flib, "${sdir}/${slib}";
9547
        }
289 dpurdie 9548
        return \@flib;
227 dpurdie 9549
    }
9550
 
9551
    foreach my $i ( @MLIBS )
9552
    {
289 dpurdie 9553
        my $pLib  = $MLIBS->Get($i);
9554
        my $pArgs = $pLib->getItems('ARGS');
9555
        my $pLibs = $pLib->getItems('LIBS');
227 dpurdie 9556
 
261 dpurdie 9557
        MakePrint "#---- (${i})\n\n";
9558
 
227 dpurdie 9559
        unless ( defined &ToolsetARMerge )
9560
        {
9561
            Warning( "Merging of libraries not supported in this toolset yet" );
9562
            Warning( "MergeLibrary: \"$i\" will not be created" );
9563
        }
9564
        else
9565
        {
9566
            #
9567
            #   Create the dependency rule
9568
            #       Target library : source library list
9569
            #           Recipe - generated by the toolset
9570
            #
289 dpurdie 9571
            foreach ( @$pArgs )
227 dpurdie 9572
            {
9573
                Warning( "Ignoring unknown argument to MergeLibrary. $_" );
9574
            }
289 dpurdie 9575
            $pLibs = MlibEntry( $i, $pLib, $pLibs );
9576
            $if->ARMerge( $i, $pArgs, $pLibs, $pLib );
227 dpurdie 9577
        }
9578
    }
9579
 
289 dpurdie 9580
#-------------------------------------------------------------------------------
9581
#   
9582
#
9583
    MakeHeader ("Construct Shared Libraries");
339 dpurdie 9584
 
227 dpurdie 9585
    foreach my $i ( @SHLIBS )
9586
    {
289 dpurdie 9587
        my $pShlib  = $SHLIBS->Get($i);
9588
        my $pArgs = $pShlib->getItems('ARGS');
9589
        my $pObjs = $pShlib->getItems('OBJS');
9590
        my $pLibs = $pShlib->getItems('LIBS');
9591
        my $version = $pShlib->{VERSION};
227 dpurdie 9592
 
289 dpurdie 9593
        $if->SHLD    ( $i, $pArgs, $pObjs, $pLibs, $version );
9594
        $if->SHLDLINT( $i, $pArgs, $pObjs, $pLibs, $version );
227 dpurdie 9595
    }
9596
 
9597
#-------------------------------------------------------------------------------
9598
#   Construct Objects
9599
#   For each object within OBJSOURCE construct the following:
9600
#
9601
#   $(OBJDIR)/object-name:     source-name [makefile]
9602
#       Toolset ...
9603
#
9604
#   
9605
#
9606
    MakeHeader ("Construct Objects");
371 dpurdie 9607
 
227 dpurdie 9608
    foreach my $i ( sort keys %OBJSOURCE )
9609
    {
9610
        my( $src, $sname, $ext, $type, @args );
9611
 
9612
        $src  = $OBJSOURCE{ $i };
9613
        $sname = StripDir( $src );
9614
        $ext  = StripFile( $src );
9615
        $ext = lc($ext)
9616
            if ( $::ScmHost ne "Unix" );
381 dpurdie 9617
        $type = ($ScmSourceTypes{ $ext } || '')
227 dpurdie 9618
            unless (( $type = $SRC_TYPE{ $sname }) );
9619
 
9620
        #
9621
        #   Object source is an object file
9622
        #   No need the generate the object, just create makefile rule
261 dpurdie 9623
        #   [ddp] Not too sure how we get here
227 dpurdie 9624
        #
9625
        if ( $ext eq ".$::o" )
9626
        {
9627
            MakePrint "$src:";
261 dpurdie 9628
            MakePrint " \$(SCM_MAKEFILE)";
227 dpurdie 9629
            MakeNewLine();
9630
            next;
9631
        }
9632
 
9633
        #
9634
        #   Need to create object file
9635
        #
9636
        @args = split( /$;/, $SRC_ARGS{ StripDir( $sname ) } )
9637
            if $SRC_ARGS{ $sname };
9638
 
9639
        push( @args, "--Shared" )
9640
            if ( exists $SHOBJ_LIB{$i} );
9641
 
9642
        #
9643
        #   Convert relative paths to absolute paths if required by the
9644
        #   toolset. Some compilers need ABS paths to generate nice debug
9645
        #   information.
9646
        #
9647
        $src = AbsPath($src)
9648
            if ( $UseAbsObjects );
9649
 
9650
        #
9651
        #   Extract any user specified dependancies
261 dpurdie 9652
        #   These will be added to the dependency list
227 dpurdie 9653
        #
9654
        my @dlist;
9655
        @dlist = split( /$;/, $SRC_DEPEND{$sname} )
9656
            if ( exists $SRC_DEPEND{$sname} );
9657
 
261 dpurdie 9658
        #
9659
        #   Create the dependency part of the object rule
9660
        #   The source file MUST be the first dependent recipes
9661
        #   may assume that $< is the name source file
9662
        #
9663
        MakeEntry( "\$(OBJDIR)/$i.$::o: $src \$(SCM_MAKEFILE)", "", " \\\n\t", "", @dlist );
227 dpurdie 9664
 
9665
        if ( $type eq ".c" ) {
9666
            $if->CC(  $src, $i, \@args );
261 dpurdie 9667
 
227 dpurdie 9668
        } elsif ( $type eq ".cc" ) {
9669
            $if->CXX( $src, $i, \@args );
261 dpurdie 9670
 
227 dpurdie 9671
        } elsif ( $type eq ".asm" ) {
9672
            $if->AS( $src, $i, \@args );
261 dpurdie 9673
 
227 dpurdie 9674
        } else {
9675
            $if->EXT( $src, $i, \@args ) ||
9676
                Warning( "Don't know how to build '$ext' images' for $src, $i" );
9677
            MakeNewLine();
9678
        }
9679
    }
9680
 
9681
#-------------------------------------------------------------------------------
9682
#   Construct Projects
9683
#   Construct toolset specific projects
9684
#
9685
    MakeHeader ("Construct Projects");
9686
    while ( my($project, $entry) = each %PROJECTS)
9687
    {
9688
        $if->PROJECT( $entry );
9689
    }
9690
 
9691
#-------------------------------------------------------------------------------
4761 dpurdie 9692
#   Automated tests
9693
#
9694
    MakeHeader ("Automated tests");
9695
 
9696
    my $idx = 0;
9697
    my @copy_set = ();
9698
 
227 dpurdie 9699
    foreach my $pEntry ( @TESTS_TO_RUN )
9700
    {                                           # Foreach test
9701
        $idx++;
9702
        $pEntry->{'index'} = $idx;
9703
        $pEntry->{'test_name'} = "run_test_$idx";
5708 dpurdie 9704
        $pEntry->{'echoname'} = $pEntry->{'utfname'} || '';  
4781 dpurdie 9705
        $pEntry->{'utfname'} = $pEntry->{'test_name'} unless defined $pEntry->{'utfname'};  
227 dpurdie 9706
 
9707
        #
9708
        #   If the test is being run within a 'FrameWork' then the underlying
9709
        #   toolset must instantiate the frame work.
9710
        #
9711
        #   This may change. Perhaps frameworks shouldn't be a part of the
9712
        #   toolset. Perhaps they should be standalone. May change
9713
        #
9714
        if ( $pEntry->{framework} )
9715
        {
9716
            $if->TESTFRAMEWORK( $pEntry );
9717
        }
9718
 
9719
        #
9720
        #   Create a rule to run the test
9721
        #
9722
 
9723
        my $tdir_alias = $pEntry->{'testdir'};
9724
        my $tdir = '$(' . $tdir_alias . ')';
9725
 
9726
        my $test_name = $pEntry->{'test_name'};
4996 dpurdie 9727
        push @TESTPROJECT_TO_URUN, $test_name;
4501 dpurdie 9728
        push @TESTPROJECT_TO_ARUN, $test_name if     ($pEntry->{'auto'} );
227 dpurdie 9729
 
9730
        my $tprog = $tdir . '/' . StripDir( $pEntry->{'prog'} );
5695 dpurdie 9731
 
9732
        #
9733
        #   Determine the maximum time that the automated test should run
9734
        #       Default is 30 minutes
9735
        #   Non-auto tests are not time limited
9736
        #       
9737
        my $timeout = '';
5848 dpurdie 9738
        if ($pEntry->{'auto'})
5695 dpurdie 9739
        {
5848 dpurdie 9740
            $timeout = 'timeout -Time:' . ($pEntry->{'maxtime'} || '30m') . ' ';
5695 dpurdie 9741
        }
227 dpurdie 9742
 
9743
        my $me = MakeEntry::New( *MAKEFILE, $test_name, '--Phony' );
4781 dpurdie 9744
 
9745
        #
4996 dpurdie 9746
        #   Export GBE_UTF... for the duration of the test
4781 dpurdie 9747
        #
9748
        $me->AddDefn('export GBE_UTFNAME', $pEntry->{'utfname'});
9749
        $me->AddDefn('export GBE_UTFUID', '$(MAKEFILEUID)' . '_' . $pEntry->{'index'});
4996 dpurdie 9750
        $me->AddDefn('export GBE_UTFFILE','$(UTFDIR_PKG)/$(GBE_PLATFORM)-$(GBE_TYPE)-$(GBE_UTFUID)' . '.xml');
4781 dpurdie 9751
 
5986 dpurdie 9752
        # Workaround for dirsep under windows when being wrapped in a timeout
9753
        $me->AddDefn('dirsep', '$(dirsep)$(dirsep)') if ($timeout && ($::ScmHost ne "Unix"));
9754
 
227 dpurdie 9755
        $me->AddDependancy( "\$(GBE_$tdir_alias)" );
9756
        $me->AddDependancy( "\$(INTERFACEDIR)/set_$::ScmPlatform.sh" );
9757
        $me->AddDependancy( $tprog ) if $pEntry->{'copyprog'};
9758
        $me->AddDependancy( @{ $pEntry->{'copyin' } } );
9759
        $me->AddDependancy( map { $tdir . '/' . StripDir($_) } @{ $pEntry->{'copyonce' } } );
9760
        $me->AddDependancy( @{ $pEntry->{'preq'} } );
9761
        $me->RecipePrefix ('$(XX_PRE)');
5708 dpurdie 9762
        $me->RecipeWrapper( $timeout . 'sh -c \'', '\'') if $timeout;
9763
        $me->RecipeComment( "------ Running test [$idx] $pEntry->{'echoname'} ..." );
227 dpurdie 9764
 
9765
        #
4996 dpurdie 9766
        #   Create package utfResults directory
9767
        #       Simplify use of the file
9768
        #
9769
        $me->AddShellRecipe ( 'mkdir -p $(UTFDIR_PKG)' );
9770
 
9771
        #
227 dpurdie 9772
        #   Extend the PATH seen by the script to include the local/bin directory
9773
        #   Allows programs and tests that have been created elsewhere in the component
9774
        #   to be accessed within the script.
9775
        #
9776
        $me->AddShellRecipe ( ". \$(INTERFACEDIR)/set_$::ScmPlatform.sh" );
9777
 
9778
        #
9779
        #   Copy in the files that we need
9780
        #
9781
        foreach my $file ( @{$pEntry->{'copyin'}} )
9782
        {
9783
            my $dst = $tdir . '/' . StripDir( $file );
9784
            UniquePush( \@COPYIN, $dst );
9785
            UniquePush( \@copy_set, $file );
9786
            $me->AddShellRecipe ( "\$(cp) -f $file $dst" );
9787
            $me->AddShellRecipe ( "\$(chmod) -f +wx $dst" );
9788
        }
9789
 
9790
        #
4778 dpurdie 9791
        #   Insert any FrameWork Recipe bits
227 dpurdie 9792
        #
9793
        $me->AddShellRecipe ( @{$pEntry->{'ShellRecipe'}} );
9794
 
4781 dpurdie 9795
        #
9796
        #   Insert command
5035 dpurdie 9797
        #       Save result code to a known file
4781 dpurdie 9798
        #
227 dpurdie 9799
        $me->AddShellRecipe ( "cd $tdir" );
9800
        $me->AddShellRecipe ( ["GBE_TYPE=\$(GBE_TYPE)",
9801
                               "GBE_HOST=\$(GBE_HOST)",
9802
                               "GBE_ROOT=\$(GBE_ROOT_ABS)",
4095 dpurdie 9803
                               "PATH=.\\$::ScmPathSep\$(BINDIR_LOCAL_PATH)\\$::ScmPathSep\$\$PATH",
5708 dpurdie 9804
                               $pEntry->{'command'},
227 dpurdie 9805
                               @{$pEntry->{'args'}},
5035 dpurdie 9806
                               ] , 
9807
                               'echo $$? > utf.$${GBE_UTFUID}.rc' );
9808
 
9809
        #
9810
        #   Create the basic command line for 'jats_runutf'
9811
        #       Use the simplistic 'internal' filter unless the user has provided one
9812
        #
9813
        my @cmdline;
9814
        push @cmdline, '--';
9815
        push @cmdline, '$(VERBOSE_OPT)';
9816
        push @cmdline, '-filter=' . ($pEntry->{'utfformat'} || 'internal');
9817
        push @cmdline, '-root=$(GBE_ROOT_ABS)' ;
9818
        push @cmdline, "-dir=$tdir";
9819
        push @cmdline, '-target=$(GBE_PLATFORM)';
9820
        push @cmdline, '-pkgdir=$(PKGDIR)';
9821
        push @cmdline, '-local=$(LOCALDIR)';
9822
        push @cmdline, '-interface=$(INTERFACEDIR)';
9823
        foreach my $entry (@{$pEntry->{'utfargs' }})
4778 dpurdie 9824
        {
5035 dpurdie 9825
            push @cmdline, '-arg=' . $entry;
4778 dpurdie 9826
        }
5035 dpurdie 9827
 
9828
        #
9829
        #   Insert commands to post process the test results according to the specified formatter
9830
        #
9831
        $me->NewSection     ();
9832
        $me->SectionIfDef   ('UTF_POSTPROCESS');
9833
        $me->RecipePrefix   ('$(XX_PRE)');
9834
        $me->AddRecipe      ( "\$(GBE_PERL) -Mjats_runutf -e processUtf " . join(" \\\n\t\t\t", @cmdline)  );
4778 dpurdie 9835
 
227 dpurdie 9836
        $me->Print();
9837
 
9838
 
9839
        #
9840
        #   Create entries to handle the copy-once files
9841
        #
9842
        foreach my $file ( @{ $pEntry->{'copyonce' } } )
9843
        {
9844
            my $tname = $tdir . '/' . StripDir($file);
9845
            my $me = MakeEntry::New( *MAKEFILE, $tname  );
9846
            $me->AddDependancy( $file );
9847
            $me->AddRecipe ( "\$(call CopyFile,CopyIn,$tname,$file,$tdir,)"  );
9848
            $me->Print();
9849
 
9850
            UniquePush( \@COPYIN, $tname );
9851
            UniquePush( \@copy_set, $file );
9852
 
9853
        }
9854
    }
9855
 
9856
    #
9857
    #   Generate sanity test for each copyin script
9858
    #   Simply to provide a nice error message for generated scripts
9859
    #   that do not exist at run-time
9860
    #
9861
    test_copy_in:
9862
    foreach my $i ( @copy_set )
9863
    {
9864
        next if ( $SCRIPTS{$i} );
9865
        foreach (  @SHLIB_TARGETS )
9866
        {
9867
            next test_copy_in if ( $i eq $_ );
9868
        }
9869
        MakePrint( "\n$i:\t\tmakefile.pl\n" .
6177 dpurdie 9870
            "\t\@if [ ! -f \"$i\" ]; then echo 'ERROR: CopyIn Script [$i] not found'; exit 2; fi\n" );
227 dpurdie 9871
    }
9872
 
261 dpurdie 9873
#-------------------------------------------------------------------------------
9874
#   Deploy rules
9875
#
9876
MakeHeader ("Deploy Rules");
227 dpurdie 9877
 
261 dpurdie 9878
print MAKEFILE <<EOF;
9879
.PHONY:		run_deploy
9880
EOF
227 dpurdie 9881
 
261 dpurdie 9882
#
9883
#   Build up the deployfile.pl command line from the available pieces
9884
#
9885
my $command_file = "";
9886
my @command_line;
9887
 
9888
if ( %DEPLOYPACKAGE )
9889
{
9890
    $command_file = $DEPLOYPACKAGE{'cmdfile'};
9891
 
9892
    push @command_line, "\$(XX_PRE)\$(GBE_PERL) -w $command_file";
9893
    push @command_line, "-r \"\$(GBE_ROOT)\"";
9894
    push @command_line, "-n \"$DEPLOYPACKAGE{'name'}\"";
9895
    push @command_line, "-d \"$DEPLOYPACKAGE{'dir'}\"";
9896
    push @command_line, "-v \"\$(BUILDVER)\"";
9897
    push @command_line, "-t \"\$(GBE_TYPE)\"";
9898
    push @command_line, "-o \"\$(BUILDPREVIOUSVER)\"";
9899
    push @command_line, "-m \"\$(GBE_PLATFORM)\"";
9900
    push @command_line, "-g \"\$(GBE_TARGET)\"";
9901
    push @command_line, "-k \"\$(GBE_PRODUCT)\""        if ( $ScmProduct );
9902
    push @command_line, "-p \"\$(DEPLOYPATCH)\""        if ( $ScmDeploymentPatch );
9903
 
9904
}
9905
 
9906
MakeEntry( "run_deploy:\t$command_file\n", "\n", "\t\t", " \\\n", @command_line );
9907
 
227 dpurdie 9908
#-------------------------------------------------------------------------------
261 dpurdie 9909
#   Custom Rules
9910
#
9911
    MakeHeader ("Custom Rules");
9912
    MakePrintList ( \@RULES );
9913
 
9914
#-------------------------------------------------------------------------------
9915
#   Generated Files
9916
#
9917
    MakeHeader ("Generated Files");
9918
    MakePrint ("\n.PHONY: phony_generate\n\n" );
9919
 
9920
    foreach my $i ( @GENERATE_FILES )
9921
    {
9922
        my $gen_tag = $i->{'index'};
9923
 
9924
        #
263 dpurdie 9925
        #   If predelete is enabled, then create a list of files to delete
9926
        #
9927
        if ( $i->{'predelete'}  )
9928
        {
9929
            MakeDefEntry( "generate_gen_$gen_tag", "=",  $i->{'gen'} );
9930
            MakePrint("\n")
9931
        }
9932
 
9933
 
9934
        #
261 dpurdie 9935
        #   Generate the basic generate rule and recipe
9936
        #   together with the prerequisites
9937
        #
9938
        MakeEntry ( "", ":", "", " ", @{$i->{'gen'}} );
9939
 
9940
        unless ( $i->{'clean'} && $i->{'shell'} )
9941
        {
9942
            MakeEntry ( "", "", " \\\n\t\t", "", @{$i->{'preq'}} );
9943
            MakeEntry ( "", "", " \\\n\t\t", "", "phony_generate" ) if $i->{'preq_sus'};
9944
            MakeEntry ( "", "", " \\\n\t\t", "", "\$(SCM_MAKEFILE)" );
9945
 
6177 dpurdie 9946
            MakePrint ("\n\t" . "\@\$(echo) '[$i->{'text'}] generating..'" );
263 dpurdie 9947
            if ( $i->{'predelete'}  )
9948
            {
9949
                MakePrint ("\n\t" . "\$(XX_PRE)\$(call RmFiles,generate_gen_$gen_tag)" );
9950
            }
261 dpurdie 9951
            MakePrint ("\n\t" . "\$(XX_PRE)\$(call generate_$gen_tag,)" );
9952
        }
9953
 
9954
        #
9955
        #   Generate 'clean' rules and recipes
9956
        #
9957
        if ( $i->{'clean'} )
9958
        {
9959
            MakePrint ("\n\nPHONY: clean_generate_$gen_tag" );
9960
            MakePrint ("\nclean_generate_$gen_tag:" );
343 dpurdie 9961
            MakePrint ("\n\t" . "\$(XX_PRE)-\$(call generate_$gen_tag,$i->{'clean'})" );
261 dpurdie 9962
        }
9963
 
9964
        #
9965
        #   Define a function to contain the body of the generation call
9966
        #   The first argument will be a 'clean' argument
9967
        #
9968
        MakePrint ("\n\ndefine generate_$gen_tag" );
9969
        if ( $i->{'shell'} )
9970
        {
9971
            MakeEntry ("\n\t(" , "\\\n\t)\n", " \\\n\t", ";" , @{$i->{'toolargs'}} );
9972
        }
9973
        else
9974
        {
9975
            MakeEntry ("\n\t" . $i->{'tool'} . ' $1', "\n", " \\\n\t\t", "" , @{$i->{'toolargs'}} );
9976
        }
9977
        MakePrint ("endef\n\n" );
9978
    }
9979
 
9980
#-------------------------------------------------------------------------------
9981
#   Toolset Post Processing
9982
#   Allow the toolset to perform any post processing, before we finally write
9983
#   out any definitions.
9984
#
9985
#   We will not interprete any more user directives, but new stuff may get added
9986
#
9987
#
9988
MakeHeader ("Toolset Post Processing");
9989
$if->Postprocess();
9990
 
9991
################################################################################
9992
#   All interactions with the toolset are now complete
9993
#   All lists are now complete
9994
#
9995
#   Can now create internal definitions
9996
#   
9997
################################################################################
9998
 
9999
    #
10000
    #   Would be nice if this would work
10001
    #   Unfortunatelty we still need $if for the CCDEPENDS and CTAGS work
10002
    #   These must be defined AFTER the definitions
10003
    #
10004
    #   Ideally we should construct our makefile in sections
10005
    #   and then we can order the sections when we write them out
10006
    #
10007
#$if = 0;                            # Ensure the MakeIf class is not called
10008
                                     # If this file is modified
10009
 
10010
#-------------------------------------------------------------------------------
227 dpurdie 10011
#   Sources
10012
#
10013
MakeHeader  ( "Sources");
10014
MakeDefEntry( "CSRCS",      "=",  \@CSRCS );
10015
MakeDefEntry( "CXXSRCS",    "=",  \@CXXSRCS );
10016
MakeDefEntry( "ASSRCS",     "=",  \@ASSRCS );
10017
 
10018
#-------------------------------------------------------------------------------
10019
#   Generated, Installed and Packaged components
10020
#
10021
MakeHeader  ("Generated, Installed and Packaged components");
10022
MakeDefEntry( "INITS",           "=",  \@INITS )   if ( @INITS );
10023
MakeDefEntry( "GENERATED",       "=",  \@GENERATED ) if ( @GENERATED );
10024
MakeDefEntry( "GENERATED_NOTSRC","=",  \@GENERATED_NOTSRC ) if ( @GENERATED_NOTSRC );
10025
MakeDefEntry( "GENERATEDCLEAN",  "=",  CreateNameList( 'clean_generate_', '', ListCleanGenerated() ));
10026
MakeDefEntry( "INSTALL_HDRS",    "=",  \%INSTALL_HDRS ) if ( %INSTALL_HDRS );
10027
MakeDefEntry( "INSTALL_CLSS",    "=",  \%INSTALL_CLSS ) if ( %INSTALL_CLSS );
10028
MakeDefEntry( "OBJS",            "=", CreateNameList( '$(OBJDIR)/', ".$::o", \@OBJS) );
10029
MakeDefEntry( "SHOBJS",          "=", CreateNameList( '$(OBJDIR)/', ".$::o", \%SHOBJ_LIB ));
289 dpurdie 10030
MakeDefEntry( "PROGOBJS",        "=", CreateNameList( '', ".$::o", \@PROGOBJS ));
10031
MakeDefEntry( "TESTPROGOBJS",    "=", CreateNameList( '', ".$::o", \@TESTPROGOBJS ));
10032
MakeDefEntry( "LIBS",            "=", $LIBS->AllTargets() ) if ($::a);
10033
MakeDefEntry( "MLIBS",           "=", $MLIBS->AllTargets() ) if ($::a);
227 dpurdie 10034
MakeDefEntry( "SHNAMES",         "=", \@SHLIBS );
10035
MakeDefEntry( "SHDIRS",          "=", CreateNameList( '$(OBJDIR)/', "", \@SHLIBS ));
10036
MakeDefEntry( "SHLIBS",          "=", \@SHLIB_TARGETS );
10037
MakeDefEntry( "SCRIPTS",         "=", CreateNameList( '$(BINDIR)/', "", \%SCRIPTS ));
10038
MakeDefEntry( "COPYIN",          "=", \@COPYIN );
289 dpurdie 10039
MakeDefEntry( "PROGS",           "=", $PROGS->AllTargets() );
227 dpurdie 10040
MakeDefEntry( "PROGS_EXTRA",     "=", \@PROGS_EXTRA );
289 dpurdie 10041
MakeDefEntry( "TESTPROGS",       "=", $TESTPROGS->AllTargets());
227 dpurdie 10042
MakeDefEntry( "LINTLIBS",        "=", CreateNameList( 'lib_', '_lint', \@LINTLIBS ));
10043
MakeDefEntry( "LINTSHLIBS",      "=", CreateNameList( 'shlib_', '_lint', \@LINTSHLIBS ));
10044
MakeDefEntry( "LINTPROGS",       "=", CreateNameList( 'prog_', '_lint', \@PROGS ));
289 dpurdie 10045
MakeDefEntry( "LINTPROGS",      "+=", CreateNameList( 'prog_', '_lint', \@TESTPROGS ));
227 dpurdie 10046
MakeDefEntry( "PROJECTS",        "=", CreateNameList( 'Project_', '', ListGeneratedProjects(1) ));
10047
MakeDefEntry( "PROJECTSGEN",     "=", CreateNameList( 'Project_', '', ListGeneratedProjects(0) ));
10048
MakeDefEntry( "PROJECTSCLEAN",   "=", CreateNameList( 'ProjectClean_', '', \%PROJECTS ));
10049
 
4501 dpurdie 10050
MakeDefEntry( "UNITTESTS",       "=", \@TESTPROJECT_TO_URUN );
10051
MakeDefEntry( "AUTOUNITTESTS",   "=", \@TESTPROJECT_TO_ARUN );
10052
 
4778 dpurdie 10053
MakeDefEntry( "AUTOUNITTESTS_PRE",    "=", \@TOOLSET_UTF_PRE );
10054
MakeDefEntry( "AUTOUNITTESTS_POST",   "=", \@TOOLSET_UTF_POST );
10055
MakeDefEntry( "AUTOUNITTESTS_COLLATE","=", \@TOOLSET_UTF_COLLATE );
10056
 
10057
 
261 dpurdie 10058
MakeHeader ("Toolset components");
10059
MakeDefEntry( "USERGENERATED",        "=", \@USERGENERATED )    if ( @USERGENERATED );
10060
MakeDefEntry( "TOOLSETGENERATED",     "=", \@TOOLSETGENERATED ) if ( @TOOLSETGENERATED );
10061
MakeDefEntry( "TOOLSETOBJS",          "=", \@TOOLSETOBJS )      if ( @TOOLSETOBJS );
10062
MakeDefEntry( "TOOLSETLIBS",          "=", \@TOOLSETLIBS )      if ( @TOOLSETLIBS );
10063
MakeDefEntry( "TOOLSETPROGS",         "=", \@TOOLSETPROGS )     if ( @TOOLSETPROGS );
10064
MakeDefEntry( "TOOLSETDIRS",          "=", \@TOOLSETDIRS )      if ( @TOOLSETDIRS );
10065
MakeDefEntry( "TOOLSETDIRTREES",      "=", \@TOOLSETDIRTREES )  if ( @TOOLSETDIRTREES );
227 dpurdie 10066
 
10067
#--------- Determine compiler flag groups to use ----------------------------
10068
#
10069
#   Allows the compiler options to be controlled for both the debug and
10070
#   the production builds. Allows control over
10071
#       1) Optimisations
10072
#       2) Debug Information
10073
#
10074
MakeHeader ("Determine compiler flag groups to use");
10075
 
10076
print MAKEFILE <<EOF;
10077
 
10078
ifneq "\$(DEBUG)" "1"
10079
USE_OPTIMISE	:= \$(PROD_USE_OPTIMISE)
10080
USE_DEBUGINFO	:= \$(PROD_USE_DEBUGINFO)
10081
else
10082
USE_OPTIMISE	:= \$(DEBUG_USE_OPTIMISE)
10083
USE_DEBUGINFO	:= \$(DEBUG_USE_DEBUGINFO)
10084
endif
10085
 
10086
EOF
10087
 
261 dpurdie 10088
#-------------------------------------------------------------------------------
10089
#   Source browsing tools
10090
#
10091
MakeHeader ("Source browsing tools");
10092
    print MAKEFILE <<EOF;
10093
.PHONY:			ctags
10094
ctags:
10095
EOF
10096
    $if->CTAGS()
10097
        if (@CSRCS || @CXXSRCS);
227 dpurdie 10098
 
261 dpurdie 10099
#-------------------------------------------------------------------------------
10100
#   Depend
10101
#   If we are build C or C++ source files then create rules and recipes
10102
#   to invoke a dependency generator.
227 dpurdie 10103
#
261 dpurdie 10104
#   NODEPEND is used to disable, at make-time, the dependency generation
10105
#   and inclusion process.
10106
#
10107
#
10108
MakeHeader ("Depend");
6133 dpurdie 10109
if ($::o && (@CSRCS || @CXXSRCS) && $ScmNotGeneric)
261 dpurdie 10110
{
10111
    $ScmDependTags = 1;
10112
    print MAKEFILE <<EOF;
10113
depend:			\$(OBJDIR)/depend
10114
 
10115
\$(OBJDIR)/depend:	\$(SCM_MAKEFILE) \$(GBE_OBJDIR)
10116
\$(OBJDIR)/depend:	\$(CSRCS) \$(CXXSRCS)
10117
ifeq (\$(NODEPEND),0)
6177 dpurdie 10118
	\@echo '[\$@] Doing a make depend..'
261 dpurdie 10119
	-\$(XX_PRE)\$(rm) -f \$(OBJDIR)/depend
10120
EOF
10121
    $if->CCDepend( "\$(OBJDIR)/depend", "\$(CSRCS)" )
10122
        if ( @CSRCS );
10123
    $if->CXXDepend( "\$(OBJDIR)/depend", "\$(CXXSRCS)" )
10124
        if ( @CXXSRCS );
10125
    MakePrint
10126
        "\t-\@\$(touch) -f \$(OBJDIR)/depend\n";
10127
    print MAKEFILE <<EOF;
10128
else
6177 dpurdie 10129
	\@echo '[\$@] Skipping make depend..'
261 dpurdie 10130
	-\$(XX_PRE)\$(rm) -f \$(OBJDIR)/depend
10131
endif
10132
EOF
10133
}
10134
else
10135
{
10136
    print MAKEFILE <<EOF;
10137
depend:
10138
EOF
10139
}
10140
 
10141
#
10142
#   Rule to unmake the depend file
2429 dpurdie 10143
#       No longer neeed.
10144
#       The file is deleted as a part of the OBJDIR cleanup
261 dpurdie 10145
#
10146
    print MAKEFILE <<EOF;
10147
 
10148
undepend:
10149
EOF
10150
 
10151
#--------- IFLAG Documentation -------------------------------------------------
10152
#
10153
#   IFLAG - iteration flag. This is setting by the calling process
10154
#                           and is a function of the phase being processed
227 dpurdie 10155
#       0   No external dependencies.
10156
#       1   Source dependency list.
261 dpurdie 10157
#       2   Shared library dependency list
10158
#       3   Application dependency list
227 dpurdie 10159
#
10160
#
261 dpurdie 10161
#--------- Dependencies --------------------------------------------------------
10162
#   Include the 'depend' file if required
10163
#
10164
    MakeHeader ("Dependency Inclusion");
10165
    print MAKEFILE <<EOF;
10166
ifeq (\$(NODEPEND),0)
10167
 ifdef IFLAG
10168
  ifneq "\$(IFLAG)" "0"
10169
-include	\$(OBJDIR)/depend
10170
  endif
227 dpurdie 10171
 endif
10172
endif
10173
 
10174
EOF
10175
 
10176
#-------------------------------------------------------------------------------
10177
#   Standard rules
10178
#
5991 dpurdie 10179
    MakeHeader ("Standard rules");
10180
    print MAKEFILE <<EOF;
373 dpurdie 10181
.PHONY:		make_clean
227 dpurdie 10182
make_clean:
10183
	-\@echo "Removing generated files (objects, libraries, binaries etc)";
10184
 
10185
.PHONY:		rmlitter
10186
rmlitter:
2429 dpurdie 10187
	-\$(AA_PRE)JatsFileUtil 'D0' 'Removing litter' '.' 'core' '*.bak' '*.tmp' '*.err'
227 dpurdie 10188
 
261 dpurdie 10189
.PHONY:		lint_init
10190
lint_init:
10191
 
227 dpurdie 10192
EOF
10193
 
261 dpurdie 10194
#
10195
#   Dependencies for 'make_init'
10196
#
10197
#
10198
my @initdep;
10199
push @initdep, '$(INITS)' if ( @INITS );
227 dpurdie 10200
 
261 dpurdie 10201
#
10202
#   Dependencies for 'make_dir'
10203
#
10204
my @mkdirdep;
289 dpurdie 10205
push @mkdirdep, '$(GBE_OBJDIR)' if ( @CSRCS || @CXXSRCS || @OBJS || @PROGOBJS || @TESTPROGOBJS );
261 dpurdie 10206
push @mkdirdep, '$(SHDIRS)'     if ( %SHOBJ_LIB || @SHLIBS);
10207
push @mkdirdep, '$(GBE_LIBDIR)' if ( @LIBS || @MLIBS || @SHLIBS || %INSTALL_LIBS || %PACKAGE_LIBS );
289 dpurdie 10208
push @mkdirdep, '$(GBE_BINDIR)' if ( @SHLIBS || %SCRIPTS || @PROGS || @TESTPROGS || %INSTALL_PROGS || %PACKAGE_PROGS );
227 dpurdie 10209
 
261 dpurdie 10210
#
10211
#   Actions for for 'unobj'
10212
#
10213
my @unobjact;
10214
push @unobjact, RmFilesCmd( 'OBJS' )            if ( @OBJS );
10215
push @unobjact, RmFilesCmd( 'SHOBJS' )          if ( %SHOBJ_LIB );
10216
push @unobjact, RmFilesCmd( 'PROGOBJS' )        if ( @PROGOBJS );
289 dpurdie 10217
push @unobjact, RmFilesCmd( 'TESTPROGOBJS' )    if ( @TESTPROGOBJS );
261 dpurdie 10218
push @unobjact, RmFilesCmd( 'TOOLSETOBJS' )     if ( @TOOLSETOBJS );
227 dpurdie 10219
 
261 dpurdie 10220
#
10221
#   Dependencies for 'make_lib'
10222
#
10223
my @libdep;
10224
push @libdep, '$(GBE_OBJDIR)', '$(GBE_LIBDIR)', '$(LIBS)' if ( @LIBS );
227 dpurdie 10225
 
261 dpurdie 10226
#
10227
#   Dependencies for 'lint_lib'
10228
#
10229
my @liblintdep;
10230
push @liblintdep, 'lint_init', '$(GBE_OBJDIR)', '$(GBE_LIBDIR)', '$(LINTLIBS)' if ( @LIBS );
227 dpurdie 10231
 
261 dpurdie 10232
#
10233
#   Dependencies for 'make_mlib'
10234
#
10235
my @mlibdep;
10236
push @mlibdep, '$(GBE_OBJDIR)', '$(GBE_LIBDIR)', '$(GBE_MLIBDIR)', '$(MLIBS)' if ( @MLIBS );
227 dpurdie 10237
 
261 dpurdie 10238
#
10239
#   Dependencies for 'make_install_shlib' (tag)
10240
#
10241
my @shlibdep;
10242
push @shlibdep, '$(SHDIRS)', '$(SHLIBS)' if ( @SHLIBS );
227 dpurdie 10243
 
261 dpurdie 10244
#
10245
#   Dependencies for 'lint_shlib'
10246
#
10247
my @shliblintdep;
10248
push @shliblintdep, 'lint_init', '$(GBE_LIBDIR)', '$(LINTSHLIBS)' if ( @SHLIBS );
227 dpurdie 10249
 
261 dpurdie 10250
#
10251
#   Actions for 'unmake_lib'
10252
#
10253
my @unlibact;
10254
push @unlibact, RmFilesCmd( 'SHLIBS' )      if ( @SHLIBS );
10255
push @unlibact, RmFilesCmd( 'MLIBS' )       if ( @MLIBS );
10256
push @unlibact, RmFilesCmd( 'LIBS' )        if ( @LIBS );
10257
push @unlibact, RmFilesCmd( 'TOOLSETLIBS' ) if ( @TOOLSETLIBS );
227 dpurdie 10258
 
261 dpurdie 10259
#
10260
#   Actions for 'unmake_mlib'
10261
#
10262
my @unmlibact;
10263
push @unmlibact, RmFilesCmd( 'MLIBS' ) if ( @MLIBS );
227 dpurdie 10264
 
261 dpurdie 10265
#
10266
#   Dependencies for 'make_script'
10267
#
10268
my @scriptdep;
10269
push @scriptdep, '$(GBE_BINDIR)', '$(SCRIPTS)' if ( %SCRIPTS );
227 dpurdie 10270
 
261 dpurdie 10271
#
10272
#   Actions for 'unmake_script'
10273
#
10274
my @unscriptact;
10275
push @unscriptact , RmFilesCmd( 'SCRIPTS' ) if ( %SCRIPTS );
10276
push @unscriptact , RmFilesCmd( 'COPYIN' )  if ( @COPYIN );
227 dpurdie 10277
 
261 dpurdie 10278
#
10279
#   Dependencies for 'make_prog'
10280
#
10281
my @progdep;
10282
push @progdep, '$(GBE_OBJDIR)', '$(GBE_BINDIR)', '$(PROGS)' if ( @PROGS );
10283
push @progdep, '$(PROGS_EXTRA)' if (@PROGS_EXTRA);
227 dpurdie 10284
 
261 dpurdie 10285
#
10286
#   Dependencies for 'make_prog' created for 'projects'
10287
#
10288
my @projectdep;
10289
push @projectdep, '$(PROJECTS)' if (ListGeneratedProjects(1) );
227 dpurdie 10290
 
261 dpurdie 10291
#
10292
#   Dependencies for 'generate' created for 'projects'
10293
#
10294
my @projectgendep;
10295
push @projectgendep, '$(PROJECTSGEN)' if (ListGeneratedProjects(0) );
227 dpurdie 10296
 
261 dpurdie 10297
#
10298
#   Dependencies for 'unmake_prog' created for 'projects'
10299
#
10300
my @projectcleandep;
10301
push @projectcleandep, '$(PROJECTSCLEAN)' if (%PROJECTS);
227 dpurdie 10302
 
261 dpurdie 10303
#
10304
#   Dependencies for 'lint_prog'
10305
#
10306
my @proglintdep;
289 dpurdie 10307
push @proglintdep, 'lint_init', '$(GBE_OBJDIR)', '$(GBE_BINDIR)', '$(LINTPROGS)' if ( @PROGS || @TESTPROGS );
227 dpurdie 10308
 
261 dpurdie 10309
#
10310
#   Actions for 'unmake_prog'
10311
#
10312
my @unprogact;
10313
push @unprogact, RmFilesCmd( 'PROGS' )        if ( @PROGS );
10314
push @unprogact, RmFilesCmd( 'TOOLSETPROGS' ) if ( @TOOLSETPROGS );
227 dpurdie 10315
 
261 dpurdie 10316
#
4728 dpurdie 10317
#   Dependencies for 'exec_tests'
261 dpurdie 10318
#
10319
my @testprogdep;
289 dpurdie 10320
push @testprogdep, '$(GBE_OBJDIR)', '$(GBE_BINDIR)', '$(TESTPROGS)' if ( @TESTPROGS );
227 dpurdie 10321
 
4501 dpurdie 10322
my @autoruntestdep;
10323
push @autoruntestdep, 'makefile.pl', '$(AUTOUNITTESTS)' if ( @TESTPROJECT_TO_ARUN );
10324
 
10325
my @runtestdep;
4996 dpurdie 10326
push @runtestdep    , 'makefile.pl', '$(UNITTESTS)' if ( @TESTPROJECT_TO_URUN );
4501 dpurdie 10327
 
227 dpurdie 10328
#
4728 dpurdie 10329
#   Dependencies for 'exec_tests' and friends
261 dpurdie 10330
#
10331
my @untestprogact;
289 dpurdie 10332
push @untestprogact ,RmFilesCmd( 'TESTPROGS' ) if ( @TESTPROGS );
227 dpurdie 10333
 
261 dpurdie 10334
#
10335
#   Dependencies for 'generated'
10336
#
10337
my @generatedep;
10338
push @generatedep, '$(GENERATED)' if ( @GENERATED );
10339
 
10340
#
10341
#   Actions for 'ungenerate'
10342
#
10343
my @ungenact;
10344
push @ungenact, RmFilesCmd( 'GENERATED' ) if ( @GENERATED );
10345
push @ungenact, RmFilesCmd( 'GENERATED_NOTSRC' ) if ( @GENERATED_NOTSRC );
10346
push @ungenact, RmFilesCmd( 'TOOLSETGENERATED' ) if ( @TOOLSETGENERATED );
10347
push @ungenact, RmFilesCmd( 'USERGENERATED' ) if ( @USERGENERATED );
10348
 
10349
#
10350
#   Dependencies for 'ungenerate'
10351
#
10352
my @ungeneratedep;
10353
push @ungeneratedep, '$(GENERATEDCLEAN)';
10354
 
227 dpurdie 10355
#-------------------------------------------------------------------------------
261 dpurdie 10356
# Function        : PrintPhonyRule
227 dpurdie 10357
#
261 dpurdie 10358
# Description     : Helper function to print some internal phony makefile targets
10359
#                   These are used to hold the basic makefile together
10360
#
10361
# Inputs          : $target         - Name of the phony target
10362
#                   $prereq         - Prerequisites
10363
#                                     Leading spaces removed
10364
#                   $recipe         - Optional Reference to an array of recipes
10365
#                                     Will be printed one per line
10366
#
10367
#
10368
sub PrintPhonyRule
227 dpurdie 10369
{
261 dpurdie 10370
    my ($target, $prereq, $recipe) = @_;
10371
    $prereq =~ s/^\s+//;
227 dpurdie 10372
 
261 dpurdie 10373
    MakePadded( 2, '.PHONY:', $target, "\n");
10374
    MakePadded( 2,"$target:", $prereq, "\n");
10375
    MakePrint ("\t\t" . $_ . "\n") foreach ( @{$recipe} );
10376
    MakePrint ("\n");
227 dpurdie 10377
}
10378
 
261 dpurdie 10379
#   make_init - Test toolset presence and sanity
10380
#   Will only be called ONCE for each platform in a recursive build
10381
#   Should be used to ensure that the required toolset is present
10382
#
4778 dpurdie 10383
PrintPhonyRule ('make_init',            "@initdep" );
227 dpurdie 10384
 
261 dpurdie 10385
#   make_dir    - Create required subdirectories
10386
#   Will be invoked as a part of most targets that create files
10387
#   Will be invoked by the calling wrappers
10388
#   Should not be invoked when cleaning
10389
#
4778 dpurdie 10390
PrintPhonyRule ('make_dir',             "@mkdirdep" );
261 dpurdie 10391
 
4778 dpurdie 10392
PrintPhonyRule ('generate',             "@generatedep @projectgendep" );
10393
PrintPhonyRule ('ungenerate',           "@ungeneratedep",  \@ungenact);
10394
PrintPhonyRule ('unobj',                "",  \@unobjact);
10395
PrintPhonyRule ('make_lib',             "@libdep" );
10396
PrintPhonyRule ('lint_lib',             "@liblintdep" );
10397
PrintPhonyRule ('make_mlib',            "@mlibdep" );
10398
PrintPhonyRule ('lint_shlib',           "@shliblintdep" );
10399
PrintPhonyRule ('unmake_lib',           "", \@unlibact );
10400
PrintPhonyRule ('unmake_mlib',          "", \@unmlibact );
10401
PrintPhonyRule ('make_script',          "@scriptdep" );
10402
PrintPhonyRule ('unmake_script',        "", \@unscriptact );
10403
PrintPhonyRule ('make_prog',            "make_script @progdep @projectdep" );
10404
PrintPhonyRule ('unmake_prog',          "unmake_script @projectcleandep", \@unprogact );
10405
PrintPhonyRule ('lint_prog',            "@proglintdep" );
10406
PrintPhonyRule ('exec_tests',           "make_script @testprogdep @runtestdep" );
10407
PrintPhonyRule ('exec_unit_tests',      "make_script @testprogdep @autoruntestdep" );
10408
PrintPhonyRule ('make_test',            "make_script @testprogdep" );
10409
PrintPhonyRule ('unmake_test',          "unmake_script", \@untestprogact );
10410
PrintPhonyRule ('preprocess_tests',     '$(AUTOUNITTESTS_PRE)' );
10411
PrintPhonyRule ('postprocess_tests',    '$(AUTOUNITTESTS_POST)' );
10412
PrintPhonyRule ('collate_test_results', '$(AUTOUNITTESTS_COLLATE)' );
261 dpurdie 10413
 
227 dpurdie 10414
#-------------------------------------------------------------------------------
10415
#   Package and Installation Summary
10416
#
10417
    MakeHeader ("Package and Installation Summary");
10418
    sub InstallTarget
10419
    {
10420
        my( $target, $hashp, $prereq, $fprereq ) = @_;
10421
        my( $element );
10422
 
5991 dpurdie 10423
        my $me = MakeEntry::New( *MAKEFILE, $target, '--Phony' );
10424
        $me->AddDependancy( $fprereq ) if ($fprereq);
227 dpurdie 10425
        foreach my $element ( sort keys %{$hashp} )
10426
        {
10427
            #
10428
            #   Skip placekeepers
10429
            #
10430
            next if ( $hashp->{$element}{'placekeeper'} );
10431
 
10432
            #
10433
            #   Prepend any prerequisites (once)
10434
            #
5991 dpurdie 10435
            $me->AddDependancy( $prereq ) if ( $prereq );
10436
            $prereq = 0;
227 dpurdie 10437
 
5991 dpurdie 10438
            $me->AddDependancyEscaped( $element );
227 dpurdie 10439
        }
5991 dpurdie 10440
        $me->Print();
10441
 
227 dpurdie 10442
    }
10443
 
10444
InstallTarget( "install_hdr",       \%INSTALL_HDRS );
10445
InstallTarget( "install_lib",       \%INSTALL_LIBS,  'make_mlib' );
261 dpurdie 10446
InstallTarget( "make_install_shlib",\%INSTALL_SHLIBS, '', "@shlibdep" );
227 dpurdie 10447
InstallTarget( "install_prog",      \%INSTALL_PROGS, 'make_script' );
10448
InstallTarget( "install_class",     \%INSTALL_CLSS );
10449
 
10450
InstallTarget( "package_files",     \%PACKAGE_FILES );
10451
InstallTarget( "package_hdr",       \%PACKAGE_HDRS );
10452
InstallTarget( "package_lib",       \%PACKAGE_LIBS );
10453
InstallTarget( "package_shlib",     \%PACKAGE_SHLIBS );
10454
InstallTarget( "package_prog",      \%PACKAGE_PROGS, 'make_script' );
10455
InstallTarget( "package_class",     \%PACKAGE_CLSS );
10456
 
10457
#-------------------------------------------------------------------------------
10458
#   Installations
10459
 
10460
MakeHeader ("Installations");
6387 dpurdie 10461
PackageRule    ( \&InstallCmd, \%INSTALL_HDRS  );
10462
PackageRule    ( \&InstallCmd, \%INSTALL_CLSS  );
10463
PackageRule    ( \&InstallCmd, \%INSTALL_LIBS  );
10464
PackageRule    ( \&InstallCmd, \%INSTALL_SHLIBS  );
10465
PackageRule    ( \&InstallCmd, \%INSTALL_PROGS  );
10466
PackageDirRule ('install_dirs',    \@INSTALL_DIRS);
227 dpurdie 10467
 
10468
#-------------------------------------------------------------------------------
10469
#   Packaging
10470
#
10471
MakeHeader ("Packaging");
6387 dpurdie 10472
PackageRule    ( \&PackageCmd, \%PACKAGE_FILES );
10473
PackageRule    ( \&PackageCmd, \%PACKAGE_HDRS );
10474
PackageRule    ( \&PackageCmd, \%PACKAGE_CLSS );
10475
PackageRule    ( \&PackageCmd, \%PACKAGE_LIBS );
10476
PackageRule    ( \&PackageCmd, \%PACKAGE_SHLIBS );
10477
PackageRule    ( \&PackageCmd, \%PACKAGE_PROGS );
10478
PackageDirRule ('package_dirs', \@PACKAGE_DIRS);
227 dpurdie 10479
 
10480
#-------------------------------------------------------------------------------
10481
#   Uninstall/unpackaging
10482
#
10483
MakeHeader ("Uninstall/unpackaging");
10484
 
6387 dpurdie 10485
UnpackageRule  ( 'uninstall_hdr',         \&UninstallCmd, \%INSTALL_HDRS );
10486
UnpackageRule  ( 'uninstall_lib',         \&UninstallCmd, \%INSTALL_LIBS );
10487
UnpackageRule  ( 'uninstall_shlib',       \&UninstallCmd, \%INSTALL_SHLIBS );
10488
UnpackageRule  ( 'uninstall_prog',        \&UninstallCmd, \%INSTALL_PROGS );
10489
UnpackageRule  ( 'uninstall_class',       \&UninstallCmd, \%INSTALL_CLSS );
10490
PackageDirRule ( 'uninstall_dirs',        \@INSTALL_DIRS);
227 dpurdie 10491
 
6387 dpurdie 10492
UnpackageRule  ( 'unpackage_files',       \&UnpackageCmd, \%PACKAGE_FILES );
10493
UnpackageRule  ( 'unpackage_hdr',         \&UnpackageCmd, \%PACKAGE_HDRS );
10494
UnpackageRule  ( 'unpackage_lib',         \&UnpackageCmd, \%PACKAGE_LIBS );
10495
UnpackageRule  ( 'unpackage_shlib',       \&UnpackageCmd, \%PACKAGE_SHLIBS );
10496
UnpackageRule  ( 'unpackage_prog',        \&UnpackageCmd, \%PACKAGE_PROGS );
10497
UnpackageRule  ( 'unpackage_class',       \&UnpackageCmd, \%PACKAGE_CLSS );
10498
PackageDirRule ( 'unpackage_dirs',        \@PACKAGE_DIRS);
227 dpurdie 10499
 
261 dpurdie 10500
#-------------------------------------------------------------------------------
267 dpurdie 10501
#   Distribution Sets
261 dpurdie 10502
#
267 dpurdie 10503
MakeHeader ("Distribution Sets");
10504
PackageSetRules();
10505
 
10506
#-------------------------------------------------------------------------------
10507
#
261 dpurdie 10508
#   Subdir deletion
10509
#   This is done AFTER the toolset functions have been invoked to create the
10510
#   build artifacts so that the toolsets can create directories too
10511
#
10512
#   Note: Toolset directories are deleted first
10513
#   Note: User Directories are deleted in the reverse order of creation
10514
#
2429 dpurdie 10515
#   Add them into the directory data structure
10516
#
10517
    foreach my $path ( @TOOLSETDIRS )
10518
    {
10519
        MkdirRule( $path, '', '--NoCreate' );
10520
    }
10521
 
10522
    foreach my $path ( @TOOLSETDIRTREES )
10523
    {
10524
        MkdirRule( $path, '', '--NoCreate' , '--RemoveAll');
10525
    }
10526
 
261 dpurdie 10527
    MakeHeader ("Subdir deletion");
10528
    RmdirRules();
10529
    MakeNewLine();
227 dpurdie 10530
 
261 dpurdie 10531
#--------- Toolset Rules -------------------------------------------------------
10532
    MakeHeader ("Toolset Rules");
10533
    MakePrintList ( \@TOOLSETRULES );
10534
 
10535
#--------- Maketags ------------------------------------------------------------
227 dpurdie 10536
 
10537
    Maketag( "make_init",           @INITS );
261 dpurdie 10538
    Maketag( "make_dir",            @mkdirdep );
10539
    Maketag( "generate",            @generatedep || @projectgendep || @USERGENERATED || ($ScmToolsetGenerate != 0) );
227 dpurdie 10540
    Maketag( "depend",              $ScmDependTags != 0 );
261 dpurdie 10541
    Maketag( "make_lib",            @libdep );
10542
    Maketag( "make_mlib",           @mlibdep );
10543
    Maketag( "make_install_shlib",  %INSTALL_SHLIBS || @shlibdep);
10544
    Maketag( "make_script",         @scriptdep );
10545
    Maketag( "make_prog",           @progdep || @projectdep );
10546
    Maketag( "make_test",           @testprogdep );
4996 dpurdie 10547
    Maketag( "exec_tests",          $TESTS_TO_RUN     || @TESTPROJECT_TO_URUN );
4728 dpurdie 10548
    Maketag( "exec_unit_tests",     $TESTS_TO_AUTORUN || @TESTPROJECT_TO_ARUN );
4778 dpurdie 10549
    Maketag( "process_tests",       @TOOLSET_UTF_PRE || @TOOLSET_UTF_POST || @TOOLSET_UTF_COLLATE);
227 dpurdie 10550
    Maketag( "install_hdr",         %INSTALL_HDRS );
10551
    Maketag( "install_class",       %INSTALL_CLSS );
10552
    Maketag( "install_lib",         %INSTALL_LIBS );
10553
    Maketag( "install_prog",        %INSTALL_PROGS );
6387 dpurdie 10554
    Maketag( "install_dirs",        @INSTALL_DIRS );
227 dpurdie 10555
    Maketag( "deploy",              %DEPLOYPACKAGE );
10556
    Maketag( "package",             %PACKAGE_FILES || %PACKAGE_HDRS || %PACKAGE_CLSS ||
10557
                                    %PACKAGE_LIBS || %PACKAGE_SHLIBS || %PACKAGE_PROGS );
10558
 
261 dpurdie 10559
    #
10560
    #   Display tags in the MAKEFILE
4778 dpurdie 10561
    #       Not used here - just for show
261 dpurdie 10562
    #
10563
    MakeHeader ("Maketags");
10564
    foreach my $tag ( sort keys %MakeTags )
10565
    {
4778 dpurdie 10566
        MakePadded( 3, "#   $tag:", '1', "\n");
261 dpurdie 10567
    }
10568
 
227 dpurdie 10569
#-------------------------------------------------------------------------------
10570
#   End of Makefile
10571
#
10572
    MakeHeader ("End of Makefile");
10573
    close( MAKEFILE );
10574
 
10575
#
10576
#   Save all platform information
10577
#   Done after the makefile is written as toolsets can extend the data
10578
#
10579
    WriteParsedConfig();
10580
 
10581
#
10582
#   Write out any accumulated DPACKAGE data
10583
#
10584
    JatsDPackage::DPackageSave();
10585
 
10586
    return 0;
10587
}
10588
 
10589
#-------------------------------------------------------------------------------
387 dpurdie 10590
# Function        : QuoteForMake
10591
#
10592
# Description     : Escape/Quote a pathname for make
10593
#                       Allow files with a $ in the name
10594
#                       Allow files with a space in the name
10595
#                       Allow files with a comma in the name
10596
#                       Allow for paths that have make-varible prefixes
6073 dpurdie 10597
#                           $(GBE_...) or ${GBE_...} or $(OBJDIR)
387 dpurdie 10598
#                           as these may be generated internally
5991 dpurdie 10599
#                       Allow for files with a colon in the name
10600
#                           Mode dependent
10601
#                               0 - No effect
10602
#                               T - \\\:
10603
#                               S = \:    
387 dpurdie 10604
#
399 dpurdie 10605
#                       Must also allow $(GBE_TYPE) in the remainder
10606
#
5991 dpurdie 10607
# Inputs          : uarg            - Arg to quote
10608
#                   mode            - Mode of operation
10609
#                                     T - Makefile target
10610
#                                     S - Makefile source
10611
#                                     0 - Neither
387 dpurdie 10612
#
10613
# Returns         : Quoted arg
10614
#
10615
 
5991 dpurdie 10616
sub QuoteForMake($;$)
387 dpurdie 10617
{
5991 dpurdie 10618
    my ($uarg, $mode) = @_;
10619
    $mode = '0' unless defined $mode;
387 dpurdie 10620
 
10621
    #
10622
    #   Split into two
10623
    #       $(xxx)/             - Makefile variables
10624
    #       Remainder           - Stuff to quote
10625
    #
10626
    $uarg =~ m~^((\$\(.*?\)/)*)(.*)~;
10627
    my $prefix = defined $1 ? $1 : '';
10628
    my $arg    = defined $3 ? $3 : '';
10629
 
6073 dpurdie 10630
    $arg =~ s~\$(?!\(GBE_[A-Z]+\)|{GBE_[A-Z]+}|\(OBJDIR\))~\$\$~g;       # $, not followed by (GBE_ or ${GBE_ or (OBJDIR)- is not $(GBE_ AND not $(OBJDIR)
387 dpurdie 10631
    $arg =~ s~ ~\\ ~g;
10632
    $arg =~ s~,~\$(comma)~g;
2764 dpurdie 10633
    $arg =~ s~%~\\%~g;
5999 dpurdie 10634
    $arg =~ s~:~\\\\\\:~g if ($mode eq 'T' &&  $::ScmHost eq "Unix");
10635
    $arg =~ s~:~\\:~g     if ($mode eq 'S' &&  $::ScmHost eq "Unix");
387 dpurdie 10636
    return $prefix . $arg;
10637
}
10638
 
10639
#-------------------------------------------------------------------------------
227 dpurdie 10640
# Function        : Maketag
10641
#
10642
# Description     : Create Makefile tags to speed up recursive makes
10643
#
10644
# Inputs          : tag_name
10645
#                   dep
10646
#
10647
# Returns         : 
10648
#
10649
sub Maketag
10650
{
10651
    my( $tag, $dep ) = @_;
10652
    $MakeTags{$tag} = 1 if ( defined($dep) && $dep );
10653
}
10654
 
10655
#-------------------------------------------------------------------------------
10656
#   Function to create and delete directories within the build system
10657
#
10658
#    To stop make regenerating directory dependent targets each time the
10659
#    directory content is modified, rule should only be dependent on a internally
10660
#    created alias file 'gbedir', which represents the time a dir was created not
10661
#    last modified.
10662
#
10663
#    Must use tags like GBE_BINDIR, GBE_LIBDIR and GBE_OBJDIR to ensure that the
10664
#    directories are created correctly.
10665
#
10666
my %MkdirRuleData;
10667
my @MkdirRuleOrder;
10668
my $MkdirRulePrinting = 0;
10669
my $MkdirRuleGbeFile = ( $::ScmHost eq "Unix" ) ? ".gbedir" : "_gbedir";
10670
 
10671
#-------------------------------------------------------------------------------
10672
# Function        : MkdirRule
10673
#
10674
# Description     : Create Rules and Recipes to create a directory at make-time
10675
#                   Mark the information for such that the directories will
10676
#                   be deleted in a 'clean'
10677
#
10678
#                   Can be called before we start writing the makefile
10679
#                   Such entries will be retained and dumped at a known time
10680
#
10681
# Inputs          : $subdir     - Symbolic name of the subdir $(OBJDIR)
10682
#                   $alias      - Optional script alias for the dir 'OBJDIR' --> GBE_OBJDIR
10683
#                   Options:
2429 dpurdie 10684
#                       --Path=path             Optional value of $subdir '$(GBE_PLATFORM)$(GBE_TYPE).OBJ'
10685
#                       --RemoveAll             Remove all files on clean
6177 dpurdie 10686
#                       --Extra=file[,file]     Additional files to remove
2429 dpurdie 10687
#                       --NoCreate              Do not Create the Directory, just delete it
227 dpurdie 10688
#
10689
# Returns         : Nothing
10690
#
10691
 
10692
sub MkdirRule
10693
{
10694
    my( $subdir, $alias, @opts ) = @_;
10695
 
10696
    #
10697
    #   Create data entry once
10698
    #
10699
    $alias =~ s~^GBE_~~ if $alias;
10700
    unless ( $MkdirRuleData{$subdir}  )
10701
    {
10702
        my %data;
10703
 
10704
        #
10705
        #   Parse options
10706
        #
10707
        foreach ( @opts )
10708
        {
10709
            if ( /^--Path=(.+)/ ) {
10710
                $data{path} = $1;
10711
            } elsif ( /^--RemoveAll/ ) {
10712
                $data{remove_all} = 1;
2429 dpurdie 10713
            } elsif ( /^--NoCreate/ ) {
10714
                $data{noCreate} = 1;
10715
            } elsif ( /^--Extra=(.+)/ ) {
10716
                @{$data{extraFiles}} = split(/,/, $1);
227 dpurdie 10717
            } else {
10718
                Error ("MkdirRule: Unknown option: $_");
10719
            }
10720
        }
10721
        $data{alias} = $alias if ( $alias );
10722
 
10723
        $MkdirRuleData{$subdir} = \%data;
10724
        push @MkdirRuleOrder, $subdir;
10725
    }
10726
 
10727
    #
10728
    #   Save or print
10729
    #
10730
    return unless ( $MkdirRulePrinting );
2429 dpurdie 10731
    return if ( $MkdirRuleData{$subdir}{noCreate} );
227 dpurdie 10732
 
10733
    #
10734
    #   Create a definition of the physical directory
10735
    #
10736
    my $path = $MkdirRuleData{$subdir}{path};
261 dpurdie 10737
    MakePadded (2, $alias, ":= $path\n") if ( $path && $alias );
227 dpurdie 10738
 
10739
    #   Create an alias to be used within rules
10740
    #   The defined aliase will be prefixed with 'GBE_'
10741
    #
261 dpurdie 10742
    MakePadded (2, "GBE_$alias", ":= $subdir/$MkdirRuleGbeFile\n") if ( $alias );
227 dpurdie 10743
 
10744
    #
10745
    #   Create a recipe to create the directory
10746
    #   This is not as simple as it sounds
10747
    #   The touch is required.
10748
    #       Had 'timestamp' issues on solaris'. The 'echo' did not appear
10749
    #       to be enough. Perhaps the output was not flushed
10750
    #
261 dpurdie 10751
    MakePadded (2, "$subdir", ": $subdir/$MkdirRuleGbeFile\n");
227 dpurdie 10752
    MakePrint
10753
        "$subdir/$MkdirRuleGbeFile:\n".
10754
        "\t\$(XX_PRE)if [ ! -d $subdir ]; then \$(mkdir) -p $subdir; fi; \\\n".
10755
        "\t\$(echo) '# DO NOT REMOVE.' > \$@; \\\n".
10756
        "\t\$(touch) \$@\n\n";
10757
}
10758
 
10759
#-------------------------------------------------------------------------------
10760
# Function        : RmdirRules
10761
#
2429 dpurdie 10762
# Description     : Create the body of a recipe to delete the directories that
227 dpurdie 10763
#                   have been created.
10764
#
2429 dpurdie 10765
#                   Use JatsFileUtil rather than shell script
10766
#                       Faster under windows (and others)
10767
#                       Solved long pathname issues
10768
#                       Simpler to use and control
227 dpurdie 10769
#
10770
# Inputs          : Uses $MkdirRuleData
10771
#
10772
# Returns         : Nothing.
10773
#                   Prints to the makefile
10774
#
10775
sub RmdirRules
10776
{
2429 dpurdie 10777
    MakePrint( ".PHONY:\tunmake_dir\n" );
10778
    MakePrint( "unmake_dir:\n" );
10779
 
227 dpurdie 10780
    #
10781
    #   Determine the list of directories to delete
2429 dpurdie 10782
    #   Sort such that subdirs are deleted first
227 dpurdie 10783
    #
2429 dpurdie 10784
    my $txt = 'Removing directories';
227 dpurdie 10785
    foreach my $subdir ( reverse sort keys %MkdirRuleData )
10786
    {
2429 dpurdie 10787
        my @args = $subdir;
10788
 
5816 dpurdie 10789
        push (@args, $MkdirRuleGbeFile, 'core', '*.bak', '*.tmp', '*.err', 'utf.*.rc')
2429 dpurdie 10790
            unless $MkdirRuleData{$subdir}{remove_all};
10791
 
10792
        push (@args, @{$MkdirRuleData{$subdir}{extraFiles}})
10793
            if ( $MkdirRuleData{$subdir}{extraFiles} );
10794
 
10795
        my $mode = $MkdirRuleData{$subdir}{remove_all} ? 'T0' : 'D0';
10796
 
10797
        MakePrint ("\t-\$(AA_PRE)JatsFileUtil ", QuoteArray( $mode, $txt, @args ), "\n");
10798
        $txt = '';
227 dpurdie 10799
    }
10800
}
10801
 
10802
#-------------------------------------------------------------------------------
10803
# Function        : CreateMkdirRules
10804
#
10805
# Description     : Create Rules to make dirs at runtime
10806
#                   This function is called to instantiate those entries
10807
#                   That have been requested before the makefile has has
10808
#                   started to be created.
10809
#
10810
#                   Once this function has been called all new MkdirRule calls
10811
#                   will result in the recipes being created in-line.
10812
#
10813
# Inputs          : Nothing
10814
#
10815
# Returns         : Even Less
10816
#
10817
#
10818
sub CreateMkdirRules
10819
{
10820
    $MkdirRulePrinting = 1;
10821
    foreach my $subdir ( @MkdirRuleOrder )
10822
    {
10823
        my $data = $MkdirRuleData{$subdir};
10824
        MkdirRule($subdir, $data->{alias}, $data->{path} );
10825
    }
10826
}
10827
 
10828
#-------------------------------------------------------------------------------
10829
# Function        : PackageRule
10830
#
10831
# Description     : Generate rules and recipes to "install" and "package" files
10832
#
10833
# Inputs          : codecmd     - A code reference to the actual installer routine
10834
#                   hashp       - A reference to a INSTALL or PACKAGE hash
10835
#
299 dpurdie 10836
#                   hashp is a reference to a hash
227 dpurdie 10837
#                       The key is the full path of the install target
10838
#                       The value is (another) hash that describes the install options
10839
#
10840
#                   Valid keys are:
10841
#                       src                 - Path of the source file [Mandatory]
10842
#                       dir                 - Target directory [Mandatory]
10843
#
10844
#                       defined             - Copy the file only if value is defined
4382 dpurdie 10845
#                       Exists              - Copy the file only if it exists
227 dpurdie 10846
#                       exe                 - Mark the file as executable
10847
#                       Mode                - File modes. Default is -w
10848
#                       placekeeper         - Marks SHARED library placekeepers
10849
#                       set                 - Distribution sets
10850
#                       type                - Copy the file in DEBUG or PROD mode
10851
#                                             Valid values are "D" or "P"         
10852
#                       version             - Shared library version information
5882 dpurdie 10853
#                       symlink             - File is a symlink
227 dpurdie 10854
#                       RemoveOnly          - Do not install the file. Entries are
10855
#                                             created to allow the removal of the file
4382 dpurdie 10856
#                       NoTarget            - Reserved - Implemented elsewhere
227 dpurdie 10857
#
10858
# Returns         :
10859
#
10860
sub PackageRule
10861
{
10862
    my ($codecmd, $hashp) = @_;
10863
 
10864
    foreach my $dest ( keys %{$hashp} )
10865
    {
10866
 
10867
        my $entry = $hashp->{$dest};
5991 dpurdie 10868
        my $destText = QuoteForMake($dest,'T');
227 dpurdie 10869
        #
10870
        #   Skip placekeepers
10871
        #
10872
        next if ( $entry->{'placekeeper'} );
10873
 
10874
        #
10875
        #   Some entries are not installed via this mechanism, but can be removed
10876
        #   if they exist. Mark these as PHONY to keep targets happy
10877
        #
10878
        if ( $entry->{'RemoveOnly'} )
10879
        {
5991 dpurdie 10880
            MakePrint ".PHONY:\t$destText\n";
10881
            MakePrint "$destText:\n\n";
227 dpurdie 10882
            next;
10883
        }
10884
 
10885
        my $fname = $entry->{'src'};
5991 dpurdie 10886
        my $fnameText = QuoteForMake($fname,'S');
227 dpurdie 10887
        my $fmode = $entry->{'Mode'};
10888
        $fmode .= "+x" if ( $entry->{'exe'}  );
5882 dpurdie 10889
        $fmode .= "+l" if ( $entry->{'symlink'}  );
227 dpurdie 10890
 
10891
        #
10892
        #   User conditionional
10893
        #   Mark both the source and the target as PHONY if the condition is not met
10894
        #   This will ensure that the target need not be built.
10895
        #
10896
        my $udef = $entry->{'defined'};
10897
        if ( $udef )
10898
        {
10899
            MakePrint "ifndef $udef \n";
5991 dpurdie 10900
            MakePrint ".PHONY:\t\t$destText\n";
10901
            MakePrint ".PHONY:\t\t$fnameText\n";
10902
            MakePrint "$destText:\n";
227 dpurdie 10903
            MakePrint "else\n"
10904
        }
10905
 
10906
        #
4382 dpurdie 10907
        #   File exists
10908
        #   Only package the file if it has been generated. ie: .exe.manifest
10909
        #
10910
        my $fexist = $entry->{'Exists'};
10911
        if ($fexist)
10912
        {
5991 dpurdie 10913
            MakePrint "ifeq (\"\$(wildcard $fnameText)\",\"\")\n";
10914
            MakePrint ".PHONY:\t\t$destText\n";
10915
            MakePrint "$destText:\n";
4382 dpurdie 10916
            MakePrint "else\n"
10917
        }
10918
 
10919
        #
227 dpurdie 10920
        #   Conditional installation for DEBUG/PRODUCTION
10921
        #
10922
        my $type = $entry->{'type'};
10923
        if ( $type )
10924
        {
10925
            if ( $type eq "D" ) {
10926
                MakePrint 'ifeq "$(DEBUG)" "0"'."\n";
10927
            } elsif ( $type eq "P" ) {
10928
                MakePrint 'ifneq "$(DEBUG)" "0"'."\n";
10929
            } else {
10930
                Error("INTERNAL: Unexpected packaging type: $type");
10931
            }
5991 dpurdie 10932
            MakePrint ".PHONY:\t\t$destText\n";
10933
            MakePrint "$destText:\n";
227 dpurdie 10934
            MakePrint "else\n"
10935
        }
10936
 
10937
        #
10938
        #   The body of the copy
10939
        #
5991 dpurdie 10940
        MakePadded( 4, $destText . ':' );
10941
        MakePrint "\t" . $fnameText . "\n";
2429 dpurdie 10942
        MakePrint $codecmd->( $dest, $fname, $fmode );
227 dpurdie 10943
        MakeNewLine();
10944
 
10945
        #
10946
        #   Unwind conditionals
10947
        #
10948
        MakePrint "endif\n" if ( $type );
4382 dpurdie 10949
        MakePrint "endif\n" if ( $fexist );
227 dpurdie 10950
        MakePrint "endif\n" if ( $udef );
10951
 
10952
        #
10953
        #   Distribution sets
10954
        #
10955
        my $dist = $entry->{'set'};
10956
        if ( $dist )
10957
        {
267 dpurdie 10958
            foreach my $set ( split( ',', $dist ) )
10959
            {
10960
                push @{$PACKAGE_SETS{$set}{LIST}}, $dest;
227 dpurdie 10961
            }
10962
            MakeNewLine();
10963
        }
10964
    }
10965
}
10966
 
10967
#-------------------------------------------------------------------------------
6387 dpurdie 10968
# Function        : PackageDirRule 
10969
#
10970
# Description     : Generate special rules for dynamic packaging/installation of directories 
10971
#
10972
# Inputs          : $mode        - package_dirs/unpackage_dirs/install_dirs/uninstall_dirs
10973
#                   $dataRef     - Ref to package/install list
10974
#                       
10975
#
10976
# Returns         : 
10977
#
10978
sub PackageDirRule
10979
{
10980
    my ($mode, $dataRef) = @_;
10981
    my $me = MakeEntry::New( *MAKEFILE, $mode , '--Phony' );
10982
 
10983
    my $modeText = 'packaging';
10984
    my $cmdText = 'PackageDir';
10985
    if ($mode =~ m~install~) {
10986
        $modeText = 'installing';
10987
        $cmdText = 'InstallDir';
10988
    }
10989
    my $cmd = 'copyDir'; 
10990
    if ($mode =~ m~^un~) {
10991
        $cmd = 'unCopyDir';
10992
        $modeText = 'un' . $modeText;
10993
        $cmdText = 'Un' . $cmdText;
10994
    }
10995
 
10996
 
10997
    foreach my $entry ( @{$dataRef}) {
10998
        $me->NewSection();
10999
 
11000
        #
11001
        #   Conditional installation for DEBUG/PRODUCTION
11002
        #
11003
        my $type = $entry->{'type'};
11004
        if ( $type )
11005
        {
11006
           if ( $type eq "D" ) {
11007
               $me->SectionIfNeq('$(DEBUG)','0');
11008
           } elsif ( $type eq "P" ) {
11009
               $me->SectionIfEq('$(DEBUG)','0');
11010
           } else {
11011
               Error("INTERNAL: Unexpected packaging type: $type");
11012
           }
11013
        }
11014
 
11015
        #
11016
        #   Quote the REs so that they can be passed to a command line
11017
        #       Replace $ with $$
11018
        #
11019
        my $QuoteRe = sub {
11020
            my ($arg) = @_;
11021
            $arg=~ s~\$~\$\$~g;
11022
            return $arg;
11023
            };
11024
 
11025
        #
11026
        #   The body of the copy
11027
        #   Create a command line for run-time command
11028
        #   
11029
        my @cmd;
11030
        push @cmd, '$(JatsRunTime)', $cmd, '--', '-$(VERBOSE_OPT)', '--Name='. $cmdText, '--';
11031
        push @cmd, '-mode=' . $modeText;
11032
        push @cmd, "'" . '-src=' . $entry->{dirTree} . "'";
11033
        push @cmd, "'" . '-dst=' . $entry->{dir} . "'";
11034
        push (@cmd, '-execute' ) if $entry->{exefile};
11035
        push (@cmd, '-noSymlink' ) if $entry->{noPreserveSymlink};
11036
        push (@cmd, '-noRecurse' ) if $entry->{noRecurse};
11037
        push (@cmd, '-stripBase' ) if $entry->{strip_base};
11038
        push (@cmd, "'" . '-exclude+=' . $QuoteRe->($_) . "'" ) foreach @{$entry->{exclude}};
11039
        push (@cmd, "'" . '-include+=' . $QuoteRe->($_) . "'" ) foreach @{$entry->{include}};
11040
        push (@cmd, "'" . '-excludeRe+=' . $QuoteRe->($_) . "'" ) foreach @{$entry->{excludeRe}};
11041
        push (@cmd, "'" . '-includeRe+=' . $QuoteRe->($_) . "'" ) foreach @{$entry->{includeRe}};
11042
 
11043
        $me->AddRecipe(join(' ', @cmd ) );
11044
    }
11045
    $me->Print();
11046
}
11047
 
11048
#-------------------------------------------------------------------------------
267 dpurdie 11049
# Function        : PackageSetRules
11050
#
11051
# Description     : Generate the packageset rules
11052
#                   These appear to be a now-defuct feature
11053
#
11054
#                   By default all packaged files are a part of package_setALL
11055
#
11056
# Inputs          : None
11057
#                   Takes data from %PACKAGE_SET
11058
#
11059
# Returns         : Nothing
11060
#
11061
sub PackageSetRules
11062
{
11063
    foreach my $set ( sort keys %PACKAGE_SETS )
11064
    {
11065
        my $me = MakeEntry::New( *MAKEFILE, "package_set$set", '--Phony' );
5991 dpurdie 11066
        $me->AddDependancyEscaped( @{$PACKAGE_SETS{$set}{LIST}} );
267 dpurdie 11067
        $me->Print();
11068
    }
11069
}
11070
 
11071
#-------------------------------------------------------------------------------
227 dpurdie 11072
# Function        : UnPackageRule
11073
#
11074
# Description     : Generate rules and recipes to "uninstall" and "unpackage" files
11075
#
11076
# Inputs          : target      - Name of the target
11077
#                   codecmd     - A code reference to the actual installer routine
11078
#                   hashp       - A reference to a INSTALL or PACKAGE hash
11079
#
11080
# Returns         :
11081
#
11082
sub UnpackageRule
11083
{
11084
    my ($target, $codecmd, $hashp) = @_;
11085
 
11086
    MakePrint ".PHONY:\t\t"."$target\n";
11087
    MakePrint "$target:\t";
11088
 
11089
    foreach my $dest ( sort keys %{$hashp} )
11090
    {
11091
 
11092
        my $entry = $hashp->{$dest};
11093
 
11094
        #
11095
        #   Skip placekeepers
11096
        #
11097
        next if ( $entry->{'placekeeper'} );
11098
 
11099
        MakePrint "\n" . $codecmd->($dest);
11100
    }
11101
    MakePrint "\n\n";
11102
}
11103
 
11104
 
11105
#
11106
#   Internal macro interface, see RULE.STD for definitions:
11107
#
11108
sub RmFilesCmd
11109
{
11110
    my ( $list ) = @_;
261 dpurdie 11111
    return "\$(call RmFiles,$list)";
227 dpurdie 11112
}
11113
 
11114
sub InstallCmd
11115
{
2429 dpurdie 11116
    my( $dest, $file, $fmode ) = @_;
227 dpurdie 11117
 
11118
    $fmode = "-w"                           # default, read-only
11119
        if ( !defined( $fmode ) || $fmode eq "" );
11120
 
5991 dpurdie 11121
    $dest = QuoteForMake($dest);
11122
    $file = QuoteForMake($file);
2429 dpurdie 11123
    return "\t\$(call InstallFile,$dest,$file,$fmode)";
227 dpurdie 11124
}
11125
 
11126
sub UninstallCmd
11127
{
11128
    my( $file ) = @_;
5991 dpurdie 11129
    $file = QuoteForMake($file);
227 dpurdie 11130
    return "\t\$(call UninstallFile,$file)";
11131
}
11132
 
11133
sub PackageCmd
11134
{
2429 dpurdie 11135
    my( $dest, $file, $fmode ) = @_;
227 dpurdie 11136
 
11137
    $fmode = "-w"                           # default, read-only
11138
        if ( !defined( $fmode ) || $fmode eq "" );
11139
 
5991 dpurdie 11140
    $dest = QuoteForMake($dest);
11141
    $file = QuoteForMake($file);
2429 dpurdie 11142
    return "\t\$(call PackageFile,$dest,$file,$fmode)";
227 dpurdie 11143
}
11144
 
11145
sub UnpackageCmd
11146
{
11147
    my( $file ) = @_;
5991 dpurdie 11148
    $file = QuoteForMake($file);
227 dpurdie 11149
    return "\t\$(call UnpackageFile,$file)";
11150
}
11151
 
11152
1;
11153