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;
263 dpurdie 6191
        }
227 dpurdie 6192
 
6193
        if ( ! /^--(.*)/ )
6194
        {
6195
            $basename = StripDir( $name );
335 dpurdie 6196
            if ( !($srcfile = $SRCS{ $basename }) ) {
6197
                $srcfile = $name;
6198
            }
6199
 
227 dpurdie 6200
            if ( $full )
6201
            {
335 dpurdie 6202
                my $subdir = StripFileExt($srcfile);
6203
                $subdir = $1
6204
                    if ( $subdir =~ m~^$ProjectBase/(.*)~ );
6205
                $dir .= '/' . $subdir;
6206
                $dir =~ s~//~/~g;
6207
                $dir =~ s~/./~/~g;
6208
                $dir =~ s~/$~~g;
6209
                $name = $basename;
227 dpurdie 6210
            }
6211
 
6212
            $name = $basename
6213
                if ( $strip );
6214
 
341 dpurdie 6215
            if ( $strip_base )
6216
            {
6217
                $name = substr $name, $strip_base;
6218
                $name =~ s~^/~~;
6219
            }
6220
 
227 dpurdie 6221
            $dir =~ s~//~/~g;
6222
            $dir =~ s~/$~~;
6223
 
6224
            #
6225
            #   Sanity test the source filename
6226
            #   User may have misused an option
6227
            #
6228
            if ( ( $srcfile =~ m/=/ ) || ( $srcfile =~ m/^-/ ) || ( $srcfile =~ m~/-~ )  )
6229
            {
6230
               Warning ("PackageFile: Suspect source filename: $srcfile");
6231
            }
6232
 
6233
            Debug( "PackageFile( $dir/$name, " .
6234
                "src: $srcfile, dest: $dir, dist: $dist, exe: $exefile )" );
6235
 
6236
            $package_entry{'src'} = $srcfile;
6237
            $package_entry{'dir'} = StripFileExt( "$dir/$name" );
6238
            $package_entry{'set'} = $dist;
6239
            $package_entry{'exe'} = $exefile if $exefile;
6240
            $package_entry{'type'} = $type if ( $type );
6241
 
6242
            $PACKAGE_FILES{ "$dir/$name" } = {%package_entry};
6243
        }
6244
    }
6245
}
6246
 
6247
sub PackageHdr
6248
{
6249
    my( $platforms, @elements ) = @_;
335 dpurdie 6250
    my( $base, $dir, $full, $path, $dist, $strip );
227 dpurdie 6251
    my( $name, $basename, $len, $srcfile );
6252
 
6253
    Debug2( "PackageHdr($platforms, @elements)" );
6254
 
6255
    return if ( !$ScmPackage );                 # Packaging enabled ?
6256
    return if ( ! ActivePlatform($platforms) );
6257
 
6258
#.. Arguments
6259
#
6260
    $dist = "ALL";                                  # Default set (ALL)
6261
    $base = $PackageInfo{'Hdr'}{'PBase'};           # Base of target
6262
    $dir = $base . $PackageInfo{'Hdr'}{'Dir'};      # Installation path (default)
335 dpurdie 6263
    $full = 0;
227 dpurdie 6264
    $strip = 0;
6265
 
285 dpurdie 6266
    foreach ( @elements )
227 dpurdie 6267
    {
6268
        my $rv = __TargetDir($T_PKG, $base, $_, \$dir);
6269
        next if ( $rv == 1 );
6270
        return if ( $rv == 2 );
6271
 
6272
        if (/^--Full/) {                        # Using full (resolved) path
6273
            $full = 1;
6274
 
6275
        } elsif (/^--Set=(.*)/) {               # Distribution set
6276
            $dist = "$1";
6277
 
6278
        } elsif (/^--Package$/) {               # Package .. call by InstallHdr
6279
        } elsif (/^--Package=(.*)/) {
6280
            $dist = "$1";
6281
 
6282
        } elsif (/^--Strip$/) {                 # Strip path from source files
6283
            $strip = 1;
6284
 
6285
        } elsif (/^--(.*)/) {
6286
            Message( "PackageHdr: unknown option $_ -- ignored\n" );
6287
        }
6288
    }
6289
 
6290
#.. Files
6291
#
285 dpurdie 6292
    foreach ( @elements )
227 dpurdie 6293
    {
6294
        my %package_entry;
6295
        if ( ! /^--(.*)/ )
6296
        {
6297
            $name = $_;
6298
            $basename = StripDir( $name );
335 dpurdie 6299
            if ( !($srcfile = $SRCS{ $basename }) ) {
6300
                $srcfile = $name;
6301
            }
6302
 
227 dpurdie 6303
            if ( $full )
6304
            {
335 dpurdie 6305
                my $subdir = StripFileExt($srcfile);
6306
                $subdir = $1
6307
                    if ( $subdir =~ m~^$ProjectBase/(.*)~ );
6308
                $dir .= '/' . $subdir;
6309
                $dir =~ s~//~/~g;
6310
                $dir =~ s~/./~/~g;
6311
                $dir =~ s~/$~~g;
6312
                $name = $basename;
227 dpurdie 6313
            }
6314
 
6315
            $name = $basename
6316
                if ( $strip );
6317
 
6318
            Debug( "PackageHdr( $dir/$name, " .
6319
                "src: $srcfile, dest: $dir, dist: $dist )" );
6320
 
6321
            $package_entry{'src'} = $srcfile;
6322
            $package_entry{'dir'} = StripFileExt( "$dir/$name" );
6323
            $package_entry{'set'} = $dist;
6324
 
6325
            $PACKAGE_HDRS{ "$dir/$name" } = {%package_entry};
6326
        }
6327
    }
6328
}
6329
 
6330
 
6331
sub PackageLib
6332
{
6333
    my( $platforms, @elements ) = @_;
6334
    my( $base, $dir, $dist, $type );
6335
    my( $lib, $org_lib, %extras, $strip );
6336
 
6337
    Debug2( "PackageLib($platforms, @elements)" );
6338
 
6339
    return if ( !$ScmPackage );                 # Packaging enabled ?
6340
    return if ( ! ActivePlatform($platforms) );
6341
 
6342
#.. Arguments
6343
#
6344
    $dist = "ALL";                              # Default set (ALL)
6345
    $base = $PackageInfo{'Lib'}{'PBase'};       # Base of target
6346
    $dir = $base . $PackageInfo{'Lib'}{'Dir'};  # Installation path (default)
6347
    $type = "";
6348
 
285 dpurdie 6349
    foreach ( @elements )
227 dpurdie 6350
    {
6351
                                                # Standard targets
6352
        my $rv = __TargetDir($T_PKG, $base, $_, \$dir, \$type);
6353
        next if ( $rv == 1 );
6354
        return if ( $rv == 2 );
6355
 
6356
        if (/^--Set=(.*)/) {                    # Distribution set(s)
6357
            $dist = "$1";
6358
 
6359
        } elsif (/^--Package$/) {               # Package .. call by PackageLib
6360
        } elsif (/^--Package=(.*)/) {
6361
            $dist = "$1";
6362
 
6363
        } elsif (/^--Extras=(.*)/) {            # Extras=[none, .. ,all]
6364
            foreach my $elem ( split( ',', $1 ) )
6365
            {
6366
                Error ("PackageLib: Unknown Extras mode: $elem")
6367
                    unless ( grep m/$elem/, qw(none stub map lint debug all) );
6368
                $extras{$elem} = 1;
6369
            }
6370
            %extras = () if ( $extras{'all'} );
6371
 
6372
        } elsif (/^--Strip$/) {                 # Strip path from source files
6373
            $strip = 1;
6374
 
6375
        } elsif (/^--(.*)/) {
6376
            Message( "PackageLib: unknown option $_ -- ignored\n" );
6377
        }
6378
    }
6379
 
6380
#.. Files
6381
#
285 dpurdie 6382
    foreach ( @elements )
227 dpurdie 6383
    {
6384
        my %package_entry;
6385
        if ( ! /^--(.*)/ )
6386
        {
6387
            $_ = StripDir( $_ )
6388
                if ( $strip );
6389
 
6390
            $org_lib = $_;                      # Original name
6391
            if ( $ScmTargetHost eq "Unix" ) {
6392
                $lib = "lib$_";                 # Prefix "lib" ....
6393
                $lib =~ s/^liblib/lib/;         # @LIBS already has lib added
6394
            } else {
6395
                $lib = $_;
6396
            }
6397
 
289 dpurdie 6398
            if (  my $libp = $SHLIBS->Get($lib) )
227 dpurdie 6399
            {
6400
                Debug( "PackageLib( $dir/$lib\$(GBE_TYPE).$::so, " .
6401
                    "src: \$(LIBDIR)/$lib\$(GBE_TYPE).$::so, dest: $dir, dist: $dist, type: $type )" );
6402
 
6403
                #
6404
                #   Create a "placekeeper" entry within $PACKAGE_SHLIBS
6405
                #   The exact format of the name of the shared library is
6406
                #   toolset specific. Create an entry to allow the toolset
6407
                #   to extend the packaging information when the shared library
6408
                #   recipe is constructed.
6409
                #
6410
                #
289 dpurdie 6411
                my $ver = $libp->{ VERSION };
227 dpurdie 6412
                my $name = "$dir/$lib.$ver.PlaceKeeper";
6413
 
6414
                $package_entry{'placekeeper'} = 1;
6415
                $package_entry{'version'} = $ver;
6416
                $package_entry{'lib'} = $lib;
6417
                $package_entry{'dir'} = $dir;
6418
                $package_entry{'set'} = $dist;
6419
                $package_entry{'type'} = $type if ( $type );
6420
                $package_entry{'extras'} = {%extras} if ( scalar %extras );
289 dpurdie 6421
 
6422
                push @{$SHLIB_PKG{$lib}}, $name;
227 dpurdie 6423
                $PACKAGE_SHLIBS{$name} = {%package_entry};
6424
            }
6425
 
289 dpurdie 6426
            #
6427
            #   Clean up the package_entry
6428
            #   Insert common items
6429
            #
6430
            %package_entry = ();
6431
            $package_entry{'lib'} = $lib;
6432
            $package_entry{'dir'} = $dir;
6433
            $package_entry{'set'} = $dist;
6434
            $package_entry{'extras'} = {%extras} if ( scalar %extras );
6435
            $package_entry{'type'} = $type if ( $type );
6436
 
227 dpurdie 6437
            if ( my $libfile = $SRCS{$org_lib} )
6438
            {
6439
                #
6440
                #   Allow the user to package a sourced file as a library
6441
                #   But must be the un-massaged name of the file.
6442
                #
289 dpurdie 6443
                $package_entry{'dst'} = "$dir/$org_lib";
6444
                $package_entry{'src'} = $libfile;
6445
            }
6446
            elsif ( $LIBS->Get($lib) )
6447
            {
6448
                #
6449
                #   Package up a library known to the makefile
6450
                #
6451
                my $libp = $LIBS->Get($lib);
227 dpurdie 6452
 
289 dpurdie 6453
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
6454
                $package_entry{'src'}    = $libp->getPath();
227 dpurdie 6455
            }
289 dpurdie 6456
            elsif ( ! $SHLIBS->Get($lib) )
227 dpurdie 6457
            {
289 dpurdie 6458
                #
6459
                #   Not a known shared lib
6460
                #   Not a known static lib
6461
                #   Not a 'sourced' file
6462
                #   Assume the a static library has magically appeared
6463
                #   in the standard LIB directory. May have been placed there
6464
                #   by a 'rule'
6465
                #
6466
                my $libp = $LIBS->New($lib);
227 dpurdie 6467
 
289 dpurdie 6468
                $package_entry{'dst'}    = $dir . '/' . $libp->getFullName();
6469
                $package_entry{'src'}    = $libp->getPath();
6470
            }
227 dpurdie 6471
 
289 dpurdie 6472
            #
6473
            #   Add entry to various lists if required
6474
            #
6475
            PackageLib_AddEntry ('PackageLib', \%LIB_PKG, \%PACKAGE_LIBS, \%package_entry )
6476
                if ( exists $package_entry{'dst'} );
227 dpurdie 6477
        }
6478
    }
6479
}
6480
 
289 dpurdie 6481
#-------------------------------------------------------------------------------
6482
# Function        : PackageLib_AddEntry
6483
#
6484
# Description     : Helper function to add a package entry
6485
#                   to the lists
6486
#
6487
# Inputs          : $directive          - Directive name
6488
#                   $pList              - Ref to array list to maintain
6489
#                   $pHash              - Ref to hash to maintain
6490
#                   $pData              - Packaging Data
6491
#                                         Must Take a copy.
6492
#
6493
# Returns         : 
6494
#
227 dpurdie 6495
 
289 dpurdie 6496
sub PackageLib_AddEntry
6497
{
6498
    my ($directive, $pList, $pHash, $pData) = @_;
6499
 
6500
    my $lib = delete $pData->{'lib'};
6501
    my $dst = delete $pData->{'dst'};
6502
 
6503
    Error ("INTERNAL PackageLib_AddEntry: lib or dst not defined")
6504
        unless ( $lib && $dst );
6505
 
6506
    Debug( "$directive( ",$dst,
6507
            ", src: " ,$pData->{'src'},
6508
            ", dest: ",$pData->{'dir'},
6509
            ", dist: ",$pData->{'set'},
6510
            ", type: ",$pData->{'type'} || '',
6511
            " )" );
6512
 
6513
    push @{$pList->{$lib }}, $dst;
6514
    $pHash->{$dst } = {%$pData};
6515
}
6516
 
6517
 
227 dpurdie 6518
sub PackageProg
6519
{
6520
    my( $platforms, @elements ) = @_;
6521
    my( $base, $dir, $dist, $type );
6522
    my( $prog, %extras, $strip );
6523
 
6524
    Debug2( "PackageProg($platforms, @elements)" );
6525
 
6526
    return if ( !$ScmPackage );                 # Packaging enabled ?
6527
    return if ( ! ActivePlatform($platforms) );
6528
 
6529
#.. Arguments
6530
#
6531
    $dist = "ALL";                              # Default set (ALL)
6532
    $base = $PackageInfo{'Prog'}{'PBase'};       # Base of target
6533
    $dir = $base . $PackageInfo{'Prog'}{'Dir'};  # Installation path (default)
6534
    $type = "";
6535
 
285 dpurdie 6536
    foreach ( @elements )
227 dpurdie 6537
    {
6538
                                                # Standard targets
6539
        my $rv = __TargetDir($T_PKG|$T_TYPE, $base, $_, \$dir, \$type);
6540
        next if ( $rv == 1 );
6541
        return if ( $rv == 2 );
6542
 
6543
        if (/^--Set=(.*)/) {                    # Distribution set(s)
6544
            $dist = "$1";
6545
 
6546
        } elsif (/^--Package$/) {               # Package .. call by PackageLib
6547
        } elsif (/^--Package=(.*)/) {
6548
            $dist = "$1";
6549
 
6550
        } elsif (/^--Tool(([=])(.*))?$/) {      # Allow Tool and Tool=xxx specfic target
6551
            my $path = ( defined( $3) ) ? "/$3" : "";
261 dpurdie 6552
            $dir = "\$(PKGDIR)$path/\$(GBE_HOSTMACH)";
227 dpurdie 6553
 
6554
        } elsif (/^--Extras=(.*)/) {            # Extras=[none, .. ,all]
6555
            foreach my $elem ( split( ',', $1 ) )
6556
            {
6557
                Error ("PackageLib: Unknown Extras mode: $elem")
6558
                    unless ( grep m/$elem/, qw(none stub map lint debug all) );
6559
                $extras{$elem} = 1;
6560
            }
6561
            %extras = () if ( $extras{'all'} );
6562
 
6563
        } elsif (/^--Strip$/) {                 # Strip path from source files
6564
            $strip = 1;
6565
 
6566
        } elsif (/^--(.*)/) {
6567
            Message( "PackageProg: unknown option $_ -- ignored\n" );
6568
        }
6569
    }
6570
 
6571
#.. Files
6572
#
285 dpurdie 6573
    foreach ( @elements )
227 dpurdie 6574
    {
6575
        my %package_entry;
6576
        if ( m~descpkg~ ) {
6577
            PackageFile($platforms, @elements);
6578
 
6579
        } elsif ( ! /^--(.*)/ ) {
6580
            $_ = StripDir( $_ )
6581
                if ( $strip );
6582
 
6583
            my $ext = "";
6584
            $prog = $_;
6585
 
6586
            #
6587
            #   If the named target is a program then append the correct
6588
            #   extension. Otherwise assume that the target is either a script
6589
            #   or a some other file - and don't append an extension
6590
            #
6591
            #   A program may not have any object files, only libraries
6592
            #
6593
            $ext = $::exe
289 dpurdie 6594
                if ( $PROGS->Get($prog) );
227 dpurdie 6595
 
6596
            #
6597
            #   A "file" that is specified with a "Src" directive may be
6598
            #   installed as though it were a program
6599
            #
6600
            my $progfile;
6601
            $progfile = "\$(BINDIR)/$prog$ext"
6602
                unless ( $progfile = $SRCS{$prog} );
6603
 
6604
            Debug( "PackageProg( $dir/$prog$ext, " .
6605
                 "src: $progfile, dest: $dir, dist: $dist, type: $type )" );
6606
 
6607
            my $target = "$dir/$prog$ext";
6608
            push @{$PROG_PKG{$prog}}, $target;
6609
 
6610
            $package_entry{'src'}   = $progfile;
6611
            $package_entry{'dir'}   = $dir;
6612
            $package_entry{'set'}   = $dist;
6613
            $package_entry{'extras'}= {%extras} if ( scalar %extras );
6614
            $package_entry{'type'}  = $type if ( $type );
6615
 
6616
            $PACKAGE_PROGS{$target} = {%package_entry};
6617
        }
6618
    }
6619
}
6620
 
6621
 
6622
sub PackageJar
6623
{
6624
    my( $platforms, @elements ) = @_;
6625
    my( $base, $dir, $dist, $type );
6626
    my( $jar );
6627
 
6628
    Debug2( "PackageJar($platforms, @elements)" );
6629
 
6630
    return if ( !$ScmPackage );                 # Packaging enabled ?
6631
    return if ( ! ActivePlatform($platforms) );
6632
 
6633
#.. Arguments
6634
#
6635
    $dist = "ALL";                              # Default set (ALL)
6636
    $base = $PackageInfo{'Jar'}{'PBase'};       # Base of target
6637
    $dir = $base . $PackageInfo{'Jar'}{'Dir'};  # Installation path (default)
6638
    $type = "";
6639
 
285 dpurdie 6640
    foreach ( @elements )
227 dpurdie 6641
    {
6642
                                                # Standard targets
6643
        my $rv = __TargetDir($T_PKG, $base, $_, \$dir, \$type);
6644
        next if ( $rv == 1 );
6645
        return if ( $rv == 2 );
6646
 
6647
        if (/^--Set=(.*)/) {                    # Distribution set(s)
6648
            $dist = "$1";
6649
 
6650
        } elsif (/^--Package$/) {               # Package .. call by InstallJar
6651
        } elsif (/^--Package=(.*)/) {
6652
            $dist = "$1";
6653
 
6654
        } elsif (/^--(.*)/) {
6655
            Message( "PackageJar: unknown option $_ -- ignored\n" );
6656
        }
6657
    }
6658
 
6659
#.. Files
6660
#
285 dpurdie 6661
    foreach ( @elements )
227 dpurdie 6662
    {
6663
        my %package_entry;
6664
        if ( ! /^--(.*)/ )
6665
        {
6666
            $jar = $_;
6667
            my $src;
6668
            my $dest;
6669
 
6670
            if ( $JAR_FILES{$jar} )
6671
            {
6672
                $src = $JAR_FILES{$jar};
6673
                $dest = $jar;
6674
            }
6675
            else
6676
            {
6677
                $src = "\$(CLSDIR)/$jar\$(GBE_TYPE).jar";
6678
                $dest = "$jar\$(GBE_TYPE).jar";
6679
            }
6680
 
6681
 
6682
            Debug( "PackageJar( $dir/$dest, " .
6683
                "src: $src, dest: $dir, dist: $dist, type: $type )" );
6684
 
6685
            $package_entry{'src'} = $src;;
6686
            $package_entry{'dir'} = $dir;
6687
            $package_entry{'set'} = $dist;
6688
            $package_entry{'type'} = $type if ( $type );
6689
 
6690
            $PACKAGE_CLSS{ "$dir/$dest" } = {%package_entry};
6691
 
6692
        }
6693
    }
6694
}
6695
 
6696
#-------------------------------------------------------------------------------
6697
# Function        : PackageProgAddFiles         - Add files to a PackageProg
6698
#                   PackageLibAddFiles          - Add files to a PackageLib
6699
#                   PackageShlibAddFiles        - Add files to a PackageLib (shared lib)
6700
#                   PackageShlibAddLibFiles     - Add files to a PackageLib (shared lib)
6701
#                                                 Add static library files
6702
#
6703
# Description     : Add files to a Program package or installation
6704
#                   For use by Tool sets to allow additional files to be
6705
#                   packaged with a program.
6706
#
6707
#                   The files are only added if the named program is being
6708
#                   packaged and/or installed.
6709
#
6710
#
6711
# Inputs          : prog        - program identifier
6712
#                   file        - A file to be add
6713
#                   args        - Additional packageing arguments
6714
#
6715
# Returns         : Nothing
6716
#
6717
 
6718
sub PackageProgAddFiles
6719
{
6720
    Debug("PackageProgAddFiles");
6721
 
6722
    PackageAddFiles ( \%PACKAGE_PROGS, \%PACKAGE_PROGS, \%PROG_PKG, @_);
6723
    PackageAddFiles ( \%INSTALL_PROGS, \%INSTALL_PROGS, \%PROG_INS, @_);
6724
}
6725
 
