Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
289 dpurdie 1
#
2
# Module name   : DELPHI7
3
# Module type   : Makefile system
4
# Compiler(s)   : Delphi Pascal
5
# Environment(s): WIN32
6
#
7
# Description:
8
#       Delphi7 for WIN32
9
#............................................................................#
10
 
11
use strict;
12
use warnings;
13
 
14
################################################################################
15
#   Globals
16
#
17
my $toolset_version;
18
my $implib_found;
19
 
20
##############################################################################
21
#   ToolsetInit()
22
#       Runtime initialisation
23
#
24
##############################################################################
25
 
26
ToolsetInit();
27
 
28
sub ToolsetInit
29
{
30
 
31
#.. Parse arguments (Toolset arguments)
32
#
33
    Debug( "Delphi7(@::ScmToolsetArgs)" );
34
 
35
    foreach $_ ( @::ScmToolsetArgs ) {
36
        if (/^--Version=(.*)/) {                # MS SDK Version
37
            $toolset_version = $1;
38
 
39
        } else {
40
            Message( "Delphi7 toolset: unknown option $_ -- ignored\n" );
41
        }
42
    }
43
 
44
#.. Parse arguments (platform arguments)
45
#
46
    Debug( "Delphi7(@::ScmPlatformArgs)" );
47
 
48
    foreach $_ ( @::ScmPlatformArgs ) {
49
        if (/^--product=(.*)/) {                # GBE product
50
 
51
        } elsif (/^--Version=(.*)/) {           # MS SDK Version
52
            $toolset_version = $1;
53
 
54
        } else {
55
            Message( "Delphi7 toolset: unknown platform argument $_ -- ignored\n" );
56
        }
57
    }
58
 
59
#.. Validate SDK version
60
#   Currently only one is supported
61
#       1) Delphi7 installed
62
#
63
    Error( "Unknown version: $toolset_version" ) if ( defined $toolset_version );
64
 
65
 
66
#.. Standard.rul requirements
67
#
68
    $::s = 'asm';
69
    $::o = '';
70
    $::a = 'dcu';
71
    $::so = 'dll';
72
    $::exe = '.exe';
73
 
74
#.. Toolset configuration
75
#
76
    $::ScmToolsetVersion = "1.0.0";             # our version
77
    $::ScmToolsetGenerate = 0;                  # generate optional
78
    $::ScmToolsetProgDependancies = 0;          # handle Prog dependancies myself
79
    $::ScmToolsetSingleType = 1;                # Cannot support debug and production builds
80
 
81
#.. define Delphi7 environment
82
    Init( "delphi7" );
83
    ToolsetDefines( "delphi7.def" );
84
    ToolsetRequire( "exctags" );                # and Exuberant Ctags
85
    ToolsetRules( "delphi7.rul" );
86
    ToolsetRules( "standard.rul" );
87
 
88
    #.. Extend the CompilerOption directive
89
    #   Create a standard data structure
90
    #   This is a hash of hashes
91
    #       The first hash is keyed by CompileOption keyword
92
    #       The second hash contains pairs of values to set or remove
93
    #
94
    %::ScmToolsetCompilerOptions =
95
    (
96
        #
97
        #   Control the thread model to use
98
        #   This will affect the compiler options and the linker options
99
        #
100
        'subsystem:windows'  => { 'LDSUBSYSTEM' , '-CG' },
101
        'subsystem:console'  => { 'LDSUBSYSTEM' , '-CC' },
102
    );
103
 
104
    #
105
    #   Set default options
106
    #
107
    $::ScmCompilerOpts{'LDSUBSYSTEM'} = '-CG';
108
 
109
#.. Cleanup rules
110
#   None at the moment as we only build projects
111
#
112
    return 1;
113
}
114
 
