Subversion Repositories DevTools

Rev

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