Subversion Repositories DevTools

Rev

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