xref: /AOO41X/main/icu/createmak.pl (revision 7ccb0d530a82b7ad7d024d7230ef1f4a7f5faac3)
1:
2eval 'exec perl -wS $0 ${1+"$@"}'
3    if 0;
4#**************************************************************
5#
6#  Licensed to the Apache Software Foundation (ASF) under one
7#  or more contributor license agreements.  See the NOTICE file
8#  distributed with this work for additional information
9#  regarding copyright ownership.  The ASF licenses this file
10#  to you under the Apache License, Version 2.0 (the
11#  "License"); you may not use this file except in compliance
12#  with the License.  You may obtain a copy of the License at
13#
14#    http://www.apache.org/licenses/LICENSE-2.0
15#
16#  Unless required by applicable law or agreed to in writing,
17#  software distributed under the License is distributed on an
18#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19#  KIND, either express or implied.  See the License for the
20#  specific language governing permissions and limitations
21#  under the License.
22#
23#**************************************************************
24
25
26#
27use XML::Parser;
28# ------------------------------------------------------------------------
29# Other global stuff
30$is_debug=0;
31my $path = $ENV{'INPATH'} . "/";
32my $quot = '"';
33my %template_hash=();
34my $architecture = "x86";
35my %vcproj_hash=();
36# ------------------------------------------------------------------------
37# Global stuff for parsing the *.vcproj files (XML::Parser)
38#
39my $ConfigurationGlobal = 1; # Release = 1, Debug=0
40my $Configuration = undef;
41my %configelements = ();
42my %files = ();
43my %files2copy = ();
44my %files_special = ();
45my $Release = 1;
46     # Release = 1, Debug = 0, undef = 2
47my $file_tmp = "";      # temporary storage for file name
48my $CustomSection = 0;
49# ------------------------------------------------------------------------
50# ------------------------------------------------------------------------
51# e.g. %object_hash with Key = blabla.cpp
52# contains a Hash:
53# Header: "..\\common\\unicode\\utypes.h ..\\common\\unicode\\uset.h"
54# CFlags: Common (set in templates file) or special sequence
55# CDefs:  Common (set in templates file) or special sequence
56# ------------------------------------------------------------------------
57my $configfile = shift;
58my $sourcePath = shift;
59if ( !$configfile ) {
60    $configfile = "createmak.cfg";
61}
62if ( !$sourcePath ) {
63    $inpath = $ENV{"INPATH"};
64    $sourcePath = $inpath . "\\misc\\build\\icu\\source";
65}
66$dir = "";
67$header = "";
68$sep = "\\\\";
69
70%project_by_id =();
71%project_by_name = ();
72%project_dependencies = ();
73my @builddeps = prepare_allinone_all_mak(\%project_by_id,\%project_by_name,\%project_dependencies,$sourcePath);
74
75fillTemplateHash($configfile);
76# The architecture is indicated in the configuration file
77$architecture=${$template_hash{"Architecture"}}[0];
78chomp $architecture;
79print "Architecture: $architecture\n" if ($is_debug);
80
81create_allinone_all_mak(\@builddeps,\%project_by_id,$sourcePath);
82my @dirs = ();
83foreach $projectname(keys %project_by_name)
84{
85    my $dir = $project_by_name{$projectname}[1];
86    $dir =~ /\.\.\\(.+)\\(.+)\.vcproj/;
87    my $dir1 = $1;
88    my $dir2 = $2;
89    if ( $dir1 !~ /$dir2$/ ) {
90        $dir1 .= "\.$dir2";
91    }
92    print "$dir1 - $dir2\n" if ($is_debug);
93    push @dirs, $dir1;
94}
95
96# set nonpro switch (linking against debug runtime if nonpro=1)
97my $nonpro = ($ENV{"PROEXT"} ne ".pro");
98print "Non Product Build" if ($nonpro);
99
100foreach $dir(@dirs)
101{
102    next if ($dir eq "data.makedata"); # very special don't overwrite this file
103    # ------------------------------------------------------------------------
104    # Reset global stuff for parsing the *.vcproj files (XML::Parser)
105    #
106    $Configuration = $ConfigurationGlobal; # Release = 1, Debug=0
107    %configelements = ();
108    %files = ();
109       # contains all relevant *.c,*.cpp,*.h,*.rc files
110    %files2copy = ();
111    %files_special = ();
112    $Release = 2;
113     # Release = 1, Debug = 0, undef = 2
114    $file_tmp = "";      # temporary storage for file name
115    $CustomSection = 0;
116    # ------------------------------------------------------------------------
117
118    my $extra_mak = "";
119    ($dir, $extra_mak) = handle_extra_mak_files($dir); # handle e.g. tools/genrb.derb entires
120
121    my @mak=(); # Array for make file *.mak
122    my %deps=();
123    my %object_hash=();
124    my %collected_header=();
125    my %collect_header_target_hash=();
126    my %collect_object_target_hash=();
127    my $vcproj_file = "";
128    my $resource_file = "";
129
130    # $dir : common,i18n,...
131    chomp $dir;
132    next if ( $dir eq "" );
133    my $fullpath = $sourcePath . "\\" . $dir;
134    if ( $extra_mak eq "" ) {
135        if ($dir =~ /(.+)+\\(.+)$/)
136        {
137            $vcproj_file = $fullpath ."\\$2.vcproj";
138        } else
139        {
140            $vcproj_file = $fullpath ."\\$dir.vcproj";
141        }
142    } else
143    {
144        $vcproj_file = $fullpath . "\\" . $extra_mak . ".vcproj";
145    }
146
147
148    # Parse the *.vcproj file
149    my $parser = new XML::Parser(ErrorContext => 2);
150    $parser->setHandlers(Start => \&start_handler,
151                 Char  => \&char_handler);
152    $parser->parsefile($vcproj_file);
153    if ( $file_tmp ) {
154        # save a file which hasn't been saved yet
155        $files{ $file_tmp } = 1;        # save it now
156        $file_tmp = "";                 # has been saved now reset it
157    }
158
159    # is there a resource file?
160    foreach $i (keys %files)
161    {
162        if ($i =~ /\.rc/)
163        {
164            $resource_file = $i;
165        }
166    }
167    # Fill hash %deps for dependencies for all files in directory ($testdir)
168    # %files contains all relevant files from *.vcproj
169
170    getAllFilesDeps($fullpath,\%deps,\%files);
171    my $includedir = $configelements{"Release"}{"OutputDirectory"};     # e.g. OutputDirectory = ..\..\lib
172    $includedir =~ s/lib/include/;
173    foreach $file( sort keys %deps)
174    {
175        $file =~ /(.+)\.(.+)/;
176        my $name = $1;
177        my $ext  = $2;
178        next if (!defined $name);
179        $object = "\$(INTDIR)\\" . "$name.obj";
180        $collect_object_target_hash{$object}=1;
181
182        createMakDepSection($dir,$name,$ext,$deps{$file},\@mak,\%files_special);
183    }
184    my %all_target_hash=();
185    foreach $header(sort keys %files2copy)
186    {
187        my $dir;
188        my $file;
189        #$pathdepth = "..\\..";
190        $file = $header;
191        $header =~ s/^\.\\//;
192        $inputpath = $file;
193        $target = $includedir . "\\" . $header;
194        $target =~ /.+\\(.+)\\.+$/;
195        $targetpath = $configelements{"Release"}{"CommandLine"};
196        chomp $targetpath;
197        # set %all_target_hash and @mak
198        createCopySection($file,$inputpath,$target,$targetpath,\@mak,\%all_target_hash);
199        $collect_header_target_hash{$target}=1;
200    }
201    my $test = $configelements{"Release"}{"OutputFile"};
202    $all_target_hash{$test}=1;
203
204    # set name of the *.mak file
205    my $mak_file="";
206    if ( $extra_mak eq "" ) {
207        $mak_file = $vcproj_file;
208        $mak_file =~ s/vcproj/mak/;
209    } else
210    {
211        # extra_mak eg. derb, stringperf
212        $mak_file = $fullpath . "\\$extra_mak" . "\.mak";
213    }
214
215    # generate the content of the *.mak file
216    # in @mak array
217    print "extra_mak=$extra_mak\n" if ($is_debug);
218    print "mak_file=$mak_file\n" if ($is_debug);
219    open(MAKFILE, ">$mak_file") || die "Can't open $mak_file\n";
220    print_all_target($fullpath, \%all_target_hash);
221
222    # $extra_mak handles further *.mak files in a directory
223    print_flags($dir,$extra_mak,'CFlags',$nonpro);    # depends on directory
224    print_simple_flag("Rules");
225    print_simple_flag("Link");
226    print_common_linkflags();
227#    print_flags($fullpath,$extra_mak,'LinkFlags'); # depends on directory
228#    print_lib32_objs($fullpath,$extra_mak,\%collect_object_target_hash,$resource_file);
229    print_flags($dir,$extra_mak,'LinkFlags'); # depends on directory
230    print_lib32_objs($dir,$extra_mak,\%collect_object_target_hash,$resource_file);
231
232    # write @mak array into the *.mak file
233    foreach $line(@mak)
234    {
235        print MAKFILE $line;
236    }
237    $|=1;
238    print "."; # user entertainment
239    $|=0;
240}
241print "\ndone\n";
242exit;
243
244############################################################################
245sub getKey      #01.04.2008 09:46
246############################################################################
247 {
248    my $line = shift;
249    $line =~ /\[(.+)\]/;
250    return $1;
251}   ##getKey
252
253############################################################################
254sub fillTemplateHash        #01.04.2008 10:48
255############################################################################
256 {
257    my $file = shift;
258    open (TEMPLATE, "< $file") || die "Can't open template file $file\n";
259    my $key = "";
260    while ( $line=<TEMPLATE> ) {
261        if ( $line =~ /\[.+\]/ ) {
262            print $line if ($is_debug);
263            if ( $key ne "" ) {
264                $template_hash{$key}=[@cmdlines];
265                @cmdlines="";
266                $key="";
267            }
268            $key = getKey( $line );
269        } else
270        {
271            push @cmdlines, $line;
272        }
273    } # while
274}   ##fillTemplateHash
275
276############################################################################
277sub createCopySection       #01.04.2008 11:37
278############################################################################
279 {
280    my $header     = shift;
281    my $inputpath  = shift;
282    my $target     = shift;
283    my $targetpath = shift;
284    my $ref_make_file = shift; # Array written later to make file *.mak
285    my $ref_all_target_hash = shift;  # reference to fill all_target_hash;
286    if ( $target !~ /\\include/ && $target !~ /\\bin/) {
287        return; # $target contains nonsense
288    }
289    if ( !$targetpath ) {
290        # $targetpath is empty! (Due to missing entry in *.vcproj file)
291        # Generate $targetpath here from $target
292        my $t = $target;
293        $t =~ /(.+)\\(.+)$/;
294        $targetpath = "copy \"\$(InputPath)\" " . $1;
295        chomp $targetpath;
296    }
297    $targetpath =~ s/\r$//; # remove x0A from EOL if the is one
298    my @template = @{$template_hash{"Copy"}};
299    my $line = "";
300    foreach $line(@template)
301    {
302        $line =~ s/<HEADER>/$header/g;
303        $line =~ s/<INPUTPATH>/$inputpath/g;
304        $line =~ s/<TARGET>/$target/g;
305        $line =~ s/<TARGETPATH>/$targetpath/;
306        push @{$ref_make_file}, $line;           # from template
307        $$ref_all_target_hash{$target} = 1;       # "\"$target\" ";
308     # save for target ALL:
309    }
310}   ##createCopySection
311
312############################################################################
313sub createMakDepSection     #01.04.2008 13:36
314############################################################################
315 {
316    # creates the dependency section in the make file
317    my $dir         = shift;
318    my $source      = shift;
319    my $extension   = shift;
320    my $ref_header_list = shift;
321    my $ref_make_file = shift; # Array written later to make file *.mak
322    my $ref_special_file = shift; # hash for special files (compiler flags, include paths)
323    my $header_list = "";
324    my $special_flag = 0;
325
326    return if ( !defined $source );
327    foreach $header(@{$ref_header_list})
328    {
329        if ( ($header =~ /^\.\.\\.+/) && (-e $header )) {
330            $header_list = $header_list . " " . $header; # this header is located in an other directory
331        } else
332        {
333            $header_list = $header_list . " .\\" . $header;
334        }
335    }
336
337    #special handling
338    # compile this file with other compiler switches
339    my $file = $source . "\." . $extension;
340    $dir =~ s/\\/_/;
341    my @template = @{$template_hash{"CFlags_$dir"}};
342    if ( defined $$ref_special_file{"AdditionalIncludeDirectories"}{$file} ) {
343        $special_flag = 1;
344        my $includepath = $$ref_special_file{"AdditionalIncludeDirectories"}{$file};
345        $includepath =~ s/\;/\/I /g;                   # subst ; with /I for multiple paths
346        $line = "CPP_SWITCH_INCLUDE=/I  $includepath\n";
347        push @{$ref_make_file}, $line;
348        foreach $line(@template)
349        {
350            if ( $line =~ /CPP_PROJ/)
351            {
352                $line =~ s/CPP_PROJ=/CPPX_PROJ=/;
353                $line =~ s/\$\(CDEFS\)/\$\(CDEFS\) \$\(CPP_SWITCH_INCLUDE\)/; # include $(CPP_SWITCH_INCLUDE)
354                push @{$ref_make_file}, $line;
355            }
356        }
357    }
358    if ( $$ref_special_file{"DisableLanguageExtensions"}{$file} )
359    {
360        # FALSE = /Ze
361        $special_flag = 1;
362        foreach $line(@template)
363        {
364            if ( $line =~ /CPP_PROJ/)
365            {
366                $line =~ s/CPP_PROJ=/CPPX_PROJ=/;
367                $line =~ s/-Za/-Ze/;
368                if ( $nonpro )
369                {
370                    # if non product link against debug libraries
371                    $line =~ s/-MD/-MDd/;
372                    $line =~ s/-MT/-MTd/;
373                }
374                push @{$ref_make_file}, $line;
375            }
376        }
377    }
378
379    @template = @{$template_hash{"Deps"}};
380    my $line = "";
381    foreach $line(@template)
382    {
383        $line =~ s/<SOURCEFILE>/$source/g;
384        $line =~ s/<EXT>/$extension/g;
385        $line =~ s/<HEADER_LIST>/$header_list/g;
386        push @{$ref_make_file}, $line;
387    }
388
389    if ( $special_flag )
390    {
391        pop @{$ref_make_file}; # remove empty line
392        push @{$ref_make_file},"\t\$(CPP) @<<\n";
393        push @{$ref_make_file},"\t\$(CPPX_PROJ) \$(SOURCE)\n";
394        push @{$ref_make_file},"<<\n\n";
395        $special_flag = 0;
396    }
397
398}   ##createMakDepSection
399
400
401############################################################################
402sub getFilenameFromPath     #10.04.2008 13:03
403############################################################################
404{
405    my $path = shift;
406    $path =~ /.+\\(.+)$/;
407    return $1;
408}   ##getFilenameFromPath
409
410############################################################################
411sub getAllFilesDeps     #08.04.2008 09:39
412############################################################################
413{
414    my $path = shift;
415    my $ref_deps = shift;
416    my $ref_allfiles = shift;       # contains all relevant files from *.vcproj
417    my %local_header_hash=();       # contains all local header
418
419    my @all_files = keys %{$ref_allfiles};
420
421    # collect lokal header names in %header_hash
422    foreach $file(@all_files)
423    {
424        if ( $file =~ /.+\.h/ ) {
425            chomp $file;
426            $local_header_hash{$file} = 1;
427        }
428    }
429
430    foreach $file(@all_files)
431    {
432        my @header_deps=();
433        my $skip = 0;
434
435        $file =~ s/^\.\\//; # remove leading .\
436
437        # exclude sub directories and several file extensions
438        # *.dep,*.h,*.in,*.mak,*.pl,*.txt,*.vcproj.*.rc and origs of patch files (*.*~) and
439        # .cvsignore (files beginning with .)
440        next if ( (-d "$path$sep$file") || ($file =~ /.+(_|\~|dep|h|in|mak|pl|txt|vcproj|rc)$/) || ($file =~ /^\.+./));
441        parse_header_deps($path,$file,\@header_deps,\%local_header_hash);
442        handle_dep_to_other_directory($path,$file,\@header_deps,$$ref_vcproj{$file}) if ($$ref_vcproj{$file});
443        $$ref_deps{$file}=[@header_deps];
444    }
445}   ##getAllFilesDeps
446
447 ############################################################################
448 sub parse_header_deps      #14.06.2006 18:04
449 ############################################################################
450  {
451    # get includes from c/cpp file
452    # call create_deps(path,file,\$link_obj)
453    #
454    my $path = shift;
455    my $cfile = shift;
456    my $ref_header_deps = shift;
457    my $ref_local_header_hash = shift;
458
459    my $fullpath = $path . $sep . $cfile;
460    my $unicodedep="";
461    open(IN, "<$fullpath") || die "can't open $fullpath\n";
462    while ( $line = <IN> ) {
463        next if ($line !~ /^.?\#include.+/); # handle include lines only
464        if ($line =~ /.+?\s(.+)/)
465        {
466            $header = $1;
467            if ( ($header !~ /^<.+/) && ($header !~ /.+\.c.+$/) ) {
468                # no <stdio> etc. header
469                $header =~ s/\s+\/\*.+\*\///; # delete <blanks>/* ... */
470                $header =~ s/\s+\/\/.+//;      # delete <blanks>//......
471                $header =~ s/\//\\/;           # subst. / with \
472                $header =~ s/^\"/\".\\/;
473                $header =~ s/\"//g;
474                $header =~ s/\.\\//;
475                my $test = $$ref_local_header_hash{$header};
476                    my $header_fullpath = $path . "\\" . $header;
477                if ( $test || (($header =~ /\\/) && (-e $header_fullpath))) {
478                    push @{$ref_header_deps}, $header;
479                }
480            }
481        }
482    }
483 }  ##parse_header_deps
484
485############################################################################
486sub handle_dep_to_other_directory       #16.04.2008 15:11
487############################################################################
488{
489    # there has been an additional include directoy detected
490    # now try to find out which header (parsed from c/cpp-file)
491    # comes from this directory by checking: does it exist there?
492    my $path = shift;
493    my $file = shift;
494    my $ref_header_deps = shift;
495    my $path_additional = shift;
496    my $search_path = $path . "\\" . $path_additional;
497    my $counter = 0;
498    foreach $header(@{$ref_header_deps})
499    {
500        my $full_path = $search_path . "\\" . $header;
501        if ( -e "$full_path" )
502        {
503            $$ref_header_deps[$counter] = $path_additional . "\\" . $header;
504        }
505        $counter++
506    }
507}   ##handle_dep_to_other_directory
508
509############################################################################
510sub print_lib32_objs        #18.04.2008 12:54
511############################################################################
512 {
513    # generate Link section
514    my $path = shift;
515    my $extra_mak = shift;
516    my $ref_objecthash = shift;
517    my $resource_file = shift;
518    # output link objects
519    print MAKFILE "LINK32_OBJS= \\\n";
520    # print objects
521    foreach $object(sort keys %{$ref_objecthash})
522    {
523        print MAKFILE "\t$object \\\n";
524    }
525
526    # print *.res if *.rc exists
527    if ( $resource_file ne "" ) {
528        my $res_file = $resource_file;
529        $res_file =~ s/\.rc/\.res/;
530        $res_file =~ /(.+)\\(.+)$/;
531        $res_file = $2;
532        print MAKFILE "\t\$(INTDIR)\\$res_file \\\n";
533    }
534
535    # add import libs and res files
536    print_flags($path,$extra_mak,"AdditionalLinkObjects");
537    my $outfile = $configelements{"Release"}{"OutputFile"};
538
539    # section for linking
540    print_link_template($path,$outfile);
541
542    # section for creating res files
543    # setting for rsc, res target etc.
544    print "resource_file=$resource_file\n" if ($is_debug);
545    print_rsc_template($resource_file) if ($resource_file);
546    print_simple_flag("Special_extra_uconv") if ($outfile =~ /uconv/);
547}   ##print_lib32_objs
548
549############################################################################
550sub print_all_target        #26.06.2008 13:27
551############################################################################
552 {
553    my $path = shift;
554    my $ref_all_target_hash = shift;
555    my $filename = getFilenameFromPath($path);
556    my $outdir = $configelements{"Release"}{"OutputDirectory"};
557    print MAKFILE "NULL=\n";
558    print MAKFILE "OUTDIR=$outdir\n";
559    print MAKFILE "OutDir=$outdir\n";
560    print MAKFILE "INTDIR=.\\Release\n\n";
561    print MAKFILE "ALL: ";
562    foreach $target(sort keys %{$ref_all_target_hash})
563    {
564        if ( $target =~ /\.exe/ ) {
565            my $out = $target;
566            $out =~ s/\.\\((x64|x86)\\)?Release/\.\.\\\.\.\\\.\.\\$1bin/;
567            $out =~ s/\$\(OutDir\)/\.\.\\\.\.\\\.\.\\bin/;
568            $out =~ s/\//\\/; # convert / to \
569            $target = $out;
570        }
571        print MAKFILE "\"$target\" ";
572    }
573
574    # Append [Target_<dir>] item e.g. ../../icuxy36.dll
575    my $targetkey = "Target_" . $filename;
576    my @target = ();
577    if ( exists $template_hash{$targetkey}  ) {
578        @target = @{$template_hash{$targetkey}};
579    }
580    my $additional_target="";
581    foreach $additional_target(@target)
582    {
583        print MAKFILE $additional_target if ($additional_target ne "");
584    }
585    print MAKFILE "\n\n";
586    print MAKFILE "\"\$(OUTDIR)\" : \n";
587    print MAKFILE "\tif not exist \"\$(OUTDIR)/\$(NULL)\" mkdir \"\$(OUTDIR)\"\n\n";
588    print MAKFILE "!IF \"\$(OUTDIR)\" != \"\$(INTDIR)\"\n";
589    print MAKFILE "\"\$(INTDIR)\" : \n";
590    print MAKFILE "\tif not exist \"\$(INTDIR)/\$(NULL)\" mkdir \"\$(INTDIR)\"\n";
591    print MAKFILE "!ENDIF\n";
592    print MAKFILE "\n\n";
593}   ##print_all_target
594
595############################################################################
596sub print_simple_flag       #18.04.2008 13:39
597############################################################################
598{
599    my $simple_flag = shift;
600    my @template = @{$template_hash{$simple_flag}};
601    foreach $line(@template)
602    {
603        print MAKFILE $line;
604    }
605}   ##print_rules
606
607############################################################################
608sub print_link_template       #18.04.2008 13:39
609############################################################################
610{
611    my $dir = shift;
612    my $outfile = shift;
613    my $manifest;
614    # set resource id for manifest file
615    if ( $outfile =~ /\.exe/ ) {
616        $manifest = 1;
617    } else
618    {
619        $manifest = 2;
620    }
621    my @template = ();
622    if ($dir =~ /stubdata/ ) {
623        @template = @{$template_hash{"Special_stubdata"}};
624    } else
625    {
626        @template = @{$template_hash{"LinkTemplate"}};
627    }
628
629    print MAKFILE "\n"; # insert blank line
630    foreach $line(@template)
631    {
632        $line =~ s/<OUTFILE>/$outfile/;
633        $line =~ s/<MANIFEST>/$manifest/;
634        print MAKFILE $line;
635    }
636
637    # insert special stuff for
638    # extras/uconv/uconv.mak
639    if ( $dir =~ /uconv/ ) {
640        print_flags($dir,"","Special");
641    }
642
643    # for *.exe files an additional
644    # copy section is required to get
645    # the stuff into the per-arch bin directory
646    my %dummy = ();
647    my @mak = ();
648    my $arch = "";
649    if ( $out =~ /x64/ ) {
650    $arch = "x64\\";
651    } elsif ( $out =~ /x86/ ) {
652    $arch = "x86\\";
653    }
654    if( $manifest ==1 )
655    {
656        # source,inputpath,target,action
657        my $out = $outfile;
658        $out =~ s/\.\\((x64|x86)\\)?Release/\.\.\\\.\.\\\.\.\\$1bin/;
659        $out =~ s/\$\(OutDir\)/\.\.\\\.\.\\\.\.\\bin/;
660        $out =~ s/\//\\/;       # subst / with \
661        $outfile =~ s/\//\\/;   # subst / with \
662        createCopySection($outfile,$outfile,$out,"copy \"\$(InputPath)\" .\\..\\..\\..\\${arch}bin",\@mak,\%dummy);
663        foreach $line(@mak)
664        {
665            print MAKFILE $line;
666        }
667    }
668}   ##print_rules
669
670############################################################################
671sub print_rsc_template      #04.11.2008 14:48
672############################################################################
673 {
674    # print resource compiler setting + resource target
675    my $resourcefile = shift;
676    # skip this if no res file required
677
678    return if (!$resourcefile);
679    $resfile = $resourcefile;
680    #remove file extension (.res)
681    $resfile =~ /(.+)\\(.+)\.(.+)/;
682    $resfile = $2;
683
684    my @template = @{$template_hash{"RSC_Template"}};
685    print MAKFILE "\n"; # insert blank line
686    foreach $line(@template)
687    {
688        $line =~ s/<FILE>/$resourcefile/;
689        $line =~ s/<FILEOUT>/$resfile/;
690        print MAKFILE $line;
691    }
692}   ##print_rsc_template
693
694############################################################################
695sub print_flags     #18.04.2008 14:19
696############################################################################
697{
698    # CFlags, LinkFlags
699    my $dir = shift;
700    my $extra_mak = shift; # eg. derb.mak, stringperf.mak
701    my $flag = shift;
702    my $nonpro = shift;
703    my @template = ();
704    my $switch = "";
705    $dir =~ s/\\/_/g if ($dir);            # change \ to _
706    $switch = "$flag" . "_" . "$dir" if ($dir);
707    handle_CFlags() if ($flag eq "CFlags");  # get and print Preprocessor defines
708    $switch .= "\." . $extra_mak if ( $extra_mak ne "" ) ;
709    if ( exists $template_hash{$switch} ) {
710        @template = @{$template_hash{$switch}};
711        foreach $line(@template)
712        {
713            if ( $nonpro )
714            {
715                # if non product link against debug libraries
716                $line =~ s/-MD/-MDd/;
717                $line =~ s/-MT/-MTd/;
718            }
719            print MAKFILE $line;
720        }
721    }
722}   ##print_flags
723
724############################################################################
725sub handle_CFlags       #28.01.2009 11:20
726############################################################################
727 {
728
729    my $ppdefs = $configelements{"Release"}{"PreprocessorDefinitions"};
730    my $ppinc  = $configelements{"Release"}{"AdditionalIncludeDirectories"};
731    my @template = @{$template_hash{"General_CFlags"}};
732    $ppdefs =~ s/;/ -D/g; # subst ; with -D switch
733    $ppdefs = "-D" . $ppdefs;
734    $ppinc =~ s/(;|,)/ -I/g; # subst ; with -I switch
735    $ppinc = "-I" . $ppinc;
736    print "ppdefs=$ppdefs\n" if ($is_debug);
737    print "ppinc =$ppinc\n" if ($is_debug);
738    foreach $line(@template)
739    {
740        $line =~ s/<AddIncDirs>/$ppinc/;
741        $line =~ s/<PreProcDefs>/$ppdefs/;
742        print MAKFILE $line;
743    }
744}   ##handle_CFlags
745
746############################################################################
747sub print_common_linkflags      #21.11.2008 11:47
748############################################################################
749 {
750    my @template = @{$template_hash{"CommonLinkFlags"}};
751    my $outfile = $configelements{"Release"}{"OutputFile"};
752    my $pdbfile = $configelements{"Release"}{"ProgramDatabaseFile"};
753    $pdbfile =~ s/\//\\/;   # subst / with \
754    $outfile =~ s/\//\\/;   # subst / with \
755    print "PATH=$path OUTFILE=$outfile\n" if ($is_debug);
756    foreach $line(@template)
757    {
758        $line =~ s/<OUTFILE>/$outfile/;
759        $line =~ s/<PDBFILE>/$pdbfile/;
760        print MAKFILE $line;
761    }
762}   ##print_common_linkflags
763
764############################################################################
765sub handle_extra_mak_files      #25.08.2008 14:32
766############################################################################
767{
768    # extract extra filename for *.mak file
769    # e.g input: tools\genrb.derb
770    #    output: derb
771    my $direntry = shift;
772    my $out = "";
773    my $dir = "";
774    if ( $direntry =~ /(.+)\.(.+)$/ ) {
775        $dir = $1;
776        $out = $2;
777    } else
778    {
779        $dir = $direntry;
780    }
781    return ($dir,$out);
782}   ##handle_extra_mak_files
783
784############################################################################
785sub prepare_allinone_all_mak
786############################################################################
787{
788    # Read in allinone.sln
789    # Fills hashes and returns an array with build order
790    # uses topographical sorting
791
792    my $href_project_by_id = shift;
793    my $href_project_by_name = shift;
794    my $href_project_dependencies = shift;
795    my $sourcePath = shift;
796
797    my $allslnfile = $sourcePath . "\\allinone\\allinone.sln";
798    my @projectdeps;
799    my $projectname;
800    my $projectpath;
801    my $projectid;
802
803    # fill hash tables
804    open (SLN, "< $allslnfile") || die "Can't open $allslnfile\n";
805    while ($line = <SLN>)
806    {
807        my @project = ();
808        if ( $line =~ /^Project\(/ ) {
809            @project = split( /,/, $line);
810            if ( $#project ) {
811                $projectname = "";
812                $projectpath = "";
813                $projectid = "";
814                @projectdeps = ();
815                my @subarray = ();
816                @subarray = split( /=/, $project[0]);
817                $projectname = $subarray[1];
818                $projectname =~ s/\"//g;      # remove "
819                $projectpath = $project[1];
820                $projectid = $project[2];
821                $projectid =~ s/\"//g;        # remove "
822                $projectid =~ s/.+\{//g;      # remove til {
823                $projectid =~ s/\}\n//g;      # remove }<CR>
824                my @pnp = ($projectname,$projectpath);
825                my @pip = ($projectid,$projectpath);
826                $$href_project_by_id{$projectid}=[@pnp];
827                $$href_project_by_name{$projectname} =[@pip];
828            }
829        } # $line =~ /^Project\(/
830        if ( $line =~ /ProjectSection\(/ ) {
831            $psect = 1;
832            next;
833        }
834        if ( $line =~ /EndProjectSection/ ) {
835            $psect = 0;
836            $$href_project_dependencies{$projectid}=[@projectdeps];
837            next;
838        }
839        if ( $psect ) {
840            my @tarray = split(/=/, $line);
841            $depends_on_id = $tarray[0];
842            $depends_on_id =~ s/.+\{//g;
843            $depends_on_id =~ s/\}.+//g;
844             print "+$depends_on_id-\n" if ($is_debug);
845
846            push @projectdeps, $depends_on_id;
847        }
848    }
849    ########################################
850    # sort here and generate build order
851    ########################################
852    $objektzahl=0;
853    %hashindex=();
854
855    foreach $projectid(keys %{$href_project_by_id})
856    {
857        if ( $$href_project_dependencies{$projectid} )
858        {
859            @deps = @{$$href_project_dependencies{$projectid}};
860        } else
861        {
862            @deps = ();
863        }
864        for  $counter(0..$#deps)
865        {
866            $v = find_or_create_element($deps[$counter]);
867            $n = find_or_create_element($projectid);
868            push @{$nachfolgerliste[$v]},$n;
869        }
870    }
871
872    for $n (0..$objektzahl-1)
873    {
874            $vorgaengerzahl[$n]=0;
875    }
876    for $v (0..$objektzahl-1)
877    {
878            for $n (@{$nachfolgerliste[$v]})
879            {
880                    ++$vorgaengerzahl[$n];
881            }
882    }
883
884    @hilfsliste=();
885    for $n (0..$objektzahl-1)
886    {
887        push(@hilfsliste,$n) if ($vorgaengerzahl[$n]==0)
888    }
889
890    $ausgabe=0;
891    @builddep =();
892    while (defined($v=pop(@hilfsliste)))
893    {
894        push @builddep, $name[$v];                           # save build order by project_id;
895        ++$ausgabe;
896        for $n (@{$nachfolgerliste[$v]})
897        {
898                --$vorgaengerzahl[$n];
899                push(@hilfsliste,$n) if ($vorgaengerzahl[$n]==0);
900        }
901    } # while
902    die "Cyclic dependencies found! Stopping now.\n" if $ausgabe<$objektzahl;
903    ##############################################################
904    # End of sorting stuff
905    ##############################################################
906
907    return @builddep;
908    ###############################################################
909    ###########################
910    # sub for sorting only
911    ###########################
912    sub find_or_create_element
913    {
914        my ($str)=@_;
915        my ($idx)=$hashindex{$str};
916        if (!defined($idx)) {               # new element ...
917                $idx=$objektzahl++;
918                $hashindex{$str}=$idx;
919                $name[$idx]=$str;
920            @{$nachfolgerliste[$idx]}=();
921        }
922        return $idx;
923    } # find_or_create_element
924}  # prepare_allinone_all_mak
925
926############################################################################
927sub create_allinone_all_mak     #09.02.2009 09:22
928############################################################################
929{
930    my $ref_buildorder = shift;
931    my $href_project_by_id = shift;
932    my $sourcePath = shift;
933    my $allmakfile = $sourcePath . "\\allinone\\all.mak";
934    open (ALLMAK, ">$allmakfile") || die "Can't write to $allmakfile \n";
935    print ALLMAK "ALL: ";
936    foreach $proj(@{$ref_buildorder})
937    {
938        print ALLMAK $$href_project_by_id{$proj}[0];
939    }
940    print ALLMAK "\n\n";
941
942    foreach $proj( @{$ref_buildorder} )
943    {
944        print "$proj $$href_project_by_id{$proj}[0] $$href_project_by_id{$proj}[1]\n";
945        my $prjdir = $$href_project_by_id{$proj}[1];
946        $prjdir =~ /(.+)\\(.+)$/;
947        $prjdir = $1;
948        $prjname = $2;
949        $prjdir =~ s/^.+\"//;
950        $prjname =~ s/\"$//;
951        $prjname =~ s/vcproj/mak/;
952        $allinonehelpstring = $prjdir;
953        $allinonehelpstring =~ s/^\.+\\//; # remove ..\
954        my $backcount = "";
955        while ($allinonehelpstring=~ /.+\\/g) # counts the occuring \
956        {
957            $backcount .= "..\\";
958        }
959        $allinonedir = $backcount . "..\\allinone";
960
961        # write all.mak
962        $$href_project_by_id{$proj}[0] =~ s/^\s+//;
963        if ( $$href_project_by_id{$proj}[0] ne "makedata" )
964        {
965            my @template = @{$template_hash{"AllInOnePrj"}};
966            foreach $line(@template)
967            {
968                $line =~ s/<PRJ>/$$href_project_by_id{$proj}[0]/;
969                $line =~ s/<PRJDIR>/$prjdir/;
970                $line =~ s/<PRJMAK>/$prjname/;
971                $line =~ s/<ALLINONEDIR>/$allinonedir/;
972                print ALLMAK $line;
973            }
974        } else
975        {
976            #special code snippet
977            print ALLMAK "makedata : \n";
978            print ALLMAK "     cd \"..\\data\"\n";
979            print ALLMAK "     nmake /f makedata.mak icumake=\$(MAKEDIR)\\..\\data cfg=$architecture/Release\n";
980            print ALLMAK "     cd \"..\\allinone\"\n\n";
981        }
982    }
983    close ALLMAK;
984}   ##create_allinone_all_mak
985
986############################################################################
987
988# ------------------------------------------------------------------------
989# XML parser handling
990# ------------------------------------------------------------------------
991
992############################################################################
993sub start_handler
994############################################################################
995{
996    my $p = shift;           # pointer to parser
997    my $el = shift;          # element
998
999    # Deal with attributes
1000
1001    my $CompilerSection = 0;
1002    my $LinkerSection = 0;
1003    my $ConfigSection = ($el eq "Configuration");
1004
1005    while (@_)
1006    {
1007 #       shift if ( $el eq "FileConfiguration" );
1008        my $att = shift;
1009        my $val = shift;
1010        $CustomSection = 0;
1011        if ($special_file && defined $att & $att ne "Name")
1012        {
1013            print "$special_file - $att - $val\n";
1014            my @param = ($att,$val);
1015            $files_special{ $special_file } = [@param]; # files with special compiler switch
1016            @test = @{$files_special{ $special_file }};
1017            print "test=@test\n";
1018            $special_file="";
1019        }
1020        if ( $ConfigSection && $att eq "Name" && $val eq "Release|Win32" ) {
1021        if ( $architecture eq "x86" ) {
1022        $Release = 1;
1023        $config = "Release";                                                             # Release
1024        } else {
1025        print "Ignoring Configuration $val\n" if ($is_debug);
1026        $Release = 2;
1027        $config = "Ignored";
1028        }
1029        }
1030        if ( $ConfigSection && $att eq "Name" && $val eq "Debug|Win32" ) {
1031        if ( $architecture eq "x86" ) {
1032        $Release = 0;                                                                    # Debug
1033        $config = "Debug";
1034        } else {
1035                print "Ignoring Configuration $val\n" if ($is_debug);
1036        $Release = 2;
1037        $config = "Ignored";
1038        }
1039        }
1040        if ( $ConfigSection && $att eq "Name" && $val eq "Release|x64" ) {
1041        if ( $architecture eq "x64" ) {
1042        $Release = 1;
1043        $config = "Release";                                                             # Release
1044        } else {
1045                print "Ignoring Configuration $val\n" if ($is_debug);
1046        $Release = 2;
1047        $config = "Ignored";
1048        }
1049        }
1050        if ( $ConfigSection && $att eq "Name" && $val eq "Debug|x64" ) {
1051        if ( $architecture eq "x64" ) {
1052        $Release = 0;                                                             # Debug
1053        $config = "Debug";
1054        } else {
1055                print "Ignoring Configuration $val\n" if ($is_debug);
1056        $Release = 2;
1057        $config = "Ignored";
1058        }
1059        }
1060        if ( $att eq "Name" && $val eq "VCCLCompilerTool" ) {
1061            $CompilerSection = 1;
1062        }
1063        if ( $att eq "Name" && $val eq "VCLinkerTool" ) {
1064            $LinkerSection = 1;
1065        }
1066        if ( $att eq "Name" && $val eq "VCCustomBuildTool" ) {
1067            $CustomSection = 1;
1068        }
1069
1070        # For Configuration Infos like compiler defines etc.
1071        if ( $att eq "PreprocessorDefinitions" && $CompilerSection ) {
1072           $configelements{$config}{$att} = $val;
1073        }
1074        if ( $att eq "AdditionalIncludeDirectories" && $CompilerSection ) {
1075           #$configelements{$config}{$att} = $val;
1076            if ( ($file_tmp ne "") && ($val ne "") ) {
1077                $files{ $file_tmp } = 1;        # save it now
1078                $file_tmp =~ s/^\.\\//;         # remove leading .\
1079                $files_special{"AdditionalIncludeDirectories"}{$file_tmp} = $val;
1080                print "Include $val: $file_tmp\n" if ($is_debug);
1081                $file_tmp = "";                 # has been saved now reset it
1082            } else
1083            {
1084               $configelements{$config}{$att} = $val;
1085            }
1086        }
1087        if ( ($att eq "DisableLanguageExtensions") && $CompilerSection ) {
1088           #$configelements{$config}{$att} = $val;
1089            if ( ($file_tmp ne "") && ($val ne "")) {
1090                $files{ $file_tmp } = 1;        # save it now
1091                $file_tmp =~ s/^\.\\//;         # remove leading .\
1092                $files_special{"DisableLanguageExtensions"}{$file_tmp} = $val;
1093                print "-Ze: $file_tmp\n" if ($is_debug);
1094                $file_tmp = "";                 # has been saved now reset it
1095            }
1096        }
1097        if ( $att eq "OutputDirectory" ) {
1098           $configelements{$config}{$att} = $val;
1099        }
1100        if ( $att eq "OutputFile" && $LinkerSection ) {
1101           if ($architecture eq "x64") {
1102              # We want the /bin/ subdirectory on all architectures
1103              $val =~ s/\\bin64\\/\\bin\\/;
1104           }
1105           $configelements{$config}{$att} = $val;
1106        }
1107        if ( $att eq "ProgramDatabaseFile" ) {
1108           $configelements{$config}{$att} = $val;
1109        }
1110        if ( $att eq "ImportLibrary" && $LinkerSection ) {
1111           $configelements{$config}{$att} = $val;
1112        }
1113        if ($att eq "CommandLine") {
1114           $configelements{$config}{$att} = $val;
1115        }
1116        if (($att eq "PreprocessorDefinitions") && $ConfigSection) {
1117           $configelements{$config}{$att} = $val;
1118        }
1119
1120        # Is the file in the step before a header
1121        # which has to be copied into the global
1122        # include path?
1123        if ( $file_tmp ne "" )
1124        {
1125            $config = "Release";
1126            if ( ($att eq "CommandLine") && ($el eq "Tool") )
1127            {
1128                if ( $file_tmp =~ /.+\.h$/ ) {
1129                    $files2copy{ $file_tmp } = $val; # unicode + layout header to copy
1130                    $file_tmp = "";                 # has been saved now reset it
1131                }
1132            }
1133        } # if $file_tmp
1134
1135        # For files
1136        if ( $att eq "RelativePath" ) {
1137            if ( $file_tmp ) {
1138                # no special file (include dir / compiler switch)
1139                $files{ $file_tmp } = 1;        # save it now
1140                $file_tmp = "";                 # has been saved now reset it
1141            }
1142            # store temporary the file name
1143            $file_tmp = $val if ($val !~ /\.mk$/);  # no *.mk files
1144        }
1145    } # while @_
1146}  # End start_handler
1147
1148############################################################################
1149sub char_handler
1150############################################################################
1151{
1152}  # End char_handler
1153