Subversion Repositories DevTools

Rev

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