Subversion Repositories DevTools

Rev

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

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