Subversion Repositories DevTools

Rev

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