Subversion Repositories DevTools

Rev

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