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