Subversion Repositories DevTools

Rev

Rev 3987 | Rev 4074 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
#
2
# Module name   : CSHARP
3
# Module type   : Makefile system
4
# Compiler(s)   : ANSI C
5
# Environment(s): WIN32
6
#
7
# Description:
8
#       CSHARP for Windows
9
#
10
#............................................................................#
11
use strict;
12
use warnings;
13
use MakeEntry;
14
 
15
#
16
#   Global data
17
#
18
my %resource_files;
19
my $pdb_none;
20
 
343 dpurdie 21
my $toolset_name = 'csharp';                           # Toolset name : Error reporting
255 dpurdie 22
my $toolset_info;
23
my $toolset_version = '1.1';
24
my %ToolsetVersion =
25
    (
26
    '1.1' => { 'def'      => 'CSHARP.DEF',              # Def file to use
27
               'pragma'   => 0,                         # True: Compiler supports #pragma
28
               'warnings' => '',                        # Comma sep list of warnings to ignore
29
             },
30
 
31
    '2.0' => { 'def'      => 'CSHARP2005.DEF',
32
               'pragma'   => 1,
33
               'warnings' => '1668',
34
             },
291 dpurdie 35
 
36
    '3.5' => { 'def'      => 'CSHARP2008.DEF',
37
               'pragma'   => 1,
38
               'warnings' => '1668',
39
             },
347 dpurdie 40
 
41
    '4.0' => { 'def'      => 'CSHARP2010.DEF',
42
               'pragma'   => 1,
43
               'warnings' => '1668',
351 dpurdie 44
               'platform' => 'x86',
347 dpurdie 45
             },
46
 
255 dpurdie 47
    );
48
 
49
 
227 dpurdie 50
##############################################################################
51
#   ToolsetInit()
52
#       Runtime initialisation
53
#
54
##############################################################################
55
 
56
ToolsetInit();
57
 
58
sub ToolsetInit
59
{
60
 
61
    #.. Parse arguments (Toolset arguments)
62
    #
343 dpurdie 63
    Debug( "$toolset_name(@::ScmToolsetArgs)" );
227 dpurdie 64
 
65
    foreach $_ ( @::ScmToolsetArgs ) {
66
        if (/^--Version=(.*)/) {                # MS SDK Version
67
            $toolset_version = $1;
68
 
69
        } else {
343 dpurdie 70
            Message( "$toolset_name toolset: unknown option $_ -- ignored\n" );
227 dpurdie 71
        }
72
    }
73
 
74
    #.. Parse arguments (platform arguments)
75
    #
343 dpurdie 76
    Debug( "$toolset_name(@::ScmPlatformArgs)" );
227 dpurdie 77
 
78
    foreach $_ ( @::ScmPlatformArgs ) {
79
        if (/^--product=(.*)/) {                # GBE product
80
 
81
        } elsif (/^--Version=(.*)/) {           # MS SDK Version
82
            $toolset_version = $1;
83
 
84
        } else {
343 dpurdie 85
            Message( "$toolset_name toolset: unknown platform argument $_ -- ignored\n" );
227 dpurdie 86
        }
87
    }
88
 
255 dpurdie 89
    #.. Validate SDK version
90
    #   Currently supported versions are described in a HASH
227 dpurdie 91
    #
255 dpurdie 92
    $toolset_info = $ToolsetVersion{$toolset_version};
343 dpurdie 93
    Error( "$toolset_name toolset: Unknown version: $toolset_version" ) unless ( defined $toolset_info );
255 dpurdie 94
 
227 dpurdie 95
    #.. Standard.rul requirements
96
    #
97
    $::s    = undef;
98
    $::o    = '';
99
    $::a    = 'netmodule';
100
    $::so   = 'dll';
101
    $::exe  = '.exe';
102
 
103
    #.. Toolset configuration
104
    #
105
    $::ScmToolsetVersion = "1.0.0";             # our version
106
    $::ScmToolsetGenerate = 0;                  # generate optional
107
    $::ScmToolsetProgDependancies = 0;          # handle Prog dependancies myself
108
    %::ScmToolsetProgSource = (                 # handle these files directly
109
            '.cs'       => '',                  # Will be flagged as "CSRCS"
110
            '.resx'     => '--Resource=',       # Will be passed with prefix
111
            '.dtd'      => '--Dtd=',            # Will be passed with prefix
112
            );
113
 
114
    #.. define Visual C/C+ environment
115
    Init( "csharp" );
255 dpurdie 116
    ToolsetDefines( $toolset_info->{'def'} );
227 dpurdie 117
    ToolsetRules( "csharp.rul" );
118
#    ToolsetRules( "standard.rul" );
119
 
120
 
121
    #.. Extend the CompilerOption directive
122
    #   Create a standard data structure
123
    #   This is a hash of hashes
124
    #       The first hash is keyed by CompileOption keyword
125
    #       The second hash contains pairs of values to set or remove
126
    #
127
    %::ScmToolsetCompilerOptions =
128
    (
129
        #
130
        #   Control the thread model to use
131
        #   This will affect the compiler options and the linker options
132
        #
133
        'noaddlibs'          => { 'ADDLINKLIBS' , undef },      # Don't add link libs
134
        'addlibs'            => { 'ADDLINKLIBS' , '1' },        # default
135
        'nowarn='            => { 'NOWARNLIST'  ,\&NoWarns },   # Suppress warnings
136
        'nopdb'              => { 'PDB_NONE', 1 },              # Disable all PDB files
137
        'pdb'                => { 'PDB_NONE', undef },          # Enable PDB files: Default
138
        'subsystem:windows'  => { 'LDSUBSYSTEM' , 'winexe' },
139
        'subsystem:console'  => { 'LDSUBSYSTEM' , 'exe' },
351 dpurdie 140
        'platform:32'        => { 'NET_PLATFORM', 'x86' },
141
        'platform:64'        => { 'NET_PLATFORM', 'x64' },
142
        'platform:any'       => { 'NET_PLATFORM', undef },
2931 dpurdie 143
        'noversiondll'       => { 'NO_VERSIONED_DLLS', 1 },
227 dpurdie 144
    );
145
 
146
    #
147
    #   Set default options
148
    #
149
    $::ScmCompilerOpts{'ADDLINKLIBS'} = '1';
255 dpurdie 150
    $::ScmCompilerOpts{'NOWARNLIST'} = $toolset_info->{'warnings'};
227 dpurdie 151
    $::ScmCompilerOpts{'LDSUBSYSTEM'} = 'winexe';
351 dpurdie 152
    $::ScmCompilerOpts{'NET_PLATFORM'} = $toolset_info->{'platform'};
2931 dpurdie 153
    $::ScmCompilerOpts{'NO_VERSIONED_DLLS'} = undef;
227 dpurdie 154
}
155
 