6726
sub PackageLibAddFiles
6727
{
6728
    Debug("PackageLibAddFiles");
6729
 
6730
    PackageAddFiles ( \%PACKAGE_LIBS, \%PACKAGE_LIBS, \%LIB_PKG, @_ );
6731
    PackageAddFiles ( \%INSTALL_LIBS, \%INSTALL_LIBS, \%LIB_INS, @_ );
6732
}
6733
 
6734
sub PackageShlibAddFiles
6735
{
6736
    my ($prog, $file, @args) = @_;
6737
    Debug("PackageShlibAddFiles");
6738
 
6739
    PackageAddFiles ( \%INSTALL_SHLIBS, \%INSTALL_SHLIBS, \%SHLIB_INS, @_ );
6740
    PackageAddFiles ( \%PACKAGE_SHLIBS, \%PACKAGE_SHLIBS, \%SHLIB_PKG, @_ );
6741
 
6742
    #
6743
    #   These files become the target of the "make_install_shlib" operation unless:
6744
    #       Conditionally packaged files are not always created
6745
    #       RemoveOnly files are not always generated
6746
    #
6747
    my $no_add;
6748
    foreach ( @args )
6749
    {
6750
        if ( m/^defined=/ or m/^RemoveOnly=/ )
6751
        {
6752
            $no_add = 1;
6753
            last;
6754
        }
6755
    }
6756
 
6757
    push (@SHLIB_TARGETS, $file ) unless $no_add;
6758
}
6759
 
6760
sub PackageShlibAddLibFiles
6761
{
6762
    Debug("PackageShlibAddLibFiles");
6763
 
6764
    PackageAddFiles ( \%PACKAGE_SHLIBS, \%PACKAGE_LIBS, \%SHLIB_PKG, @_ , 'Class=lib');
6765
    PackageAddFiles ( \%INSTALL_SHLIBS, \%INSTALL_LIBS, \%SHLIB_INS, @_ , 'Class=lib');
6766
}
6767
 
6768
#-------------------------------------------------------------------------------
6769
# Function        : PackageAddFiles
6770
#
6771
# Description     : Internal function to add files to the data structures that
6772
#                   describe a package or installation
6773
#
6774
#                   Use this function to package or install additional files with
6775
#                   the Progs and Libs
6776
#
6777
#                   ie: Add a LIB file to be packaged with a Shared Library
6778
#                   ie: Add a MAP file to be packaged with a program
6779
#
6780
# Inputs          : ref_spkg  - Reference to the hash that contains the package data
6781
#                   ref_dpkg  - Reference to the target package/install hash
6782
#                               Normally the same as ref_dpkg, but does allow
289 dpurdie 6783
#                               a static library to be added to a dynamic library
227 dpurdie 6784
#                               package.
6785
#                   ref_list  - Reference to a hash that may contain package keys to process
6786
#                   prog      - Key for index to above
6787
#                   file      - A file to be added
6788
#                   args      - Additional packaging arguments
6789
#
6790
# Returns         :
6791
#
6792
sub PackageAddFiles
6793
{
6794
    my ($ref_spkg, $ref_dpkg, $ref_list, $prog, $file, @args ) = @_;
6795
 
6796
    #
6797
    #   Process entry
6798
    #   The files may need to be added to multiple packages
6799
    #
6800
    Debug("PackageAddFiles: $file");
6801
 
6802
    return unless ( $ref_list->{$prog} );
6803
 
6804
    #
6805
    #   Parse arguments and extract the "Class=xxx" argument. This may be used
6806
    #   to limit the extra files piggybacked with the base file
6807
    #   All files without a class will be treated as base files
6808
    #
6809
    my $class;
6810
    foreach ( @args )
6811
    {
6812
        next unless ( m~^Class=(.*)$~ );
6813
        $class = $1 unless ( $1 eq 'none' );
6814
    }
6815
    Debug("PackageAddFiles: Class: ", $class || 'Default=None');
6816
 
6817
    foreach my $entry_key ( @{$ref_list->{$prog}} )
6818
    {
6819
        Debug("PackageAddFiles: Entry found: $entry_key");
6820
 
6821
        #
6822
        #   Copy of the template entry
6823
        #
6824
        my %package_entry = %{$ref_spkg->{$entry_key}};
6825
        Error ("INTERNAL: Expected entry in PACKAGE_ hash not found: $entry_key" )
6826
            unless ( %package_entry );
6827
 
6828
        #
6829
        #   Do not add the file if the user has limited the extra files added
6830
        #   to the packaging list and the current file is not in the class list
6831
        #
6832
        if ( $class && $package_entry{'extras'} )
6833
        {
6834
            next unless ( $package_entry{'extras'}{$class} );
6835
        }
6836
 
6837
        #
6838
        #   Create new entries for the file
6839
        #
6840
        $package_entry{'src'} = $file;
6841
        foreach ( @args )
6842
        {
6843
            m~^(.*)=(.*)$~;
6844
            $package_entry{$1} = $2;
6845
        }
6846
 
6847
        #
6848
        #   Clean out useless fields
6849
        #   Must remove the placekeeper marker to allow the entry to be visible
6850
        #
6851
        delete $package_entry{'placekeeper'};
6852
        delete $package_entry{'version'};
6853
        delete $package_entry{'lib'};
261 dpurdie 6854
#       delete $package_entry{'extras'};                   # Keep these
227 dpurdie 6855
        delete $package_entry{'Class'};
6856
 
6857
        #
6858
        #   Add the entry
6859
        #
6860
        #   Under some conditions is it possible to attempt to add the same named
6861
        #   file. This will result in a circular dependancy in the makefile
6862
        #
6863
        #   The condition is when merged libaries with PDBs (WINCE+WIN32) are merged
261 dpurdie 6864
        #   and the source for the merge is the "local directory.
227 dpurdie 6865
        #
6866
        #
6867
        my $dst = $package_entry{'dir'} ;
6868
        ( my $dfile = $file) =~ s~.*/~~;
6869
        Debug( "    added $dst/$dfile = $file" );
6870
 
6871
        $ref_dpkg->{"$dst/$dfile"} = {%package_entry}
6872
            unless ( "$dst/$dfile" eq "$file" );
6873
    }
6874
}
6875
 
6876
#-------------------------------------------------------------------------------
6877
# Function        : PackageProgRemoveFiles
6878
#
6879
# Description     : Flag a Packaged program to be not packaged
6880
#                   This mechanism is used to remove a program from packageing
6881
#                   under conditions where the toolset has generated a different
6882
#                   program.
6883
#
6884
#                   The entry is flagged as a placeholder
6885
#
6886
# Inputs          : prog        - Program to process
6887
#
6888
# Returns         : Nothing
6889
#
6890
sub PackageProgRemoveFiles
6891
{
6892
    my ($prog) = @_;
6893
    Verbose ("PackageProgRemoveFiles: $prog" );
6894
    return unless (exists($PROG_PKG{$prog}));
6895
 
6896
    #
6897
    #   Must lookup the TAG to locate the  required entry
6898
    #
6899
    my $tag = $PROG_PKG{$prog};
6900
    foreach my $entry ( @$tag )
6901
    {
6902
        Verbose("Do not package: $entry");
6903
        if ( exists $PACKAGE_PROGS{$entry} )
6904
        {
6905
            $PACKAGE_PROGS{$entry}{placekeeper} = 'ProgRemoved';
6906
        }
6907
    }
6908
}
6909
 
6910
#-------------------------------------------------------------------------------
6911
# Function        : DPackageLibrary
6912
#
6913
# Description     : Collect information to allow the generation of a DPACKAGE
299 dpurdie 6914
#                   file. This directive allows the generation of "Library"
227 dpurdie 6915
#                   directives within the final DPACKAGE
6916
#
6917
#                   This directive does generate the DPACKAGE file.
6918
#
6919
# Inputs          : platform    - This does not need to be an active platform
6920
#                                 it is simply passed to the DPACKAGE builder
6921
#
6922
#                   using       - The "using" target
6923
#
6924
#                   ...         - Arguments for the Library directive
6925
#
6926
# Returns         :
6927
#
6928
sub DPackageLibrary
6929
{
6930
    JatsDPackage::DPackageAdd ( @_ );
299 dpurdie 6931
    $DPackageDirective = 1;
227 dpurdie 6932
}
6933
 
6934
#-------------------------------------------------------------------------------
6935
# Function        : SetProjectBase
6936
#
6937
# Description     : Allows the user to modify the build's concept of the Base
6938
#                   of the build. By default the base is the same directory as
6939
#                   the build.pl file, but in some contorted environments it
6940
#                   is a great deal simpler to specify a differnt base.
6941
#
6942
#                   The use may use the variable $ProjectBase as a path
6943
#                   specifier to locate files and directories
6944
#
6945
#                   Both absolute and relative paths are supported
6946
#                   If the initial value of $ProjectBase is relative then
6947
#                   it will be maintained as a relative path.
6948
#
6949
# Inputs          : elements        path to base
6950
#                                   These may be:
6951
#                                       --Up=xx
6952
#                                       name
6953
#
6954
# Returns         : Nothing
6955
#
6956
 
6957
#
6958
#   Allow the user to modify the project base variable
6959
#
6960
sub SetProjectBase
6961
{
6962
    my $rip = 0;
6963
    my $path = "";
6964
    my $is_relative;
6965
 
6966
    Debug("ProjectBase Initial: $ProjectBase, @_");
6967
 
6968
    #
6969
    #   Ensure that the ProjectBase is in a "nice" form
6970
    #   1) No /./ bits
6971
    #   2) No trailing /
6972
    #   3) Not equal to .
6973
    #   4) No training /.
6974
    #   5) No //
6975
    #
6976
    $ProjectBase =~ s~/\./~/~g;
6977
    $ProjectBase =~ s~/$~~g;
6978
    $ProjectBase =~ s~^\.$~~g;
6979
    $ProjectBase =~ s~/\.$~~g;
6980
    $ProjectBase =~ s~//$~/~g;
6981
 
6982
    #
6983
    #   ProjectBase may be absolute or relative
6984
    #   Determine this before we mess with it
6985
    #
6986
    $is_relative = ($ProjectBase !~ m~^/~);
6987
 
6988
    #
6989
    #   Process each argument
6990
    #
6991
    foreach ( @_ )
6992
    {
6993
        if ( /^--Up=([0-9]*)/ ) {
6994
            $rip = $1;
6995
        } elsif ( /^--/ ) {
6996
            Warning( "SetProjectBase - unknown option \"$_\" - ignored" );
6997
        } else {
6998
            $path = $_;
6999
        }
7000
    }
7001
 
7002
    #
7003
    #   Process the UP requests
7004
    #   If the tail directory is a ".." then up is done by adding another ".."
7005
    #   If the tail directory is not a "..", then up is done by removing it
7006
    #
7007
    #   If we go past the start of the path then simply add ".."
7008
    #
7009
    while ( $rip-- > 0 )
7010
    {
7011
        Debug2("ProjectBase: $ProjectBase, Up: $rip, IsRel: $is_relative");
7012
 
7013
        #
7014
        #   If ending in a /.. or is exactly equal to ..
7015
        #   Then its a dot-dot and the way to go UP is to append another ..
7016
        #
7017
        if ( $ProjectBase =~ m~(/\.\.$)|(^\.\.$)~ )
7018
        {
7019
            $ProjectBase .= '/..';
7020
        }
7021
        else
7022
        {
7023
            #
7024
            #   Not a dot-dot ending
7025
            #   Attempt to remove the last directory of the form
7026
            #       /xxxxx
7027
            #   Where the leading / is optional
7028
            #   Note: Must have at least one character in the dirname
7029
            #         This prevents leading / from matching - which is needed
7030
            #
7031
            unless ($ProjectBase =~ s~/?[^/]+$~~)
7032
            {
7033
                #
7034
                #   Removal failed
7035
                #   If a relative path then we can keep on going up,
7036
                #   otherwise we are dead.
7037
                #
7038
                Error ("ProjectBase outside project") unless ($is_relative);
7039
                $ProjectBase = '..';
7040
            }
7041
 
7042
            #
7043
            #   Ensure that the leading / in an absolute path is not deleted
7044
            #
7045
            $ProjectBase = '/'
7046
                unless ( $is_relative || $ProjectBase );
7047
        }
7048
    }
7049
 
7050
    #
7051
    #   Append the user path
7052
    #
7053
    $ProjectBase .= '/' . $path if ( $path );
7054
    $ProjectBase = '.' unless ( $ProjectBase );
7055
    Debug("ProjectBase set to : $ProjectBase");
7056
 
7057
    #
7058
    #   Once upon a time I tried to convert paths that contained spaces into
7059
    #   short (mangled) names. This was not sucessful because:
7060
    #       1) Clearcase dynamic views do not support name mangling
7061
    #       2) Samba file system does not appear to support name mangling
7062
    #
7063
    #   Spaces in paths are not good for MAKE
7064
    #   Now I simple generate a message
7065
    #
7066
    Warning( "ProjectBase contains a space: $ProjectBase")
7067
        if ( $ProjectBase =~ m/ / );
7068
 
7069
    #
7070
    #   Sanity check
7071
    #   Absolute paths can be checked easily
7072
    #   Checking of relative paths does not appear to work
7073
    #   When I tested it chdir, opendir and stat would limit themselves
7074
    #   and drop into the root directory ( under windows )
7075
    #
7076
    #   Solution: Check the path does not extend beyond the file tree
7077
    #
7078
    my $distance = 1;
7079
    my $tpath = $ProjectBase;
7080
 
7081
    if ( $is_relative && $tpath ne '.' )
7082
    {
7083
        #
7084
        #   Build up the complete pathname by merging it with the
7085
        #   current directory. Then clean it up.
7086
        #
7087
        $tpath = $::Cwd . '/' . $ProjectBase;
7088
 
7089
        #
7090
        #   Scan the list of diretories and count the distance from the root
7091
        #   This should not be greater than zero for sanity
7092
        #   Note: Get an empty elemement from the split due to
7093
        #         the leading / of the ABS path
7094
        #
7095
        $distance = 0;
7096
        foreach (  split ('/', $tpath) )
7097
        {
7098
            if ( m~\.\.~ )
7099
            {
7100
                $distance--;
7101
            }
7102
            else
7103
            {
7104
                $distance++;
7105
            }
7106
        }
7107
    }
7108
 
7109
    #
7110
    #   Warn if not a valid directory
7111
    #
7112
    Warning( "ProjectBase is not a directory: $ProjectBase")
7113
        if ( $distance <= 0 || !  -d $tpath  );
7114
 
7115
    #
7116
    #   $ProjectBase will always be a valid directory, but if its the top
7117
    #   directory (/) and it is added to a path we will get //path
7118
    #   This is not good, so // will be removed later in the AddIncDir and
7119
    #   AddSrcDir commands where $ProjectBase is really used.
7120
    #
7121
    #   Alternatively we could set $ProjectBase to an empty string, but then
7122
    #   this may be confused with an empty relative directory
7123
    #
7124
    Debug("ProjectBase Final  : $ProjectBase");
7125
}
7126
 
7127
#-------------------------------------------------------------------------------
7128
# Function        : DeployPackage
7129
#
7130
# Description     : Generate a deployed package
7131
#                   This is a gateway to a different packaging system
7132
#
7133
#                  DeployPackage and PackageXxxxx directives are mutually
7134
#                  exclusive. Only one person can play in the package area.
7135
#
7136
# Inputs          : Platform Specifier
7137
#                   Package Name    (Optional)
7138
#                   Options
7139
#                       --Name : Base name of the package. The default is taken
7140
#                                from the build.pl file
7141
#                       --Dir  : Package directory
7142
#                                The default is based on the package name
7143
#
7144
# Returns         :
7145
#
7146
sub DeployPackage
7147
{
7148
    my( $platforms, @elements ) = @_;
7149
    my $dir;
7150
    my $name;
7151
 
267 dpurdie 7152
    #
7153
    #   Flag that this build creates a deployable package, even if its not
7154
    #   active on this platform.
7155
    #
7156
    $DEPLOYPACKAGE = 1;
7157
 
7158
 
227 dpurdie 7159
    Debug2( "DeployPackage($platforms, @elements)" );
7160
    return if ( ! ActivePlatform($platforms) );
7161
 
7162
    #
7163
    #   Only allow one use of this directive
7164
    #
7165
    Error("DeployPackage can only be used once" ) if ( %DEPLOYPACKAGE );
267 dpurdie 7166
    $DEPLOYPACKAGE = 2;
227 dpurdie 7167
 
7168
    #
7169
    #   Ensure that the deployment file is available
7170
    #
7171
    my $command_file = $ScmDeploymentPatch ? "deploypatch.pl" : "deployfile.pl";
7172
    Error("DeployPackage: $command_file not found") unless (-f "./$command_file");
7173
    #
7174
    #   Collect arguments
7175
    #
7176
    foreach (@elements )
7177
    {
7178
        if ( m/^--Dir=(.*)/ ) {
7179
            Error ("DeployPackage: Package directory defined multiple times") if $dir;
7180
            $dir = $1;
7181
 
7182
        } elsif ( m/^--Name=(.*)/ ) {
7183
            Error ("DeployPackage: Package name defined multiple times") if $name;
7184
            $name = $1;
7185
 
7186
        } elsif ( m/^--/ ) {
7187
            Warning( "DeployPackage: Unknown option ignored: $_");
7188
 
7189
        } else {
7190
            Error ("DeployPackage: Package name defined multiple times") if $name;
7191
            $name = $_;
7192
 
7193
        }
7194
    }
7195
 
7196
    $name = $::ScmBuildPackage unless ( $name );
7197
 
7198
    #
7199
    #   Save the deployment data
7200
    #
7201
    $dir = lc($name) unless ( $dir );
7202
    $DEPLOYPACKAGE{'name'} = $name;
7203
    $DEPLOYPACKAGE{'dir'} = $dir;
7204
    $DEPLOYPACKAGE{'cmdfile'} = $command_file;
7205
 
7206
    #
7207
    #   Flag that toolset tests should be supressed
7208
    #   The Deploy world does not really use the full makefiles and if the
7209
    #   compilers are not installed will not be able to create deployment
7210
    #   packages
7211
    #
7212
    $ScmNoToolsTest = 1;
7213
}
7214
 
7215
 
7216
###############################################################################
7217
###############################################################################
7218
# Private function section.
7219
#       The following functions are used INTERNALLY by makelib.pl2.
7220
###############################################################################
7221
 
7222
###############################################################################
7223
#   A collection of functions to write to the MAKEFILE handle
7224
#
7225
#   MakeHeader          - Write a nice section header
7226
#   MakeNewLine         - Print a new line
7227
#   MakePrint           - Print a line ( without trailing \n)
7228
#   MakeQuote           - Escape \ and " character, then print a line
7229
#   MakePrintList       - Print an array
7230
#   MakeEntry           - Complex line printer
7231
#   MakePadded          - Padded line printer (internal)
7232
#   PadToPosn           - Calc space+tabs to tabstop (internal)
7233
#   MakeEntry3          - Complex Line Printer
7234
#   MakeDefEntry        - Print a definition line (Production + Debug support)
7235
#   MakeIfDefEntry      - Print ifdef entry
261 dpurdie 7236
#   MakeIfnDefEntry     - Print ifndef entry
7237
#   MakeIfZeroEntry     - Print ifeq entry
227 dpurdie 7238
#
7239
###############################################################################
7240
 
7241
sub MakeHeader
7242
{
7243
    my ($text, @rest) = @_;
7244
    my $length = length ($text);
7245
 
7246
    print MAKEFILE "\n";
7247
    print MAKEFILE "#--------- $text ", '-' x (80 - 12 - $length)  ,"\n";
7248
    print MAKEFILE "#    $_\n" foreach  ( @rest ) ;
7249
    print MAKEFILE "#\n";
7250
}
7251
 
7252
sub MakeNewLine         # Print a newline to the current 'Makefile'
7253
{
7254
    print MAKEFILE "\n";
7255
}
7256
 
7257
sub MakePrint           # Print to the current 'Makefile'
7258
{
7259
    print MAKEFILE @_
7260
        if ( defined $_[0] );
7261
}
7262
 
7263
sub MakeQuote           # Quote a makefile text line
7264
{
7265
    my( $line ) = @_;
7266
    $line =~ s/\\/\\\\/g;                       # quote all '\' characters
7267
    $line =~ s/"/\\"/g;                         # Then quote '"' characters
255 dpurdie 7268
    $line =~ s/=#/=\\#/g;                       # Then quote '=#' sequence
227 dpurdie 7269
    print MAKEFILE $line;
7270
}
7271
 
7272
sub MakePrintList
7273
{
7274
    print MAKEFILE $_ . "\n" foreach (@{$_[0]});
7275
}
7276
 
7277
 
7278
#-------------------------------------------------------------------------------
7279
# Function        : MakeEntry
7280
#
7281
# Description     : Build a entry based on the element list
7282
#                   Creates text of the form
7283
#                       $(BINDIR)/prog.exe: object1.obj \
7284
#                                           object2.obj
7285
#
7286
#
7287
# Inputs          : $prelim         - Preamble (one-off)
7288
#                   $postlim        - Postamble (one-off)
7289
#                   $prefix         - Pefix (to each element of array)
7290
#                   $postfix        - Postfix (to each element of array )
7291
#                   @elements       - Array of element to wrap
7292
#
7293
# Returns         :   1 Always
7294
#
7295
# Notes:
7296
#       The above description means that the following entry format is
7297
#       produced:
7298
#
7299
#           <preliminary><prefix><variant1><prefix><variant2>...<final>
7300
#
7301
#       With judicious use of newline and tab characters, a target
7302
#       and dependency list along with the command(s) to build the
7303
#       target can be constructed.
7304
#
7305
sub MakeEntry
7306
{
7307
    my( $prelim, $postlim, $prefix, $postfix, @elements ) = @_;
7308
 
7309
    MakePrint $prelim;
7310
    MakePrint "${prefix}${_}${postfix}" foreach ( @elements );
7311
    MakePrint $postlim if ($postlim);
7312
    return 1;
7313
}
7314
 
