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