Subversion Repositories DevTools

Rev

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

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