7315
#-------------------------------------------------------------------------------
7316
# Function        : MakePadded
7317
#
7318
# Description     : Generate aligned output of the form
7319
#                       Prefix_text           Aligned_text
7320
#                   where the aligned text is at a specified TAB boundary
7321
#
7322
# Inputs          : $align      - Tab stop (One tab = 8 chars)
7323
#                   $prefix     - Text to print before alignment occurs
7324
#                   @line       - Remainder of the line
7325
#
7326
sub MakePadded          # Print to the current 'Makefile', tab aligning
7327
{
7328
    my( $align, $prefix, @line ) = @_;
7329
 
7330
    my $strlen = length( $prefix );
7331
    my $pad = PadToPosn( $strlen, $align * 8 );
7332
 
7333
    print MAKEFILE $prefix . $pad;
7334
    print MAKEFILE @line;
7335
}
7336
 
7337
#-------------------------------------------------------------------------------
7338
# Function        : PadToPosn
7339
#
7340
# Description     : Given that we are at $startposn return a tab and space
7341
#                   string to place us at $endposn
7342
#
7343
sub PadToPosn
7344
{
7345
    my ($startposn, $endposn ) = @_;
7346
 
7347
 
7348
    #
7349
    #   Case where we are already too far into the line
7350
    #
7351
    return ( ' ' )if ( $endposn <= $startposn );
7352
 
7353
    my $tcount = 0;
7354
    my $scount = 0;
7355
 
7356
    while ( $startposn < $endposn )
7357
    {
7358
        $tcount ++;
7359
        $startposn = ($startposn >> 3) * 8 + 8;
7360
 
7361
        my $delta = $endposn - $startposn;
7362
        if ( $delta < 8 )
7363
        {
7364
            $scount = $delta;
7365
            last;
7366
        }
7367
 
7368
    }
7369
    return ( "\t" x $tcount .  ' ' x $scount );
7370
}
7371
 
7372
#-------------------------------------------------------------------------------
7373
# Function        : MakeEntry3
7374
#
7375
# Description     : Build a makefile entry based on the element list, tab aligned
7376
#                   Can creat text of the form:
7377
#                       TAG = NAME0 \       TAG : NAME0 \ 
7378
#                             NAME1               NAME1
7379
#
7380
#
7381
# Inputs          : $prelim             - Preliminary text
7382
#                   $presep             - Preliminary seperator
7383
#                   $elem_ref           - Either a single name or a reference to
7384
#                                         and array of names, or a hash.
7385
#
7386
# Returns         : Writes directly to the Makefile
7387
#
7388
sub MakeEntry3
7389
{
7390
    my( $prelim, $presep, $elem_ref ) = @_;
7391
 
7392
    #
7393
    #   The prelim may have some "\n" characters at the start
7394
    #   These simplify formatting, but mess up the nice formatting
7395
    #
7396
    if ($prelim =~ m~(^\n+)(.*)~ )
7397
    {
7398
        MakePrint $1;
7399
        $prelim = $2;
7400
    }
7401
 
7402
    #
7403
    #   Print the definition and the sep with nice padding
7404
    #
7405
    MakePadded ( 3, $prelim, $presep );
7406
    my $leadin = ' ';
7407
 
7408
    #
7409
    #   If a HASH reference then use a sorted list of keys from the hash.
7410
    #
7411
    if ( ref ($elem_ref) eq "HASH" )
7412
    {
7413
        my @hash_list;
7414
        @hash_list = sort keys ( %{$elem_ref} );
7415
        $elem_ref = \@hash_list;
7416
    }
7417
 
7418
    #
7419
    #   If the list is only one element long, then create a simple form
7420
    #   If the list is not an array ref, then treat it as a single element
7421
    #
7422
    if ( ref ($elem_ref) eq "ARRAY" )
7423
    {
7424
        my $line = 0;
7425
        foreach my $element ( @$elem_ref )
7426
        {
7427
            print MAKEFILE $leadin . $element;
7428
            $leadin = " \\\n" . PadToPosn(0,24 + length( $presep ) + 1 ) unless ($line++);
7429
        }
7430
    }
7431
    elsif ( defined $elem_ref )
7432
    {
7433
            print MAKEFILE $leadin . $elem_ref;
7434
    }
7435
    MakeNewLine();
7436
    return 1;
7437
}
7438
 
7439
#-------------------------------------------------------------------------------
7440
# Function        : MakeDefEntry
7441
#
7442
# Description     : Make a definition entry of the form
7443
#
7444
#                       TAG = NAME0 \
7445
#                             NAME1
7446
#
7447
#                   Support a list of definitions that will always be created
7448
#                   as well as a production and a debug list.
7449
#
7450
#                   Will always generate the "TAG = " string, even if the list
7451
#                   is empty.
7452
#
7453
#                   Will supress the TAG if there is no data if the FIRST opr starts with a '+'
7454
#
7455
# Inputs          : TAG         - Text tag to create
7456
#                   FIRST       - First assignement opr. = or +=
7457
#                   ALL_LIST    - A reference to a list of names to assign
7458
#                                 or a single name.
7459
#                   PROD_LIST   - Optional list to extend the definition with for a production build
7460
#                   DEBUG_LIST  - Optional list to extend the definition with for a debug build
7461
#
7462
# Returns         : Nothing
7463
#
7464
 
7465
sub MakeDefEntry
7466
{
7467
    my( $tag, $assign, $all, $prod, $debug ) = @_;
7468
 
7469
    #
7470
    #   Do not generate anything if the $opr is "+=" and there is no data
7471
    #   to output. ie: Supress empty TAG += statements
7472
    #
7473
    return if ( $assign =~ m/\+/ && ( ref($all) && ! defined $all->[0] ) );
7474
 
7475
    #
7476
    #   TAG for all entries
7477
    #
7478
    MakeEntry3( $tag, $assign, $all );
7479
 
7480
 
7481
    #
7482
    #   TAGs for PROD build
7483
    #   TAGs for DEBUG build
7484
    #
7485
    if ( defined $prod && defined $prod->[0] )
7486
    {
7487
        print MAKEFILE 'ifeq "$(DEBUG)" "0"' . "\n";
7488
        MakeEntry3( $tag, "+=", $prod );
267 dpurdie 7489
        print MAKEFILE 'endif' . "\n";
227 dpurdie 7490
    }
7491
 
7492
    if ( defined $debug && defined $debug->[0] )
7493
    {
7494
        print MAKEFILE 'ifeq "$(DEBUG)" "1"' . "\n";
7495
        MakeEntry3( $tag, "+=", $debug );
267 dpurdie 7496
        print MAKEFILE 'endif' . "\n";
227 dpurdie 7497
    }
7498
 
7499
}
7500
 
7501
sub MakeIfDefEntry
7502
{
7503
    my( $iftag, @rest ) = @_;
7504
 
7505
    print MAKEFILE "ifdef $iftag\n";
7506
    MakeDefEntry (@rest);
7507
    print MAKEFILE "endif\n\n";
7508
}
7509
 
7510
sub MakeIfnDefEntry
7511
{
7512
    my( $iftag, @rest ) = @_;
7513
 
7514
    print MAKEFILE "ifndef $iftag\n";
7515
    MakeDefEntry (@rest);
7516
    print MAKEFILE "endif\n\n";
7517
}
7518
 
261 dpurdie 7519
sub MakeIfZeroEntry
7520
{
7521
    my( $iftag, @rest ) = @_;
7522
 
7523
    print MAKEFILE "ifeq (\$($iftag),0)\n";
7524
    MakeDefEntry (@rest);
7525
    print MAKEFILE "endif\n\n";
7526
}
7527
 
227 dpurdie 7528
#-------------------------------------------------------------------------------
7529
# Function        : CreateNameList
7530
#
7531
# Description     : Create a list of names by adding a prefix and suffix to a
7532
#                   list of items. This is used to add a directory prefix and a
7533
#                   file suffix to a list of files.
7534
#
7535
# Inputs          : $prefix             ie: '$(OBJDIR)/'
7536
#                   $suffix             ie: '.obj'
7537
#                   $elem_ref           ie: A list of files ( passed be ref )
7538
#                                           If a Hash then its sorted keys is used
7539
#
7540
# Returns         : A ref to the resulting list
7541
#
7542
sub CreateNameList
7543
{
7544
    my( $prefix, $suffix, $elem_ref ) = @_;
7545
    my @result;
7546
 
7547
    if ( ref ($elem_ref) eq "HASH" )
7548
    {
7549
        my @hash_list;
7550
        @hash_list = sort keys ( %{$elem_ref} );
7551
        $elem_ref = \@hash_list;
7552
    }
7553
 
7554
    foreach  ( @$elem_ref )
7555
    {
7556
        push @result, $prefix . $_ . $suffix;
7557
    }
7558
    return \@result;
7559
}
7560
 
7561
#-------------------------------------------------------------------------------
7562
# Function        : ListGeneratedProjects
7563
#
7564
# Description     : Return a list of generated/nongenerated projects
7565
#                   Used in conjunction with CreateNameList
7566
#
7567
# Inputs          : $type       - TRUE : Generated
7568
#                                 FALSE: Not Generated
7569
#
7570
# Returns         : A reference to a list of projects
7571
#                   undef will be retuend if there are no projects
7572
#
7573
sub ListGeneratedProjects
7574
{
7575
    my ($type) = @_;
7576
    my @list;
7577
    foreach my $project ( @PROJECTS_ORDER )
7578
    {
7579
        if ( exists($PROJECTS{$project}->{'generated'}) xor $type )
7580
        {
7581
            push @list, $project;
7582
        }
7583
    }
7584
    return @list ? \@list : undef;
7585
}
7586
 
7587
#-------------------------------------------------------------------------------
7588
# Function        : ListCleanGenerated
7589
#
7590
# Description     : return a list of generated targets that have 'clean'
7591
#                   operations. This is used in conjunction with CreateNameList
7592
#
7593
# Inputs          : None
7594
#
7595
# Returns         : A list of project indexes, that can be cleaned
7596
#
7597
sub ListCleanGenerated
7598
{
7599
    my @list;
7600
    foreach my $i ( @GENERATE_FILES )
7601
    {
7602
        push @list, $i->{'index'}
7603
            if ( $i->{'clean'} );
7604
    }
7605
    return \@list;
7606
}
7607
 
251 dpurdie 7608
#-------------------------------------------------------------------------------
7609
# Function        : MakeResolve
7610
#
7611
# Description     : Internal Function
7612
#                   Locate a source file by examining a list of directories
7613
#
7614
#                   Don't use directly
7615
#                   Use MakeSrcResolve or MakeSrcResolveExtended
7616
#
7617
# Inputs          : $dirs           - Ref to an array of directories to scan
7618
#                   $source         - File to locate
7619
#
7620
# Returns         : Resolved path to the file
7621
#                   Will warn if multiple instances of the file are found
7622
#
227 dpurdie 7623
sub MakeResolve
7624
{
7625
    my( $dirs, $source ) = @_;
285 dpurdie 7626
    my( $first, $count );
227 dpurdie 7627
 
237 dpurdie 7628
    #
7629
    #   If the path contains a '$' then its assumed to be
7630
    #   a variable name in the path. Just assume that it exists
7631
    #
7632
    return $source if ( $source =~ m#\$# );
7633
 
7634
    #
7635
    #   If the path is absolute or contains a leading ., then don't search
7636
    #   Warn if it can't be found
7637
    #
7638
    if ( $source =~ m#^(/|\.)# )
7639
    {
7640
        Warning( "Unable to resolve '$source' path" ) unless -f $source;
7641
        return $source;
227 dpurdie 7642
    }
7643
 
237 dpurdie 7644
 
227 dpurdie 7645
#.. search local path first
7646
#
7647
    $count = 0;
7648
    $first = "";
331 dpurdie 7649
    $first = "$source"                              # was ./$source
227 dpurdie 7650
        if (-r "$source");
7651
 
7652
#.. search directory paths
7653
#
285 dpurdie 7654
    foreach my $dir (@$dirs)
227 dpurdie 7655
    {
331 dpurdie 7656
        next if ( $dir eq '.' );
7657
        my $temp = "$dir/$source";                  # was ./$dir/$source
227 dpurdie 7658
        Debug2( "MakeResolve: Looking in: $temp" );
7659
        if (-r "$temp")
7660
        {
7661
            if ($first eq "") {
7662
                $first = $temp;
7663
            } else {
7664
                Warning( "Duplicate '$source' image - '$temp'" );
7665
                $count++;
7666
            }
7667
        }
7668
        Debug3( "MakeResolve: $count, $temp" );
7669
    }
7670
 
7671
    if ($first eq "") {
7672
        $first = $source;
7673
        Warning( "Unable to resolve '$source' path" );
7674
    } else {
7675
        Warning( "          using '$first'" )
7676
            if ($count);
7677
    }
7678
    return $first;
7679
}
7680
 
251 dpurdie 7681
#-------------------------------------------------------------------------------
7682
# Function        : MakeSrcResolve
7683
#
7684
# Description     : Locate a source file by examining the list of source
7685
#                   directories. There are a few frills
7686
#
7687
#                   Look for a source file in
7688
#                       1) %::BUILD_KNOWNFILES
7689
#                       2) %SRCS
7690
#                       3) Dirs specified by the array @SRCSDIRS
7691
#
7692
# Inputs          : Name of a file to resolve
7693
#
7694
# Returns         : Resolved path.
283 dpurdie 7695
#                   Input file - if not found at all
251 dpurdie 7696
#
227 dpurdie 7697
sub MakeSrcResolve
7698
{
7699
    my ($name) = @_;
7700
    my $file;
7701
 
251 dpurdie 7702
    if ( exists ( $::BUILD_KNOWNFILES{$name} ) ) {
7703
        #
7704
        #   The Known Files list is relative to ScmRoot
7705
        #   This must be included in the full path
7706
        #
7707
        $file = $ScmRoot . '/' . $::BUILD_KNOWNFILES{$name};
7708
 
7709
    } elsif ( exists $SRCS{$name} ) {
7710
        $file = $SRCS{$name};
7711
 
7712
    } else {
7713
        $file = MakeResolve( \@SRCDIRS, @_ )
7714
    }
227 dpurdie 7715
    return $file;
7716
}
7717
 
7718
 
7719
# MakeSrcResolveExtended
7720
#   from_global = 0 : Search user specified directories
7721
#               = 1 : Search LinkPkgArchive list
7722
#
7723
our @PkgSrcDirList;
7724
sub MakeSrcResolveExtended
7725
{
7726
    my ( $from_global, $file ) = @_;
7727
 
7728
    #
7729
    #   Simple Case. Resolve source from known source directories
7730
    #
7731
    #
7732
    return MakeSrcResolve( $file )
7733
        unless ( $from_global );
7734
 
7735
    #
7736
    #   Not so simple Case
7737
    #   Resolve the source from the imported packages
7738
    #
7739
    #   Create a list of directores to search, but only the first time
311 dpurdie 7740
    #       - Interface directories - from BuildPkgArchive
227 dpurdie 7741
    #       - LnkPkgArchive directories
7742
    #         Using target,product,platform include directories
7743
    #
7744
    unless ( @PkgSrcDirList )
7745
    {
7746
        for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} })
7747
        {
311 dpurdie 7748
            next if ( $entry->{'TYPE'} eq 'build' ); # Ignore BuildPkgArchives
7749
 
227 dpurdie 7750
            for (@{$entry->{'PINCDIRS'}}, @{$entry->{'THXDIRS'}}, '' )
7751
            {
7752
                my $dir = $entry->{'ROOT'} . "/" . $_ ;
7753
                $dir =~ s~//~/~g;
7754
                $dir =~ s~/$~~;
311 dpurdie 7755
                push ( @PkgSrcDirList, $dir );
227 dpurdie 7756
            }
7757
        }
311 dpurdie 7758
    }
227 dpurdie 7759
 
7760
    return MakeResolve( \@PkgSrcDirList, $file );
7761
}
7762
 
7763
#-------------------------------------------------------------------------------
7764
# Function        : GetPackageRoot
7765
#
7766
# Description     : Determine the root directory for a given package
7767
#                   This routine is intended for non-standard JATS scripts that
7768
#                   access package contents directly
7769
#
7770
#                   Note: This routine does not attempt to handle multiple
7771
#                         instances of a package ( sysbasetypes ).
7772
#
7773
# Inputs          : $pname          - Name of the package
7774
#
7775
# Returns         :
7776
#
7777
sub GetPackageRoot
7778
{
7779
    my( $pname ) = @_;
7780
    Debug( "GetPackageRoot(@_)" );
7781
 
7782
    my $result = undef;
7783
    my $pkg = GetPackageEntry( $pname );
7784
    if ( $pkg )
7785
    {
7786
        $result = $pkg->{'ROOT'};
7787
        Debug( "GetPackageRoot: $result" );
7788
    }
7789
 
7790
    return $result;
7791
}
7792
 
7793
#-------------------------------------------------------------------------------
7794
# Function        : ActiveProject
7795
#
7796
# Description     : Determine if the specified project is currenly 'active'
7797
#
345 dpurdie 7798
# Inputs          : $project            - one or more project names separated
7799
#                                         by either a comma or a colon
227 dpurdie 7800
#
7801
# Returns         : TRUE    if the project is active
7802
#
7803
sub ActiveProject
7804
{
7805
    my ($project) = @_;
345 dpurdie 7806
    foreach (  split( '\s*[:,]\s*', $project ) )
227 dpurdie 7807
    {
7808
        return 1
7809
            if ( $_ eq $::ScmBuildProject );
7810
    }
7811
    return 0;
7812
}
7813
 
345 dpurdie 7814
#-------------------------------------------------------------------------------
7815
# Function        : ActiveDefine
7816
#
7817
# Description     : Determine if the specified definition is currenly 'active'
7818
#
7819
# Inputs          : $defs               - one or more variable names separated
7820
#                                         by either a comma or a colon
7821
#
7822
# Returns         : TRUE    if any of the definitions are known
7823
#
7824
sub ActiveDefine
7825
{
7826
    my ($defs) = @_;
7827
    no strict 'refs';
7828
    foreach (  split( '\s*[:,]\s*', $defs ) )
7829
    {
7830
        return 1
7831
            if ( defined( $$_ ) || defined( @$_ ) );
7832
    }
7833
    use strict 'refs';
7834
    return 0;
7835
}
227 dpurdie 7836
 
7837
#-------------------------------------------------------------------------------
345 dpurdie 7838
# Function        : ActiveMachType
7839
#
7840
# Description     : Determine if the specified MachType is currenly 'active'
7841
#
7842
# Inputs          : $mtype              - one or more machine names separated
7843
#                                         by either a comma or a colon
7844
#
7845
# Returns         : TRUE    if any of the current MachType is in the list
7846
#
7847
sub ActiveMachType
7848
{
7849
    my ($mtype) = @_;
7850
    foreach (  split( '\s*[:,]\s*', $mtype ) )
7851
    {
7852
        return 1
7853
            if ( uc($_) eq uc($::GBE_MACHTYPE) );
7854
    }
7855
    return 0;
7856
}
7857
 
7858
#-------------------------------------------------------------------------------
227 dpurdie 7859
# Function        : ActivePlatform
7860
#
7861
# Description     : Determine if the specified platform is currently 'active'
7862
#                   This is used by all user directives in order to determine
7863
#                   if the directive should be ignored for the current platform
7864
#
7865
# Inputs          : $platform_spec      - A platform specifier
7866
#                                         This is a bit complex.
7867
#
241 dpurdie 7868
#                   Format of platform_spec. One or more of
7869
#                       PlatformName
7870
#                       AliasName
7871
#                       TargetName,--Target
345 dpurdie 7872
#                   Special Options (Must all be True)
7873
#                       --Project=ProjectName[:ProjectName]+
7874
#                       --Defined=SomeValue[:SomeValue]+
7875
#                       --MachType=SomeValue[:SomeValue]+
7876
 
