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