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