7877
#                   Each can be prefixed with a '!' to negate the test
227 dpurdie 7878
#
241 dpurdie 7879
#                   Valid options are:
271 dpurdie 7880
#                       --Target        - indicates that the platform is a 'target'
241 dpurdie 7881
#
7882
# Returns         : TRUE if the platform spec is satisfied
7883
#
227 dpurdie 7884
sub ActivePlatform
7885
{
7886
    my( $platform_spec ) = @_;
7887
    my( @platforms, $scmplatform, $platform );
7888
    my( %arguments, @args, $filter );
241 dpurdie 7889
    my @plist;
7890
    my ($match_count, $count_invert, $count_vert) = (0,0,0);
227 dpurdie 7891
 
241 dpurdie 7892
    #
7893
    #   Short circuit check
7894
    #   '*' is used so often that it pays to check it first
7895
    #
7896
    if ( $platform_spec eq '*' )
7897
    {
7898
        Debug3( " ActivePlatform(@_) = TRUE" );
7899
        return 1;
7900
    }
227 dpurdie 7901
 
241 dpurdie 7902
    #
7903
    #   Platform specifier may be a comma seperated list
7904
    #   ie:  WIN32,MOS,XXX
7905
    #   Extract non-platform arguments
279 dpurdie 7906
    #   Process to yield a dummy platform of '0' or '1' - these will be seen later
241 dpurdie 7907
    #
7908
    foreach ( split( '\s*,\s*', $platform_spec ) )
7909
    {
345 dpurdie 7910
        my ($result, $not);
7911
        if ( m~^(!?)--Project=(.+)~ ) {
325 dpurdie 7912
            $not = $1;
345 dpurdie 7913
            $result = ActiveProject($2);
277 dpurdie 7914
 
345 dpurdie 7915
        } elsif ( m~^(!?)--Defined=(.+)~ ) {
325 dpurdie 7916
            $not = $1;
345 dpurdie 7917
            $result = ActiveDefine($2);
241 dpurdie 7918
 
345 dpurdie 7919
        } elsif ( m~^(!?)--MachType=(.+)~ ) {
325 dpurdie 7920
            $not = $1;
345 dpurdie 7921
            $result = ActiveMachType($2);
7922
 
325 dpurdie 7923
        } else {
7924
            #
7925
            #   Must be a platform argument
7926
            #   Add to a list
7927
            #
7928
            push @platforms, $_;
241 dpurdie 7929
            next;
7930
        }
7931
 
7932
        #
325 dpurdie 7933
        #   Continue processing non-platform arguments
345 dpurdie 7934
        #   Each one must be TRUE, allowing for negation.
241 dpurdie 7935
        #
325 dpurdie 7936
        $result = $result ? 1 : 0;
345 dpurdie 7937
        $result = ! $result if ( $not );
7938
        return 0 unless ( $result );
241 dpurdie 7939
    }
7940
 
7941
    #   Platform specified may be an Alias
7942
    #   Perform alias expansion
7943
    #
7944
    @platforms = ExpandPlatforms( @platforms );         # aliasing
227 dpurdie 7945
    Debug3( " ActivePlatform(@_)" );
325 dpurdie 7946
#    Debug0( " Platforms(@platforms)", "PLIST(@plist)" );
227 dpurdie 7947
 
7948
#.. Arguments
241 dpurdie 7949
#   At this point we have a list of platforms and arguments
7950
#   Build up a hash of arguments for each platform being parsed
227 dpurdie 7951
#   Multiple arguments can follow a platform name
241 dpurdie 7952
#   Arguments apply to the preceeding platform name
227 dpurdie 7953
#
241 dpurdie 7954
    $platform = undef;
227 dpurdie 7955
    foreach ( @platforms )
7956
    {
241 dpurdie 7957
        if ( /^--Target/ ) {                     # Arguments
7958
            if ( $platform ) {
7959
                $arguments{$platform}{'Target'} = 1;
7960
            } else {
317 dpurdie 7961
                Warning ("No Platform preceding platform option: $_");
241 dpurdie 7962
            }
7963
 
305 dpurdie 7964
        } elsif ( /^--Only(Prod)|(Debug)/ || /--board=/ ) {
273 dpurdie 7965
            # Known arguments
305 dpurdie 7966
            # Bit of a kludge. Must be a better way
273 dpurdie 7967
 
241 dpurdie 7968
        } elsif ( /^--/ ) {
7969
            Warning ("Unknown platform option: $_");
7970
 
227 dpurdie 7971
        } else {                                # Target
7972
            $platform = $_;
241 dpurdie 7973
            push @plist, $platform;
227 dpurdie 7974
        }
7975
    }
7976
 
241 dpurdie 7977
#.. Scan the expression
227 dpurdie 7978
#
7979
    $scmplatform = uc( $ScmPlatform );          # current platform
325 dpurdie 7980
 
241 dpurdie 7981
    foreach ( @plist )
227 dpurdie 7982
    {
7983
        $platform = uc( Trim( $_ ) );           # trim white and convert case
7984
 
7985
        #
241 dpurdie 7986
        #   Determine filter comparison
7987
        #   Either a Platform or a Target
7988
        #
7989
        if ( $arguments{$platform}{'Target'} )
227 dpurdie 7990
        {
241 dpurdie 7991
            $filter = uc( $ScmTarget );
227 dpurdie 7992
        }
241 dpurdie 7993
        else
7994
        {
7995
            $filter = $scmplatform;             # filter specification
7996
        }
7997
 
227 dpurdie 7998
        Debug3( "   Platform=$platform, Filter=$filter" );
7999
 
8000
        #
8001
        #   Examine platform names
8002
        #   Allow negation of name (!), but all the names must be negated
8003
        #   as a mix does not make sense.
8004
        #   ie:     !P1,!P2,!P3     - All except P1,P2 or P3
8005
        #            P1,P2,P2       - Only P1,P2,P3
8006
        #
241 dpurdie 8007
        my $invert = 0;
8008
        if ( substr($platform, 0, 1) eq '!' )
8009
        {
8010
            $count_invert++;
8011
            $platform = substr($platform, 1);
227 dpurdie 8012
        }
8013
        else
241 dpurdie 8014
        {
8015
            $count_vert++;
8016
        }
227 dpurdie 8017
 
241 dpurdie 8018
        $match_count++ if ( $platform eq ''  ||
8019
                            $platform eq '*' ||
8020
                            $platform eq '1' ||
8021
                            $platform eq $filter );
227 dpurdie 8022
    }
8023
 
241 dpurdie 8024
    #
8025
    #   Sanity test
8026
    #   Force failure on bad sanity
8027
    #
8028
    if ( $count_vert && $count_invert )
8029
    {
8030
        Warning( "Platform expression makes no sense. Mixed use of '!' operator",
8031
                 "Expression: @_" );
8032
        return 0;
8033
    }
8034
 
8035
    #
8036
    #   Test for pass
8037
    #   If not using '!', then any match passes : P1 or P2 or P3
8038
    #   If are using '!', then any match is bad : !P1 and !P2 and !P3 == !(P1 or P2 or P3)
8039
    #
8040
    if ( ( $count_vert && $match_count ) || ( $count_invert && ( not $match_count) )   )
8041
    {
227 dpurdie 8042
        Debug3( " ActivePlatform(@_ == $ScmPlatform) = TRUE" );
8043
        return 1;
8044
    }
241 dpurdie 8045
 
227 dpurdie 8046
    Debug3( " ActivePlatform(@_ == $ScmPlatform) = FALSE" );
8047
    return 0;
8048
}
8049
 
8050
#-------------------------------------------------------------------------------
321 dpurdie 8051
# Function        : If
8052
#
8053
# Description     : Function for embedding arguments in directives
8054
#                   To be used within another directive
8055
#                   ie:
8056
#                       AnyDirective ('*',  arg1, arg2, ...
8057
#                                           If (SomePlatform, arg1, .. ,argn))
8058
#
8059
# Inputs          : $platform               - Active Platform speciifier
8060
#                   @args                   - Args
8061
#
8062
# Returns         : @args or nothing
8063
#
8064
sub  If
8065
{
8066
    my $platform = shift;
8067
    return @_
8068
        if ( ActivePlatform( $platform ));
8069
    return;
8070
}
8071
 
8072
#-------------------------------------------------------------------------------
227 dpurdie 8073
# Function        : RegisterMakefileGenerate
8074
#
8075
# Description     : Register a function to be called at the start of the
8076
#                   makefile generation process
8077
#
8078
# Inputs          : $fname      - Name of the function
8079
#                   $args       - Function Arguments
8080
#
8081
# Returns         : Nothing
8082
#
8083
our @MF_Generators;
8084
sub RegisterMakefileGenerate
8085
{
8086
   my ($fref) = @_;
8087
   my $rtype = ref($fref) || 'not a reference';
8088
 
8089
   Error ("RegisterMakefileGenerate called incorrectly",
8090
          "First argument MUST be a code reference",
8091
          "It is a $rtype"
8092
          ) unless ( $rtype eq 'CODE' );
8093
 
8094
   #
8095
   #    Save the arguments by reference in an array
8096
   #    The array will be processed later
8097
   #
8098
   push @MF_Generators, \@_;
8099
}
8100
 
8101
#-------------------------------------------------------------------------------
271 dpurdie 8102
# Function        : RegisterSrcHook
8103
#
8104
# Description     : Register a function to be called when a source file is
8105
#                   declared
8106
#
8107
# Inputs          : $ext        - Extension of interest
8108
#                                 '*' will be used by all
8109
#                   $fname      - Name of the function
8110
#                   $args       - Function Arguments
8111
#
8112
# Returns         : Nothing
8113
#
8114
sub RegisterSrcHook
8115
{
8116
    my $ext = shift;
8117
    my ($fref) = @_;
8118
    my $rtype = ref($fref) || 'not a reference';
8119
 
8120
    Error ("RegisterSrcHook called incorrectly",
8121
           "Second argument MUST be a code reference",
8122
           "It is a $rtype"
8123
           ) unless ( $rtype eq 'CODE' );
8124
 
8125
    #
8126
    #    Save the arguments by reference in an array
8127
    #    The array will be processed later
8128
    #
8129
    push @{$MF_RegisterSrcHooks{$ext}}, \@_;
8130
}
8131
 
8132
 
8133
#-------------------------------------------------------------------------------
227 dpurdie 8134
# Function        : MakefileHeader
8135
#
8136
# Description:    : Generate a "standard" makefile header.
8137
#
8138
#..
8139
 
8140
sub MakefileHeader
8141
{
8142
    my ($file, $desc, $by, @trailing) = @_;
8143
    my ($diff);
8144
 
8145
    $diff = 0 if (($diff = ((80-5) - length($desc))) < 0);
8146
    $desc .= ' ' . ('-' x $diff);
8147
 
8148
    print $file <<EOF;
8149
# -*- mode: mak; -*-
8150
#-- $desc
8151
#
8152
#                   -- Please do not edit this file. --
8153
#
8154
#       To do so may result in a system failure, in additional to any
8155
#       changes made shall be overwritten.
8156
#
8157
# Created by $by
8158
#         on $::CurrentTime
8159
#
8160
EOF
8161
    #
8162
    #   Print out the trailer
8163
    #   This is an array. Place each entry on a new line
8164
    #
8165
    print $file $_ . "\n" for ( @trailing );
8166
}
8167
 
8168
###############################################################################
8169
# MakeFileGenerate:
8170
#       This subroutine does all of the actual make file generation based
8171
#       on information provided in the calls to the various public
8172
#       interface routines.
8173
#
8174
# Inputs:
8175
#
8176
# Returns:
8177
###############################################################################
8178
 