115
#-------------------------------------------------------------------------------
116
# Function        : ToolsetGenLibName
117
#
118
# Description     : Function to generate the names of static libraries
119
#                   Will be used if it exists
120
#
121
# Inputs          : $name                   - Base Name of the library
122
#
123
# Returns         : Path to generated name
124
#
125
sub ToolsetGenLibName
126
{
127
    my ($name) = @_;
128
    return "$name.$::a";
129
}
130
 
131
#-------------------------------------------------------------------------------
132
# Function        : ToolsetPreprocess
133
#
134
# Description     : Called once all the user directives have been parsed
135
#                   In this toolset it is used as a hook to allow
136
#                   the creation of a 'simple' target to perform some
137
#                   level of dependency testing
138
#
139
#                   Basically. Create a target that consists on ALL the
140
#                   source files. This is then used as a prerequisite
141
#                   for all Libs, SharedLibs and Progs
142
#
143
#                   It is crude and ugly - but it does the job
144
#                   Would be better to parse the Delphi project files
145
#                   and determine the prerequisites ourselves, but ...
146
#
147
# Inputs          : None
148
#
149
# Returns         : Nothing directly
150
#
151
sub ToolsetPreprocess
152
{
153
    my @dlist;
154
 
155
    foreach ( values %::SRCS )
156
    {
157
        #
158
        #   Strip out known project files
159
        #   Must leave in .pas files
160
        #
161
        next if ( m~\.dpr~ );
162
        next if ( m~\.dpk~ );
163
        next if ( m~descpkg~ );
164
        push @dlist, $_;
165
    }
166
 
167
    if ( @dlist )
168
    {
169
        #
170
        #   Would like to use nice function that create nice text, but
171
        #   at the moment the makefile is not yet being written
172
        #
173
        #   Trick: Create an in-memory filehandle and use it
174
        #          The MAKEFILE handle is used by nice writers
175
        #
176
        my $data;
177
        local (*MAKEFILE);
178
        open(MAKEFILE, '>>', \$data) || Error ("Cannot open in-memory file");
179
 
180
        MakeHeader  ( "All Delphi Sources");
181
        MakeDefEntry( "DELPHISRCS", "=",  \@dlist );
182
 
183
        close MAKEFILE;
184
 
185
        #
186
        #   Add the generated data as a 'define'
187
        #   This will be placed early in the makefile so that it can be used
188
        #   by the rules that need it.
189
        #
190
        ToolsetDefine ($data);
191
    }
192
}
193
 
194
#-------------------------------------------------------------------------------
195
# Function        : ToolsetAR
196
#
197
# Description     : Toolset processing to create a static library
198
#                   In Delphi these are called a unit
199
#                   In Delphi there are several restrictions
200
#                       * Name of the library and the name of the source are
201
#                         fixed - the user cannot provide a source name
202
#
203
#                       * A library can contain only one element
204
#
205
#
206
# Inputs          : $name   - Base name of the library
207
#                   $pArgs  - Ref to an array of arguments
208
#                   $pObjs  - Ref to an array of objects
209
#                   $pLib   - Ref to complete library entry
210
#
211
# Returns         : 
212
#
213
 
214
sub ToolsetAR
215
{
216
    my( $name, $pArgs, $pObjs, $pLib ) = @_;
217
 
218
    #.. Parse arguments
219
    #
220
    foreach $_ ( @$pArgs )
221
    {
222
        Message( "AR: unknown option $_ -- ignored" );
223
    }
224
 
225
    #
226
    #   Ensure that the user has not provided a source
227
    #   The name of the source will be calculated from the target
228
    #
229
    Error( "Delphi7 toolset: User source file names not supported")
230
        if ( scalar @$pObjs );
231
 
232
    #
233
    #   Source the required source file
234
    #   It must exist
235
    #
236
    my $sfile = MakeSrcResolve ( "$name.pas" );
237
    Error ("AR: Required source file not found: $sfile")
238
        unless ( -f $sfile );
239
    my $lib_name = $pLib->getPath();
240
 
241
    #
242
    #   Rule to create the target
243
    #
244
    my $me = MakeEntry::New (*MAKEFILE, $lib_name );
245
    $me->AddComment ("Build Unit: $name as a DCU" );
246
    $me->AddDependancy ( $sfile );
247
    $me->AddDependancy ( '$(SCM_MAKEFILE)' );
248
    $me->AddDependancy ( '$(DELPHISRCS)' );
249
    $me->AddRecipe ( '$(DCC_AR)' );
250
    $me->AddDefn ('PSOURCE', $sfile );
251
    $me->Print();
252
}
253
 
