Subversion Repositories DevTools

Rev

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

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