8179
my $MakefileGenerate_once = 0;
8180
sub MakefileGenerate
8181
{
8182
    my $Makefile = "$ScmPlatform.mk";
8183
    Debug( "MakefileGenerate: $Makefile" );
8184
 
8185
    #
8186
    #   Nasty things happen when we generate a makefile twice
8187
    #   Just warn the user and do nothing
8188
    #   If its in the common makefile.pl then just ignore it
8189
    #
8190
    if ( $ScmProcessingRootMake )
8191
    {
8192
        Warning ("MakefileGenerate directive is not allowed in common makefile.pl");
8193
        return;
8194
    }
8195
 
8196
    if ( $MakefileGenerate_once )
8197
    {
8198
        Warning ("MakefileGenerate should only be called once.",
8199
                 "Dir: $::Cwd");
8200
        return;
8201
    }
8202
    $MakefileGenerate_once = 1;
8203
 
8204
    #
8205
    #   Invoke all registered Makefile Generator functions
8206
    #   These allow clever directives to collect information to be
8207
    #   processed before the makefiles are created
8208
    #
8209
    while ( @MF_Generators )
8210
    {
8211
        Debug( "MakefileGenerate: Invoke RegisterMakefileGenerate function" );
8212
        my ($fname, @args) = @{shift @MF_Generators};
8213
        &$fname ( @args );
8214
    }
8215
 
8216
    #
8217
    #   Allow the toolset the opportunity to process all the collected data
8218
    #   before the makefile is created. This is optional
8219
    #
8220
    my( $if ) = MakeIf::Factory();              # build interface
8221
    $if->Preprocess();
8222
 
8223
    #
343 dpurdie 8224
    #   If we have supressed the Toolset use, then we need to sanity test
8225
    #   the use of the toolset
8226
    #
8227
    if ( $ScmNoToolsTest )
8228
    {
8229
        ReportError ("Building programs not supported with --NoToolset") if ( @PROGS || @TESTPROGS );
8230
        ReportError ("Building libraries not supported with --NoToolset") if ( @LIBS || @MLIBS || @SHLIBS );
8231
        ReportError ("Building projects not supported with --NoToolset") if ( %PROJECTS );
8232
        ErrorDoExit();
8233
    }
8234
 
8235
    #
227 dpurdie 8236
    #   Auto package the 'descpkg' file
8237
    #   If this makefile packages any files, then it can also package the descpkg file
8238
    #   The descpkg will be piggybacked into all makefiles that do a package
8239
    #
8240
    if ( %PACKAGE_FILES || %PACKAGE_HDRS || %PACKAGE_CLSS || %PACKAGE_LIBS
8241
                        || %PACKAGE_SHLIBS || %PACKAGE_PROGS )
8242
    {
251 dpurdie 8243
        Src ('*', 'descpkg') unless ($SRCS{ descpkg });
8244
        PackageFile ('*', 'descpkg');
227 dpurdie 8245
    }
8246
 
8247
    #
8248
    #   Some toolsets NEED a relative root
261 dpurdie 8249
    #   Note: At the moment ScmRoot is relative anyway, thus this code
8250
    #         does nothing
227 dpurdie 8251
    #
8252
    my $gbe_root = $::ScmRoot;
8253
    if ( $::UseRelativeRoot )
8254
    {
8255
        $gbe_root =  RelPath( $::ScmRoot );
8256
    }
8257
 
8258
    #
8259
    #   Now start to create the makefile
8260
    #
285 dpurdie 8261
    open( MAKEFILE, '>', $Makefile ) || Error( "Cannot create $Makefile" );
227 dpurdie 8262
    ::MakefileHeader( *MAKEFILE,
8263
                      'Auto-generated Platform Dependent Makefile',
8264
                      "$ScmMakelib (version $ScmVersion)",
343 dpurdie 8265
                      "# Copyright (C) 1995-$::CurrentYear Vix-ERG, All rights reserved",
227 dpurdie 8266
                      '#',
8267
                      "# Located in $::Cwd",
8268
                      "# Platform $::ScmPlatform",
8269
                      '#' . ('-' x 79),
8270
                      );
8271
 
8272
    #
8273
    #   Ensure that some essential variables are set
8274
    #
8275
    print MAKEFILE <<EOF;
8276
#
8277
#   Validate essential environment variables
8278
#
8279
ifndef GBE_BIN
8280
    \$(error ERROR: GBE_BIN is not available)
8281
endif
8282
ifndef GBE_PERL
8283
    \$(error ERROR: GBE_PERL is not available)
8284
endif
8285
ifndef DEBUG
8286
    \$(error ERROR: DEBUG is not defined)
8287
endif
8288
EOF
8289
 
8290
 
8291
    print MAKEFILE <<EOF;
8292
 
8293
#
8294
#   Basic definitions
8295
#
343 dpurdie 8296
GBE_ROOT      := $gbe_root
8297
GBE_ROOT_ABS  := \$(abspath \$(GBE_ROOT))
8298
GBE_HOST      := $::ScmHost
8299
GBE_HOSTMACH  := $::GBE_MACHTYPE
8300
GBE_TARGET    := $::ScmTarget
8301
GBE_MACHTYPE  := $::ScmMachType
8302
GBE_PLATFORM  := $::ScmPlatform
8303
GBE_PBASE     := $::Pbase
8304
GBE_TYPE      := \$(if \$(findstring 1,\$(DEBUG)),D,P)
227 dpurdie 8305
EOF
8306
 
343 dpurdie 8307
MakePrint( "GBE_ARGS      := @ScmPlatformArgs\n" )
227 dpurdie 8308
    if ( scalar @ScmPlatformArgs );
8309
 
343 dpurdie 8310
MakePrint( "GBE_PRODUCT   := $ScmProduct\n" )
227 dpurdie 8311
    if ( $ScmProduct ne "" );
8312
 
343 dpurdie 8313
MakePrint( "GBE_OS_COMMON := $::BUILDINFO{$ScmPlatform}{OS_COMMON}\n" )
227 dpurdie 8314
    if ( exists($::BUILDINFO{$ScmPlatform}{OS_COMMON}) );
8315
 
8316
 
8317
    print MAKEFILE <<EOF;
8318
 
8319
SHELL           := \$(GBE_BIN)/sh
8320
SHELLARGS       :=
8321
EXTENDED_LINE   := \$(GBE_BIN)/extend.lst
8322
export EXTENDED_LINE MAKE
8323
 
343 dpurdie 8324
MFLAGS           := --no-print --warn -r
8325
BUILDNAME        := $::ScmBuildName
8326
BUILDVER         := $::ScmBuildVersionFull
8327
BUILDVERNUM      := $::ScmBuildVersion
227 dpurdie 8328
BUILDPREVIOUSVER := $::ScmBuildPreviousVersion
343 dpurdie 8329
DEPLOYPATCH      := $ScmDeploymentPatch
8330
GBE_NOTOOLSTEST  := $ScmNoToolsTest
227 dpurdie 8331
 
8332
#
8333
#   Ensure PWD is correctly set
8334
#
8335
PWD             := \$(CURDIR)
8336
export PWD
8337
 
261 dpurdie 8338
#
8339
#   NOSCMDEPEND - Used to remove dependency checking of build files
8340
#                 Used internally by the build system
8341
#   NODEPEND    - Used to suppress generated dependency file checking
8342
#                 Mostly done in jmake.pl
8343
#   EXPERT      - Used to suppress dependency on this makefile
8344
#
8345
EOF
8346
 
285 dpurdie 8347
MakePrint( "NOSCMDEPEND\t?= " . ($ScmExpert ? '1' : '0' ) . "\n" );
8348
MakePrint( "EXPERT\t\t?= " . ($ScmExpert ? '1' : '0' ) . "\n" );
8349
MakePrint( "NODEPEND\t?= 0\n" );
261 dpurdie 8350
 
8351
print MAKEFILE <<EOF;
8352
 
8353
#
8354
#   SCM_MAKEFILE - The name of the file to depend upon
8355
#                  Supressed in EXPERT mode
8356
#
8357
ifneq (\$(EXPERT),0)
8358
SCM_MAKEFILE	:=
8359
NOSCMDEPEND	:= 1
8360
else
8361
SCM_MAKEFILE	:= $Makefile
8362
endif
8363
EOF
8364
 
267 dpurdie 8365
#
8366
#   Setup the base directory for the packaging process
8367
#   When building a deployable package the base directory is changed to match
8368
#   that used by the deployment world. This is done so that the descpkg file
8369
#   can be created in the correct location
8370
#
8371
my  $PKGDIR = "pkg/$::Pbase";
8372
    $PKGDIR = "build/deploy" if ( $DEPLOYPACKAGE );
8373
Verbose("Setting PKGDIR: $PKGDIR");
8374
 
261 dpurdie 8375
print MAKEFILE <<EOF;
8376
 
227 dpurdie 8377
#--------- Targets -------------------------------------------------------------
8378
 
8379
.PHONY: 	default all build install package unpackage uninstall \\
8380
		clean unbuild clobber deploy
8381
 
8382
default:	make_usage
8383
all:		install package deploy
8384
build:		make_init generate install_hdr depend make_lib \\
8385
		install_lib make_install_shlib make_prog install_class
8386
install:	build install_prog
8387
package:	package_files package_hdr package_lib package_shlib package_prog \\
8388
		package_class
8389
unpackage:	unpackage_class unpackage_prog unpackage_shlib \\
8390
		unpackage_lib unpackage_hdr unpackage_files
8391
uninstall:	uninstall_class uninstall_prog uninstall_shlib \\
8392
		uninstall_lib uninstall_hdr
8393
clean:		make_clean unmake_prog unmake_test unmake_lib unobj \\
261 dpurdie 8394
		undepend ungenerate rmlitter unmake_dir
227 dpurdie 8395
unbuild:	clean uninstall
8396
clobber:	unpackage unbuild
8397
deploy:		install run_deploy
8398
 
8399
#--------- Macros --------------------------------------------------------------
8400
 
8401
OBJDIR		= \$(GBE_PLATFORM)\$(GBE_TYPE).OBJ
8402
LIBDIR		= \$(GBE_PLATFORM).LIB
8403
BINDIR		= \$(GBE_PLATFORM)\$(GBE_TYPE).BIN
8404
CLSDIR		= classes\$(GBE_TYPE)
8405
 
267 dpurdie 8406
PKGDIR		= \$(GBE_ROOT)/$PKGDIR
227 dpurdie 8407
INCDIR_PKG	= \$(PKGDIR)/include
8408
LIBDIR_PKG	= \$(PKGDIR)/lib
8409
BINDIR_PKG	= \$(PKGDIR)/bin
8410
CLSDIR_PKG	= \$(PKGDIR)/classes
8411
 
8412
LOCALDIR	= \$(GBE_ROOT)/local
8413
INCDIR_LOCAL	= \$(LOCALDIR)/inc
8414
LIBDIR_LOCAL	= \$(LOCALDIR)/lib
8415
BINDIR_LOCAL	= \$(LOCALDIR)/bin
8416
CLSDIR_LOCAL	= \$(LOCALDIR)/classes
8417
BINDIR_LOCAL_PATH = \$(GBE_ROOT_ABS)/local/bin/\$(GBE_PLATFORM)\$(GBE_TYPE)
8418
 
8419
INTERFACEDIR	= \$(GBE_ROOT)/$ScmInterface
8420
INCDIR_INTERFACE= \$(INTERFACEDIR)/include
8421
LIBDIR_INTERFACE= \$(INTERFACEDIR)/lib
8422
BINDIR_INTERFACE= \$(INTERFACEDIR)/bin
8423
CLSDIR_INTERFACE= \$(INTERFACEDIR)/classes
8424
 
8425
.SUFFIXES:		# Delete the default suffixes
8426
 
8427
EOF
8428
 
8429
    MakePrintList( \@DEFINES );
8430
    MakeNewLine();
8431
 
8432
#-------------------------------------------------------------------------------
8433
#
8434
#
261 dpurdie 8435
    MakeHeader ("Defines, flags and file sets");
227 dpurdie 8436
 
8437
    # Flags
261 dpurdie 8438
    foreach my $opt ( keys %ScmCompilerOpts )
8439
    {
8440
        MakeDefEntry ( $opt, "=", $ScmCompilerOpts{$opt} );
8441
    }
227 dpurdie 8442
 
261 dpurdie 8443
    MakeDefEntry( "CFLAGS",         "=", \@CFLAGS, \@CFLAGS_PROD, \@CFLAGS_DEBUG );
8444
    MakeDefEntry( "CLINTFLAGS",     "=", \@CLINTFLAGS, \@CLINTFLAGS_PROD, \@CLINTFLAGS_DEBUG );
8445
    MakeDefEntry( "CDEPENDFLAGS",   "=", \@CFLAGS, \@CFLAGS_PROD, \@CFLAGS_DEBUG );
8446
    MakeDefEntry( "CXXFLAGS",       "=", \@CXXFLAGS, \@CXXFLAGS_PROD, \@CXXFLAGS_DEBUG );
8447
    MakeDefEntry( "CXXLINTFLAGS",   "=", \@CXXLINTFLAGS, \@CXXLINTFLAGS_PROD, \@CXXLINTFLAGS_DEBUG );
8448
    MakeDefEntry( "CXXDEPENDFLAG",  "=", \@CXXFLAGS, \@CXXFLAGS_PROD, \@CXXFLAGS_DEBUG );
267 dpurdie 8449
    MakeDefEntry( "ASFLAGS",        "=", \@ASFLAGS, \@ASFLAGS_PROD, \@ASFLAGS_DEBUG );
8450
    MakeDefEntry( "LDFLAGS",        "=", \@LDFLAGS, \@LDFLAGS_PROD, \@LDFLAGS_DEBUG );
227 dpurdie 8451
 
8452
 
8453
#-------------------------------------------------------------------------------
8454
#   
8455
#
261 dpurdie 8456
    MakeHeader ("Tool Search Path",
8457
                "Extend the PATH seen by all the tools to include",
8458
                "The tools/bin directories discovered in Packages" );
8459
    my $put_PATH;
8460
    my $put_LD_LIBRARY_PATH;
8461
    for my $path ( ToolExtensionPaths() )
8462
    {
8463
        MakePrint( "PATH := $path$::ScmPathSep\$(PATH)\n" );
8464
        $put_PATH = 1;
227 dpurdie 8465
 
261 dpurdie 8466
        if ( $::ScmHost eq "Unix" )
8467
        {
227 dpurdie 8468
        MakePrint( "LD_LIBRARY_PATH ?= \n" );
8469
        MakePrint( "LD_LIBRARY_PATH := $path$::ScmPathSep\$(LD_LIBRARY_PATH)\n" );
261 dpurdie 8470
            $put_LD_LIBRARY_PATH =1;
8471
        }
227 dpurdie 8472
    }
8473
 
261 dpurdie 8474
    #   Export the appropriate environment variables
8475
    #   Note: Windows has an issue with PATH and Path
8476
    #         Haven't got to the bottom of it yet, but it would appear that DLL
8477
    #         searching uses Path and other stuff uses PATH. Not too sure how we
8478
    #         end up with two (or more in the environment)
8479
    #
8480
    #
8481
    if ( $put_LD_LIBRARY_PATH )
8482
    {
343 dpurdie 8483
        MakePrint( "export LD_LIBRARY_PATH\n" );
261 dpurdie 8484
    }
227 dpurdie 8485
 
261 dpurdie 8486
    if ( $put_PATH )
8487
    {
343 dpurdie 8488
        MakePrint( "Path := \$(PATH)\n" );
8489
        MakePrint( "export PATH Path\n" );
261 dpurdie 8490
    }
227 dpurdie 8491
 
8492
#-------------------------------------------------------------------------------
8493
#   
8494
#
261 dpurdie 8495
    MakeHeader ("Perl Module Search Path",
8496
                "Extend the PERL5LIB seen by invocations of perl");
227 dpurdie 8497
 
261 dpurdie 8498
    my $perl_module_found;
8499
    for my $path ( ToolExtensionPaths() )
227 dpurdie 8500
    {
261 dpurdie 8501
        if (glob( "$path/*.pm"))
8502
        {
227 dpurdie 8503
        MakePrint( "PERL5LIB := $path$::ScmPathSep\$(PERL5LIB)\n" );
261 dpurdie 8504
            $perl_module_found = 1;
8505
        }
227 dpurdie 8506
    }
261 dpurdie 8507
    if ( $perl_module_found  )
8508
    {
227 dpurdie 8509
    MakePrint( "export PERL5LIB\n" );
261 dpurdie 8510
    }
227 dpurdie 8511
 
261 dpurdie 8512
#-------------------------------------------------------------------------------
8513
#   Internal Helper Functions
8514
#   Creating INCLUDE and LIBRARY paths
8515
#
8516
 
8517
# Assist in creating a list paths
8518
#   $pList  - Reference to an array to which $data will be added
8519
#   $pSeen  - Hash Ref to track tags that have been seen
8520
#   $data   - Data item to add, if tag is defined, but not seen
8521
#   $tag    - Resolved name for item
8522
#
227 dpurdie 8523
    sub PushPath
8524
    {
8525
        my ($pList, $pSeen, $data, $tag) = @_;
8526
        if ( $tag )
8527
        {
8528
            unless ( exists $pSeen->{$tag} )
8529
            {
8530
                $pSeen->{$tag} = 1;
8531
                push @{$pList}, $data;
8532
            }
8533
        }
8534
    }
8535
 
8536
    #
8537
    # Search paths for include files and libraries
8538
    # Currently symbolic paths are created, but there is very little need for this
8539
    #
8540
    sub MakePaths
8541
    {
8542
        my( $root ) = @_;
8543
        my @pathlist;
8544
        my %seen;
8545
 
8546
 
8547
        #   eg. SCA_WIN32   and SCA_WIN32       and SCA_SOLARIS
8548
        #       SCA             WIN32_i386          SPARC
8549
        #       WIN32           SCA                 SCA
8550
        #       .               WIN32               SOLARIS
8551
        #                       .                   .
8552
        #..
8553
        PushPath( \@pathlist, \%seen, "$root/\$(GBE_PLATFORM)",   $ScmPlatform );
8554
        PushPath( \@pathlist, \%seen, "$root/\$(GBE_PRODUCT)",    $ScmProduct );
8555
 
8556
        #
8557
        #   Insert extra path elements found in BUILDPLATFORM_PARTS
8558
        #   These will be present for BuildProduct (XXXX,-Uses=YYYY)
8559
        #   Note: Don't do for LOCAL paths, only INTERFACE
8560
        #
8561
        if ( $root =~ /INTERFACE/ ) {
8562
            my @parts = @{$::BUILDINFO{$ScmPlatform}{PARTS}};
8563
            foreach ( @parts ) {
8564
                PushPath( \@pathlist, \%seen, "$root/$_",   $_ );
8565
            }
8566
        }
8567
 
8568
        PushPath( \@pathlist, \%seen, "$root/\$(GBE_TARGET)",     $ScmTarget );
8569
 
8570
        push @pathlist, "$root";
8571
 
8572
        return \@pathlist;
8573
    }
8574
 
8575
#-------------------------------------------------------------------------------
8576
#   
8577
#
261 dpurdie 8578
    MakeHeader ("Include Search Paths",
8579
                "Local Include Paths" );
227 dpurdie 8580
 
8581
    # Include search path
8582
    #
8583
    #   user-local
8584
    #   local/
8585
    #           see above
8586
    #   interface/
8587
    #           see above
8588
    #   user-global
8589
    #
8590
 
261 dpurdie 8591
    MakeDefEntry ( "\nLINCDIRS",    "=", \@L_INCDIRS );     # .. Local
8592
    MakeDefEntry ( "LINCDIRS",      "+=", MakePaths( '$(INCDIR_LOCAL)' ));     # .. Sandbox interface
8593
    MakeDefEntry ( "LINCDIRS",      "+=", MakePaths( '$(INCDIR_INTERFACE)' )); # .. Sandbox interface
8594
    MakeDefEntry ( "LINCDIRS",      "+=", \@G_INCDIRS );    # .. Global
227 dpurdie 8595
 
261 dpurdie 8596
    MakeDefEntry   ( "INCDIRS",  "= ",  '$(LINCDIRS)' );
8597
    MakeIfDefEntry ( "PINCDIRS", "INCDIRS", "+=", '$(PINCDIRS)' );
8598
    MakeDefEntry   ( "LINCDIRS",    "+=", \@S_INCDIRS );    # .. System
227 dpurdie 8599
 
8600
    # Source search path
8601
 
261 dpurdie 8602
    MakeDefEntry( "\nNODEPDIRS",        "=", \@NODEPDIRS );
227 dpurdie 8603
 
261 dpurdie 8604
    MakeDefEntry( "\nSRCDIRS",          "=" , [ @L_SRCDIRS, @G_SRCDIRS ] );
8605
    MakeIfDefEntry ( "PINCDIRS", "SRCDIRS", "+= ", '$(PINCDIRS)' );
8606
    MakeDefEntry   ( "SRCDIRS",    "+=", \@S_INCDIRS );    # .. System
227 dpurdie 8607
 
8608
    # Library search path
8609
    #
8610
    #   user-local
8611
    #   local/
8612
    #           see above
8613
    #   interface/
8614
    #           see above
8615
    #   user-global
8616
 
261 dpurdie 8617
    MakeDefEntry( "\nLIBDIRS",  "=",  '$(LIBDIR)' );                    # User Local
8618
    MakeDefEntry( "LIBDIRS",    "+=", \@L_LIBDIRS );                    # Local
8619
    MakeDefEntry( "LIBDIRS",    "+=", MakePaths( '$(LIBDIR_LOCAL)' ));  # Sandbox/interface
8620
    MakeDefEntry( "LIBDIRS",    "+=", MakePaths( '$(LIBDIR_INTERFACE)' ));
8621
    MakeDefEntry( "LIBDIRS",    "+=", \@G_LIBDIRS );                    # Global
8622
    MakeIfDefEntry ( "PLIBDIRS", "LIBDIRS", "+= ", '$(PLIBDIRS)' );
8623
    MakeDefEntry( "LIBDIRS",    "+=", \@S_LIBDIRS );                    # System
227 dpurdie 8624
 
8625
#-------------------------------------------------------------------------------
8626
#
8627
#   Subdir creation and deletion
8628
#   Creation is done on the fly
8629
#   Deletion is done AFTER the toolset functions have been invoked to create the
8630
#   build artifacts so that the toolsets can create directories too
8631
 
8632
    MakeHeader ("Subdir creation");
8633
    CreateMkdirRules();
343 dpurdie 8634
    MkdirRule( '$(OBJDIR)', 'OBJDIR' );                # Object build directory
8635
    MkdirRule( '$(OBJDIR)/'.$_ ) foreach (@SHLIBS);    # Shared library build directory
8636
    MkdirRule( '$(LIBDIR)', 'LIBDIR' );                # Library directory
8637
    MkdirRule( '$(BINDIR)', 'BINDIR' );                # Binary directory
227 dpurdie 8638
 
261 dpurdie 8639
    #
8640
    #   Create a directory for library merge tool to work within
8641
    #
8642
    MkdirRule( "\$(MLIBDIR)", 'MLIBDIR', '--Path=$(GBE_PLATFORM).MRG', '--RemoveAll' ) if (@MLIBS);
8643
 
227 dpurdie 8644
#-------------------------------------------------------------------------------
8645
#   Generate rules and recipes to create all the toolset specific parts
8646
#   This is done fairly early to allow the toolsets to extend various
8647
#   definitions that may be used later in the makefile construction
8648
#
8649
    MakeHeader ("Construct Programs");
8650
 
8651
    foreach my $i ( @PROGS )
8652
    {
289 dpurdie 8653
        my $pProg = $PROGS->Get($i);
8654
        my $pArgs = $pProg->getItems('ARGS');
8655
        my $pObjs = $pProg->getItems('OBJS');
8656
        my $pLibs = $pProg->getItems('LIBS');
227 dpurdie 8657
 
289 dpurdie 8658
        #
8659
        #   Create a list of program object files
8660
        #
8661
        push @PROGOBJS, @$pObjs;
227 dpurdie 8662
 
8663
        MakePrint( "#---- (${i})\n\n" );
8664
        if ( $ScmToolsetProgDependancies )
8665
        {
261 dpurdie 8666
            #
8667
            #   Original style Prog Interface
271 dpurdie 8668
            #   Write some dependency information here and some in the toolset
8669
            #   Problems:
8670
            #       1) Errors in library dependency generation will be
8671
            #          reported after all the object files have been created
8672
            #          Thus the error message and the make-stop are seperated
8673
            #          by many,many lines of output. This makes it difficult
8674
            #          to see the error.
261 dpurdie 8675
            #
271 dpurdie 8676
            #       2) Lack of Flexability
8677
            #
293 dpurdie 8678
            MakeEntry( "\$(BINDIR)/$i$::exe: ", "", "\\\n\t\t", ".$::o ", @$pObjs );
227 dpurdie 8679
        }
8680
        else
8681
        {
261 dpurdie 8682
            #
8683
            #   New Style Prog Interface
8684
            #   The toolset does it all
8685
            #
8686
            #   Flag the progam packaging as a placeholder.
8687
            #   The toolset will replace/update it.
8688
            #
227 dpurdie 8689
            PackageProgRemoveFiles( $i );
8690
        }
8691
 
289 dpurdie 8692
        $if->LD    ( $i, $pArgs, $pObjs, $pLibs );
8693
        $if->LDLINT( $i, $pArgs, $pObjs, $pLibs );
227 dpurdie 8694
    }
8695
 
8696
#-------------------------------------------------------------------------------
8697
#   
8698
#
8699
    MakeHeader ("Construct Test Programs");
289 dpurdie 8700
    foreach my $i ( @TESTPROGS )
227 dpurdie 8701
    {
289 dpurdie 8702
        my $pProg = $TESTPROGS->Get($i);
8703
        my $pArgs = $pProg->getItems('ARGS');
8704
        my $pObjs = $pProg->getItems('OBJS');
8705
        my $pLibs = $pProg->getItems('LIBS');
227 dpurdie 8706
 
289 dpurdie 8707
        #
8708
        #   Create a list of program object files
8709
        #
8710
        push @TESTPROGOBJS, @$pObjs;
8711
 
227 dpurdie 8712
        MakePrint( "#---- (${i})\n\n" );
8713
        if ( $ScmToolsetProgDependancies )
8714
        {
293 dpurdie 8715
            MakeEntry( "\$(BINDIR)/$i$::exe: ", "", "\\\n\t\t", ".$::o ", @$pObjs );
227 dpurdie 8716
        }
8717
        else
8718
        {
8719
            PackageProgRemoveFiles( $i );
8720
        }
8721
 
289 dpurdie 8722
        $if->LD    ( $i, $pArgs, $pObjs, $pLibs );
8723
        $if->LDLINT( $i, $pArgs, $pObjs, $pLibs );
227 dpurdie 8724
    }
8725
 
8726
#-------------------------------------------------------------------------------
8727
#
8728
#
8729
    MakeHeader ("Transfer Scripts to BINDIR");
8730
    foreach my $i ( sort ( values %SCRIPTS ))
8731
    {
8732
        my $tname = "\$(BINDIR)/" . StripDir( $i );
8733
 
8734
 
8735
        MakePrint( "$i:\t\tmakefile.pl\n" .
261 dpurdie 8736
            "\t\$(XX_PRE)if [ ! -f \"$i\" ]; then echo Script [$i] not found; exit 2; fi\n\n" );
227 dpurdie 8737
 
8738
        #
8739
        #   Create a rule to copy the script into the BIN directory
8740
        #   Mark the script as executable - It can't hurt and its there
8741
        #   to be run as part of a test.
8742
        #
8743
        MakePrint "$tname:\t\$(GBE_BINDIR) $i\n" .
8744
                  "\t\$(XX_PRE)\$(cp) -f $i $tname\n" .
8745
                  "\t\$(XX_PRE)\$(chmod) -f +wx $tname\n\n"
8746
    }
8747
 
8748
#-------------------------------------------------------------------------------
8749
#   
8750
#
8751
    MakeHeader ("Construct Libraries");
8752
    foreach my $i ( @LIBS )
8753
    {
289 dpurdie 8754
        my $pLib  = $LIBS->Get($i);
8755
        my $pArgs = $pLib->getItems('ARGS');
8756
        my $pObjs = $pLib->getItems('OBJS');
227 dpurdie 8757
 
299 dpurdie 8758
        Error ("Library has no component objects: $i")
8759
            if ( scalar @$pObjs <= 0 );
8760
 
227 dpurdie 8761
        MakePrint "#---- (${i})\n\n";
289 dpurdie 8762
        $if->AR(     $i, $pArgs, $pObjs, $pLib);
8763
        $if->ARLINT( $i, $pArgs, $pObjs, $pLib );
227 dpurdie 8764
    }
8765
 
289 dpurdie 8766
#-------------------------------------------------------------------------------
8767
#   
8768
#
8769
    MakeHeader ("Construct Merged Libraries");
227 dpurdie 8770
    sub MlibEntry
8771
    {
289 dpurdie 8772
        my( $mlib, $plib, $pLibs ) = @_;
227 dpurdie 8773
        my @flib;
8774
 
289 dpurdie 8775
        MakePrint '$(LIBDIR)/' . GenLibName($mlib) . ":";
8776
        foreach my $lib ( @$pLibs )
227 dpurdie 8777
        {
289 dpurdie 8778
            #
8779
            #   Each library name may contains one embedded option which
8780
            #   specifies the source directory
8781
            #       libname[,--Option | BaseSubdir]
8782
            #
227 dpurdie 8783
            my ($slib, $sdir) = split( ',', $lib );
343 dpurdie 8784
            my $mode;
227 dpurdie 8785
 
8786
            #
283 dpurdie 8787
            #   By default the librares are pulled from LOCAL unless the
8788
            #   library is built in this directory, in which case it will
289 dpurdie 8789
            #   be used.
227 dpurdie 8790
            #
289 dpurdie 8791
            $sdir = ( $LIBS->Get($slib) ) ? '--Here' : '--Local'
8792
                unless ( $sdir );
227 dpurdie 8793
 
8794
            #
8795
            #   --Interface     - Pull library from the interface directory
8796
            #   --Local         - Pull library from the local directory
8797
            #   --SubDir=xxxx   - Pull library from specified subdirectory
283 dpurdie 8798
            #   --Here          - Pull from local directory if built locally
227 dpurdie 8799
            #   otherwise       - Pull library from specified subdirectory
8800
            #
8801
            if ($sdir eq '--Interface') {
8802
                $sdir = '$(LIBDIR_INTERFACE)/$(GBE_PLATFORM)';
8803
 
343 dpurdie 8804
 
8805
            } elsif ($sdir eq '--InterfacePlain') {
8806
                $sdir = '$(LIBDIR_INTERFACE)/$(GBE_PLATFORM)';
8807
                $mode = 1;
8808
 
227 dpurdie 8809
            } elsif ( $sdir eq '--Local') {
8810
                $sdir = $PackageInfo{'Lib'}{'IBase'} .  # Base of Installed libs
8811
                        $PackageInfo{'Lib'}{'Dir'};     # Default subdir
8812
 
8813
            } elsif ( $sdir =~ m~^--SubDir=(.*)~ ) {
8814
                $sdir = $1 . '/$(LIBDIR)';
8815
 
283 dpurdie 8816
            } elsif ( $sdir eq '--Here') {
8817
                $sdir = '$(LIBDIR)';
8818
 
227 dpurdie 8819
            } else {
8820
                $sdir .= '/$(LIBDIR)';
8821
            }
8822
 
343 dpurdie 8823
            MakePrint " \\\n\t\t${sdir}/" . GenLibName($slib, $mode);
227 dpurdie 8824
            push @flib, "${sdir}/${slib}";
8825
        }
289 dpurdie 8826
        return \@flib;
227 dpurdie 8827
    }
8828
 
8829
    foreach my $i ( @MLIBS )
8830
    {
289 dpurdie 8831
        my $pLib  = $MLIBS->Get($i);
8832
        my $pArgs = $pLib->getItems('ARGS');
8833
        my $pLibs = $pLib->getItems('LIBS');
227 dpurdie 8834
 
261 dpurdie 8835
        MakePrint "#---- (${i})\n\n";
8836
 
227 dpurdie 8837
        unless ( defined &ToolsetARMerge )
8838
        {
8839
            Warning( "Merging of libraries not supported in this toolset yet" );
8840
            Warning( "MergeLibrary: \"$i\" will not be created" );
8841
        }
8842
        else
8843
        {
8844
            #
8845
            #   Create the dependency rule
8846
            #       Target library : source library list
8847
            #           Recipe - generated by the toolset
8848
            #
289 dpurdie 8849
            foreach ( @$pArgs )
227 dpurdie 8850
            {
8851
                Warning( "Ignoring unknown argument to MergeLibrary. $_" );
8852
            }
289 dpurdie 8853
            $pLibs = MlibEntry( $i, $pLib, $pLibs );
8854
            $if->ARMerge( $i, $pArgs, $pLibs, $pLib );
227 dpurdie 8855
        }
8856
    }
8857
 
289 dpurdie 8858
#-------------------------------------------------------------------------------
8859
#   
8860
#
8861
    MakeHeader ("Construct Shared Libraries");
339 dpurdie 8862
 
227 dpurdie 8863
    foreach my $i ( @SHLIBS )
8864
    {
289 dpurdie 8865
        my $pShlib  = $SHLIBS->Get($i);
8866
        my $pArgs = $pShlib->getItems('ARGS');
8867
        my $pObjs = $pShlib->getItems('OBJS');
8868
        my $pLibs = $pShlib->getItems('LIBS');
8869
        my $version = $pShlib->{VERSION};
227 dpurdie 8870
 
289 dpurdie 8871
        $if->SHLD    ( $i, $pArgs, $pObjs, $pLibs, $version );
8872
        $if->SHLDLINT( $i, $pArgs, $pObjs, $pLibs, $version );
227 dpurdie 8873
    }
8874
 
8875
#-------------------------------------------------------------------------------
8876
#   Construct Objects
8877
#   For each object within OBJSOURCE construct the following:
8878
#
8879
#   $(OBJDIR)/object-name:     source-name [makefile]
8880
#       Toolset ...
8881
#
8882
#   
8883
#
8884
    MakeHeader ("Construct Objects");
8885
    foreach my $i ( sort keys %OBJSOURCE )
8886
    {
8887
        my( $src, $sname, $ext, $type, @args );
8888
 
8889
        $src  = $OBJSOURCE{ $i };
8890
        $sname = StripDir( $src );
8891
        $ext  = StripFile( $src );
8892
        $ext = lc($ext)
8893
            if ( $::ScmHost ne "Unix" );
8894
        $type = $ScmSourceTypes{ $ext }
8895
            unless (( $type = $SRC_TYPE{ $sname }) );
8896
 
8897
        #
8898
        #   Object source is an object file
8899
        #   No need the generate the object, just create makefile rule
261 dpurdie 8900
        #   [ddp] Not too sure how we get here
227 dpurdie 8901
        #
8902
        if ( $ext eq ".$::o" )
8903
        {
8904
            MakePrint "$src:";
261 dpurdie 8905
            MakePrint " \$(SCM_MAKEFILE)";
227 dpurdie 8906
            MakeNewLine();
8907
            next;
8908
        }
8909
 
8910
        #
8911
        #   Need to create object file
8912
        #
8913
        @args = split( /$;/, $SRC_ARGS{ StripDir( $sname ) } )
8914
            if $SRC_ARGS{ $sname };
8915
 
8916
        push( @args, "--Shared" )
8917
            if ( exists $SHOBJ_LIB{$i} );
8918
 
8919
        #
8920
        #   Convert relative paths to absolute paths if required by the
8921
        #   toolset. Some compilers need ABS paths to generate nice debug
8922
        #   information.
8923
        #
8924
        $src = AbsPath($src)
8925
            if ( $UseAbsObjects );
8926
 
8927
        #
8928
        #   Extract any user specified dependancies
261 dpurdie 8929
        #   These will be added to the dependency list
227 dpurdie 8930
        #
8931
        my @dlist;
8932
        @dlist = split( /$;/, $SRC_DEPEND{$sname} )
8933
            if ( exists $SRC_DEPEND{$sname} );
8934
 
261 dpurdie 8935
        #
8936
        #   Create the dependency part of the object rule
8937
        #   The source file MUST be the first dependent recipes
8938
        #   may assume that $< is the name source file
8939
        #
8940
        MakeEntry( "\$(OBJDIR)/$i.$::o: $src \$(SCM_MAKEFILE)", "", " \\\n\t", "", @dlist );
227 dpurdie 8941
 
8942
        if ( $type eq ".c" ) {
8943
            $if->CC(  $src, $i, \@args );
261 dpurdie 8944
 
227 dpurdie 8945
        } elsif ( $type eq ".cc" ) {
8946
            $if->CXX( $src, $i, \@args );
261 dpurdie 8947
 
227 dpurdie 8948
        } elsif ( $type eq ".asm" ) {
8949
            $if->AS( $src, $i, \@args );
261 dpurdie 8950
 
227 dpurdie 8951
        } else {
8952
            $if->EXT( $src, $i, \@args ) ||
8953
                Warning( "Don't know how to build '$ext' images' for $src, $i" );
8954
            MakeNewLine();
8955
        }
8956
    }
8957
 
8958
#-------------------------------------------------------------------------------
8959
#   Construct Projects
8960
#   Construct toolset specific projects
8961
#
8962
    MakeHeader ("Construct Projects");
8963
    while ( my($project, $entry) = each %PROJECTS)
8964
    {
8965
        $if->PROJECT( $entry );
8966
    }
8967
 
8968
#-------------------------------------------------------------------------------
8969
#   Automated tests
8970
#
8971
    MakeHeader ("Automated tests");
8972
 
8973
    my $idx = 0;
8974
    my @test_set = ("makefile.pl");
8975
    my @test_set_auto = ("makefile.pl");
8976
    my @copy_set = ();
8977
 
8978
    foreach my $pEntry ( @TESTS_TO_RUN )
8979
    {                                           # Foreach test
8980
        $idx++;
8981
        $pEntry->{'index'} = $idx;
8982
        $pEntry->{'test_name'} = "run_test_$idx";
8983
 
8984
        #
8985
        #   If the test is being run within a 'FrameWork' then the underlying
8986
        #   toolset must instantiate the frame work.
8987
        #
8988
        #   This may change. Perhaps frameworks shouldn't be a part of the
8989
        #   toolset. Perhaps they should be standalone. May change
8990
        #
8991
        if ( $pEntry->{framework} )
8992
        {
8993
            $if->TESTFRAMEWORK( $pEntry );
8994
        }
8995
 
8996
        #
8997
        #   Create a rule to run the test
8998
        #
8999
 
9000
        my $tdir_alias = $pEntry->{'testdir'};
9001
        my $tdir = '$(' . $tdir_alias . ')';
9002
 
9003
        my $test_name = $pEntry->{'test_name'};
9004
        push @test_set, $test_name;
9005
        push @test_set_auto, $test_name if ($pEntry->{'auto'} );
9006
 
9007
        my $tprog = $tdir . '/' . StripDir( $pEntry->{'prog'} );
9008
 
9009
        my $me = MakeEntry::New( *MAKEFILE, $test_name, '--Phony' );
9010
        $me->AddDependancy( "\$(GBE_$tdir_alias)" );
9011
        $me->AddDependancy( "\$(INTERFACEDIR)/set_$::ScmPlatform.sh" );
9012
        $me->AddDependancy( $tprog ) if $pEntry->{'copyprog'};
9013
        $me->AddDependancy( @{ $pEntry->{'copyin' } } );
9014
        $me->AddDependancy( map { $tdir . '/' . StripDir($_) } @{ $pEntry->{'copyonce' } } );
9015
        $me->AddDependancy( @{ $pEntry->{'preq'} } );
9016
        $me->RecipePrefix ('$(XX_PRE)');
9017
        $me->RecipeComment( "------ Running test [$idx] ..." );
9018
 
9019
        #
9020
        #   Extend the PATH seen by the script to include the local/bin directory
9021
        #   Allows programs and tests that have been created elsewhere in the component
9022
        #   to be accessed within the script.
9023
        #
9024
        $me->AddShellRecipe ( ". \$(INTERFACEDIR)/set_$::ScmPlatform.sh" );
9025
 
9026
        #
9027
        #   Copy in the files that we need
9028
        #
9029
        foreach my $file ( @{$pEntry->{'copyin'}} )
9030
        {
9031
            my $dst = $tdir . '/' . StripDir( $file );
9032
            UniquePush( \@COPYIN, $dst );
9033
            UniquePush( \@copy_set, $file );
9034
            $me->AddShellRecipe ( "\$(cp) -f $file $dst" );
9035
            $me->AddShellRecipe ( "\$(chmod) -f +wx $dst" );
9036
        }
9037
 
9038
        #
9039
        #   Insert and FrameWork Recipe bits
9040
        #
9041
        $me->AddShellRecipe ( @{$pEntry->{'ShellRecipe'}} );
9042
 
9043
        $me->AddShellRecipe ( "cd $tdir" );
9044
        $me->AddShellRecipe ( ["GBE_TYPE=\$(GBE_TYPE)",
9045
                               "GBE_HOST=\$(GBE_HOST)",
9046
                               "GBE_ROOT=\$(GBE_ROOT_ABS)",
9047
                    		   "PATH=.\\$::ScmPathSep\$(BINDIR_LOCAL_PATH)\\$::ScmPathSep\$\$PATH",
9048
                               $pEntry->{'command'},
9049
                               @{$pEntry->{'args'}},
9050
                               ] );
9051
        $me->Print();
9052
 
9053
 
9054
        #
9055
        #   Create entries to handle the copy-once files
9056
        #
9057
        foreach my $file ( @{ $pEntry->{'copyonce' } } )
9058
        {
9059
            my $tname = $tdir . '/' . StripDir($file);
9060
            my $me = MakeEntry::New( *MAKEFILE, $tname  );
9061
            $me->AddDependancy( $file );
9062
            $me->AddRecipe ( "\$(call CopyFile,CopyIn,$tname,$file,$tdir,)"  );
9063
            $me->Print();
9064
 
9065
            UniquePush( \@COPYIN, $tname );
9066
            UniquePush( \@copy_set, $file );
9067
 
9068
        }
9069
    }
9070
 
9071
    #
9072
    #   Generate a target that specifies the tests to be run
9073
    #   Each test is provided with a dummy name
9074
    #
9075
    push @test_set, @TESTPROJECT_TO_ARUN;
9076
    push @test_set, @TESTPROJECT_TO_URUN;
9077
    MakeEntry3("\nrun_tests", ":", \@test_set )
9078
        if (@test_set);
9079
 
9080
    push @test_set_auto, @TESTPROJECT_TO_ARUN;
9081
    MakeEntry3("\nrun_unit_tests", ":", \@test_set_auto )
9082
        if (@test_set_auto);
9083
 
9084
    #
9085
    #   Generate sanity test for each copyin script
9086
    #   Simply to provide a nice error message for generated scripts
9087
    #   that do not exist at run-time
9088
    #
9089
    test_copy_in:
9090
    foreach my $i ( @copy_set )
9091
    {
9092
        next if ( $SCRIPTS{$i} );
9093
        foreach (  @SHLIB_TARGETS )
9094
        {
9095
            next test_copy_in if ( $i eq $_ );
9096
        }
9097
        MakePrint( "\n$i:\t\tmakefile.pl\n" .
9098
            "\t\@if [ ! -f \"$i\" ]; then echo ERROR: CopyIn Script [$i] not found; exit 2; fi\n" );
9099
    }
9100
 
261 dpurdie 9101
#-------------------------------------------------------------------------------
9102
#   Deploy rules
9103
#
9104
MakeHeader ("Deploy Rules");
227 dpurdie 9105
 
261 dpurdie 9106
print MAKEFILE <<EOF;
9107
.PHONY:		run_deploy
9108
EOF
227 dpurdie 9109
 
261 dpurdie 9110
#
9111
#   Build up the deployfile.pl command line from the available pieces
9112
#
9113
my $command_file = "";
9114
my @command_line;
9115
 
9116
if ( %DEPLOYPACKAGE )
9117
{
9118
    $command_file = $DEPLOYPACKAGE{'cmdfile'};
9119
 
9120
    push @command_line, "\$(XX_PRE)\$(GBE_PERL) -w $command_file";
9121
    push @command_line, "-r \"\$(GBE_ROOT)\"";
9122
    push @command_line, "-n \"$DEPLOYPACKAGE{'name'}\"";
9123
    push @command_line, "-d \"$DEPLOYPACKAGE{'dir'}\"";
9124
    push @command_line, "-v \"\$(BUILDVER)\"";
9125
    push @command_line, "-t \"\$(GBE_TYPE)\"";
9126
    push @command_line, "-o \"\$(BUILDPREVIOUSVER)\"";
9127
    push @command_line, "-m \"\$(GBE_PLATFORM)\"";
9128
    push @command_line, "-g \"\$(GBE_TARGET)\"";
9129
    push @command_line, "-k \"\$(GBE_PRODUCT)\""        if ( $ScmProduct );
9130
    push @command_line, "-p \"\$(DEPLOYPATCH)\""        if ( $ScmDeploymentPatch );
9131
 
9132
}
9133
 
9134
MakeEntry( "run_deploy:\t$command_file\n", "\n", "\t\t", " \\\n", @command_line );
9135
 
227 dpurdie 9136
#-------------------------------------------------------------------------------
261 dpurdie 9137
#   Custom Rules
9138
#
9139
    MakeHeader ("Custom Rules");
9140
    MakePrintList ( \@RULES );
9141
 
9142
#-------------------------------------------------------------------------------
9143
#   Generated Files
9144
#
9145
    MakeHeader ("Generated Files");
9146
    MakePrint ("\n.PHONY: phony_generate\n\n" );
9147
 
9148
    foreach my $i ( @GENERATE_FILES )
9149
    {
9150
        my $gen_tag = $i->{'index'};
9151
 
9152
        #
263 dpurdie 9153
        #   If predelete is enabled, then create a list of files to delete
9154
        #
9155
        if ( $i->{'predelete'}  )
9156
        {
9157
            MakeDefEntry( "generate_gen_$gen_tag", "=",  $i->{'gen'} );
9158
            MakePrint("\n")
9159
        }
9160
 
9161
 
9162
        #
261 dpurdie 9163
        #   Generate the basic generate rule and recipe
9164
        #   together with the prerequisites
9165
        #
9166
        MakeEntry ( "", ":", "", " ", @{$i->{'gen'}} );
9167
 
9168
        unless ( $i->{'clean'} && $i->{'shell'} )
9169
        {
9170
            MakeEntry ( "", "", " \\\n\t\t", "", @{$i->{'preq'}} );
9171
            MakeEntry ( "", "", " \\\n\t\t", "", "phony_generate" ) if $i->{'preq_sus'};
9172
            MakeEntry ( "", "", " \\\n\t\t", "", "\$(SCM_MAKEFILE)" );
9173
 
9174
            MakePrint ("\n\t" . "\@\$(echo) [$i->{'text'}] generating.." );
263 dpurdie 9175
            if ( $i->{'predelete'}  )
9176
            {
9177
                MakePrint ("\n\t" . "\$(XX_PRE)\$(call RmFiles,generate_gen_$gen_tag)" );
9178
            }
261 dpurdie 9179
            MakePrint ("\n\t" . "\$(XX_PRE)\$(call generate_$gen_tag,)" );
9180
        }
9181
 
9182
        #
9183
        #   Generate 'clean' rules and recipes
9184
        #
9185
        if ( $i->{'clean'} )
9186
        {
9187
            MakePrint ("\n\nPHONY: clean_generate_$gen_tag" );
9188
            MakePrint ("\nclean_generate_$gen_tag:" );
343 dpurdie 9189
            MakePrint ("\n\t" . "\$(XX_PRE)-\$(call generate_$gen_tag,$i->{'clean'})" );
261 dpurdie 9190
        }
9191
 
9192
        #
9193
        #   Define a function to contain the body of the generation call
9194
        #   The first argument will be a 'clean' argument
9195
        #
9196
        MakePrint ("\n\ndefine generate_$gen_tag" );
9197
        if ( $i->{'shell'} )
9198
        {
9199
            MakeEntry ("\n\t(" , "\\\n\t)\n", " \\\n\t", ";" , @{$i->{'toolargs'}} );
9200
        }
9201
        else
9202
        {
9203
            MakeEntry ("\n\t" . $i->{'tool'} . ' $1', "\n", " \\\n\t\t", "" , @{$i->{'toolargs'}} );
9204
        }
9205
        MakePrint ("endef\n\n" );
9206
    }
9207
 
9208
#-------------------------------------------------------------------------------
9209
#   Toolset Post Processing
9210
#   Allow the toolset to perform any post processing, before we finally write
9211
#   out any definitions.
9212
#
9213
#   We will not interprete any more user directives, but new stuff may get added
9214
#
9215
#
9216
MakeHeader ("Toolset Post Processing");
9217
$if->Postprocess();
9218
 
9219
################################################################################
9220
#   All interactions with the toolset are now complete
9221
#   All lists are now complete
9222
#
9223
#   Can now create internal definitions
9224
#   
9225
################################################################################
9226
 
9227
    #
9228
    #   Would be nice if this would work
9229
    #   Unfortunatelty we still need $if for the CCDEPENDS and CTAGS work
9230
    #   These must be defined AFTER the definitions
9231
    #
9232
    #   Ideally we should construct our makefile in sections
9233
    #   and then we can order the sections when we write them out
9234
    #
9235
#$if = 0;                            # Ensure the MakeIf class is not called
9236
                                     # If this file is modified
9237
 
9238
#-------------------------------------------------------------------------------
227 dpurdie 9239
#   Sources
9240
#
9241
MakeHeader  ( "Sources");
9242
MakeDefEntry( "CSRCS",      "=",  \@CSRCS );
9243
MakeDefEntry( "CXXSRCS",    "=",  \@CXXSRCS );
9244
MakeDefEntry( "ASSRCS",     "=",  \@ASSRCS );
9245
 
9246
#-------------------------------------------------------------------------------
9247
#   Generated, Installed and Packaged components
9248
#
9249
MakeHeader  ("Generated, Installed and Packaged components");
9250
MakeDefEntry( "INITS",           "=",  \@INITS )   if ( @INITS );
9251
MakeDefEntry( "GENERATED",       "=",  \@GENERATED ) if ( @GENERATED );
9252
MakeDefEntry( "GENERATED_NOTSRC","=",  \@GENERATED_NOTSRC ) if ( @GENERATED_NOTSRC );
9253
MakeDefEntry( "GENERATEDCLEAN",  "=",  CreateNameList( 'clean_generate_', '', ListCleanGenerated() ));
9254
MakeDefEntry( "INSTALL_HDRS",    "=",  \%INSTALL_HDRS ) if ( %INSTALL_HDRS );
9255
MakeDefEntry( "INSTALL_CLSS",    "=",  \%INSTALL_CLSS ) if ( %INSTALL_CLSS );
9256
MakeDefEntry( "OBJS",            "=", CreateNameList( '$(OBJDIR)/', ".$::o", \@OBJS) );
9257
MakeDefEntry( "SHOBJS",          "=", CreateNameList( '$(OBJDIR)/', ".$::o", \%SHOBJ_LIB ));
289 dpurdie 9258
MakeDefEntry( "PROGOBJS",        "=", CreateNameList( '', ".$::o", \@PROGOBJS ));
9259
MakeDefEntry( "TESTPROGOBJS",    "=", CreateNameList( '', ".$::o", \@TESTPROGOBJS ));
9260
MakeDefEntry( "LIBS",            "=", $LIBS->AllTargets() ) if ($::a);
9261
MakeDefEntry( "MLIBS",           "=", $MLIBS->AllTargets() ) if ($::a);
227 dpurdie 9262
MakeDefEntry( "SHNAMES",         "=", \@SHLIBS );
9263
MakeDefEntry( "SHDIRS",          "=", CreateNameList( '$(OBJDIR)/', "", \@SHLIBS ));
9264
MakeDefEntry( "SHLIBS",          "=", \@SHLIB_TARGETS );
9265
MakeDefEntry( "SCRIPTS",         "=", CreateNameList( '$(BINDIR)/', "", \%SCRIPTS ));
9266
MakeDefEntry( "COPYIN",          "=", \@COPYIN );
289 dpurdie 9267
MakeDefEntry( "PROGS",           "=", $PROGS->AllTargets() );
227 dpurdie 9268
MakeDefEntry( "PROGS_EXTRA",     "=", \@PROGS_EXTRA );
289 dpurdie 9269
MakeDefEntry( "TESTPROGS",       "=", $TESTPROGS->AllTargets());
227 dpurdie 9270
MakeDefEntry( "LINTLIBS",        "=", CreateNameList( 'lib_', '_lint', \@LINTLIBS ));
9271
MakeDefEntry( "LINTSHLIBS",      "=", CreateNameList( 'shlib_', '_lint', \@LINTSHLIBS ));
9272
MakeDefEntry( "LINTPROGS",       "=", CreateNameList( 'prog_', '_lint', \@PROGS ));
289 dpurdie 9273
MakeDefEntry( "LINTPROGS",      "+=", CreateNameList( 'prog_', '_lint', \@TESTPROGS ));
227 dpurdie 9274
MakeDefEntry( "PROJECTS",        "=", CreateNameList( 'Project_', '', ListGeneratedProjects(1) ));
9275
MakeDefEntry( "PROJECTSGEN",     "=", CreateNameList( 'Project_', '', ListGeneratedProjects(0) ));
9276
MakeDefEntry( "PROJECTSCLEAN",   "=", CreateNameList( 'ProjectClean_', '', \%PROJECTS ));
9277
 
261 dpurdie 9278
MakeHeader ("Toolset components");
9279
MakeDefEntry( "USERGENERATED",        "=", \@USERGENERATED )    if ( @USERGENERATED );
9280
MakeDefEntry( "TOOLSETGENERATED",     "=", \@TOOLSETGENERATED ) if ( @TOOLSETGENERATED );
9281
MakeDefEntry( "TOOLSETOBJS",          "=", \@TOOLSETOBJS )      if ( @TOOLSETOBJS );
9282
MakeDefEntry( "TOOLSETLIBS",          "=", \@TOOLSETLIBS )      if ( @TOOLSETLIBS );
9283
MakeDefEntry( "TOOLSETPROGS",         "=", \@TOOLSETPROGS )     if ( @TOOLSETPROGS );
9284
MakeDefEntry( "TOOLSETDIRS",          "=", \@TOOLSETDIRS )      if ( @TOOLSETDIRS );
9285
MakeDefEntry( "TOOLSETDIRTREES",      "=", \@TOOLSETDIRTREES )  if ( @TOOLSETDIRTREES );
227 dpurdie 9286
 
9287
#--------- Determine compiler flag groups to use ----------------------------
9288
#
9289
#   Allows the compiler options to be controlled for both the debug and
9290
#   the production builds. Allows control over
9291
#       1) Optimisations
9292
#       2) Debug Information
9293
#
9294
MakeHeader ("Determine compiler flag groups to use");
9295
 
9296
print MAKEFILE <<EOF;
9297
 
9298
ifneq "\$(DEBUG)" "1"
9299
USE_OPTIMISE	:= \$(PROD_USE_OPTIMISE)
9300
USE_DEBUGINFO	:= \$(PROD_USE_DEBUGINFO)
9301
else
9302
USE_OPTIMISE	:= \$(DEBUG_USE_OPTIMISE)
9303
USE_DEBUGINFO	:= \$(DEBUG_USE_DEBUGINFO)
9304
endif
9305
 
9306
EOF
9307
 
261 dpurdie 9308
#-------------------------------------------------------------------------------
9309
#   Source browsing tools
9310
#
9311
MakeHeader ("Source browsing tools");
9312
    print MAKEFILE <<EOF;
9313
.PHONY:			ctags
9314
ctags:
9315
EOF
9316
    $if->CTAGS()
9317
        if (@CSRCS || @CXXSRCS);
227 dpurdie 9318
 
261 dpurdie 9319
#-------------------------------------------------------------------------------
9320
#   Depend
9321
#   If we are build C or C++ source files then create rules and recipes
9322
#   to invoke a dependency generator.
227 dpurdie 9323
#
261 dpurdie 9324
#   NODEPEND is used to disable, at make-time, the dependency generation
9325
#   and inclusion process.
9326
#
9327
#
9328
MakeHeader ("Depend");
9329
if ($::o && (@CSRCS || @CXXSRCS))
9330
{
9331
    $ScmDependTags = 1;
9332
    print MAKEFILE <<EOF;
9333
depend:			\$(OBJDIR)/depend
9334
 
9335
\$(OBJDIR)/depend:	\$(SCM_MAKEFILE) \$(GBE_OBJDIR)
9336
\$(OBJDIR)/depend:	\$(CSRCS) \$(CXXSRCS)
9337
ifeq (\$(NODEPEND),0)
9338
	\@echo [\$@] Doing a make depend..
9339
	-\$(XX_PRE)\$(rm) -f \$(OBJDIR)/depend
9340
EOF
9341
    $if->CCDepend( "\$(OBJDIR)/depend", "\$(CSRCS)" )
9342
        if ( @CSRCS );
9343
    $if->CXXDepend( "\$(OBJDIR)/depend", "\$(CXXSRCS)" )
9344
        if ( @CXXSRCS );
9345
    MakePrint
9346
        "\t-\@\$(touch) -f \$(OBJDIR)/depend\n";
9347
    print MAKEFILE <<EOF;
9348
else
9349
	\@echo [\$@] Skipping make depend..
9350
	-\$(XX_PRE)\$(rm) -f \$(OBJDIR)/depend
9351
endif
9352
EOF
9353
}
9354
else
9355
{
9356
    print MAKEFILE <<EOF;
9357
depend:
9358
EOF
9359
}
9360
 
9361
#
9362
#   Rule to unmake the depend file
9363
#
9364
    print MAKEFILE <<EOF;
9365
 
9366
undepend:
9367
	-\$(XX_PRE)\$(rm) -f \$(OBJDIR)/depend
9368
EOF
9369
 
9370
#--------- IFLAG Documentation -------------------------------------------------
9371
#
9372
#   IFLAG - iteration flag. This is setting by the calling process
9373
#                           and is a function of the phase being processed
227 dpurdie 9374
#       0   No external dependencies.
9375
#       1   Source dependency list.
261 dpurdie 9376
#       2   Shared library dependency list
9377
#       3   Application dependency list
227 dpurdie 9378
#
9379
#
261 dpurdie 9380
#--------- Dependencies --------------------------------------------------------
9381
#   Include the 'depend' file if required
9382
#
9383
    MakeHeader ("Dependency Inclusion");
9384
    print MAKEFILE <<EOF;
9385
ifeq (\$(NODEPEND),0)
9386
 ifdef IFLAG
9387
  ifneq "\$(IFLAG)" "0"
9388
-include	\$(OBJDIR)/depend
9389
  endif
227 dpurdie 9390
 endif
9391
endif
9392
 
9393
EOF
9394
 
9395
#-------------------------------------------------------------------------------
9396
#   Standard rules
9397
#
9398
MakeHeader ("Standard rules");
9399
 
9400
    print MAKEFILE <<EOF;
9401
.PHONY:		make_usage
9402
make_usage:
9403
	\@echo -e \\
9404
	" make [SHOWENV=1] [LEAVETMP=1] [OPTIONS=[opt][,...]] {DEBUG=0|1} target(s)\\n"\\
9405
	"\\n"\\
9406
	"Build one or more of the following targets for the platform\\n"\\
9407
	"$ScmPlatform, recursively checking each configured sub directories.\\n"\\
9408
	"\\n"\\
9409
	"Valid targets include:\\n"\\
9410
	"  all:             build, install and package\\n"\\
9411
	"  build:           build everything\\n"\\
9412
	"  debug:           build all things for debug\\n"\\
9413
	"  prod:            build all things for production\\n"\\
9414
	"  install:         install of public usage\\n"\\
9415
	"  depend:          construct the dependencies\\n"\\
9416
	"  lint:            lints C and C++ source\\n"\\
9417
	"  package:         build all packages\\n"\\
9418
	"  package-{set}:   build specific package\\n"\\
9419
	"  unpackage:       remove all packages\\n"\\
9420
	"  run_tests:       Run the tests specified in the makefile\\n"\\
9421
	"  run_unit_tests:  Run the automatic unit tests specified in the makefile\\n"\\
9422
	"  deploy:          Run the deployment scripts\\n"\\
9423
	"  rmlitter:        remove litter (core, bak, tmp, err and cmd files)\\n"\\
9424
	"  clean:           delete generate, obj, libraries and programs\\n"\\
9425
	"  unbuild:         delete everything which can be remade\\n"\\
9426
	"  clobber:         unbuilds and deletes packages\\n"\\
9427
EOF
9428
 
9429
    print MAKEFILE <<EOF;
9430
	"\\n"
9431
 
9432
make_clean:
9433
	-\@echo "Removing generated files (objects, libraries, binaries etc)";
9434
 
9435
#
9436
#   Under windows/cygwin, there is a problem with the rm being used
9437
#   The expansion of wildcards will terminate the command if:
9438
#       1) No files exist to expand  : Solution : touch a file of that type
9439
#       2) A directory is involved   : Solution : cd to directory
9440
#
9441
#   Cannot use make's wildcard function as this only operates in the current directory
9442
#
9443
.PHONY:		rmlitter
9444
rmlitter:
315 dpurdie 9445
	-\$(AA_PRE)( echo "Removing litter";\\
227 dpurdie 9446
		\$(touch) _delete.bak _delete.tmp _delete.err ;\\
9447
		\$(rm) -f core *.bak *.tmp *.err ;\\
293 dpurdie 9448
		for subdir in \$(SHDIRS) '' ; do \\
9449
			if [ -d "\$\$subdir" ] ; then \\
227 dpurdie 9450
				( cd \$\$subdir ;\\
9451
				\$(touch) _delete.err _delete.cmd ;\\
289 dpurdie 9452
				\$(rm) -r * ; );\\
9453
			fi ;\\
9454
		done;\\
293 dpurdie 9455
		for subdir in \$(OBJDIR) '' ; do \\
9456
			if [ -d "\$\$subdir" ] ; then \\
289 dpurdie 9457
				( cd \$\$subdir ;\\
9458
				\$(touch) _delete.err _delete.cmd ;\\
227 dpurdie 9459
				\$(rm) -r *.err *.cmd ; );\\
9460
			fi ;\\
9461
		done;\\
9462
	)
9463
 
261 dpurdie 9464
.PHONY:		lint_init
9465
lint_init:
9466
 
227 dpurdie 9467
EOF
9468
 
261 dpurdie 9469
#
9470
#   Dependencies for 'make_init'
9471
#
9472
#
9473
my @initdep;
9474
push @initdep, '$(INITS)' if ( @INITS );
227 dpurdie 9475
 
261 dpurdie 9476
#
9477
#   Dependencies for 'make_dir'
9478
#
9479
my @mkdirdep;
289 dpurdie 9480
push @mkdirdep, '$(GBE_OBJDIR)' if ( @CSRCS || @CXXSRCS || @OBJS || @PROGOBJS || @TESTPROGOBJS );
261 dpurdie 9481
push @mkdirdep, '$(SHDIRS)'     if ( %SHOBJ_LIB || @SHLIBS);
9482
push @mkdirdep, '$(GBE_LIBDIR)' if ( @LIBS || @MLIBS || @SHLIBS || %INSTALL_LIBS || %PACKAGE_LIBS );
289 dpurdie 9483
push @mkdirdep, '$(GBE_BINDIR)' if ( @SHLIBS || %SCRIPTS || @PROGS || @TESTPROGS || %INSTALL_PROGS || %PACKAGE_PROGS );
227 dpurdie 9484
 
261 dpurdie 9485
#
9486
#   Actions for for 'unobj'
9487
#
9488
my @unobjact;
9489
push @unobjact, RmFilesCmd( 'OBJS' )            if ( @OBJS );
9490
push @unobjact, RmFilesCmd( 'SHOBJS' )          if ( %SHOBJ_LIB );
9491
push @unobjact, RmFilesCmd( 'PROGOBJS' )        if ( @PROGOBJS );
289 dpurdie 9492
push @unobjact, RmFilesCmd( 'TESTPROGOBJS' )    if ( @TESTPROGOBJS );
261 dpurdie 9493
push @unobjact, RmFilesCmd( 'TOOLSETOBJS' )     if ( @TOOLSETOBJS );
227 dpurdie 9494
 
261 dpurdie 9495
#
9496
#   Dependencies for 'make_lib'
9497
#
9498
my @libdep;
9499
push @libdep, '$(GBE_OBJDIR)', '$(GBE_LIBDIR)', '$(LIBS)' if ( @LIBS );
227 dpurdie 9500
 
261 dpurdie 9501
#
9502
#   Dependencies for 'lint_lib'
9503
#
9504
my @liblintdep;
9505
push @liblintdep, 'lint_init', '$(GBE_OBJDIR)', '$(GBE_LIBDIR)', '$(LINTLIBS)' if ( @LIBS );
227 dpurdie 9506
 
261 dpurdie 9507
#
9508
#   Dependencies for 'make_mlib'
9509
#
9510
my @mlibdep;
9511
push @mlibdep, '$(GBE_OBJDIR)', '$(GBE_LIBDIR)', '$(GBE_MLIBDIR)', '$(MLIBS)' if ( @MLIBS );
227 dpurdie 9512
 
261 dpurdie 9513
#
9514
#   Dependencies for 'make_install_shlib' (tag)
9515
#
9516
my @shlibdep;
9517
push @shlibdep, '$(SHDIRS)', '$(SHLIBS)' if ( @SHLIBS );
227 dpurdie 9518
 
261 dpurdie 9519
#
9520
#   Dependencies for 'lint_shlib'
9521
#
9522
my @shliblintdep;
9523
push @shliblintdep, 'lint_init', '$(GBE_LIBDIR)', '$(LINTSHLIBS)' if ( @SHLIBS );
227 dpurdie 9524
 
261 dpurdie 9525
#
9526
#   Actions for 'unmake_lib'
9527
#
9528
my @unlibact;
9529
push @unlibact, RmFilesCmd( 'SHLIBS' )      if ( @SHLIBS );
9530
push @unlibact, RmFilesCmd( 'MLIBS' )       if ( @MLIBS );
9531
push @unlibact, RmFilesCmd( 'LIBS' )        if ( @LIBS );
9532
push @unlibact, RmFilesCmd( 'TOOLSETLIBS' ) if ( @TOOLSETLIBS );
227 dpurdie 9533
 
261 dpurdie 9534
#
9535
#   Actions for 'unmake_mlib'
9536
#
9537
my @unmlibact;
9538
push @unmlibact, RmFilesCmd( 'MLIBS' ) if ( @MLIBS );
227 dpurdie 9539
 
261 dpurdie 9540
#
9541
#   Dependencies for 'make_script'
9542
#
9543
my @scriptdep;
9544
push @scriptdep, '$(GBE_BINDIR)', '$(SCRIPTS)' if ( %SCRIPTS );
227 dpurdie 9545
 
261 dpurdie 9546
#
9547
#   Actions for 'unmake_script'
9548
#
9549
my @unscriptact;
9550
push @unscriptact , RmFilesCmd( 'SCRIPTS' ) if ( %SCRIPTS );
9551
push @unscriptact , RmFilesCmd( 'COPYIN' )  if ( @COPYIN );
227 dpurdie 9552
 
261 dpurdie 9553
#
9554
#   Dependencies for 'make_prog'
9555
#
9556
my @progdep;
9557
push @progdep, '$(GBE_OBJDIR)', '$(GBE_BINDIR)', '$(PROGS)' if ( @PROGS );
9558
push @progdep, '$(PROGS_EXTRA)' if (@PROGS_EXTRA);
227 dpurdie 9559
 
261 dpurdie 9560
#
9561
#   Dependencies for 'make_prog' created for 'projects'
9562
#
9563
my @projectdep;
9564
push @projectdep, '$(PROJECTS)' if (ListGeneratedProjects(1) );
227 dpurdie 9565
 
261 dpurdie 9566
#
9567
#   Dependencies for 'generate' created for 'projects'
9568
#
9569
my @projectgendep;
9570
push @projectgendep, '$(PROJECTSGEN)' if (ListGeneratedProjects(0) );
227 dpurdie 9571
 
261 dpurdie 9572
#
9573
#   Dependencies for 'unmake_prog' created for 'projects'
9574
#
9575
my @projectcleandep;
9576
push @projectcleandep, '$(PROJECTSCLEAN)' if (%PROJECTS);
227 dpurdie 9577
 
261 dpurdie 9578
#
9579
#   Dependencies for 'lint_prog'
9580
#
9581
my @proglintdep;
289 dpurdie 9582
push @proglintdep, 'lint_init', '$(GBE_OBJDIR)', '$(GBE_BINDIR)', '$(LINTPROGS)' if ( @PROGS || @TESTPROGS );
227 dpurdie 9583
 
261 dpurdie 9584
#
9585
#   Actions for 'unmake_prog'
9586
#
9587
my @unprogact;
9588
push @unprogact, RmFilesCmd( 'PROGS' )        if ( @PROGS );
9589
push @unprogact, RmFilesCmd( 'TOOLSETPROGS' ) if ( @TOOLSETPROGS );
227 dpurdie 9590
 
261 dpurdie 9591
#
9592
#   Dependencies for 'lint_prog'
9593
#
9594
my @testprogdep;
289 dpurdie 9595
push @testprogdep, '$(GBE_OBJDIR)', '$(GBE_BINDIR)', '$(TESTPROGS)' if ( @TESTPROGS );
227 dpurdie 9596
 
9597
#
261 dpurdie 9598
#   Dependencies for 'run_tests' and friends
9599
#
9600
my @untestprogact;
289 dpurdie 9601
push @untestprogact ,RmFilesCmd( 'TESTPROGS' ) if ( @TESTPROGS );
227 dpurdie 9602
 
261 dpurdie 9603
#
9604
#   Dependencies for 'generated'
9605
#
9606
my @generatedep;
9607
push @generatedep, '$(GENERATED)' if ( @GENERATED );
9608
 
9609
#
9610
#   Actions for 'ungenerate'
9611
#
9612
my @ungenact;
9613
push @ungenact, RmFilesCmd( 'GENERATED' ) if ( @GENERATED );
9614
push @ungenact, RmFilesCmd( 'GENERATED_NOTSRC' ) if ( @GENERATED_NOTSRC );
9615
push @ungenact, RmFilesCmd( 'TOOLSETGENERATED' ) if ( @TOOLSETGENERATED );
9616
push @ungenact, RmFilesCmd( 'USERGENERATED' ) if ( @USERGENERATED );
9617
 
9618
#
9619
#   Dependencies for 'ungenerate'
9620
#
9621
my @ungeneratedep;
9622
push @ungeneratedep, '$(GENERATEDCLEAN)';
9623
 
227 dpurdie 9624
#-------------------------------------------------------------------------------
261 dpurdie 9625
# Function        : PrintPhonyRule
227 dpurdie 9626
#
261 dpurdie 9627
# Description     : Helper function to print some internal phony makefile targets
9628
#                   These are used to hold the basic makefile together
9629
#
9630
# Inputs          : $target         - Name of the phony target
9631
#                   $prereq         - Prerequisites
9632
#                                     Leading spaces removed
9633
#                   $recipe         - Optional Reference to an array of recipes
9634
#                                     Will be printed one per line
9635
#
9636
#
9637
sub PrintPhonyRule
227 dpurdie 9638
{
261 dpurdie 9639
    my ($target, $prereq, $recipe) = @_;
9640
    $prereq =~ s/^\s+//;
227 dpurdie 9641
 
261 dpurdie 9642
    MakePadded( 2, '.PHONY:', $target, "\n");
9643
    MakePadded( 2,"$target:", $prereq, "\n");
9644
    MakePrint ("\t\t" . $_ . "\n") foreach ( @{$recipe} );
9645
    MakePrint ("\n");
227 dpurdie 9646
}
9647
 
261 dpurdie 9648
#   make_init - Test toolset presence and sanity
9649
#   Will only be called ONCE for each platform in a recursive build
9650
#   Should be used to ensure that the required toolset is present
9651
#
9652
PrintPhonyRule ('make_init',       "@initdep" );
227 dpurdie 9653
 
261 dpurdie 9654
#   make_dir    - Create required subdirectories
9655
#   Will be invoked as a part of most targets that create files
9656
#   Will be invoked by the calling wrappers
9657
#   Should not be invoked when cleaning
9658
#
9659
PrintPhonyRule ('make_dir',       "@mkdirdep" );
9660
 
9661
 
9662
PrintPhonyRule ('generate',       "@generatedep @projectgendep" );
9663
PrintPhonyRule ('ungenerate',     "@ungeneratedep",  \@ungenact);
9664
PrintPhonyRule ('unobj',          "",  \@unobjact);
9665
PrintPhonyRule ('make_lib',       "@libdep" );
9666
PrintPhonyRule ('lint_lib',       "@liblintdep" );
9667
PrintPhonyRule ('make_mlib',      "@mlibdep" );
9668
PrintPhonyRule ('lint_shlib',     "@shliblintdep" );
9669
PrintPhonyRule ('unmake_lib',     "", \@unlibact );
9670
PrintPhonyRule ('unmake_mlib',    "", \@unmlibact );
9671
PrintPhonyRule ('make_script',    "@scriptdep" );
9672
PrintPhonyRule ('unmake_script',  "", \@unscriptact );
9673
PrintPhonyRule ('make_prog',      "@scriptdep @progdep @projectdep" );
9674
PrintPhonyRule ('lint_prog',      "@proglintdep" );
9675
PrintPhonyRule ('run_tests',      "@scriptdep @testprogdep" );
9676
PrintPhonyRule ('run_unit_tests', "@scriptdep @testprogdep" );
9677
PrintPhonyRule ('unmake_prog',    "unmake_script @projectcleandep", \@unprogact );
9678
PrintPhonyRule ('make_test',      "@scriptdep @testprogdep" );
9679
PrintPhonyRule ('unmake_test',    "unmake_script", \@untestprogact );
9680
 
227 dpurdie 9681
#-------------------------------------------------------------------------------
9682
#   Package and Installation Summary
9683
#
9684
    MakeHeader ("Package and Installation Summary");
9685
    sub InstallTarget
9686
    {
9687
        my( $target, $hashp, $prereq, $fprereq ) = @_;
9688
        my( $element );
9689
 
343 dpurdie 9690
        MakePrint ".PHONY:\t\t"."$target\n";
227 dpurdie 9691
        MakePrint "$target:";
9692
        MakePrint "\t$fprereq" if ($fprereq);
9693
 
9694
        foreach my $element ( sort keys %{$hashp} )
9695
        {
9696
            #
9697
            #   Skip placekeepers
9698
            #
9699
            next if ( $hashp->{$element}{'placekeeper'} );
9700
 
9701
            #
9702
            #   Prepend any prerequisites (once)
9703
            #
9704
            if ( $prereq )
9705
            {
9706
                MakePrint " \\\n\t${prereq}";
9707
                $prereq = 0;
9708
            }
9709
 
9710
            MakePrint " \\\n\t${element}";
9711
        }
9712
        MakePrint "\n\n";
9713
    }
9714
 
9715
InstallTarget( "install_hdr",       \%INSTALL_HDRS );
9716
InstallTarget( "install_lib",       \%INSTALL_LIBS,  'make_mlib' );
261 dpurdie 9717
InstallTarget( "make_install_shlib",\%INSTALL_SHLIBS, '', "@shlibdep" );
227 dpurdie 9718
InstallTarget( "install_prog",      \%INSTALL_PROGS, 'make_script' );
9719
InstallTarget( "install_class",     \%INSTALL_CLSS );
9720
 
9721
InstallTarget( "package_files",     \%PACKAGE_FILES );
9722
InstallTarget( "package_hdr",       \%PACKAGE_HDRS );
9723
InstallTarget( "package_lib",       \%PACKAGE_LIBS );
9724
InstallTarget( "package_shlib",     \%PACKAGE_SHLIBS );
9725
InstallTarget( "package_prog",      \%PACKAGE_PROGS, 'make_script' );
9726
InstallTarget( "package_class",     \%PACKAGE_CLSS );
9727
 
9728
#-------------------------------------------------------------------------------
9729
#   Installations
9730
 
9731
MakeHeader ("Installations");
9732
PackageRule ( \&InstallCmd, \%INSTALL_HDRS  );
9733
PackageRule ( \&InstallCmd, \%INSTALL_CLSS  );
9734
PackageRule ( \&InstallCmd, \%INSTALL_LIBS  );
9735
PackageRule ( \&InstallCmd, \%INSTALL_SHLIBS  );
9736
PackageRule ( \&InstallCmd, \%INSTALL_PROGS  );
9737
 
9738
 
9739
#-------------------------------------------------------------------------------
9740
#   Packaging
9741
#
9742
MakeHeader ("Packaging");
9743
PackageRule ( \&PackageCmd, \%PACKAGE_FILES );
9744
PackageRule ( \&PackageCmd, \%PACKAGE_HDRS );
9745
PackageRule ( \&PackageCmd, \%PACKAGE_CLSS );
9746
PackageRule ( \&PackageCmd, \%PACKAGE_LIBS );
9747
PackageRule ( \&PackageCmd, \%PACKAGE_SHLIBS );
9748
PackageRule ( \&PackageCmd, \%PACKAGE_PROGS );
9749
 
9750
#-------------------------------------------------------------------------------
9751
#   Uninstall/unpackaging
9752
#
9753
MakeHeader ("Uninstall/unpackaging");
9754
 
9755
UnpackageRule( "uninstall_hdr",         \&UninstallCmd, \%INSTALL_HDRS );
9756
UnpackageRule( "uninstall_lib",         \&UninstallCmd, \%INSTALL_LIBS );
9757
UnpackageRule( "uninstall_shlib",       \&UninstallCmd, \%INSTALL_SHLIBS );
9758
UnpackageRule( "uninstall_prog",        \&UninstallCmd, \%INSTALL_PROGS );
9759
UnpackageRule( "uninstall_class",       \&UninstallCmd, \%INSTALL_CLSS );
9760
 
9761
UnpackageRule( "unpackage_files",       \&UnpackageCmd, \%PACKAGE_FILES );
9762
UnpackageRule( "unpackage_hdr",         \&UnpackageCmd, \%PACKAGE_HDRS );
9763
UnpackageRule( "unpackage_lib",         \&UnpackageCmd, \%PACKAGE_LIBS );
9764
UnpackageRule( "unpackage_shlib",       \&UnpackageCmd, \%PACKAGE_SHLIBS );
9765
UnpackageRule( "unpackage_prog",        \&UnpackageCmd, \%PACKAGE_PROGS );
9766
UnpackageRule( "unpackage_class",       \&UnpackageCmd, \%PACKAGE_CLSS );
9767
 
261 dpurdie 9768
#-------------------------------------------------------------------------------
267 dpurdie 9769
#   Distribution Sets
261 dpurdie 9770
#
267 dpurdie 9771
MakeHeader ("Distribution Sets");
9772
PackageSetRules();
9773
 
9774
#-------------------------------------------------------------------------------
9775
#
261 dpurdie 9776
#   Subdir deletion
9777
#   This is done AFTER the toolset functions have been invoked to create the
9778
#   build artifacts so that the toolsets can create directories too
9779
#
9780
#   Note: Toolset directories are deleted first
9781
#   Note: User Directories are deleted in the reverse order of creation
9782
#
9783
    MakeHeader ("Subdir deletion");
285 dpurdie 9784
    MakePrint( ".PHONY:\t\tunmake_dir\n" );
261 dpurdie 9785
    MakePrint( "unmake_dir:\n" );
9786
    MakePrint( "\t-\$(AA_PRE)echo Removing directories;" );
9787
    MakePrint( " \\\n\t\$(rmdir) \$(TOOLSETDIRS);" )            if ( @TOOLSETDIRS );
9788
    MakePrint( " \\\n\t\$(rm) -rf \$(TOOLSETDIRTREES);" )       if ( @TOOLSETDIRTREES );
9789
    RmdirRules();
9790
    MakeNewLine();
227 dpurdie 9791
 
261 dpurdie 9792
#--------- Toolset Rules -------------------------------------------------------
9793
    MakeHeader ("Toolset Rules");
9794
    MakePrintList ( \@TOOLSETRULES );
9795
 
227 dpurdie 9796
#-------------------------------------------------------------------------------
9797
#   Makefile targets
9798
#
261 dpurdie 9799
MakeHeader ("Makefile targets",
9800
            "These targets are not used by JATS",
9801
            "They can only used when the makefile is used directly",
9802
            "This is not the intended use of this makefile",
9803
           );
227 dpurdie 9804
 
9805
#
9806
#   Examine %INC and extract included files within JATS
9807
#   These will be added to the list of dependent files
9808
#
9809
foreach  (  values %INC)
9810
{
9811
    next if ( m/Makefile.*\.cfg$/ );    # Skip my config
9812
    if ( ( m/^\./)          ||
9813
         ( m/^$::GBE_CORE/) ||
9814
         ( m/^$::GBE_BIN/)  ||
9815
         ( m/^$::GBE_PERL/) ||
9816
         ( m/^$::GBE_TOOLS/) )
9817
    {
9818
        UniquePush (\@ScmDepends, $_ )
9819
    }
9820
}
9821
 
9822
MakeDefEntry    ( "GBE_DEPENDS", "=" );
261 dpurdie 9823
MakeIfZeroEntry ( "NOSCMDEPEND", "GBE_DEPENDS", "+=", \@ScmDepends );
227 dpurdie 9824
 
9825
    print MAKEFILE <<EOF;
9826
 
9827
\$(GBE_PLATFORM).mk:	\$(GBE_DEPENDS)
9828
	\@echo One or more JATS source or internal files have changed, "rebuild" required
261 dpurdie 9829
	\@for i in \$? ; do echo "      Changed: \$\$i"; done
227 dpurdie 9830
	\@exit 10
9831
 
9832
EOF
9833
 
261 dpurdie 9834
#--------- Maketags ------------------------------------------------------------
227 dpurdie 9835
 
9836
    Maketag( "make_init",           @INITS );
261 dpurdie 9837
    Maketag( "make_dir",            @mkdirdep );
9838
    Maketag( "generate",            @generatedep || @projectgendep || @USERGENERATED || ($ScmToolsetGenerate != 0) );
227 dpurdie 9839
    Maketag( "depend",              $ScmDependTags != 0 );
261 dpurdie 9840
    Maketag( "make_lib",            @libdep );
9841
    Maketag( "make_mlib",           @mlibdep );
9842
    Maketag( "make_install_shlib",  %INSTALL_SHLIBS || @shlibdep);
9843
    Maketag( "make_script",         @scriptdep );
9844
    Maketag( "make_prog",           @progdep || @projectdep );
9845
    Maketag( "make_test",           @testprogdep );
263 dpurdie 9846
    Maketag( "run_tests",           @TESTS_TO_RUN || @TESTPROJECT_TO_URUN || $TESTS_TO_RUN);
227 dpurdie 9847
    Maketag( "run_unit_tests",      $TESTS_TO_AUTORUN || @TESTPROJECT_TO_ARUN);
9848
    Maketag( "install_hdr",         %INSTALL_HDRS );
9849
    Maketag( "install_class",       %INSTALL_CLSS );
9850
    Maketag( "install_lib",         %INSTALL_LIBS );
9851
    Maketag( "install_prog",        %INSTALL_PROGS );
9852
    Maketag( "deploy",              %DEPLOYPACKAGE );
9853
    Maketag( "package",             %PACKAGE_FILES || %PACKAGE_HDRS || %PACKAGE_CLSS ||
9854
                                    %PACKAGE_LIBS || %PACKAGE_SHLIBS || %PACKAGE_PROGS );
9855
 
261 dpurdie 9856
    #
9857
    #   Display tags in the MAKEFILE
9858
    #   Not used here - just for show
9859
    #
9860
    MakeHeader ("Maketags");
9861
    foreach my $tag ( sort keys %MakeTags )
9862
    {
9863
        MakePadded( 2, "#   $tag:", defined ($MakeTags{$tag}) ? 1 : 0, "\n");
9864
    }
9865
 
227 dpurdie 9866
#-------------------------------------------------------------------------------
9867
#   End of Makefile
9868
#
9869
    MakeHeader ("End of Makefile");
9870
    close( MAKEFILE );
9871
 
9872
#
9873
#   Save all platform information
9874
#   Done after the makefile is written as toolsets can extend the data
9875
#
9876
    WriteParsedConfig();
9877
 
9878
#
9879
#   Write out any accumulated DPACKAGE data
9880
#
9881
    JatsDPackage::DPackageSave();
9882
 
9883
    return 0;
9884
}
9885
 
