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