Subversion Repositories DevTools

Rev

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

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