9886
#-------------------------------------------------------------------------------
9887
# Function        : Maketag
9888
#
9889
# Description     : Create Makefile tags to speed up recursive makes
9890
#
9891
# Inputs          : tag_name
9892
#                   dep
9893
#
9894
# Returns         : 
9895
#
9896
sub Maketag
9897
{
9898
    my( $tag, $dep ) = @_;
9899
    $MakeTags{$tag} = 1 if ( defined($dep) && $dep );
9900
}
9901
 
9902
#-------------------------------------------------------------------------------
9903
#   Function to create and delete directories within the build system
9904
#
9905
#    To stop make regenerating directory dependent targets each time the
9906
#    directory content is modified, rule should only be dependent on a internally
9907
#    created alias file 'gbedir', which represents the time a dir was created not
9908
#    last modified.
9909
#
9910
#    Must use tags like GBE_BINDIR, GBE_LIBDIR and GBE_OBJDIR to ensure that the
9911
#    directories are created correctly.
9912
#
9913
my %MkdirRuleData;
9914
my @MkdirRuleOrder;
9915
my $MkdirRulePrinting = 0;
9916
my $MkdirRuleGbeFile = ( $::ScmHost eq "Unix" ) ? ".gbedir" : "_gbedir";
9917
 
9918
#-------------------------------------------------------------------------------
9919
# Function        : MkdirRule
9920
#
9921
# Description     : Create Rules and Recipes to create a directory at make-time
9922
#                   Mark the information for such that the directories will
9923
#                   be deleted in a 'clean'
9924
#
9925
#                   Can be called before we start writing the makefile
9926
#                   Such entries will be retained and dumped at a known time
9927
#
9928
# Inputs          : $subdir     - Symbolic name of the subdir $(OBJDIR)
9929
#                   $alias      - Optional script alias for the dir 'OBJDIR' --> GBE_OBJDIR
9930
#                   Options:
9931
#                       --Path=path     Optional value of $subdir '$(GBE_PLATFORM)$(GBE_TYPE).OBJ'
9932
#                       --RemoveAll     Remove all files on clean
9933
#
9934
# Returns         : Nothing
9935
#
9936
 
