Subversion Repositories DevTools

Rev

Rev 4700 | Details | Compare with Previous | Last modification | View Log | RSS feed

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