Subversion Repositories DevTools

Rev

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

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