Subversion Repositories DevTools

Rev

Rev 6177 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
# -*- mode: perl; tabs: 4; -*-
6177 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
227 dpurdie 3
#
4
# Module name   : gen_msprojects
5
# Module type   : Makefile system
6
#
7
# Description   : Generate Microsoft Workspace and Project files from JATS source
8
#                 This implemenation relies on a complex datafile being generated
9
#                 by the JATS build scripts.
10
#
11
#
12
# Version   Who     Date       Description
13
#           DDP     5-May-04   Created
14
#............................................................................#
15
 
16
use strict;
17
use JatsError;
18
use JatsSystem;
19
use JatsMakeInfo;
20
use ReadBuildConfig qw(:All);
21
use JatsMakeConfig;
22
use ConfigurationFile;
23
use Pod::Usage;                             # required for help support
24
use Getopt::Long;
25
 
26
my $VERSION = "2.0.1";                      # Update this
27
 
28
#
29
#   Global variables
30
#
31
our @cf_filelist;                           # List of non-root makefiles
32
our %msproj_info;                           # Generated
33
 
34
our $ScmBuildMachType;                      # from Makefile.gbe
35
our $ScmRoot;
36
our $ScmInterface;
37
 
38
 
39
#
40
#   Project names. Indexed by directory
41
#
42
my %pnames;
43
my %pnames_files;
44
my %pnames_sname;
45
my %platforms_all;                          # Complete list of target platform names
46
my $default_platform;
47
my $bsc_file;
48
my $build_file_name;
49
my $project_name;
50
my $interface_path;
51
my $jats_path;
52
 
53
 
54
#
55
#   Options
56
#
57
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
58
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
59
my $opt_help = 0;
60
my $opt_manual = 0;
61
my $opt_platform;
62
my $opt_rebuild;
63
my $opt_interface;
64
my $opt_make_debug;
65
my $opt_make_prod;
66
 
67
#-------------------------------------------------------------------------------
68
# Function        : Mainline Entry Point
69
#
70
# Description     :
71
#
72
# Inputs          :
73
#
74
my $result = GetOptions (
75
                "help+"         => \$opt_help,
76
                "manual"        => \$opt_manual,
77
                "verbose+"      => \$opt_verbose,
78
                "platform=s"    => \$opt_platform,
79
                "interface=s"   => \$opt_interface,
80
                "rebuild"       => \$opt_rebuild,
81
                "debug"         => \$opt_make_debug,
82
                "production"    => \$opt_make_prod,
83
                );
84
 
85
                #
86
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
87
                #
88
 
89
#
90
#   Process help and manual options
91
#
92
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ($opt_help == 1 || ! $result );
93
pod2usage(-verbose => 1)  if ($opt_help == 2 );
94
pod2usage(-verbose => 2)  if ($opt_manual || ($opt_help > 2));
95
 
96
#
97
#   Configure the Error reporting process now that we have the user options
98
#
99
ErrorConfig( 'name'    =>'VSGEN', 'verbose' => $opt_verbose );
100
 
101
#
102
#   Sanity test
103
#
104
Error ("Conflicting options: -debug and -prod")
105
    if ( $opt_make_debug && $opt_make_prod );
106
 
107
#
108
#   Determine the mode of operation
109
#   Extract one key work from the argument list
110
#
111
my $cmd = pop @ARGV;
112
 
113
if (! $cmd or  $cmd eq "create" ) {
114
    create_msprojects();
115
 
116
} elsif ( $cmd eq "build" ) {
117
    build_msproject();
118
 
119
} elsif ( $cmd eq "clean" ) {
120
    clean_msproject();
121
 
122
} elsif ( $cmd eq "make" ) {
123
    make_msproject();
124
 
125
} else {
126
    Error( "Command not known: $cmd\n");
127
}
128
exit;
129
 
130
#-------------------------------------------------------------------------------
131
# Function        : make_msproject
132
#
133
# Description     : This function processes build and make requests from the
134
#                   visual studio project "build" comands
135
#
136
#                   Make componets + manage source browser updates
137
#
138
# Inputs          :
139
#
140
# Returns         :
141
#
142
sub make_msproject
143
{
144
    load_msproject_config();
145
 
146
    #
147
    #   If rebuilding then clean first
148
    #   Use "unbuild" as this will also delete "installed" files
149
    #
150
    if ( $opt_rebuild )
151
    {
152
        System ("\"$jats_path\" make ${opt_platform}_unbuild");
153
        unlink ($msproj_info{'BSC_FILE'});
154
    }
155
 
156
    System ("\"$jats_path\" make ${opt_platform}_all_$msproj_info{'tname'} OPTIONS=gensbr");
157
 
158
    if ( $msproj_info{$opt_platform}{'SBR_ROOTS'} )
159
    {
160
        #
161
        #   Now combine SBR files into a common BSC file for source browsing
162
        #
163
        print "Creating Source Browser Information: $msproj_info{'BSC_FILE'} for $opt_platform\n";
164
 
165
        my @files;
166
        foreach my $dir ( @{$msproj_info{$opt_platform}{'SBR_ROOTS'}} )
167
        {
168
            if ( -d $dir )
169
            {
170
                print "Creating filelist in: $dir\n";
171
                push @files, qx (find $dir -type f -name *.sbr);
172
            }
173
            else
174
            {
175
                print "Object directory not found: $dir\n";
176
            }
177
        }
178
 
179
        if ( @files )
180
        {
181
            my $file_list = join ' ', @files;
182
            $file_list =~ s~/~\\~g;
183
            Verbose ("Files: $file_list\n");
184
            print "Running bscmake over all the files\n";
185
            System ("bscmake -v -o $msproj_info{'BSC_FILE'} $file_list" );
186
        }
187
        else
188
        {
189
            print "ERROR: No SBR files found\n";
190
        }
191
    }
192
}
193
 
