Subversion Repositories DevTools

Rev

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