Subversion Repositories DevTools

Rev

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