Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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