Subversion Repositories DevTools

Rev

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

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