Subversion Repositories DevTools

Rev

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

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