9937
sub MkdirRule
9938
{
9939
    my( $subdir, $alias, @opts ) = @_;
9940
 
9941
    #
9942
    #   Create data entry once
9943
    #
9944
    $alias =~ s~^GBE_~~ if $alias;
9945
    unless ( $MkdirRuleData{$subdir}  )
9946
    {
9947
        my %data;
9948
 
9949
        #
9950
        #   Parse options
9951
        #
9952
        foreach ( @opts )
9953
        {
9954
            if ( /^--Path=(.+)/ ) {
9955
                $data{path} = $1;
9956
            } elsif ( /^--RemoveAll/ ) {
9957
                $data{remove_all} = 1;
9958
            } else {
9959
                Error ("MkdirRule: Unknown option: $_");
9960
            }
9961
        }
9962
        $data{alias} = $alias if ( $alias );
9963
 
9964
        $MkdirRuleData{$subdir} = \%data;
9965
        push @MkdirRuleOrder, $subdir;
9966
    }
9967
 
9968
    #
9969
    #   Save or print
9970
    #
9971
    return unless ( $MkdirRulePrinting );
9972
 
9973
    #
9974
    #   Create a definition of the physical directory
9975
    #
9976
    my $path = $MkdirRuleData{$subdir}{path};
261 dpurdie 9977
    MakePadded (2, $alias, ":= $path\n") if ( $path && $alias );
227 dpurdie 9978
 
9979
    #   Create an alias to be used within rules
9980
    #   The defined aliase will be prefixed with 'GBE_'
9981
    #
261 dpurdie 9982
    MakePadded (2, "GBE_$alias", ":= $subdir/$MkdirRuleGbeFile\n") if ( $alias );
227 dpurdie 9983
 
9984
    #
9985
    #   Create a recipe to create the directory
9986
    #   This is not as simple as it sounds
9987
    #   The touch is required.
9988
    #       Had 'timestamp' issues on solaris'. The 'echo' did not appear
9989
    #       to be enough. Perhaps the output was not flushed
9990
    #
261 dpurdie 9991
    MakePadded (2, "$subdir", ": $subdir/$MkdirRuleGbeFile\n");
227 dpurdie 9992
    MakePrint
9993
        "$subdir/$MkdirRuleGbeFile:\n".
9994
        "\t\$(XX_PRE)if [ ! -d $subdir ]; then \$(mkdir) -p $subdir; fi; \\\n".
9995
        "\t\$(echo) '# DO NOT REMOVE.' > \$@; \\\n".
9996
        "\t\$(touch) \$@\n\n";
9997
}
9998
 
