Subversion Repositories DevTools

Rev

Rev 289 | Rev 299 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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