Subversion Repositories DevTools

Rev

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