156
 
157
#-------------------------------------------------------------------------------
158
# Function        : NoWarns
159
#
160
# Description     : ScmToolsetCompilerOptions  extension function
255 dpurdie 161
#                   Accumulates the NoWarn options as a comma seperated list
227 dpurdie 162
#
163
# Inputs          : $key        - Name of the Option
164
#                   $value      - Option Value. Comma sep list of numbers
255 dpurdie 165
#                   $ukey       - User key (within $::ScmCompilerOpts)
227 dpurdie 166
#
167
# Returns         : New sting to save
168
#
169
sub NoWarns
170
{
255 dpurdie 171
    my ($key, $value, $ukey) = @_;
172
    my @NoWarnList =  split (',', $::ScmCompilerOpts{$ukey});
261 dpurdie 173
    UniquePush ( \@NoWarnList, split (',', $value) );
227 dpurdie 174
    return join ',', @NoWarnList;
175
}
176
 
177
##############################################################################
178
#   ToolsetPreprocess()
179
#       Process collected data before the makefile is generated
180
#       This, optional, routine is called from within MakefileGenerate()
181
#       It allows the toolset to massage any of the collected data before
182
#       the makefile is created
183
#
184
##############################################################################
185
sub ToolsetPreprocess
186
{
187
    #
188
    #   Extract the current state of PDB_NONE
189
    #   Are PDB files to be constructed.
190
    #
191
    $pdb_none = $::ScmCompilerOpts{'PDB_NONE'};
192
}
193
 
194
##############################################################################
195
#   ToolsetPostprocess
196
#       Process collected data as the makefile is generated
197
#       This, optional, routine is called from within MakefileGenerate()
198
#       It allows the toolset to massage any of the collected data before
199
#       the makefile is finally closed created
200
#
201
##############################################################################
202
 
203
sub ToolsetPostprocess
204
{
205
    #
206
    #   Generate Recipes to create Resource Files
207
    #   This is done outside of the Prog and Lib routines
208
    #   so that they can be agregated
209
    #
210
    #   Note: don't make the makefile a dependant as changes to the
211
    #         makefile won't affect the file
212
    #
213
    for my $resource ( sort keys %resource_files )
214
    {
215
        my $src  = $resource_files{$resource}{src};
216
        my $root = $resource_files{$resource}{root};
217
 
218
        my $me = MakeEntry::New (*MAKEFILE, $resource );
219
        $me->AddComment ("Build Resource: $root" );
261 dpurdie 220
#        $me->AddDependancy ( '$(SCM_MAKEFILE)' );
227 dpurdie 221
        $me->AddDependancy ( $src );
222
        $me->AddRecipe ( '$(RESGEN)' );
223
        $me->Print();
224
 
225
        #
226
        #   Add to the deletion list
227
        #
228
        ToolsetGenerate( $resource );
229
    }
230
}
231
 
