Subversion Repositories DevTools

Rev

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