194
#-------------------------------------------------------------------------------
195
# Function        : build_msproject
196
#
197
# Description     : This function processes build and make requests from the
198
#                   visual studio project "build" comands
199
#
200
#                       Rebuild the makefiles + project files
201
#
202
# Inputs          :
203
#
204
# Returns         :
205
#
206
sub build_msproject
207
{
208
    load_msproject_config();
209
    System ("\"$jats_path\" -b $msproj_info{'BUILD_FILE'} build");
210
 
211
}
212
 
213
#-------------------------------------------------------------------------------
214
# Function        : clean_msproject
215
#
216
# Description     : This function will delete all the MSDEV files created
217
#
218
# Inputs          :
219
#
220
# Returns         :
221
#
222
sub clean_msproject
223
{
224
    ReadMakeInfo();
225
    $opt_interface = "$::ScmRoot/$::ScmInterface";
226
    load_msproject_config();
227
    foreach my $file ( @{$msproj_info{'FILES'}} )
228
    {
229
        print "Delete: $file\n";
230
        unlink $file;
231
    }
232
 
233
}
234
 
235
 
236
#-------------------------------------------------------------------------------
237
# Function        : load_msproject_config
238
#
6798 dpurdie 239
# Description     : Load the special gen_msproject.cfg file
227 dpurdie 240
#                   This file conatins lots of goodies
241
#
242
# Inputs          :
243
#
244
# Returns         :
245
#
246
sub load_msproject_config
247
{
248
    Error("No interface path specified") unless ( $opt_interface );
249
    Error("Interface directory not found" ) unless ( -d $opt_interface );
250
 
251
    my $cfg_file = "$opt_interface/gen_msproject.cfg";
252
    Error("Internal config file not found") unless -f ($cfg_file);
253
    require $cfg_file;
254
 
255
    $jats_path = $msproj_info{'JATS'}
256
}
257
 
258
#-------------------------------------------------------------------------------
259
# Function        : create_msprojects
260
#
261
# Description     : Create a tree of MS projects
262
#
263
# Inputs          : None
264
#
265
# Returns         : Nothing
266
#
267
 