232
#-------------------------------------------------------------------------------
233
# Function        : Toolset_genres
234
#
235
# Description     : Internal function to assist in the creation of a resource
236
#                   In many cases it will create an entry for later processing
237
#
238
# Inputs          : $subdir         - Root of the target directory for the generated
239
#                                     resource file
240
#                   $src            - Path to the sorce resource file
241
#
242
# Returns         : Path to the generated resource file
243
#                   This will be FQN named file
244
#                   Path to the associated .CS file
245
#
246
# Notes           : Create and maintain the %resource_files hash
247
#                   Key is the path to the compiled file
248
#                   Values are:
249
#                       {src}   - Path to the source file
250
#                       {root}  - Basic file name (Display Purposes Only)
251
#
252
#                   Need to create a '.resource' file with a FQN name
253
#                   This is not that simple. Need to
254
#                       1) Extract the (optional) ThisName from the .resx file
255
#                          If not specified then the ThisName is the rootfilename
256
#                          without any .as[pca]x extension.
257
#                       2) Extract the namespace from the associated .cs file
258
#                       3) FQN = NameSpace.ThisName
259
#
260
#
261
sub Toolset_genres
262
{
263
    my ($subdir, $src ) = @_;
264
 
265
    #
266
    #   Ensure that the .cs file also exists
267
    #
268
    (my $csfile = $src) =~ s~\.resx$~.cs~;
3967 dpurdie 269
    (my $designerfile = $src) =~ s~\.resx$~.Designer.cs~;
270
 
3987 dpurdie 271
    $csfile = $designerfile if ( -f $designerfile && -s $designerfile);
3967 dpurdie 272
 
273
    Warning ("$toolset_name toolset: Resx File without a .cs or Designer.cs file",
379 dpurdie 274
           "File: $src") unless ( -f $csfile );
227 dpurdie 275
 
276
    #
277
    #   Scan the .resx file looking for the ThisName element
278
    #   A very simple and crude parser
279
    #
280
    my $ThisName;
3967 dpurdie 281
    my $ThisNameGuess;
227 dpurdie 282
    open ( SCAN, '<', $src ) || Error ("Cannot open file for reading: $!", "File: $src" );
283
    while ( <SCAN> )
284
    {
285
        if ( m~\<data name=\"\$this\.Name\"\>~ )
286
        {
287
            # Next line will contain the needed data item
288
            my $element = <SCAN>;
289
            $element =~ m~\<.+\>(.+)\</.+\>~;
290
            $ThisName = $1;
343 dpurdie 291
            Error ("$toolset_name toolset: Resx parsing: Bad this.Name", "File: $src") unless $ThisName;
227 dpurdie 292
            $ThisName =~ s~\s+~~g;
293
            last;
294
        }
295
    }
296
    close SCAN;
297
 
298
    #
299
    #   Name not found
300
    #   Use a default. Filename with any .aspx, .asax, .ascx removed
301
    #
302
    unless ( $ThisName )
303
    {
3967 dpurdie 304
        $ThisNameGuess = $ThisName;
305
        $ThisNameGuess = StripDirExt($src);
306
        $ThisNameGuess =~ s~\.as[pac]x~~i;
227 dpurdie 307
    }
308
 
309
    #
3967 dpurdie 310
    #   Scan the.cs file looking for the namespace and class
227 dpurdie 311
    #   A very simple and crude parser
312
    #
313
    my $NameSpace;
3967 dpurdie 314
    my $ClassName;
315
 
227 dpurdie 316
    open ( SCAN, '<', $csfile ) || Error ("Cannot open file for reading: $!", "File: $csfile" );
317
    while ( <SCAN> )
318
    {
3967 dpurdie 319
        next if ( m ~\s*//~);
320
 
321
        if ( m~namespace\s+(\S+)~ ) {
227 dpurdie 322
            $NameSpace = $1;
3967 dpurdie 323
 
324
        } elsif ( m~\s+class\s+(\S+)~ ) {
325
            $ClassName = $1;
326
 
227 dpurdie 327
        }
3967 dpurdie 328
        last if ( defined($NameSpace) && defined($ClassName) );
329
 
227 dpurdie 330
    }
331
    close SCAN;
343 dpurdie 332
    Error ("$toolset_name toolset: Resx parsing: NameSpace not found", "File: $csfile") unless $NameSpace;
227 dpurdie 333
 
334
    #
335
    #   Need to create an output file name that is a function of the FQN
3967 dpurdie 336
    #   To be backwardly compatible
337
    #       Use the ClassName - if it was found
338
    #       Else Use the ThisName - if it was found
339
    #       Else Use the Guessed ThisName
227 dpurdie 340
    #
3967 dpurdie 341
    if ( !defined($ClassName)) {
342
        $ClassName = $ThisName;
343
        if ( !defined($ClassName)) {
344
            $ClassName = $ThisNameGuess;
345
        }
346
    }
347
 
348
    my $root = "$NameSpace.$ClassName.resources";
227 dpurdie 349
    my $resource = $subdir . '/' . $root;
350
    $resource_files{$resource}{src} = $src;
351
    $resource_files{$resource}{root} = $root;
352
 
353
    return $resource, $csfile;
354
}
355
 
356
 
357
#-------------------------------------------------------------------------------
358
# Function        : Toolset_gensnk
359
#
360
# Description     : Function to create a wrapper file for the processing
361
#                   of a StrongNameKey file
362
#
363
#                   Create only one wrapper per SNK file
364
#
365
# Inputs          : $name       - Name of component
366
#                   $snk        - Path to the SNK file
367
#
368
# Returns         : Path to the wrapper file
369
#
370
my %snk_data;
371
sub Toolset_gensnk
372
{
373
    my ($name, $snk ) = @_;
374
    my $file = StripDirExt( $snk );
375
 
376
    #
377
    #   Only create the file once
378
    #   Otherwise we will get nasty make messages
379
    #
380
 
381
    if ( exists $snk_data{$snk} )
382
    {
383
        return $snk_data{$snk}{output};
384
    }
385
 
386
    #
387
    #   Determine the target name
388
    #   Create the source file in the currentt directory
389
    #   If we build it in the OBJ directory we get two files
390
    #
391
    my $snk_file = '$(OBJDIR)/' . "Jats_${file}.cs";
392
    $snk_data{$snk}{output} = $snk_file;
393
    ToolsetGenerate( $snk_file );
394
 
395
    #
396
    #   Determine the Tag Name
397
    #   Used to conatin information in the makefile
398
    #
399
    my $tag = "${file}_snk";
400
 
401
    #
402
    #   Create Rules and Recipes to create the SNK wrapper file
403
    #
404
    my $me = MakeEntry::New (*MAKEFILE, $snk_file );
405
    $me->AddComment ("Build Strong Name Key File Wrapper: $snk" );
406
    $me->AddDependancy ( $snk );
261 dpurdie 407
    $me->AddDependancy ( '$(SCM_MAKEFILE)' );
227 dpurdie 408
    $me->AddRecipe ( '$(call GenSnkWrapper,' . $tag .  ')' );
409
    $me->Print();
410
 
411
    #
412
    #   Create the data t be placed into the wrapper file
413
    #
414
    my ($io) = ToolsetPrinter::New();
415
 
416
    my $ms_snk = $snk;
417
 
418
    $io->Label( "SNK Wrapper file content", $tag );    # label
419
    $io->SetTag( $tag );                                # macro tag
255 dpurdie 420
    $io->Cmd( '// This is JATS GENERATED FILE' );
421
    $io->Cmd( '//    Do not edit' );
422
    $io->Cmd( '//    Do not version control' );
423
 
227 dpurdie 424
    $io->Cmd( 'using System.Reflection;' );
425
    $io->Cmd( 'using System.Runtime.CompilerServices;' );
426
 
427
    $io->Cmd( '//' );
428
    $io->Cmd( '// In order to sign your assembly you must specify a key to use. Refer to the' );
429
    $io->Cmd( '// Microsoft .NET Framework documentation for more information on assembly signing.' );
430
    $io->Cmd( '//' );
431
    $io->Cmd( '// Use the attributes below to control which key is used for signing.' );
432
    $io->Cmd( '//' );
433
    $io->Cmd( '// Notes:' );
434
    $io->Cmd( '//   (*) If no key is specified, the assembly is not signed.' );
435
    $io->Cmd( '//   (*) KeyName refers to a key that has been installed in the Crypto Service' );
436
    $io->Cmd( '//       Provider (CSP) on your machine. KeyFile refers to a file which contains' );
437
    $io->Cmd( '//       a key.' );
438
    $io->Cmd( '//   (*) If the KeyFile and the KeyName values are both specified, the' );
439
    $io->Cmd( '//       following processing occurs:' );
440
    $io->Cmd( '//       (1) If the KeyName can be found in the CSP, that key is used.' );
441
    $io->Cmd( '//       (2) If the KeyName does not exist and the KeyFile does exist, the key' );
442
    $io->Cmd( '//           in the KeyFile is installed into the CSP and used.' );
443
    $io->Cmd( '//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.' );
444
    $io->Cmd( '//       When specifying the KeyFile, the location of the KeyFile should be' );
445
    $io->Cmd( '//       relative to the project output directory which is' );
446
    $io->Cmd( '//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is' );
447
    $io->Cmd( '//       located in the project directory, you would specify the AssemblyKeyFile' );
448
    $io->Cmd( '//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]' );
449
    $io->Cmd( '//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework' );
450
    $io->Cmd( '//       documentation for more information on this.' );
451
    $io->Cmd( '//' );
452
 
453
    $io->Cmd( '[assembly: AssemblyDelaySign(false)]' );
255 dpurdie 454
    $io->Cmd( '#pragma warning disable 1699' ) if ($toolset_info->{'pragma'});
227 dpurdie 455
    $io->Cmd( '[assembly: AssemblyKeyFile(@"'. $snk  .'")]' );
255 dpurdie 456
    $io->Cmd( '#pragma warning restore 1699' ) if ($toolset_info->{'pragma'});
227 dpurdie 457
    $io->Cmd( '[assembly: AssemblyKeyName("")]' );
458
    $io->Newline();
459
 
460
    #
461
    #   Return the path to where the file will be created
462
    #
463
    return $snk_file;
464
}
465
 
466
 
467
###############################################################################
468
#   ToolsetLD( $name, \@args, \@objs, \@libraries )
469
#       This subroutine takes the user options and builds the rules
470
#       required to link the program 'name'.
471
#
472
#   Arguments:
473
#       $name       - Name of the target program
474
#       $pArgs      - Ref to an array of argumennts
475
#       $pObjs      - Ref to an array of object files
476
#       $pLibs      - Ref to an array of libraries
477
#
478
#   Output:
479
#       Makefile recipes to create the Program
480
#
481
#   Notes:
482
#       This Program Builder will handle its own dependancies
483
#       It will also create rules and recipes to construct various
484
#       parts directly fromm source
485
#
486
#   Options:
487
#       --Resource=file.resx
488
#       --Dtd=file.dtd
489
#       --Icon=file
490
#       --Entry=xxxxx                   # Entry point
491
#       --Console                       # Console app
492
#       --Windows                       # Windows app (default)
493
#       --DLL                           # As a DLL (No P|D)
494
#       --Doc
495
#       --NoPDB
496
#       CSharpSourceFile
497
#
498
#
499
###############################################################################
500
 
501
sub ToolsetLD
502
{
503
    my ( $name, $pArgs, $pObjs, $pLibs ) = @_;
504
    my ( @reslist, @resources, @csource, @dtd );
505
    my $no_pdb = $pdb_none;
506
    my $entry;
507
    my $noaddlibs;
508
    my $icon;
509
    my $docFile;
510
    my ($base, $root, $full );
511
    my $link_target = $::ScmCompilerOpts{'LDSUBSYSTEM'};
512
    my $snk;
513
    my $is_a_dll;
514
 
515
    #.. Parse arguments
516
    #
517
    foreach ( @$pArgs ) {
518
        if (/^--Resource=(.+)/) {               # Resource definition
519
            push @reslist, MakeSrcResolve($1);
520
 
521
        } elsif (/^--Dtd=(.+)/) {               # dtd definition
522
            push @dtd, MakeSrcResolve($1);
523
 
524
        } elsif (/^--Icon=(.+)/) {
343 dpurdie 525
            Error ("$toolset_name LD: Only one Icon file allowed") if ( $icon );
227 dpurdie 526
            $icon = MakeSrcResolve($1);
527
 
528
        } elsif (/^--StrongNameKey=(.+)/) {
343 dpurdie 529
            Error ("$toolset_name LD: Only one SNK file allowed") if ( $snk );
227 dpurdie 530
            $snk = MakeSrcResolve($1);
531
 
532
        } elsif (/^--Entry=(.+)/) {
533
            $entry = $1;
534
 
535
        } elsif (/^--Doc/) {
536
            $docFile = 1;
537
 
538
        } elsif (/^--Windows/) {
539
            $link_target = 'winexe';
540
 
541
        } elsif (/^--Console/) {
542
            $link_target = 'exe';
543
 
544
        } elsif (/^--DLL/) {
545
            $is_a_dll = 1;
546
 
547
        } elsif (/^--NoPDB$/) {
548
            $no_pdb = 1;
549
 
550
        } elsif ( !/^-/ ) {
551
            push @csource, MakeSrcResolve($_);
552
 
553
        } else {
343 dpurdie 554
            Message( "$toolset_name LD: unknown option $_ -- ignored\n" );
227 dpurdie 555
 
556
        }
557
    }
558
 
559
    #
560
    #   Determine the target output name
561
    #
562
    $base = $name;
563
    $root = "\$(BINDIR)/$base";
564
    $full = $root . $::exe;
565
    $docFile = "$root.xml" if ( $docFile );
566
 
567
    #
568
    #   Special case for DLLs that need to be created without a D or P mangled
569
    #   into the name. Create them as Progs just to fool the system
570
    #   Used when creating specialised web services
571
    #
572
    if ( $is_a_dll )
573
    {
574
        #
575
        #   Create a phony target
576
        #   The EXE name is not actually created, but the EXE target needs to be retained
577
        #
578
        my $exe_name = $root . $::exe;
579
        my $dll_name = $root . '.' . $::so;
580
        $full = $dll_name;
581
        $link_target = 'library';
582
 
583
        my $me = MakeEntry::New (*MAKEFILE, $exe_name, '--Phony' );
584
        $me->AddComment ("Build Program: $name as a DLL" );
585
        $me->AddDependancy ( $dll_name );
586
        $me->Print();
255 dpurdie 587
 
588
        #
589
        #   Need to specifically clean this up, since we have fiddled with the
590
        #   name of the generated file
591
        #
592
        ToolsetGenerate( $dll_name );
227 dpurdie 593
    }
594
 
595
    #
596
    #   Create Rules and Recipes to convert the .resx files to .resource files
597
    #
598
    foreach my $res ( @reslist )
599
    {
600
        my ($res, $cs) = Toolset_genres ('$(OBJDIR)', $res );
601
 
602
        UniquePush ( \@resources, $res );
603
        UniquePush ( \@csource, $cs );
604
    }
605
 
606
    #
607
    #   Create Rules and Recipes to provide Assembly instructions
608
    #   for the creation of a StrongNameKey
609
    #
610
    if ( $snk )
611
    {
612
        UniquePush ( \@csource, Toolset_gensnk ($name, $snk ) );
613
    }
614
 
335 dpurdie 615
    my ($io) = ToolsetPrinter::New();
616
    my $dep = $io->SetLdTarget( $name );
617
 
227 dpurdie 618
    #
619
    #   Create Rules and Recipes to create the Program
620
    #   This will be a combination of source, libraries and resources
621
    #
622
    my $me = MakeEntry::New (*MAKEFILE, $full );
623
    $me->AddComment ("Build Program: $name" );
624
    $me->AddName    ( $docFile ) if ( $docFile );
335 dpurdie 625
    $me->AddDependancy ( $dep );
261 dpurdie 626
    $me->AddDependancy ( '$(SCM_MAKEFILE)' );
227 dpurdie 627
    $me->AddDependancy ( @resources );
628
    $me->AddDependancy ( @csource );
629
    $me->AddDependancy ( @dtd );
630
    $me->AddDependancy ( $icon );
631
    $me->AddRecipe ( '$(CSC)' );
632
    $me->Print();
633
 
634
 
635
    #
636
    #.. Compiler command file
637
    #       Now piece together a variable $(name_ld) which ends up in
638
    #       the command file linking the application.
639
    #
640
    $io->Label( "Linker commands", $name );     # label
641
    $io->SetTag( "${name}_ld" );                # macro tag
642
 
643
    $io->Label( "Linker Command File", $name ); # label
644
 
645
    #
646
    #   Basic options
647
    #
648
    $io->Cmd( "/target:$link_target" );
649
    $io->Cmd("/doc:$docFile") if ( $docFile ) ;
650
    $io->Cmd( "/win32icon:\$(subst /,\\\\,$icon)" ) if $icon;
651
    $io->Cmd( "/main:$entry" ) if $entry;
652
 
653
    #
654
    #   Add in the Resource Files
655
    #          the source files
656
    #          the libraries
657
    #
658
    $io->Cmd( "/res:\$(subst /,\\\\,$_)" ) foreach @resources;
659
    $io->Cmd( "/res:\$(subst /,\\\\,$_)" ) foreach @dtd;
660
    $io->Cmd( "\$(subst /,\\\\,$_)" ) foreach @csource;
661
    $io->LibList( $name, $pLibs, \&ToolsetLibRecipe );
335 dpurdie 662
    $io->Newline();
227 dpurdie 663
 
664
 
335 dpurdie 665
    #.. Dependency link,
666
    #   Create a library dependency file
667
    #       Create command file to build applicaton dependency list
668
    #       from the list of dependent libraries
227 dpurdie 669
    #
335 dpurdie 670
    #       Create makefile directives to include the dependency
671
    #       list into the makefile.
227 dpurdie 672
    #
335 dpurdie 673
    $io->DepRules( $pLibs, \&ToolsetLibRecipe, $full );
674
    $io->LDDEPEND();
227 dpurdie 675
 
676
    #
677
    #   Files to clean up
678
    #
679
    ToolsetGenerate( "$root.ld" );
680
    ToolsetGenerate( "$root.pdb" );
681
    ToolsetGenerate( $docFile ) if $docFile;
682
 
683
 
684
    #.. Package up files that are a part of the program
685
    #
686
    PackageProgAddFiles ( $name, $full );
687
    PackageProgAddFiles ( $name, "$root.pdb", "Class=debug" ) unless ( $no_pdb );
688
    PackageProgAddFiles ( $name, $docFile, "Class=map" ) if ( $docFile );
689
}
690
 
691
###############################################################################
289 dpurdie 692
#   ToolsetSHLD( $name, \@args, \@objs, \@libraries, $ver )
227 dpurdie 693
#       This subroutine takes the user options and builds the rules
694
#       required to link the program 'name'.
695
#
696
#   Arguments:
697
#       $name       - Name of the target program
698
#       $pArgs      - Ref to an array of argumennts
699
#       $pObjs      - Ref to an array of object files
700
#       $pLibs      - Ref to an array of libraries
289 dpurdie 701
#       $ver        - Library Version string
227 dpurdie 702
#
703
#   Output:
704
#       Makefile recipes to create the DLL
705
#       Will create both versioned and unversioned DLLs
706
#
707
#   Notes:
708
#       This Library Builder will handle its own dependancies
709
#       It will also create rules and recipes to construct various
710
#       parts directly from source
711
#
712
#       This is SO close to the ToolsetLD function that its not funny
713
#
714
#   Options:
715
#       --Resource=file.resx
716
#       --Icon=file
717
#       --StrongNameKey=file
718
#       --Doc
719
#       --NoPDB
2931 dpurdie 720
#       --NoVersionDll
227 dpurdie 721
#       CSharpSourceFile
722
#
723
#
724
###############################################################################
725
sub ToolsetSHLD
726
{
727
    #
728
    #   Note: Use globals to kill warnings from internal sub
729
    #         Use _ prefix so that they don't get saved in Makefile_x.cfg
730
    #         Init as they are global
731
    #
289 dpurdie 732
    our ( $_name, $_pArgs, $_pObjs, $_pLibs, $_ver ) = @_;
227 dpurdie 733
    our ( @_reslist, @_resources, @_csource, @_dtd ) = ();
734
    our $_no_pdb = $pdb_none;
735
    our $_noaddlibs = 0;
736
    our $_icon = undef;
737
    our $_docFile = undef;
738
    our $_snk = undef;
739
 
2931 dpurdie 740
    my $noVersionedDlls = $::ScmCompilerOpts{'NO_VERSIONED_DLLS'};
741
 
227 dpurdie 742
    #.. Parse arguments
743
    #
744
    foreach ( @$_pArgs ) {
4031 dpurdie 745
        if (/^--Resource=(.+)/i) {               # Resource definition
227 dpurdie 746
            push @_reslist, MakeSrcResolve($1);
747
 
4031 dpurdie 748
        } elsif (/^--Dtd=(.+)/i) {               # dtd definition
227 dpurdie 749
            push @_dtd, MakeSrcResolve($1);
750
 
4031 dpurdie 751
        } elsif (/^--Icon=(.+)/i) {
343 dpurdie 752
            Error ("$toolset_name SHLD: Only one Icon file allowed") if ( $_icon );
227 dpurdie 753
            $_icon = MakeSrcResolve($1);
754
 
4031 dpurdie 755
        } elsif (/^--StrongNameKey=(.+)/i) {
343 dpurdie 756
            Error ("$toolset_name SHLD: Only one SNK file allowed") if ( $_snk );
227 dpurdie 757
            $_snk = MakeSrcResolve($1);
758
 
4031 dpurdie 759
        } elsif (/^--Doc/i) {
227 dpurdie 760
            $_docFile = 1;
761
 
4031 dpurdie 762
        } elsif (/^--NoPDB$/i) {
227 dpurdie 763
            $_no_pdb = 1;
764
 
4031 dpurdie 765
        } elsif (/^--NoVersionDll/i) {
2931 dpurdie 766
            $noVersionedDlls = 1;
767
 
227 dpurdie 768
        } elsif ( !/^-/ ) {
769
            push @_csource, MakeSrcResolve($_);
770
 
771
        } else {
343 dpurdie 772
            Message( "$toolset_name SHLD: unknown option $_ -- ignored\n" );
227 dpurdie 773
 
774
        }
775
    }
776
 
777
    #
778
    #   Create Rules and Recipes to convert the .resx files to .resource files
779
    #
780
    foreach my $res ( @_reslist )
781
    {
782
        my ($res, $cs) = Toolset_genres ('$(OBJDIR)/' . $_name, $res );
783
 
784
        UniquePush ( \@_resources, $res );
785
        UniquePush ( \@_csource, $cs );
786
    }
787
 
788
    #
789
    #   Create Rules and Recipes to provide Assembly instructions
790
    #   for the creation of a StrongNameKey
791
    #
792
    if ( $_snk )
793
    {
794
        UniquePush ( \@_csource, Toolset_gensnk ($_name, $_snk ) );
795
    }
796
 
797
    #
798
    #   Build Rules
799
    #   $1  - Base Name
800
    #   $2  - Name of the output DLL
801
    #
802
    sub BuildSHLD
803
    {
804
        my ($name, $lib ) = @_;
805
        my ($root, $full, $link_target);
806
 
807
        #
808
        #   Determine the target output name
809
        #
810
        $root = "\$(LIBDIR)/$lib";
811
        $full = "$root.$::so";
812
        $link_target = "library";
813
        $_docFile = "$full.xml" if ($_docFile);
814
 
335 dpurdie 815
        my ($io) = ToolsetPrinter::New();
816
        my $dep = $io->SetShldTarget( $lib );
817
 
227 dpurdie 818
        #
819
        #   Create Rules and Recipes to create the Program
820
        #   This will be a combination of source, libraries and resources
821
        #
822
        my $me = MakeEntry::New (*MAKEFILE, $full );
823
        $me->AddComment ("Build Shared Library: $name" );
824
        $me->AddName    ( $_docFile ) if ( $_docFile );
261 dpurdie 825
        $me->AddDependancy ( '$(SCM_MAKEFILE)' );
335 dpurdie 826
        $me->AddDependancy ( $dep );
227 dpurdie 827
        $me->AddDependancy ( @_resources );
828
        $me->AddDependancy ( @_csource );
829
        $me->AddDependancy ( @_dtd );
830
        $me->AddDependancy ( $_icon );
831
        $me->AddRecipe ( '$(CSC)' );
832
        $me->Print();
833
 
834
 
835
        #
836
        #.. Compiler command file
837
        #       Now piece together a variable $(name_ld) which ends up in
838
        #       the command file linking the application.
839
        #
840
 
841
        $io->Label( "Linker commands", $name );     # label
842
        $io->SetTag( "${lib}_ld" );                 # macro tag
843
 
844
        $io->Label( "Linker Command File", $lib ); # label
845
 
846
        #
847
        #   Basic options
848
        #
849
        $io->Cmd( "/target:$link_target" );
850
        $io->Cmd( "/doc:$_docFile")                    if ( $_docFile ) ;
851
        $io->Cmd( "/win32icon:\$(subst /,\\\\,$_icon)" ) if $_icon;
852
 
853
        #
854
        #   Add in the Resource Files
855
        #          the source files
856
        #          the libraries
857
        #
858
        $io->Cmd( "/res:\$(subst /,\\\\,$_)" ) foreach @_resources;
859
        $io->Cmd( "/res:\$(subst /,\\\\,$_)" ) foreach @_dtd;
860
        $io->Cmd( "\$(subst /,\\\\,$_)" ) foreach @_csource;
861
        $io->LibList( $name, $_pLibs, \&ToolsetLibRecipe );
335 dpurdie 862
        $io->Newline();
227 dpurdie 863
 
335 dpurdie 864
        #.. Dependency link,
865
        #   Create a library dependency file
866
        #       Create command file to build applicaton dependency list
867
        #       from the list of dependent libraries
227 dpurdie 868
        #
335 dpurdie 869
        #       Create makefile directives to include the dependency
870
        #       list into the makefile.
227 dpurdie 871
        #
335 dpurdie 872
        $io->DepRules( $_pLibs, \&ToolsetLibRecipe, $full );
873
        $io->SHLDDEPEND( $name, $lib  );
227 dpurdie 874
 
875
        #
876
        #   Files to clean up
877
        #
878
        ToolsetGenerate( "$root.ld" );
879
        ToolsetGenerate( "$root.pdb" );
880
        ToolsetGenerate( $_docFile ) if $_docFile;
881
 
882
 
883
        #.. Package up files that are a part of the Library
884
        #
885
        PackageShlibAddFiles ( $name, $full );
886
        PackageShlibAddFiles ( $name, "$root.pdb", "Class=debug" ) unless ( $_no_pdb );
887
        PackageShlibAddFiles ( $name, $_docFile  , "Class=map" ) if ( $_docFile );
888
 
889
        #
890
        #   Return the full name of the created DLL.
891
        #
892
        return $full;
893
    }
894
 
895
    #
896
    #   Generate DLLs
897
    #
898
    #       a) Unversioned DLL  $_name$(GBE_TYPE).dll
899
    #       b) Versioned DLL    $_name$(GBE_TYPE).xx.xx.xx.dll
900
    #
901
    my $funver = BuildSHLD( "$_name", "$_name\$(GBE_TYPE)" );
2931 dpurdie 902
    unless ($noVersionedDlls)
903
    {
904
        my $fver   = BuildSHLD( "$_name", "$_name\$(GBE_TYPE).$_ver" );
227 dpurdie 905
 
2931 dpurdie 906
        #
907
        #   Create a dependancy between the version and unversioned DLLs
908
        #
909
        my $me = MakeEntry::New (*MAKEFILE, $fver );
910
        $me->AddComment ("Link Version and Unversioned Images: $_name" );
911
        $me->AddDependancy ( $funver );
912
        $me->Print();
913
    }
227 dpurdie 914
}
915
 
916
########################################################################
917
#
918
#   Generate a linker/depend library recipe.  This is a helper function
919
#   used within this toolset.
920
#
921
#   Arguments:
922
#       $io         I/O stream
923
#
924
#       $target     Name of the target
925
#
926
#       $lib        Library specification
927
#
928
#       $dp         If building a depend list, the full target name.
929
#
930
########################################################################
931
 
932
sub ToolsetLibRecipe
933
{
934
    my ($io, $target, $lib, $dp) = @_;
935
 
936
    if ( !defined($dp) ) {                      # linker
937
        $io->Cmd( "/reference:\$(subst /,\\\\,\$(strip $lib)).$::so" );
938
 
939
    } else {                                    # depend
255 dpurdie 940
        $io->Cmd( "$dp:\t@(vglob2,$lib.$::so,CS_LIB)" );
227 dpurdie 941
    }
942
}
943
 
944
########################################################################
945
#
946
#   Generate a project from the provided project solution file
947
#   This is aimed at .NET work
948
#
949
#   Arguments   : $name             - Base name of the project
950
#                 $solution         - Path to the solutionn file
951
#                 $pArgs            - Project specific options
952
#
953
########################################################################
954
 
955
my $project_defines_done = 0;
956
sub ToolsetPROJECT
957
{
958
    my( $name, $solution ,$pArgs ) = @_;
959
    my $buildcmd = 'devenv =DSW= /build =TYPE= /useenv /out =LOG=';
960
    my $cleancmd = 'devenv =DSW= /clean =TYPE= /useenv';
343 dpurdie 961
    my $release = 'RELEASE';
962
    my $debug = 'DEBUG';
227 dpurdie 963
 
964
    #
965
    #   Process options
966
    #
967
    foreach ( @$pArgs ) {
343 dpurdie 968
        if ( m/^--TargetProd*=(.+)/ ) {
969
            $release = $1;
970
 
971
        } elsif ( m/^--TargetDebug=(.+)/ ) {
972
            $debug = $1;
973
 
974
        } else {
975
            Message( "$toolset_name PROJECT: unknown option $_ -- ignored\n" );
976
        }
227 dpurdie 977
    }
978
 
979
    my ($io) = ToolsetPrinter::New();
980
 
981
    #
343 dpurdie 982
    #   Setup toolset specific difinitions. Once
227 dpurdie 983
    #
984
    unless( $project_defines_done )
985
    {
986
        $project_defines_done = 1;
343 dpurdie 987
        $io->PrtLn( 'project_target = $(if $(findstring 1,$(DEBUG)),$2,$1)' );
227 dpurdie 988
        $io->Newline();
989
    }
990
 
991
    #
992
    #   Process the build and clean commands
993
    #       Substitute arguments
994
    #           =TYPE=
995
    #           =LOG=
996
    #           =DSW=
997
    #
343 dpurdie 998
    $buildcmd =~ s~=TYPE=~"\$(call project_target,$release,$debug)"~g;
227 dpurdie 999
    $buildcmd =~ s~=LOG=~$name\$(GBE_TYPE).log~g;
1000
    $buildcmd =~ s~=DSW=~$solution~g;
1001
 
343 dpurdie 1002
    $cleancmd =~ s~=TYPE=~"\$(call project_target,$release,$debug)"~g;
227 dpurdie 1003
    $cleancmd =~ s~=LOG=~$name\$(GBE_TYPE).log~g;
1004
    $cleancmd =~ s~=DSW=~$solution~g;
1005
 
1006
    #
1007
    #   Generate the recipe to create the project
1008
    #   Use the set_<PLATFORM>.sh file to extend the DLL search path
1009
    #
1010
    $io->Label( "Build project", $name );
1011
    $io->PrtLn( "Project_$name: $solution \$(INTERFACEDIR)/set_$::ScmPlatform.sh" );
1012
 
1013
    $io->PrtLn( "\t\$(XX_PRE)( \$(rm) -f $name\$(GBE_TYPE).log; \\" );
1014
    $io->PrtLn( "\t. \$(INTERFACEDIR)/set_$::ScmPlatform.sh; \\" );
255 dpurdie 1015
    $io->PrtLn( "\t\$(show_environment); \\" );
227 dpurdie 1016
    $io->PrtLn( "\t$buildcmd; \\" );
1017
    $io->PrtLn( "\tret=\$\$?; \\" );
1018
    $io->PrtLn( "\t\$(GBE_BIN)/cat $name\$(GBE_TYPE).log; \\" );
1019
    $io->PrtLn( "\texit \$\$ret )" );
1020
    $io->Newline();
1021
 
1022
    #
1023
    #   Generate the recipe to clean the project
1024
    #
1025
    $io->Label( "Clean project", $name );
1026
    $io->PrtLn( "ProjectClean_$name: $solution" );
1027
    $io->PrtLn( "\t-\$(XX_PRE)$cleancmd" );
1028
    $io->PrtLn( "\t-\$(XX_PRE)\$(rm) -f $name\$(GBE_TYPE).log" );
1029
    $io->Newline();
1030
 
1031
}
1032
 
1033
#-------------------------------------------------------------------------------
1034
# Function        : ToolsetTESTFRAMEWORK_NUNIT
1035
#
1036
# Description     : Toolset specfic support for the NUNIT Test FrameWork
1037
#                   Accessed with RunTest ('*', --FrameWork=nunit, ... );
1038
#
1039
#                   Manipulates the pEntry structure to allow JATS to
1040
#                   construct a test entry to run Nunit tests
1041
#
1042
# Inputs          : $pEntry                 - Unit Test Hash
1043
#
1044
# Returns         : Modified Hash
1045
#
1046
sub ToolsetTESTFRAMEWORK_NUNIT
1047
{
1048
    my ($pEntry) = @_;
1049
    my $test_dll_name;
1050
    my @copy_dlls;
1051
    my %copy_dll_flags;
1052
 
1053
    #
1054
    #   Extract base name of DLL under test
1055
    #   Thsi will not have any extension.
1056
    #
1057
    $test_dll_name = $pEntry->{'prog'};
1058
    Error ("Nunit Framework. No TestDLL specified") unless $test_dll_name;
1059
 
1060
    #
1061
    #   Process the FrameWork Options
1062
    #
1063
    foreach  ( @{$pEntry->{'framework_opts'}} )
1064
    {
1065
        if ( m/^--Uses=(.+)/ ) {
1066
            my ($dll, @opts) = split (',', $1 );
1067
            push @copy_dlls, $dll;
1068
            foreach  ( @opts )
1069
            {
1070
                if ( m~^--NonJats~i ) {
1071
                    $copy_dll_flags{$dll}{'NonJats'} = 1;
1072
                } elsif ( m~--Jats~ ) {
1073
                    $copy_dll_flags{$dll}{'NonJats'} = 0;
1074
                } else {
1075
                    Error ("Nunit Framework. Unknown sub option to --Uses: $_");
1076
                }
1077
            }
1078
        } else {
1079
            Error ("Nunit Framework. Unknown option: $_");
1080
        }
1081
    }
1082
 
1083
    #
1084
    #   Locate the Nunit essentials
261 dpurdie 1085
    #       This list may change with each version of nunit
1086
    #       Look for a known file and use its contents
1087
    #       Format:
1088
    #           One file name per line
1089
    #           Line comments only
1090
    #           Comment marker is a #
1091
    #           First one MUST be the executable
227 dpurdie 1092
    #
261 dpurdie 1093
    my @nunit_files;
227 dpurdie 1094
 
261 dpurdie 1095
    my $mfile = 'nunit-jats-manifest.txt';
1096
    my $nunit_file = ToolExtensionProgram ( $mfile );
1097
    Error ("Cannot find Nunit Jats Manifest: $mfile") unless ( $nunit_file );
1098
    open (JM, $nunit_file ) || Error( "Cannot open file: $nunit_file", "Reason: $!" );
1099
    while ( <JM> )
1100
    {
1101
        s~\s+$~~;                   # Remove trailing white space
1102
        s~^\s+~~;                   # Remove Leading whitespace
1103
        next unless ( $_ );         # Skip block lines
1104
        next if ( m~^#~ );          # Skip comments
1105
        Verbose ("Nunit File: $_");
1106
        push @nunit_files, $_;
1107
    }
1108
    close JM;
1109
 
1110
    #
1111
    #   Locate all the required files
1112
    #   The first one will be the console executable
1113
    #
227 dpurdie 1114
    my @nunit_framework;
1115
    foreach my $file ( @nunit_files )
1116
    {
1117
        my $path = ToolExtensionProgram ($file );
1118
        Error ("Cannot locate nunit file: $file") unless ( $path );
1119
        push @nunit_framework, $path;
1120
    }
261 dpurdie 1121
    my $nunit_console = $nunit_framework[0];
1122
    Error ("Nunit console executable not specified") unless ( $nunit_console );
227 dpurdie 1123
 
1124
    #
1125
    #   Locate the test DLL.
1126
    #   This will be created locally within this makefile
1127
    #   It will be a known shared library
1128
    #
1129
    Errror( "TestDLL does not appear to be locally created: $test_dll_name" )
289 dpurdie 1130
        unless ( $::SHLIBS->Get($test_dll_name) );
227 dpurdie 1131
 
1132
    #
1133
    #   Hard bit. Determine the name/path of the DLL under test
1134
    #   It will have been created within this makefile
1135
    #   This is not a physical file.
1136
    #
1137
    $test_dll_name = $test_dll_name . '$(GBE_TYPE).' . $::so;
1138
    my $test_dll = '$(LIBDIR)/' . $test_dll_name;
1139
 
1140
    #
1141
    #   Other hard bit
1142
    #   Locate the other dll's needed by this test
1143
    #   Need to use P in production and D in Debug unless otherwise specified
1144
    #   These might be in:
1145
    #       an external package
1146
    #       within the local directory
1147
    #       the current makefile
1148
    #   ie: We can only determine the location of the files at run-time
1149
    #
1150
    #   The mechanism used is:
1151
    #       Create makefile recipe entries to
1152
    #           Use cmdfile to create a command file with copy command
1153
    #           Execute the command file
1154
    #
1155
    #   Complications include:
1156
    #       The windows shell used does not honour 'set -e', so we need to
1157
    #       detect error conditions ourselves
1158
    #
1159
    my $ofile = "\$(TESTDIR)/$pEntry->{test_name}.cmd";
1160
    push @{$pEntry->{'ShellRecipe'}}, "rm -f $ofile";
1161
 
1162
    my @cmds;
363 dpurdie 1163
    push @cmds, "\$(cmdfile) -wk1W1o$ofile";
227 dpurdie 1164
    foreach my $dll ( @copy_dlls )
1165
    {
1166
        #
1167
        #   Generate in-line commands to locate and copy in the required
1168
        #   DLL's. The 'cmdfile' utility can be used to do this at runtime
1169
        #
1170
        my $dll_name = $dll;
1171
        $dll_name .= '$(GBE_TYPE)' unless ( $copy_dll_flags{$dll}{'NonJats'} );
1172
 
363 dpurdie 1173
        push @cmds, '"' . "cp -f @(vglob2,$dll_name.$::so,PATH,/) \$(TESTDIR) || exit 98" . '\n"';
227 dpurdie 1174
    }
1175
    push @cmds, "|| exit 99";
1176
    push @{$pEntry->{'ShellRecipe'}}, \@cmds;
1177
    push @{$pEntry->{'ShellRecipe'}}, ". $ofile";
1178
 
1179
 
1180
    #
1181
    #   Add items to the Unit Test Hash
1182
    #       command     - command to execute to run the test program
1183
    #       prog        - test command/script that must be in the test dir
1184
    #       copyprog    - Prog must be copied in
1185
    #       args        - Arguments to the test
1186
    #       copyin      - Array of files to copy into the test directory
1187
    #       copyonce    - Array of files to copy only once
1188
    #       prereq      - Prerequiste conditions
1189
    #       testdir     - Symbolic name of the test directory
1190
    #       ShellRecipe - Recipe Bits to add
1191
    #
1192
    $pEntry->{'command'}  = $nunit_console . ' ' . $test_dll_name;
1193
    unshift @{$pEntry->{args}}, "/xml=$pEntry->{test_name}.xml";
1194
    $pEntry->{'prog'} = $test_dll_name;
1195
    $pEntry->{'copyprog'} = 0;
1196
    push @{$pEntry->{'copyin'}}, $test_dll;
261 dpurdie 1197
    push @{$pEntry->{'copyonce'}}, @nunit_framework;
227 dpurdie 1198
    $pEntry->{'testdir'}  = 'TESTDIR';
1199
 
1200
    #   
1201
    #   Create the Test Directory
1202
    #   Tests will be done in a .NUNIT subdir
1203
    #
1204
    MkdirRule( "\$(TESTDIR)", 'TESTDIR', '--Path=$(GBE_PLATFORM)$(GBE_TYPE).NUNIT', '--RemoveAll' );
1205
 
1206
    #
1207
    #   Files created by the Unit Test
1208
    #
1209
    ToolsetGenerate ( "\$(TESTDIR)/$pEntry->{test_name}.xml"  );
1210
    ToolsetGenerate ( $ofile  );
1211
 
1212
}
1213
 
1214
#.. Successful termination
1215
1;
1216