Subversion Repositories DevTools

Rev

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

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