268
sub create_msprojects
269
{
270
    ($jats_path = find_in_path ("jats.bat")) =~ s~/~\\~g;
271
    $msproj_info{'JATS'} = $jats_path;
272
 
273
    #
274
    #   Retain the type of the project
275
    #
276
    if ( $opt_make_prod )
277
    {
278
        print "Creating a Production Builder\n";
279
        $msproj_info{'tname'} = 'prod';
280
        $msproj_info{'tletter'} = 'P';
281
    }
282
    else
283
    {
284
        print "Creating a Debug Builder\n";
285
        $msproj_info{'tname'} = 'debug';
286
        $msproj_info{'tletter'} = 'D';
287
    }
288
 
289
    $msproj_info{'FILES'} = ();
290
 
291
    #
292
    #   Locate the base of the JATS build
293
    #   This will be provided by Makefile.gbe
294
    #
295
    ReadMakeInfo();
296
    $interface_path = "$::ScmRoot/$::ScmInterface";
297
 
298
    #
299
    #   Read in the global build variables
300
    #
301
    ReadBuildConfig( $interface_path );
302
 
303
    $build_file_name = $::ScmBuildSrc;
304
    die "ERROR: Cannot determine buildfile name\n" unless ( defined $build_file_name );
305
 
306
    #
307
    #   Create a 'Nice' project name
308
    #   MS will screw up if there is a "-" in the name
309
    #
310
    die "ERROR: Cannot determine package name\n" unless ( defined $::ScmBuildPackage );
311
    $project_name = $::ScmBuildPackage;
312
    $project_name =~ s~-~_~g;
313
 
314
    $msproj_info{'BUILD_FILE'} = $build_file_name;
315
    $msproj_info{'PROJECT'} = $project_name;
316
 
317
    #
318
    #   Determine the root directory
319
    #
320
    die "ERROR: Cannot determine build root\n" unless ( defined $::ScmRoot );
321
    my $root_dir = $::ScmRoot;
322
 
323
    $bsc_file = $root_dir . '/' . $project_name . ".bsc";
324
    $bsc_file =~ s~//~/~g;
325
    $bsc_file =~ s~/~\\~g;
326
    print "BSC File: $bsc_file\n";
327
 
328
    $msproj_info{'ROOT_DIR'} = $root_dir;
329
    $msproj_info{'BSC_FILE'} = $bsc_file;
330
    unlink ($msproj_info{'BSC_FILE'});
331
 
332
    #
333
    #   Read in all the makefile data in one hit
334
    #
335
    my $mfdata = JatsMakeConfigReader::GetAllMakeInfo();
336
 
337
    #
338
    #   Scan the projects and create unique names for each project
339
    #   Cannot simply base the project name on the subdirectory
340
    #
341
    foreach my $dir ( $mfdata->AllDirs() )
342
    {
343
        #
344
        #   Get the data for this makefile entry
345
        #
346
        my $mff = $mfdata->GetEntry($dir);
347
        print "Scanning: $dir\n";
348
 
349
        #
350
        #   Exclude the root makefile
351
        #   Exclude makefiles without any platforms - causes havoc with MSDEV
352
        #
353
        next if $mff->GetInfoItem('noplatforms');
354
 
355
        push @cf_filelist, $dir;
356
 
357
        foreach my $tgt ( $mff->GetPlatforms() )
358
        {
359
            $platforms_all{$tgt} = "Win32 Jats $tgt";
360
 
361
            #
362
            #   Save info to allow building of source browser data
363
            #
364
            if ( $mff->GetDataItem($tgt, '$TS_sbr_support') )
365
            {
366
                #
367
                #   Record the base directory for each makefile
368
                #   This may be used to locate SBR files later
369
                #       Only process debug objects
370
                #       Only process subdirs that are a part of this project
371
                #
372
                my $sbr_dir = $mff->GetDataItem($tgt, '$Cwd') . "/${tgt}$msproj_info{'tletter'}.OBJ";
373
                push @{$msproj_info{$tgt}{'SBR_ROOTS'}}, $sbr_dir;
374
 
375
                #
376
                #   Remove any existing SBR files to ensure that any processed
377
                #   SBR files are deleted
378
                #
379
                if ( -d $sbr_dir )
380
                {
381
                    print "Delete SBR files\n";
382
                    unlink split( ' ', qx (find $sbr_dir -type f -name *.sbr));
383
                }
384
            }
385
        }
386
    }
387
 
388
    #
389
    #   Simplify the Project Name
390
    #   Clean it up as much as possible by removing as much of the common
391
    #   part of the source directory name as possible from each name
392
    #
393
    my %pname_hash;
394
    my $first_key;
395
    foreach my $key ( @cf_filelist )
396
    {
397
        $first_key = $key unless ( $first_key );
398
        $pname_hash{$key} = [split '/', $key ]
399
    }
400
    my $miss = 0;
401
    my $kill_level;
402
    foreach my $level ( 1..10 )
403
    {
404
        my $first_arg = @{$pname_hash{$first_key}}[$level];
405
        unless ( $first_arg)
406
        {
407
            $kill_level = $level - 1;
408
            $miss = 1;
409
            last;
410
        }
411
 
412
        $kill_level = $level;
413
        foreach my $key ( @cf_filelist )
414
        {
415
            unless ( @{$pname_hash{$key}}[$level] eq $first_arg  )
416
            {
417
                $miss = 1;
418
            }
419
        }
420
        last if ( $miss );
421
    }
422
 
423
    #
424
    #    Generate "nice" names for the projects
425
    #    Prepend Jats to avoid conflict with the any existing names
426
    #
427
    foreach my $key ( @cf_filelist )
428
    {
429
        my @list = @{$pname_hash{$key}};
430
        my $nname = join( '_', @list[$kill_level .. $#list] );
431
 
432
        $nname =~ s~-~_~g;
433
        $nname = "Jats_" . $nname;
434
        $pnames{$key} = $nname;
435
 
436
        my $project_path = $key . "/" . $nname . ".dsp";
437
        $pnames_files{$key} = $project_path;
438
 
439
        my $sname = $key;
440
        $sname =~ s~.*/~~;
441
        $pnames_sname{$key} = $sname;
442
    }
443
 
444
    #
445
    #   Deterine the default project
446
    #   Use a WIN32 project if it is present
447
    #
448
    if ( $platforms_all{'WIN32'} )
449
    {
450
        $default_platform = 'WIN32';
451
    }
452
    else
453
    {
454
        ($default_platform) = sort keys( %platforms_all );
455
    }
456
    print "Default Platform: $default_platform\n";
457
 
458
    #
459
    #   Add entry for the Top project
460
    #
461
    $pnames{"."}       = "Project_Make_"  . $project_name;
462
    $pnames_files{"."} = "Project_Make_"  . $project_name . ".dsp";
463
    $pnames_sname{"."} = $project_name;
464
 
465
    #
466
    #   Generate a top-level Workspace file
467
    #   This file will reference a project file for each child makefile
468
    #
469
    GenerateStudioWorkspace  ( ".", "Project_Build_" . $project_name, keys(%pnames) );
470
    GenerateStudioProjectRoot( ".", "Project_Build_" . $project_name );
471
    GenerateStudioProjectTop ( ".", $pnames{"."} );
472
 
473
    #
474
    #   Generate Workspace / Project files for each of the subdirectores
475
    #   The information for each subdierctory is held in a different Makefile*.cfg
476
    #   file. Process each one in turn.
477
    #
478
    foreach my $key ( @cf_filelist )
479
    {
480
        #
481
        #   Get the data for this makefile entry
482
        #
483
        my $mff = $mfdata->GetEntry($key);
484
 
485
        GenerateStudioWorkspace( $key,  $pnames{$key} );
486
        GenerateStudioProject  ( $key,  $pnames{$key}, $mff );
487
    }
488
 
489
 
490
    #
491
    #   Create a file in the interface directory to communicate
492
    #   Essential information to build time instances of this program
493
    #   It is easier to pass them via a file than through the command line
494
    #
495
    my $cfg_file = "$interface_path/gen_msproject.cfg";
496
    print "Creating: $cfg_file\n";
497
 
498
    my $fh = ConfigurationFile::New( $cfg_file );
499
    $fh->HeaderSimple( "gen_msproject",
500
                       "JATS Information for gen_msproject" );
501
 
502
    $fh->Dump( [\%msproj_info], [qw(*msproj_info)] );
503
    $fh->Close();
504
}
505
 
506
 
507
#-------------------------------------------------------------------------------
508
# Function        : print_dsf
509
#
510
# Description     : Print a line to the Developer Studio file
511
#                   The DSF files need to be \r\n terminated, even when generated
512
#                   within a unix environment. This is achieved by opening the file
513
#                   in binary mode and forcing a "\r\n" line terminator
514
#
515
# Inputs          :
516
#
517
# Returns         :
518
#
519
sub print_dsf
520
{
521
    print DSF "@_\r\n";
522
}
523
 
524
#-------------------------------------------------------------------------------
525
# Function        : GenerateStudioWorkspace
526
#
527
# Description     : Generate a Microsoft Developer Studio Workspace file
528
#
529
# Inputs          : $1  - Target directory
530
#                   $2  - Workspace Name
531
#                   $3  - Array of target sub project directories
532
#
533
# Returns         :
534
#
535
sub GenerateStudioWorkspace
536
{
537
    my ($tdir, $fname, @subdirs ) = @_;
538
 
539
 
540
    foreach ( qw( opt ncb dsw ) )
541
    {
542
        unlink ("$tdir/$fname.$_");
543
        push @{$msproj_info{'FILES'}}, "$tdir/$fname.$_";
544
    }
545
 
546
    push @{$msproj_info{'FILES'}}, "$tdir/$fname.dsw";
547
    open( DSF, ">$tdir/$fname.dsw" ) ||
548
        die "ERROR: cannot create $tdir/$fname.dsw\n";
549
    binmode DSF;
550
 
551
    #
552
    #   Generate the Workspace header
553
    #
554
    print_dsf "Microsoft Developer Studio Workspace File, Format Version 6.00";
555
    print_dsf "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!";
556
    print_dsf "# Generated by JATS";
557
    print_dsf "";
558
    print_dsf "###############################################################################";
559
    print_dsf "";
560
 
561
    #
562
    #   Generate project sections for each subproject
563
    #   The Root project simply references all the known subprojects
564
    #   Non-Root projects are associated with a local project file and possible
565
    #   sub project files.
566
    #
567
    my $project_name = $fname;
568
    my $project_path = "./" . $fname;
569
 
570
    print_dsf "###############################################################################";
571
    print_dsf "Project: \"$project_name\"=$project_path.dsp - Package Owner=<4>";
572
    print_dsf "";
573
    print_dsf "Package=<5>";
574
    print_dsf "{{{";
575
    print_dsf "}}}";
576
    print_dsf "";
577
    print_dsf "Package=<4>";
578
    print_dsf "{{{";
579
    print_dsf "}}}";
580
    print_dsf "";
581
 
582
 
583
    foreach my $subdir ( @subdirs )
584
    {
585
        print_dsf "###############################################################################";
586
        print_dsf "Project: \"$pnames{$subdir}\"=$pnames_files{$subdir} - Package Owner=<4>";
587
        print_dsf "";
588
        print_dsf "Package=<5>";
589
        print_dsf "{{{";
590
        print_dsf "}}}";
591
        print_dsf "";
592
        print_dsf "Package=<4>";
593
        print_dsf "{{{";
594
        print_dsf "}}}";
595
        print_dsf "";
596
    }
597
 
598
    #
599
    #   Generate the global section
600
    #
601
    print_dsf "###############################################################################";
602
    print_dsf "";
603
    print_dsf "Global:";
604
    print_dsf "";
605
    print_dsf "Package=<5>";
606
    print_dsf "{{{";
607
    print_dsf "}}}";
608
    print_dsf "";
609
    print_dsf "Package=<3>";
610
    print_dsf "{{{";
611
    print_dsf "}}}";
612
    print_dsf "";
613
    print_dsf "###############################################################################";
614
 
615
    close DSF;
616
 
617
}
618
 
619
 
620
#-------------------------------------------------------------------------------
621
# Function        : GenerateStudioProjectRoot
622
#
623
# Description     : Generate a Microsoft Developer Studio Project file for
624
#                   the toplevel project. This is a special project file
625
#
626
# Inputs          : $1  - Target directory
627
#                   $2  - Project Name
628
#
629
# Returns         :
630
#
631
sub GenerateStudioProjectRoot
632
{
633
    my ( $tdir, $fname ) = @_;
634
 
635
    #
636
    #   Determine the various platforms for the project and generate
637
    #   a configuration for each platforms
638
    #
639
    my %platform;
640
    my $first_platform;
641
    my $vs_config;
642
    my $cfg = "$fname - Win32 Jats WIN32";
643
    print "Project Config: $cfg\n";
644
 
645
    #
646
    #   Create the Project File and generate the basic header
647
    #
648
    push @{$msproj_info{'FILES'}}, "$tdir/$fname.dsp";
649
    open( DSF, ">$tdir/$fname.dsp" ) ||
650
        die "ERROR: cannot create $tdir/$fname.dsp\n";
651
    binmode DSF;
652
 
653
    print_dsf "# Microsoft Developer Studio Project File - Name=\"$fname\" - Package Owner=<4>";
654
 
655
    print_dsf "# Microsoft Developer Studio Generated Build File, Format Version 6.00";
656
    print_dsf "# ** DO NOT EDIT **";
657
    print_dsf "# Generated by JATS";
658
    print_dsf "";
659
 
660
    #
661
    #   Generate the default configuration entry
662
    #
663
    print_dsf "# TARGTYPE \"Win32 (x86) External Target\" 0x0106";
664
    print_dsf "";
665
    print_dsf "CFG=$cfg";
666
 
667
    #
668
    #   Generate the MESSAGE section
669
    #
670
    print_dsf "!MESSAGE This is not a valid makefile. To build this project using NMAKE,";
671
    print_dsf "!MESSAGE use the Export Makefile command and run";
672
    print_dsf "!MESSAGE ";
673
    print_dsf "!MESSAGE NMAKE /f \"$fname.mak\".";
674
    print_dsf "!MESSAGE ";
675
    print_dsf "!MESSAGE You can specify a configuration when running NMAKE";
676
    print_dsf "!MESSAGE by defining the macro CFG on the command line. For example:";
677
    print_dsf "!MESSAGE ";
678
    print_dsf "!MESSAGE NMAKE /f \"$fname.mak\" CFG=\"$fname - Win32 Jats make\"";
679
    print_dsf "!MESSAGE ";
680
    print_dsf "!MESSAGE Possible choices for configuration are:";
681
    print_dsf "!MESSAGE ";
682
 
683
    print_dsf "!MESSAGE \"$cfg\" (based on \"Win32 (x86) External Target\")";
684
 
685
    print_dsf "!MESSAGE ";
686
    print_dsf "";
687
 
688
    #
689
    #   Generate a Project
690
    #
691
    print_dsf "# Begin Project";
692
    print_dsf "# PROP AllowPerConfigDependencies 0";
693
    print_dsf "# PROP Scc_ProjName \"\"";
694
    print_dsf "# PROP Scc_LocalPath \"\"";
695
 
696
    #
697
    #   Generate configuration section
698
    #
699
    print_dsf "# PROP BASE Use_MFC 0";
700
    print_dsf "# PROP BASE Use_Debug_Libraries 0";
701
    print_dsf "# PROP BASE Output_Dir \"\"";
702
    print_dsf "# PROP BASE Intermediate_Dir \"\"";
703
    print_dsf "# PROP BASE Cmd_Line \"CommandLine\"";
704
    print_dsf "# PROP BASE Rebuild_Opt \"Rebuild\"";
705
    print_dsf "# PROP BASE Target_File \"Output\"";
706
    print_dsf "# PROP BASE Bsc_Name \"\"";
707
    print_dsf "# PROP BASE Target_Dir \"\"";
708
    print_dsf "# PROP Use_MFC 0";
709
    print_dsf "# PROP Use_Debug_Libraries 0";
710
    print_dsf "# PROP Output_Dir \"\"";
711
    print_dsf "# PROP Intermediate_Dir \"\"";
712
    print_dsf "# PROP Cmd_Line \"\"$jats_path\" gen_msproject build -interface=$interface_path\"";
713
    print_dsf "# PROP Rebuild_Opt \"-rebuild\"";
714
    print_dsf "# PROP Bsc_Name \"$bsc_file\"";
715
    print_dsf "# PROP Target_Dir \"\"";
716
 
717
    #
718
    #   Generate the Target section
719
    #
720
 
721
    print_dsf "# Begin Target";
722
    print_dsf "";
723
    print_dsf "# Name \"$cfg\"";
724
 
725
    #
726
    #   Create various groups of files
727
    #
728
    my @file_list;
729
 
730
 
731
    #
732
    #   List of main builder files
733
    #   Note that build.pl may not always be the main build file
734
    #
735
    for ( $build_file_name, qw( makefile.pl warnings.mri))
736
    {
737
        push @file_list, $_
738
            if ( -f $_ );
739
    }
740
    print_dsp_group ("Jats Builder", "pl"   , @file_list );
741
 
742
    #
743
    #   Other useful builder files
744
    #
745
    @file_list = ();
746
    push @file_list, "build.pl"
747
        if ( $build_file_name ne "build.pl" );
748
    print_dsp_group ("Other Jats Builder", "pl"   , @file_list );
749
 
750
 
751
    @file_list = glob ( "warnings.*" );
752
    print_dsp_group ("Warning Filter", "pl"   , @file_list );
753
 
754
    print_dsf "# End Target";
755
    print_dsf "# End Project";
756
 
757
    close DSF;
758
}
759
 
760
#-------------------------------------------------------------------------------
761
# Function        : GenerateStudioProjectTop
762
#
763
# Description     : Generate a Microsoft Developer Studio Project file for
764
#                   the toplevel project. This is a special project file
765
#                   that will allow the user to make the ENTIRE project
766
#
767
# Inputs          : $1  - Target directory
768
#                   $2  - Project Name
769
#
770
# Returns         :
771
#
772
sub GenerateStudioProjectTop
773
{
774
    my ( $tdir, $fname ) = @_;
775
 
776
    #
777
    #   Create the Project File and generate the basic header
778
    #
779
    push @{$msproj_info{'FILES'}}, "$tdir/$fname.dsp";
780
    open( DSF, ">$pnames_files{$tdir}" ) ||
781
        die "ERROR: cannot create $pnames_files{$tdir}\n";
782
    binmode DSF;
783
 
784
    print_dsf "# Microsoft Developer Studio Project File - Name=\"$pnames{$tdir}\" - Package Owner=<4>";
785
 
786
    print_dsf "# Microsoft Developer Studio Generated Build File, Format Version 6.00";
787
    print_dsf "# ** DO NOT EDIT **";
788
    print_dsf "# Generated by JATS";
789
    print_dsf "";
790
 
791
    #
792
    #   Generate the default configuration entry
793
    #
794
    print_dsf "# TARGTYPE \"Win32 (x86) External Target\" 0x0106";
795
    print_dsf "";
796
    print_dsf "CFG=$fname - $platforms_all{$default_platform}";
797
 
798
    #
799
    #   Generate the MESSAGE section
800
    #
801
    print_dsf "!MESSAGE This is not a valid makefile. To build this project using NMAKE,";
802
    print_dsf "!MESSAGE use the Export Makefile command and run";
803
    print_dsf "!MESSAGE ";
804
    print_dsf "!MESSAGE NMAKE /f \"$fname.mak\".";
805
    print_dsf "!MESSAGE ";
806
    print_dsf "!MESSAGE You can specify a configuration when running NMAKE";
807
    print_dsf "!MESSAGE by defining the macro CFG on the command line. For example:";
808
    print_dsf "!MESSAGE ";
809
    print_dsf "!MESSAGE NMAKE /f \"$fname.mak\" CFG=\"$fname - Win32 Jats make\"";
810
    print_dsf "!MESSAGE ";
811
    print_dsf "!MESSAGE Possible choices for configuration are:";
812
    print_dsf "!MESSAGE ";
813
 
814
    for ( sort keys %platforms_all)
815
    {
816
        print_dsf "!MESSAGE \"$fname - $platforms_all{$_}\" (based on \"Win32 (x86) External Target\")";
817
    }
818
 
819
    print_dsf "!MESSAGE ";
820
    print_dsf "";
821
 
822
    #
823
    #   Generate a Project
824
    #
825
    print_dsf "# Begin Project";
826
    print_dsf "# PROP AllowPerConfigDependencies 0";
827
    print_dsf "# PROP Scc_ProjName \"\"";
828
    print_dsf "# PROP Scc_LocalPath \"\"";
829
 
830
    #
831
    #   Generate per-configuration sections
832
    #
833
    my $if_statement = "IF";
834
    for (sort keys %platforms_all)
835
    {
836
        print_dsf "!$if_statement  \"\$(CFG)\" == \"$fname - $platforms_all{$_}\"";
837
        $if_statement = "ELSEIF";
838
 
839
        print_dsf "# PROP BASE Use_MFC 0";
840
        print_dsf "# PROP BASE Use_Debug_Libraries 0";
841
        print_dsf "# PROP BASE Output_Dir \"\"";
842
        print_dsf "# PROP BASE Intermediate_Dir \"\"";
843
        print_dsf "# PROP BASE Cmd_Line \"CommandLine\"";
844
        print_dsf "# PROP BASE Rebuild_Opt \"Rebuild\"";
845
        print_dsf "# PROP BASE Target_File \"Output\"";
846
        print_dsf "# PROP BASE Bsc_Name \"\"";
847
        print_dsf "# PROP BASE Target_Dir \"\"";
848
        print_dsf "# PROP Use_MFC 0";
849
        print_dsf "# PROP Use_Debug_Libraries 0";
850
        print_dsf "# PROP Output_Dir \"\"";
851
        print_dsf "# PROP Intermediate_Dir \"\"";
852
        print_dsf "# PROP Cmd_Line \"\"$jats_path\" gen_msproject make -platform=$_ -interface=$interface_path\"";
853
        print_dsf "# PROP Rebuild_Opt \"-rebuild\"";
854
        print_dsf "# PROP Target_File \"\"";
855
        print_dsf "# PROP Bsc_Name \"$bsc_file\"";
856
        print_dsf "# PROP Target_Dir \"\"";
857
    }
858
    print_dsf "!ENDIF";
859
 
860
    #
861
    #   Generate the Target section
862
#
863
 
864
    print_dsf "# Begin Target";
865
    print_dsf "";
866
 
867
    for (sort keys %platforms_all)
868
    {
869
        print_dsf "# Name \"$fname - $platforms_all{$_}\"";
870
    }
871
 
872
    print_dsf "# End Target";
873
    print_dsf "# End Project";
874
    close DSF;
875
}
876
 
877
 
878
#-------------------------------------------------------------------------------
879
# Function        : GenerateStudioProject
880
#
881
# Description     : Generate a Microsoft Developer Studio Project file
882
#                   The name of the generated file is taken from the
883
#                   current directory.
884
#
885
# Inputs          : $1  - Target directory
886
#                   $2  - Project Name
887
#                   $3  - Ref to an object that conatins data for this project
888
#
889
# Returns         :
890
#
891
sub GenerateStudioProject
892
{
893
    my ( $tdir, $fname, $pdata ) = @_;
894
    my $sname = $pnames_sname{$tdir};
895
 
896
    #
897
    #   Plaforms in this makefile
898
    #
899
    my @platform = sort ( $pdata->GetPlatforms() );
900
 
901
    #
902
    #   Create the Project File and generate the basic header
903
    #
904
    push @{$msproj_info{'FILES'}}, "$pnames_files{$tdir}";
905
    open( DSF, ">$pnames_files{$tdir}" ) ||
906
        die "ERROR: cannot create $pnames_files{$tdir}\n";
907
    binmode DSF;
908
 
909
    print_dsf "# Microsoft Developer Studio Project File - Name=\"$pnames{$tdir}\" - Package Owner=<4>";
910
 
911
    print_dsf "# Microsoft Developer Studio Generated Build File, Format Version 6.00";
912
    print_dsf "# ** DO NOT EDIT **";
913
    print_dsf "# Generated by JATS";
914
    print_dsf "";
915
 
916
    #
917
    #   Generate the default configuration entry
918
    #
919
    print_dsf "# TARGTYPE \"Win32 (x86) External Target\" 0x0106";
920
    print_dsf "";
921
    print_dsf "CFG=$fname - $platforms_all{$default_platform}";
922
 
923
    #
924
    #   Generate the MESSAGE section
925
    #
926
    print_dsf "!MESSAGE This is not a valid makefile. To build this project using NMAKE,";
927
    print_dsf "!MESSAGE use the Export Makefile command and run";
928
    print_dsf "!MESSAGE ";
929
    print_dsf "!MESSAGE NMAKE /f \"$fname.mak\".";
930
    print_dsf "!MESSAGE ";
931
    print_dsf "!MESSAGE You can specify a configuration when running NMAKE";
932
    print_dsf "!MESSAGE by defining the macro CFG on the command line. For example:";
933
    print_dsf "!MESSAGE ";
934
    print_dsf "!MESSAGE NMAKE /f \"$fname.mak\" CFG=\"$fname - Win32 Jats make\"";
935
    print_dsf "!MESSAGE ";
936
    print_dsf "!MESSAGE Possible choices for configuration are:";
937
    print_dsf "!MESSAGE ";
938
 
939
    for (@platform)
940
    {
941
        print_dsf "!MESSAGE \"$fname - $platforms_all{$_}\" (based on \"Win32 (x86) External Target\")";
942
    }
943
    print_dsf "!MESSAGE ";
944
    print_dsf "";
945
 
946
    #
947
    #   Generate a Project
948
    #
949
    print_dsf "# Begin Project";
950
    print_dsf "# PROP AllowPerConfigDependencies 0";
951
    print_dsf "# PROP Scc_ProjName \"\"";
952
    print_dsf "# PROP Scc_LocalPath \"\"";
953
 
954
    #
955
    #   Generate per-configuration sections
956
    #
957
    my $if_statement = "IF";
958
    for (@platform)
959
    {
960
 
961
        #
962
        #   Extract some platform specific data
963
        #
964
        my $target_file = $pdata->GetDataItem($_, '$TS_target_file');
965
 
966
        #
967
        #   Convert symbolic paths to physical paths
968
        #
969
        $target_file =~ s~\$\(BINDIR\)~${_}$msproj_info{'tletter'}.BIN~;
970
        $target_file =~ s~\$\(LIBDIR\)~$_.LIB~;
971
        $target_file =~ s~\$\(GBE_TYPE\)~$msproj_info{'tletter'}~;
972
 
973
        print_dsf "!$if_statement  \"\$(CFG)\" == \"$fname - $platforms_all{$_}\"";
974
        $if_statement = "ELSEIF";
975
 
976
        print_dsf "# PROP BASE Use_MFC 0";
977
        print_dsf "# PROP BASE Use_Debug_Libraries 0";
978
        print_dsf "# PROP BASE Output_Dir \"\"";
979
        print_dsf "# PROP BASE Intermediate_Dir \"\"";
980
        print_dsf "# PROP BASE Cmd_Line \"CommandLine\"";
981
        print_dsf "# PROP BASE Rebuild_Opt \"Rebuild\"";
982
        print_dsf "# PROP BASE Target_File \"Output\"";
983
        print_dsf "# PROP BASE Bsc_Name \"\"";
984
        print_dsf "# PROP BASE Target_Dir \"\"";
985
        print_dsf "# PROP Use_MFC 0";
986
        print_dsf "# PROP Use_Debug_Libraries 0";
987
        print_dsf "# PROP Output_Dir \"${_}$msproj_info{'tletter'}.BIN\"";
988
        print_dsf "# PROP Intermediate_Dir \"${_}$msproj_info{'tletter'}.OBJ\"";
989
        print_dsf "# PROP Cmd_Line \"\"$jats_path\" gen_msproject make -platform=$_ -interface=$interface_path\"";
990
        print_dsf "# PROP Rebuild_Opt \"-rebuild\"";
991
        print_dsf "# PROP Target_File \"$target_file\"";
992
        print_dsf "# PROP Bsc_Name \"$bsc_file\"";
993
        print_dsf "# PROP Target_Dir \"\"";
994
    }
995
    print_dsf "!ENDIF";
996
 
997
    #
998
    #   Generate the Target section
999
    #
1000
 
1001
    print_dsf "# Begin Target";
1002
    print_dsf "";
1003
    for (@platform)
1004
    {
1005
        print_dsf "# Name \"$fname - $platforms_all{$_}\"";
1006
    }
1007
 
1008
    #
1009
    #   Generate the various file groups for each of the platforms
1010
    #   Crunch the various known file groups and merge all the platform
1011
    #   source files into one common view
1012
    #       If a file is common to all platforms then place it in one folder
1013
    #       Remaining files are placed in platform folders
1014
    #
1015
    my %common_srcs;                    # Hash of all common files
1016
    my %other_srcs;                     # Hash, by platform, of non-common files
1017
 
1018
 
1019
    #
1020
    #   Generate a complete list of all file names in all platforms
1021
    #   The hash value may be common - if the file is common on all platforms
1022
    #   This assumption will be used
1023
    #
1024
    my %complete_list;
1025
    for (@platform)
1026
    {
1027
        my $sentry = $pdata->GetDataItem($_, '%SRCS');
1028
        for my $file ( keys %{$sentry} )
1029
        {
1030
            $complete_list{$file} = $sentry->{$file};
1031
        }
1032
    }
1033
 
1034
#    print "Processing from : $base\n";
1035
#    print Dumper ( $pdata->{$base}{'%SRCS'} );
1036
 
1037
    for my $file ( keys %complete_list )
1038
    {
1039
        my $missing;
1040
        my $full_name = $complete_list{$file};
1041
        for (@platform)
1042
        {
1043
            unless ( $pdata->GetDataItem($_, '%SRCS')->{$file} eq $full_name )
1044
            {
1045
                $missing = 1;
1046
                last;
1047
            }
1048
        }
1049
        if ( $missing )
1050
        {
1051
            #
1052
            #   Add files to non-common list
1053
            #
1054
            for (@platform)
1055
            {
1056
                my $sentry = $pdata->GetDataItem($_, '%SRCS');
1057
                $other_srcs{$_}{$file} = $sentry->{$file}
1058
                    if ( defined $sentry->{$file} );
1059
            }
1060
        }
1061
        else
1062
        {
1063
            #   Add files to the common list
1064
            #
1065
            $common_srcs{$file} = $full_name;
1066
        }
1067
    }
1068
 
1069
#    print Dumper ( \%common_srcs );
1070
#    print Dumper ( \%other_srcs );
1071
 
1072
 
1073
 
1074
    #
1075
    #   Create various groups of files
1076
    #
1077
    print_dsp_group ("Jats Builder", "pl"   , "makefile.pl" );
1078
 
1079
    print_dsp_group_begin("Source", "*");
1080
    print_dsp_group ( "Common"  , "*"    , values %common_srcs );
1081
    for (@platform)
1082
    {
1083
        print_dsp_group ( "$_"  , "*"    , values %{$other_srcs{$_}} );
1084
    }
1085
    print_dsp_group_end();
1086
 
1087
#    print_dsp_group ( "C Source"    , "c"    , @{$pdata->{'WIN32'}{'@CSRCS'}} );
1088
#    print_dsp_group ( "C++ Source"  , "cpp"  , @{$pdata->{'WIN32'}{'@CXXSRCS'}} );
1089
#    print_dsp_group ( "Header"      , "h"    , @{$pdata->{'WIN32'}{'@CHDRS'}} );
1090
#    print_dsp_group ( "Unknown"     , ""     , keys(%srcs_left) );
1091
 
1092
    print_dsf "# End Target";
1093
    print_dsf "# End Project";
1094
 
1095
    close DSF;
1096
}
1097
 
1098
#-------------------------------------------------------------------------------
1099
# Function        : find_in_path
1100
#
1101
# Description     : Find a file within the users path
1102
#
1103
# Inputs          : $1  - Name of the file to find
1104
#
1105
# Returns         :  Full pathname
1106
#
1107
#
1108
sub find_in_path
1109
{
1110
    (my $name) = @_;
1111
    for my $path (split ';', $ENV{ 'PATH' })
1112
    {
1113
        my $tn = $path . "/" . $name;
1114
        return ( $tn ) if ( -f $tn )
1115
    }
1116
    return $name;
1117
}
1118
 
1119
#-------------------------------------------------------------------------------
1120
# Function        : print_dsp_group
1121
#
1122
# Description     : Print a group entry for a MS DSP file
1123
#
1124
# Inputs          : $1  - Name of the group
1125
#                   $2  - Filter string. (c;h)
1126
#                   $3  - Array of files to process
1127
#
1128
# Returns         :
1129
#
1130
sub print_dsp_group_begin
1131
{
1132
    my ($name, $filter) = @_;
1133
    print_dsf "";
1134
    print_dsf "# Begin Group \"$name Files\"";
1135
    print_dsf "# PROP Default_Filter \"$filter\"";
1136
}
1137
 
1138
sub print_dsp_group_end
1139
{
1140
    print_dsf "# End Group";
1141
}
1142
 
1143
 
1144
sub print_dsp_group
1145
{
1146
    my ( $name, $filter, @files ) = @_;
1147
 
1148
    if ( $#files >= 0 )
1149
    {
1150
        print_dsp_group_begin( $name, $filter );
1151
        for ( @files )
1152
        {
1153
            #
1154
            #   Convert the filename into a full path
1155
            #
1156
            my $full_name = $_;
1157
            $full_name =~ s~/~\\~g;
1158
 
1159
            print_dsf "# Begin Source File";
1160
            print_dsf "SOURCE=$full_name";
1161
            print_dsf "# PROP Ignore_Default_Tool 1";
1162
            print_dsf "# End Source File";
1163
            print_dsf "";
1164
        }
1165
        print_dsp_group_end();
1166
    }
1167
}
1168
 
1169
#-------------------------------------------------------------------------------
1170
#   Documentation
1171
#
1172
 
1173
=pod
1174
 
1175
=head1 NAME
1176
 
1177
gen_msproject - JATS utility to create and maintain Visual Studio6 projects
1178
 
1179
=head1 SYNOPSIS
1180
 
1181
 JATS gen_msproject [options] [mode]
1182
 
1183
 Options:
1184
    -help              - brief help message
1185
    -help -help        - Detailed help message
1186
    -man               - Full documentation
1187
    -debug             - Create a debug builder (default)
1188
    -production        - Create a production builder
1189
 
1190
 Modes:
1191
    create             - Create DSW and DSP files (default)
1192
    build              - Rebuild JATS makefiles (internal)
1193
    make               - Run JATS make (internal)
1194
    clean              - Delete generated DSW and DSP files
1195
 
1196
=head1 OPTIONS
1197
 
1198
=over 8
1199
 
1200
=item B<-help>
1201
 
1202
Print a brief help message and exits.
1203
 
1204
=item B<-help -help>
1205
 
1206
Print a detailed help message with an explanation for each option.
1207
 
1208
=item B<-man>
1209
 
1210
Prints the manual page and exits.
1211
 
1212
=item B<-debug>
1213
 
1214
The makefiles created will build the debug version of the target.
1215
This is the default option. It is mutually exclusive with B<-prod>
1216
 
1217
=item B<-production>
1218
 
1219
The makefiles created will build the production version of the target.
1220
This is the default option. It is mutually exclusive with B<-debug>
1221
 
1222
=back
1223
 
1224
=head1 MODES
1225
 
1226
=over 8
1227
 
1228
=item B<create>
1229
 
1230
Create a set Visual Studio6 Workspace and Project files based on the JATS
1231
build.pl and makefile.pl files.
1232
 
1233
Before running this command the JATS workspace MUST be prepared with the "JATS
1234
build" command as this command saves information used by this program.
1235
 
1236
=item B<build>
1237
 
1238
This mode is used only by the generated projects files to rebuild the JATS
1239
makefiles. It is not intended to be used externally.
1240
 
1241
=item B<make>
1242
 
1243
This mode is used only by the generated projects files to rebuild the JATS
1244
makefiles. It is not intended to be used externally.
1245
 
1246
=item B<clean>
1247
 
1248
This command will delete the Visual Studio6 Workspace, Project files and related
1249
files created by the 'build' process.
1250
 
1251
=back
1252
 
1253
=head1 DESCRIPTION
1254
 
361 dpurdie 1255
This program will build a set Visual Studio6 Workspace and Project files to
1256
assist intended the migration from Visual Studio6 to JATS.
227 dpurdie 1257
 
361 dpurdie 1258
=for htmlclass Note
1259
 
1260
Note: gen_msprojects only supports Version 6 of Visual Studio. This is the
1261
compiler used by the B<WIN32> build target.
1262
 
227 dpurdie 1263
In normal operation the program will:
1264
 
1265
=over 8
1266
 
1267
=item *
1268
 
1269
Create A DSW and DSP file for each JATS makefile.pl
1270
 
1271
=item *
1272
 
1273
Create a global DSW and DSP file for the entire JATS build
1274
 
1275
=item *
1276
 
1277
Create a psude DSP file to allow the user to build the entire project
1278
 
1279
=back
1280
 
1281
The generated project files allow the components to be rebuilt with JATS.
1282
 
1283
The generated project files allow source browsing of WIN32 components of the
1284
project.
1285
 
1286
=cut
1287