254
###############################################################################
255
#   ToolsetSHLD( $name, \@args, \@objs, \@libraries, $ver )
256
#       This subroutine takes the user options and builds the rules
257
#       required to link the shared library 'name'.
258
#
259
#   Arguments:
260
#       $name       - Name of the target program
261
#       $pArgs      - Ref to an array of argumennts
262
#       $pObjs      - Ref to an array of object files
263
#       $pLibs      - Ref to an array of libraries
264
#       $ver        - Version String
265
#
266
#   Output:
267
#       Makefile recipes to create the Program
268
#
269
#   Notes:
270
#       This Program Builder will handle its own dependancies
271
#       It will also create rules and recipes to construct various
272
#       parts directly from source
273
#
274
#       In Delphi there are several restrictions
275
#           * Name of the program and the name of the source are
276
#             linked. The user can provide only one file
277
#
278
#   Options:
279
#       --NoImplib                      # Supress creation of Import Library
280
#       --Package                       # Force Package Mode
281
#       Source File                     # Dependency usage only
282
#
283
#
284
###############################################################################
285
 
286
sub ToolsetSHLD
287
{
288
    my ( $name, $pArgs, $pObjs, $pLibs, $ver ) = @_;
289
    my @psource;
290
    my $no_implib = 0;
291
    my $isa_package = undef;
292
 
293
    #.. Parse arguments
294
    #
295
    foreach ( @$pArgs ) {
296
        if (/^--NoImplib$/) {
297
            $no_implib = 1;
298
 
299
        } elsif ( !/^--Package/ ) {
300
            $isa_package = 1;
301
 
302
        } elsif ( !/^--NoPackage/ ) {
303
            $isa_package = 0;
304
 
305
        } elsif ( !/^-/ ) {
306
            push @psource, MakeSrcResolve($_);
307
 
308
        } else {
309
            Message( "Delphi7 LD: unknown option $_ -- ignored\n" );
310
 
311
        }
312
    }
313
 
314
    #
315
    #   Objs are not supported in this toolset
316
    #
317
    Error( "Delphi7 toolset: User source file names not supported")
318
        if ( scalar @$pObjs );
319
 
320
 
321
    #
322
    #   Determine the source project name
323
    #   Will have the same name as the EXE, but the suffix may be
324
    #   .dpr or .pas
325
    #
326
    my $source;
327
    $::ScmQuiet = 3;                                # Can be done better !
328
    foreach my $suffix ( '.dpk', '.dpr', '.pas' )
329
    {
330
        $source = MakeSrcResolve ( "$name$suffix" );
331
        last if ( -f $source );
332
        $source = undef;
333
    }
334
    $::ScmQuiet = 0;
335
 
336
    Error ("Shared Library source not found",
337
           "It must have the same name as the library: $name")
338
            unless ( $source  );
339
 
340
    #
341
    #   Determine the type of SharedLib being created
342
    #       Library that creates DLLs
343
    #       Library that creates a Delphi Package
344
    #
345
    #   User can force the mode
346
    #
347
    unless ( defined $isa_package )
348
    {
349
        $isa_package = ($source =~ m~\.dpk~);
350
    }
351
 
352
    if ( $isa_package )
353
    {
354
        #
355
        #   Determine the target output name
356
        #
357
        my $base = $name;
358
        my $root = "\$(LIBDIR)/$base";
359
        my $bpl = $root . '.bpl';
360
        my $bcp = $root . '.dcp';
361
 
362
        #
363
        #   Create Rules and Recipes to create the Package
364
        #
365
        my $me = MakeEntry::New (*MAKEFILE, $bpl );
366
        $me->AddComment ("Build Delpi Package: $name" );
367
        $me->AddName ( $bcp );
368
        $me->AddDependancy ( $source );
369
        $me->AddDependancy ( '$(SCM_MAKEFILE)' );
370
        $me->AddDependancy ( '$(DELPHISRCS)' );
371
        $me->AddDependancy ( @psource );
372
        $me->AddRecipe ( '$(SHDCC)' );
373
        $me->AddDefn ('SHLIBBASE', $base );
374
        $me->AddDefn ('PSOURCE', $source );
375
        $me->AddDefn ('PFLAGS',  '' );
376
        $me->AddDefn ('PACKAGES',  join ' ', @$pLibs );
377
        $me->Print();
378
 
379
        #
380
        #   Files to clean up
381
        #
382
        ToolsetGenerate( "$root.map" );
383
        ToolsetGenerate( "$base.drc" );                 # Created in CWD
384
 
385
        #
386
        #   Specify the files to be packaged as part of the shared library
387
        #
388
        PackageShlibAddFiles ( $name, $bpl );
389
        PackageShlibAddFiles ( $name, $bcp );
390
        PackageShlibAddFiles ( $name, "$root.map", "Class=map" );
391
    }
392
    else
393
    {
394
        #
395
        #   Determine the target output name
396
        #
397
        my $base = $name;
398
        my $root = "\$(LIBDIR)/$base";
399
        my $full = $root . '.' . $::so;
400
        my $stub = $root . '.lib';
401
 
402
        #
403
        #   Create Rules and Recipes to create the Shared Library
404
        #
405
        my $me = MakeEntry::New (*MAKEFILE, $full );
406
        $me->AddComment ("Build Shared Library: $name" );
407
        $me->AddDependancy ( $source );
408
        $me->AddDependancy ( '$(SCM_MAKEFILE)' );
409
        $me->AddDependancy ( '$(DELPHISRCS)' );
410
        $me->AddDependancy ( @psource );
411
        $me->AddRecipe ( '$(SHDCC)' );
412
        $me->AddDefn ('SHLIBBASE', $base );
413
        $me->AddDefn ('PSOURCE', $source );
414
        $me->AddDefn ('PFLAGS',  '' );
415
        $me->AddDefn ('PACKAGES',  join ' ', @$pLibs );
416
        $me->Print();
417
 
418
        #
419
        #   Files to clean up
420
        #
421
        ToolsetGenerate( "$root.map" );
422
        ToolsetGenerate( "$base.drc" );                 # Created in CWD
423
 
424
        #
425
        #   Specify the files to be packaged as part of the shared library
426
        #
427
        PackageShlibAddFiles ( $name, $full );
428
        PackageShlibAddFiles ( $name, "$root.map", "Class=map" );
429
 
430
 
431
        #
432
        #   Shared libaries are really need an import library
433
        #   Create an import library
434
        #
435
        unless ( $no_implib )
436
        {
437
            #
438
            #   Ensure we have required tools
439
            #
440
            unless ( $implib_found )
441
            {
442
                $implib_found = 1;
443
                Error ("Delphi7. Required program node found: implib32",
444
                       "You may need the DelphiTool (or equiv) package")
445
                    unless ( ToolExtensionProgram( 'implib32', '.exe' ) );
446
            }
447
 
448
            my $me = MakeEntry::New (*MAKEFILE, $stub );
449
            $me->AddComment ("Build Import Library: $name" );
450
            $me->AddDependancy ( $full );
451
            $me->AddRecipe ( '$(IMPLIB)' );
452
            $me->Print();
453
 
454
            ToolsetGenerate( "$root.exp" );
455
            PackageShlibAddFiles ( $name, $stub );
456
        }
457
    }
458
}
459
 