9999
#-------------------------------------------------------------------------------
10000
# Function        : RmdirRules
10001
#
10002
# Description     : Create the body of a recipe to delete the directoeis that
10003
#                   have been created.
10004
#
10005
#                   The rule header will have been written to the makefile
10006
#
10007
# Inputs          : Uses $MkdirRuleData
10008
#
10009
# Returns         : Nothing.
10010
#                   Prints to the makefile
10011
#
10012
sub RmdirRules
10013
{
10014
    #
10015
    #   Determine the list of directories to delete
10016
    #   Sort such that subdirs are deleted files
10017
    #
10018
    foreach my $subdir ( reverse sort keys %MkdirRuleData )
10019
    {
10020
        MakePrint "\\\n";                       # join to previous line
261 dpurdie 10021
        MakePrint "\tif [ -d $subdir ]; then \\\n";
10022
        unless ( $MkdirRuleData{$subdir}{remove_all} )
10023
        {
10024
            MakePrint "\t\t\$(rm) -f $subdir/$MkdirRuleGbeFile; \\\n";
10025
            MakePrint "\t\t\$(rmdir) $subdir; \\\n";
10026
        }
10027
        else
10028
        {
10029
            MakePrint "\t\t\$(rm) -rf $subdir; \\\n";
10030
        }
227 dpurdie 10031
        MakePrint "\tfi;";
10032
    }
10033
}
10034
 
10035
#-------------------------------------------------------------------------------
10036
# Function        : CreateMkdirRules
10037
#
10038
# Description     : Create Rules to make dirs at runtime
10039
#                   This function is called to instantiate those entries
10040
#                   That have been requested before the makefile has has
10041
#                   started to be created.
10042
#
10043
#                   Once this function has been called all new MkdirRule calls
10044
#                   will result in the recipes being created in-line.
10045
#
10046
# Inputs          : Nothing
10047
#
10048
# Returns         : Even Less
10049
#
10050
#
10051
sub CreateMkdirRules
10052
{
10053
    $MkdirRulePrinting = 1;
10054
    foreach my $subdir ( @MkdirRuleOrder )
10055
    {
10056
        my $data = $MkdirRuleData{$subdir};
10057
        MkdirRule($subdir, $data->{alias}, $data->{path} );
10058
    }
10059
}
10060
 
10061
#-------------------------------------------------------------------------------
10062
# Function        : PackageRule
10063
#
10064
# Description     : Generate rules and recipes to "install" and "package" files
10065
#
10066
# Inputs          : codecmd     - A code reference to the actual installer routine
10067
#                   hashp       - A reference to a INSTALL or PACKAGE hash
10068
#
299 dpurdie 10069
#                   hashp is a reference to a hash
227 dpurdie 10070
#                       The key is the full path of the install target
10071
#                       The value is (another) hash that describes the install options
10072
#
10073
#                   Valid keys are:
10074
#                       src                 - Path of the source file [Mandatory]
10075
#                       dir                 - Target directory [Mandatory]
10076
#
10077
#                       defined             - Copy the file only if value is defined
10078
#                       exe                 - Mark the file as executable
10079
#                       Mode                - File modes. Default is -w
10080
#                       placekeeper         - Marks SHARED library placekeepers
10081
#                       set                 - Distribution sets
10082
#                       type                - Copy the file in DEBUG or PROD mode
10083
#                                             Valid values are "D" or "P"         
10084
#                       version             - Shared library version information
10085
#                       RemoveOnly          - Do not install the file. Entries are
10086
#                                             created to allow the removal of the file
10087
#
10088
# Returns         :
10089
#
10090
sub PackageRule
10091
{
10092
    my ($codecmd, $hashp) = @_;
10093
 
10094
    foreach my $dest ( keys %{$hashp} )
10095
    {
10096
 
10097
        my $entry = $hashp->{$dest};
10098
 
10099
        #
10100
        #   Skip placekeepers
10101
        #
10102
        next if ( $entry->{'placekeeper'} );
10103
 
10104
        #
10105
        #   Some entries are not installed via this mechanism, but can be removed
10106
        #   if they exist. Mark these as PHONY to keep targets happy
10107
        #
10108
        if ( $entry->{'RemoveOnly'} )
10109
        {
10110
            MakePrint ".PHONY:\t$dest\n";
10111
            MakePrint "$dest:\n\n";
10112
            next;
10113
        }
10114
 
10115
        my $fname = $entry->{'src'};
10116
        my $fmode = $entry->{'Mode'};
10117
        $fmode .= "+x" if ( $entry->{'exe'}  );
10118
 
10119
        #
10120
        #   User conditionional
10121
        #   Mark both the source and the target as PHONY if the condition is not met
10122
        #   This will ensure that the target need not be built.
10123
        #
10124
        my $udef = $entry->{'defined'};
10125
        if ( $udef )
10126
        {
10127
            MakePrint "ifndef $udef \n";
10128
            MakePrint ".PHONY:\t\t$dest\n";
10129
            MakePrint ".PHONY:\t\t$fname\n";
10130
            MakePrint "$dest:\n";
10131
            MakePrint "else\n"
10132
        }
10133
 
10134
        #
10135
        #   Conditional installation for DEBUG/PRODUCTION
10136
        #
10137
        my $type = $entry->{'type'};
10138
        if ( $type )
10139
        {
10140
            if ( $type eq "D" ) {
10141
                MakePrint 'ifeq "$(DEBUG)" "0"'."\n";
10142
            } elsif ( $type eq "P" ) {
10143
                MakePrint 'ifneq "$(DEBUG)" "0"'."\n";
10144
            } else {
10145
                Error("INTERNAL: Unexpected packaging type: $type");
10146
            }
10147
            MakePrint ".PHONY:\t\t$dest\n";
10148
            MakePrint "$dest:\n";
10149
            MakePrint "else\n"
10150
        }
10151
 
10152
        #
10153
        #   The body of the copy
10154
        #
10155
        MakePadded( 4, "$dest:" );
10156
        MakePrint "\t$fname\n";
10157
        MakePrint $codecmd->( $dest, $fname, $entry->{'dir'}, $fmode );
10158
        MakeNewLine();
10159
 
10160
 
10161
        #
10162
        #   Unwind conditionals
10163
        #
10164
        MakePrint "endif\n" if ( $type );
10165
        MakePrint "endif\n" if ( $udef );
10166
 
10167
        #
10168
        #   Distribution sets
10169
        #
10170
        my $dist = $entry->{'set'};
10171
        if ( $dist )
10172
        {
267 dpurdie 10173
            foreach my $set ( split( ',', $dist ) )
10174
            {
10175
                push @{$PACKAGE_SETS{$set}{LIST}}, $dest;
227 dpurdie 10176
            }
10177
            MakeNewLine();
10178
        }
10179
    }
10180
}
10181
 
10182
#-------------------------------------------------------------------------------
267 dpurdie 10183
# Function        : PackageSetRules
10184
#
10185
# Description     : Generate the packageset rules
10186
#                   These appear to be a now-defuct feature
10187
#
10188
#                   By default all packaged files are a part of package_setALL
10189
#
10190
# Inputs          : None
10191
#                   Takes data from %PACKAGE_SET
10192
#
10193
# Returns         : Nothing
10194
#
10195
sub PackageSetRules
10196
{
10197
    foreach my $set ( sort keys %PACKAGE_SETS )
10198
    {
10199
        my $me = MakeEntry::New( *MAKEFILE, "package_set$set", '--Phony' );
10200
        $me->AddDependancy( @{$PACKAGE_SETS{$set}{LIST}} );
10201
        $me->Print();
10202
    }
10203
}
10204
 
10205
#-------------------------------------------------------------------------------
227 dpurdie 10206
# Function        : UnPackageRule
10207
#
10208
# Description     : Generate rules and recipes to "uninstall" and "unpackage" files
10209
#
10210
# Inputs          : target      - Name of the target
10211
#                   codecmd     - A code reference to the actual installer routine
10212
#                   hashp       - A reference to a INSTALL or PACKAGE hash
10213
#
10214
# Returns         :
10215
#
10216
sub UnpackageRule
10217
{
10218
    my ($target, $codecmd, $hashp) = @_;
10219
 
10220
    MakePrint ".PHONY:\t\t"."$target\n";
10221
    MakePrint "$target:\t";
10222
 
10223
    foreach my $dest ( sort keys %{$hashp} )
10224
    {
10225
 
10226
        my $entry = $hashp->{$dest};
10227
 
10228
        #
10229
        #   Skip placekeepers
10230
        #
10231
        next if ( $entry->{'placekeeper'} );
10232
 
10233
        MakePrint "\n" . $codecmd->($dest);
10234
    }
10235
    MakePrint "\n\n";
10236
}
10237
 
10238
 
10239
#
10240
#   Internal macro interface, see RULE.STD for definitions:
10241
#
10242
sub RmFilesCmd
10243
{
10244
    my ( $list ) = @_;
261 dpurdie 10245
    return "\$(call RmFiles,$list)";
227 dpurdie 10246
}
10247
 
10248
sub InstallCmd
10249
{
10250
    my( $dest, $file, $path, $fmode ) = @_;
10251
 
10252
    $path =~ s~/$~~;                        # remove trailing "/"
10253
    $fmode = "-w"                           # default, read-only
10254
        if ( !defined( $fmode ) || $fmode eq "" );
10255
 
10256
    return "\t\$(call InstallFile,$dest,$file,$path,$fmode)";
10257
}
10258
 
10259
sub UninstallCmd
10260
{
10261
    my( $file ) = @_;
10262
 
10263
    return "\t\$(call UninstallFile,$file)";
10264
}
10265
 
10266
sub PackageCmd
10267
{
10268
    my( $dest, $file, $path, $fmode ) = @_;
10269
 
10270
    $path =~ s~/$~~;                        # remove trailing "/"
10271
    $fmode = "-w"                           # default, read-only
10272
        if ( !defined( $fmode ) || $fmode eq "" );
10273
 
10274
    return "\t\$(call PackageFile,$dest,$file,$path,$fmode)";
10275
}
10276
 
10277
sub UnpackageCmd
10278
{
10279
    my( $file ) = @_;
10280
    return "\t\$(call UnpackageFile,$file)";
10281
}
10282
 
10283
1;
10284