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