460
###############################################################################
461
#   ToolsetLD( $name, \@args, \@objs, \@libraries )
462
#       This subroutine takes the user options and builds the rules
463
#       required to link the program 'name'.
464
#
465
#   Arguments:
466
#       $name       - Name of the target program
467
#       $pArgs      - Ref to an array of argumennts
468
#       $pObjs      - Ref to an array of object files
469
#       $pLibs      - Ref to an array of libraries
470
#
471
#   Output:
472
#       Makefile recipes to create the Program
473
#
474
#   Notes:
475
#       This Program Builder will handle its own dependancies
476
#       It will also create rules and recipes to construct various
477
#       parts directly from source
478
#
479
#       In Delphi there are several restrictions
480
#           * Name of the program and the name of the source are
481
#             linked. The user can provide only one file
482
#
483
#   Options:
484
#       --Console                       # Console app
485
#       --Windows                       # Windows app (default)
486
#       Source File                     # Dependency usage only
487
#
488
#
489
###############################################################################
490
 
491
sub ToolsetLD
492
{
493
    my ( $name, $pArgs, $pObjs, $pLibs ) = @_;
494
    my @psource;
495
    my $link_target = $::ScmCompilerOpts{'LDSUBSYSTEM'};
496
 
497
    #.. Parse arguments
498
    #
499
    foreach ( @$pArgs ) {
500
        if (/^--Windows/) {
501
            $link_target = '-CC';
502
 
503
        } elsif (/^--Console/) {
504
            $link_target = '-CG';
505
 
506
        } elsif ( !/^-/ ) {
507
            push @psource, MakeSrcResolve($_);
508
 
509
        } else {
510
            Message( "Delphi7 LD: unknown option $_ -- ignored\n" );
511
 
512
        }
513
    }
514
 
515
    #
516
    #   Objs are not supported in this toolset
517
    #
518
    Error( "Delphi7 toolset: User source file names not supported")
519
        if ( scalar @$pObjs );
520
 
521
    #
522
    #   Determine the target output name
523
    #
524
    my $base = $name;
525
    my $root = "\$(BINDIR)/$base";
526
    my $full = $root . $::exe;
527
 
528
    #
529
    #   Determine the source project name
530
    #   Will have the same name as the EXE, but the suffix may be
531
    #   .dpr or .pas
532
    #
533
    my $source;
534
    $::ScmQuiet = 3;                                # Can be done better !
535
    foreach my $suffix ( '.dpr', '.pas' )
536
    {
537
        $source = MakeSrcResolve ( "$name$suffix" );
538
        last if ( -f $source );
539
        $source = undef;
540
    }
541
    $::ScmQuiet = 0;
542
 
543
    Error ("Program source not found",
544
           "It must have the same name as the program: $name")
545
            unless ( $source  );
546
 
547
    #
548
    #   Create Rules and Recipes to create the Program
549
    #   This will be a combination of source
550
    #
551
    my $me = MakeEntry::New (*MAKEFILE, $full );
552
    $me->AddComment ("Build Program: $name" );
553
    $me->AddDependancy ( $source );
554
    $me->AddDependancy ( '$(SCM_MAKEFILE)' );
555
    $me->AddDependancy ( '$(DELPHISRCS)' );
556
    $me->AddDependancy ( @psource );
557
    $me->AddRecipe ( '$(DCC)' );
558
    $me->AddDefn ('PSOURCE', $source );
559
    $me->AddDefn ('PFLAGS',  $link_target );
560
    $me->AddDefn ('PACKAGES',  join ' ', @$pLibs );
561
    $me->Print();
562
 
563
    #
564
    #   Files to clean up
565
    #
566
    ToolsetGenerate( "$root.map" );
567
    ToolsetGenerate( "$base.drc" );                 # Created in CWD
568
 
569
 
570
    #.. Package up files that are a part of the program
571
    #
572
    PackageProgAddFiles ( $name, $full );
573
    PackageProgAddFiles ( $name, "$root.map", "Class=map" );
574
}
575
#.. Successful termination
576
1;
577