1# Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. 2# 3# Redistribution and use in source and binary forms, with or without 4# modification, are permitted provided that the following conditions 5# are met: 6# 7# 1. Redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer. 9# 2. Redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution. 12# 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 13# its contributors may be used to endorse or promote products derived 14# from this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 17# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 20# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27# Module to share code to get to WebKit directories. 28 29use strict; 30use warnings; 31use FindBin; 32use File::Basename; 33use POSIX; 34use VCSUtils; 35 36BEGIN { 37 use Exporter (); 38 our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); 39 $VERSION = 1.00; 40 @ISA = qw(Exporter); 41 @EXPORT = qw(&chdirWebKit &baseProductDir &productDir &XcodeOptions &XcodeOptionString &XcodeOptionStringNoConfig &passedConfiguration &setConfiguration &safariPath &checkFrameworks ¤tSVNRevision); 42 %EXPORT_TAGS = ( ); 43 @EXPORT_OK = (); 44} 45 46our @EXPORT_OK; 47 48my $architecture; 49my $baseProductDir; 50my @baseProductDirOption; 51my $configuration; 52my $configurationForVisualStudio; 53my $configurationProductDir; 54my $sourceDir; 55my $currentSVNRevision; 56my $osXVersion; 57my $isQt; 58my %qtFeatureDefaults; 59my $isGtk; 60my $isWx; 61my @wxArgs; 62my $isChromium; 63 64# Variables for Win32 support 65my $vcBuildPath; 66my $windowsTmpPath; 67 68sub determineSourceDir 69{ 70 return if $sourceDir; 71 $sourceDir = $FindBin::Bin; 72 $sourceDir =~ s|/+$||; # Remove trailing '/' as we would die later 73 74 # walks up path checking each directory to see if it is the main WebKit project dir, 75 # defined by containing JavaScriptCore, WebCore, and WebKit 76 until ((-d "$sourceDir/JavaScriptCore" && -d "$sourceDir/WebCore" && -d "$sourceDir/WebKit") || (-d "$sourceDir/Internal" && -d "$sourceDir/OpenSource")) 77 { 78 if ($sourceDir !~ s|/[^/]+$||) { 79 die "Could not find top level webkit directory above source directory using FindBin.\n"; 80 } 81 } 82 83 $sourceDir = "$sourceDir/OpenSource" if -d "$sourceDir/OpenSource"; 84} 85 86# used for scripts which are stored in a non-standard location 87sub setSourceDir($) 88{ 89 ($sourceDir) = @_; 90} 91 92sub determineBaseProductDir 93{ 94 return if defined $baseProductDir; 95 determineSourceDir(); 96 97 if (isAppleMacWebKit()) { 98 # Silently remove ~/Library/Preferences/xcodebuild.plist which can 99 # cause build failure. The presence of 100 # ~/Library/Preferences/xcodebuild.plist can prevent xcodebuild from 101 # respecting global settings such as a custom build products directory 102 # (<rdar://problem/5585899>). 103 my $personalPlistFile = $ENV{HOME} . "/Library/Preferences/xcodebuild.plist"; 104 if (-e $personalPlistFile) { 105 unlink($personalPlistFile) || die "Could not delete $personalPlistFile: $!"; 106 } 107 108 open PRODUCT, "defaults read com.apple.Xcode PBXApplicationwideBuildSettings 2> /dev/null |" or die; 109 $baseProductDir = join '', <PRODUCT>; 110 close PRODUCT; 111 112 $baseProductDir = $1 if $baseProductDir =~ /SYMROOT\s*=\s*\"(.*?)\";/s; 113 undef $baseProductDir unless $baseProductDir =~ /^\//; 114 115 if (!defined($baseProductDir)) { 116 open PRODUCT, "defaults read com.apple.Xcode PBXProductDirectory 2> /dev/null |" or die; 117 $baseProductDir = <PRODUCT>; 118 close PRODUCT; 119 if ($baseProductDir) { 120 chomp $baseProductDir; 121 undef $baseProductDir unless $baseProductDir =~ /^\//; 122 } 123 } 124 } 125 126 if (!defined($baseProductDir)) { # Port-spesific checks failed, use default 127 $baseProductDir = $ENV{"WEBKITOUTPUTDIR"} || "$sourceDir/WebKitBuild"; 128 } 129 130 if (isGit() && isGitBranchBuild()) { 131 my $branch = gitBranch(); 132 $baseProductDir = "$baseProductDir/$branch"; 133 } 134 135 if (isAppleMacWebKit()) { 136 $baseProductDir =~ s|^\Q$(SRCROOT)/..\E$|$sourceDir|; 137 $baseProductDir =~ s|^\Q$(SRCROOT)/../|$sourceDir/|; 138 $baseProductDir =~ s|^~/|$ENV{HOME}/|; 139 die "Can't handle Xcode product directory with a ~ in it.\n" if $baseProductDir =~ /~/; 140 die "Can't handle Xcode product directory with a variable in it.\n" if $baseProductDir =~ /\$/; 141 @baseProductDirOption = ("SYMROOT=$baseProductDir", "OBJROOT=$baseProductDir"); 142 } 143 144 if (isCygwin()) { 145 my $dosBuildPath = `cygpath --windows \"$baseProductDir\"`; 146 chomp $dosBuildPath; 147 $ENV{"WEBKITOUTPUTDIR"} = $dosBuildPath; 148 } 149 150 if (isAppleWinWebKit()) { 151 my $unixBuildPath = `cygpath --unix \"$baseProductDir\"`; 152 chomp $unixBuildPath; 153 $baseProductDir = $unixBuildPath; 154 } 155} 156 157sub setBaseProductDir($) 158{ 159 ($baseProductDir) = @_; 160} 161 162sub determineConfiguration 163{ 164 return if defined $configuration; 165 determineBaseProductDir(); 166 if (open CONFIGURATION, "$baseProductDir/Configuration") { 167 $configuration = <CONFIGURATION>; 168 close CONFIGURATION; 169 } 170 if ($configuration) { 171 chomp $configuration; 172 # compatibility for people who have old Configuration files 173 $configuration = "Release" if $configuration eq "Deployment"; 174 $configuration = "Debug" if $configuration eq "Development"; 175 } else { 176 $configuration = "Release"; 177 } 178} 179 180sub determineArchitecture 181{ 182 return if defined $architecture; 183 # make sure $architecture is defined for non-apple-mac builds 184 $architecture = ""; 185 return unless isAppleMacWebKit(); 186 187 determineBaseProductDir(); 188 if (open ARCHITECTURE, "$baseProductDir/Architecture") { 189 $architecture = <ARCHITECTURE>; 190 close ARCHITECTURE; 191 } 192 if ($architecture) { 193 chomp $architecture; 194 } else { 195 if (isTiger() or isLeopard()) { 196 $architecture = `arch`; 197 } else { 198 my $supports64Bit = `sysctl -n hw.optional.x86_64`; 199 chomp $supports64Bit; 200 $architecture = $supports64Bit ? 'x86_64' : `arch`; 201 } 202 chomp $architecture; 203 } 204} 205 206sub argumentsForConfiguration() 207{ 208 determineConfiguration(); 209 determineArchitecture(); 210 211 my @args = (); 212 push(@args, '--debug') if $configuration eq "Debug"; 213 push(@args, '--release') if $configuration eq "Release"; 214 push(@args, '--32-bit') if $architecture ne "x86_64"; 215 push(@args, '--qt') if isQt(); 216 push(@args, '--gtk') if isGtk(); 217 push(@args, '--wx') if isWx(); 218 push(@args, '--chromium') if isChromium(); 219 return @args; 220} 221 222sub determineConfigurationForVisualStudio 223{ 224 return if defined $configurationForVisualStudio; 225 determineConfiguration(); 226 $configurationForVisualStudio = $configuration; 227 return unless $configuration eq "Debug"; 228 setupCygwinEnv(); 229 chomp(my $dir = `cygpath -ua '$ENV{WEBKITLIBRARIESDIR}'`); 230 $configurationForVisualStudio = "Debug_Internal" if -f "$dir/bin/CoreFoundation_debug.dll"; 231} 232 233sub determineConfigurationProductDir 234{ 235 return if defined $configurationProductDir; 236 determineBaseProductDir(); 237 determineConfiguration(); 238 if (isAppleWinWebKit() && !isWx()) { 239 $configurationProductDir = "$baseProductDir/bin"; 240 } else { 241 # [Gtk] We don't have Release/Debug configurations in straight 242 # autotool builds (non build-webkit). In this case and if 243 # WEBKITOUTPUTDIR exist, use that as our configuration dir. This will 244 # allows us to run run-webkit-tests without using build-webkit. 245 if ($ENV{"WEBKITOUTPUTDIR"} && isGtk()) { 246 $configurationProductDir = "$baseProductDir"; 247 } else { 248 $configurationProductDir = "$baseProductDir/$configuration"; 249 } 250 } 251} 252 253sub setConfigurationProductDir($) 254{ 255 ($configurationProductDir) = @_; 256} 257 258sub determineCurrentSVNRevision 259{ 260 return if defined $currentSVNRevision; 261 determineSourceDir(); 262 $currentSVNRevision = svnRevisionForDirectory($sourceDir); 263 return $currentSVNRevision; 264} 265 266 267sub chdirWebKit 268{ 269 determineSourceDir(); 270 chdir $sourceDir or die; 271} 272 273sub baseProductDir 274{ 275 determineBaseProductDir(); 276 return $baseProductDir; 277} 278 279sub sourceDir 280{ 281 determineSourceDir(); 282 return $sourceDir; 283} 284 285sub productDir 286{ 287 determineConfigurationProductDir(); 288 return $configurationProductDir; 289} 290 291sub configuration() 292{ 293 determineConfiguration(); 294 return $configuration; 295} 296 297sub configurationForVisualStudio() 298{ 299 determineConfigurationForVisualStudio(); 300 return $configurationForVisualStudio; 301} 302 303sub currentSVNRevision 304{ 305 determineCurrentSVNRevision(); 306 return $currentSVNRevision; 307} 308 309sub XcodeOptions 310{ 311 determineBaseProductDir(); 312 determineConfiguration(); 313 determineArchitecture(); 314 return (@baseProductDirOption, "-configuration", $configuration, "ARCHS=$architecture"); 315} 316 317sub XcodeOptionString 318{ 319 return join " ", XcodeOptions(); 320} 321 322sub XcodeOptionStringNoConfig 323{ 324 return join " ", @baseProductDirOption; 325} 326 327sub XcodeCoverageSupportOptions() 328{ 329 my @coverageSupportOptions = (); 330 push @coverageSupportOptions, "GCC_GENERATE_TEST_COVERAGE_FILES=YES"; 331 push @coverageSupportOptions, "GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES"; 332 push @coverageSupportOptions, "EXTRA_LINK= \$(EXTRA_LINK) -ftest-coverage -fprofile-arcs"; 333 push @coverageSupportOptions, "OTHER_CFLAGS= \$(OTHER_CFLAGS) -DCOVERAGE -MD"; 334 push @coverageSupportOptions, "OTHER_LDFLAGS=\$(OTHER_LDFLAGS) -ftest-coverage -fprofile-arcs -framework AppKit"; 335 return @coverageSupportOptions; 336} 337 338my $passedConfiguration; 339my $searchedForPassedConfiguration; 340sub determinePassedConfiguration 341{ 342 return if $searchedForPassedConfiguration; 343 $searchedForPassedConfiguration = 1; 344 345 my $isWinCairo = checkForArgumentAndRemoveFromARGV("--cairo-win32"); 346 347 for my $i (0 .. $#ARGV) { 348 my $opt = $ARGV[$i]; 349 if ($opt =~ /^--debug$/i || $opt =~ /^--devel/i) { 350 splice(@ARGV, $i, 1); 351 $passedConfiguration = "Debug"; 352 $passedConfiguration .= "_Cairo" if ($isWinCairo && isCygwin()); 353 return; 354 } 355 if ($opt =~ /^--release$/i || $opt =~ /^--deploy/i) { 356 splice(@ARGV, $i, 1); 357 $passedConfiguration = "Release"; 358 $passedConfiguration .= "_Cairo" if ($isWinCairo && isCygwin()); 359 return; 360 } 361 if ($opt =~ /^--profil(e|ing)$/i) { 362 splice(@ARGV, $i, 1); 363 $passedConfiguration = "Profiling"; 364 $passedConfiguration .= "_Cairo" if ($isWinCairo && isCygwin()); 365 return; 366 } 367 } 368 $passedConfiguration = undef; 369} 370 371sub passedConfiguration 372{ 373 determinePassedConfiguration(); 374 return $passedConfiguration; 375} 376 377sub setConfiguration 378{ 379 setArchitecture(); 380 381 if (my $config = shift @_) { 382 $configuration = $config; 383 return; 384 } 385 386 determinePassedConfiguration(); 387 $configuration = $passedConfiguration if $passedConfiguration; 388} 389 390 391my $passedArchitecture; 392my $searchedForPassedArchitecture; 393sub determinePassedArchitecture 394{ 395 return if $searchedForPassedArchitecture; 396 $searchedForPassedArchitecture = 1; 397 398 for my $i (0 .. $#ARGV) { 399 my $opt = $ARGV[$i]; 400 if ($opt =~ /^--32-bit$/i) { 401 splice(@ARGV, $i, 1); 402 if (isAppleMacWebKit()) { 403 $passedArchitecture = `arch`; 404 chomp $passedArchitecture; 405 } 406 return; 407 } 408 } 409 $passedArchitecture = undef; 410} 411 412sub passedArchitecture 413{ 414 determinePassedArchitecture(); 415 return $passedArchitecture; 416} 417 418sub architecture() 419{ 420 determineArchitecture(); 421 return $architecture; 422} 423 424sub setArchitecture 425{ 426 if (my $arch = shift @_) { 427 $architecture = $arch; 428 return; 429 } 430 431 determinePassedArchitecture(); 432 $architecture = $passedArchitecture if $passedArchitecture; 433} 434 435 436sub safariPathFromSafariBundle 437{ 438 my ($safariBundle) = @_; 439 440 return "$safariBundle/Contents/MacOS/Safari" if isAppleMacWebKit(); 441 return $safariBundle if isAppleWinWebKit(); 442} 443 444sub installedSafariPath 445{ 446 my $safariBundle; 447 448 if (isAppleMacWebKit()) { 449 $safariBundle = "/Applications/Safari.app"; 450 } elsif (isAppleWinWebKit()) { 451 $safariBundle = `"$configurationProductDir/FindSafari.exe"`; 452 $safariBundle =~ s/[\r\n]+$//; 453 $safariBundle = `cygpath -u '$safariBundle'`; 454 $safariBundle =~ s/[\r\n]+$//; 455 $safariBundle .= "Safari.exe"; 456 } 457 458 return safariPathFromSafariBundle($safariBundle); 459} 460 461# Locate Safari. 462sub safariPath 463{ 464 # Use WEBKIT_SAFARI environment variable if present. 465 my $safariBundle = $ENV{WEBKIT_SAFARI}; 466 if (!$safariBundle) { 467 determineConfigurationProductDir(); 468 # Use Safari.app in product directory if present (good for Safari development team). 469 if (isAppleMacWebKit() && -d "$configurationProductDir/Safari.app") { 470 $safariBundle = "$configurationProductDir/Safari.app"; 471 } elsif (isAppleWinWebKit() && -x "$configurationProductDir/bin/Safari.exe") { 472 $safariBundle = "$configurationProductDir/bin/Safari.exe"; 473 } else { 474 return installedSafariPath(); 475 } 476 } 477 my $safariPath = safariPathFromSafariBundle($safariBundle); 478 die "Can't find executable at $safariPath.\n" if isAppleMacWebKit() && !-x $safariPath; 479 return $safariPath; 480} 481 482sub builtDylibPathForName 483{ 484 my $libraryName = shift; 485 determineConfigurationProductDir(); 486 if (isQt() or isChromium()) { 487 return "$configurationProductDir/$libraryName"; 488 } 489 if (isWx()) { 490 return "$configurationProductDir/libwxwebkit.dylib"; 491 } 492 if (isGtk()) { 493 return "$configurationProductDir/$libraryName/../.libs/libwebkit-1.0.so"; 494 } 495 if (isAppleMacWebKit()) { 496 return "$configurationProductDir/$libraryName.framework/Versions/A/$libraryName"; 497 } 498 if (isAppleWinWebKit()) { 499 if ($libraryName eq "JavaScriptCore") { 500 return "$baseProductDir/lib/$libraryName.lib"; 501 } else { 502 return "$baseProductDir/$libraryName.intermediate/$configuration/$libraryName.intermediate/$libraryName.lib"; 503 } 504 } 505 506 die "Unsupported platform, can't determine built library locations."; 507} 508 509# Check to see that all the frameworks are built. 510sub checkFrameworks 511{ 512 return if isCygwin(); 513 my @frameworks = ("JavaScriptCore", "WebCore"); 514 push(@frameworks, "WebKit") if isAppleMacWebKit(); 515 for my $framework (@frameworks) { 516 my $path = builtDylibPathForName($framework); 517 die "Can't find built framework at \"$path\".\n" unless -x $path; 518 } 519} 520 521sub libraryContainsSymbol 522{ 523 my $path = shift; 524 my $symbol = shift; 525 526 if (isCygwin()) { 527 # FIXME: Implement this for Windows. 528 return 0; 529 } 530 531 my $foundSymbol = 0; 532 if (-e $path) { 533 open NM, "-|", "nm", $path or die; 534 while (<NM>) { 535 $foundSymbol = 1 if /$symbol/; 536 } 537 close NM; 538 } 539 return $foundSymbol; 540} 541 542sub hasSVGSupport 543{ 544 my $path = shift; 545 546 if (isQt()) { 547 return 1; 548 } 549 550 if (isWx()) { 551 return 0; 552 } 553 554 return libraryContainsSymbol($path, "SVGElement"); 555} 556 557sub removeLibraryDependingOnSVG 558{ 559 my $frameworkName = shift; 560 my $shouldHaveSVG = shift; 561 562 my $path = builtDylibPathForName($frameworkName); 563 return unless -x $path; 564 565 my $hasSVG = hasSVGSupport($path); 566 system "rm -f $path" if ($shouldHaveSVG xor $hasSVG); 567} 568 569sub checkWebCoreSVGSupport 570{ 571 my $required = shift; 572 my $framework = "WebCore"; 573 my $path = builtDylibPathForName($framework); 574 my $hasSVG = hasSVGSupport($path); 575 if ($required && !$hasSVG) { 576 die "$framework at \"$path\" does not include SVG Support, please run build-webkit --svg\n"; 577 } 578 return $hasSVG; 579} 580 581sub hasAcceleratedCompositingSupport 582{ 583 return 0 if isCygwin() || isQt(); 584 585 my $path = shift; 586 return libraryContainsSymbol($path, "GraphicsLayer"); 587} 588 589sub checkWebCoreAcceleratedCompositingSupport 590{ 591 my $required = shift; 592 my $framework = "WebCore"; 593 my $path = builtDylibPathForName($framework); 594 my $hasAcceleratedCompositing = hasAcceleratedCompositingSupport($path); 595 if ($required && !$hasAcceleratedCompositing) { 596 die "$framework at \"$path\" does not use accelerated compositing\n"; 597 } 598 return $hasAcceleratedCompositing; 599} 600 601sub has3DRenderingSupport 602{ 603 return 0 if isQt(); 604 605 my $path = shift; 606 return libraryContainsSymbol($path, "WebCoreHas3DRendering"); 607} 608 609sub checkWebCore3DRenderingSupport 610{ 611 my $required = shift; 612 my $framework = "WebCore"; 613 my $path = builtDylibPathForName($framework); 614 my $has3DRendering = has3DRenderingSupport($path); 615 if ($required && !$has3DRendering) { 616 die "$framework at \"$path\" does not include 3D rendering Support, please run build-webkit --3d-rendering\n"; 617 } 618 return $has3DRendering; 619} 620 621sub hasWMLSupport 622{ 623 my $path = shift; 624 return libraryContainsSymbol($path, "WMLElement"); 625} 626 627sub removeLibraryDependingOnWML 628{ 629 my $frameworkName = shift; 630 my $shouldHaveWML = shift; 631 632 my $path = builtDylibPathForName($frameworkName); 633 return unless -x $path; 634 635 my $hasWML = hasWMLSupport($path); 636 system "rm -f $path" if ($shouldHaveWML xor $hasWML); 637} 638 639sub checkWebCoreWMLSupport 640{ 641 my $required = shift; 642 my $framework = "WebCore"; 643 my $path = builtDylibPathForName($framework); 644 my $hasWML = hasWMLSupport($path); 645 if ($required && !$hasWML) { 646 die "$framework at \"$path\" does not include WML Support, please run build-webkit --wml\n"; 647 } 648 return $hasWML; 649} 650 651sub hasXHTMLMPSupport 652{ 653 my $path = shift; 654 return libraryContainsSymbol($path, "isXHTMLMPDocument"); 655} 656 657sub checkWebCoreXHTMLMPSupport 658{ 659 my $required = shift; 660 my $framework = "WebCore"; 661 my $path = builtDylibPathForName($framework); 662 my $hasXHTMLMP = hasXHTMLMPSupport($path); 663 if ($required && !$hasXHTMLMP) { 664 die "$framework at \"$path\" does not include XHTML MP Support\n"; 665 } 666 return $hasXHTMLMP; 667} 668 669sub hasWCSSSupport 670{ 671 # FIXME: When WCSS support is landed this should be updated to check for WCSS 672 # being enabled in a manner similar to how we check for XHTML MP above. 673 return 0; 674} 675 676sub checkWebCoreWCSSSupport 677{ 678 my $required = shift; 679 my $framework = "WebCore"; 680 my $path = builtDylibPathForName($framework); 681 my $hasWCSS = hasWCSSSupport($path); 682 if ($required && !$hasWCSS) { 683 die "$framework at \"$path\" does not include WCSS Support\n"; 684 } 685 return $hasWCSS; 686} 687 688sub isQt() 689{ 690 determineIsQt(); 691 return $isQt; 692} 693 694sub qtFeatureDefaults() 695{ 696 determineQtFeatureDefaults(); 697 return %qtFeatureDefaults; 698} 699 700sub determineQtFeatureDefaults() 701{ 702 return if %qtFeatureDefaults; 703 my $originalCwd = getcwd(); 704 chdir File::Spec->catfile(sourceDir(), "WebCore"); 705 my $defaults = `qmake CONFIG+=compute_defaults 2>&1`; 706 chdir $originalCwd; 707 708 while ($defaults =~ m/(\S*?)=(.*?)( |$)/gi) { 709 $qtFeatureDefaults{$1}=$2; 710 } 711} 712 713sub checkForArgumentAndRemoveFromARGV 714{ 715 my $argToCheck = shift; 716 foreach my $opt (@ARGV) { 717 if ($opt =~ /^$argToCheck$/i ) { 718 @ARGV = grep(!/^$argToCheck$/i, @ARGV); 719 return 1; 720 } 721 } 722 return 0; 723} 724 725sub determineIsQt() 726{ 727 return if defined($isQt); 728 729 # Allow override in case QTDIR is not set. 730 if (checkForArgumentAndRemoveFromARGV("--qt")) { 731 $isQt = 1; 732 return; 733 } 734 735 # The presence of QTDIR only means Qt if --gtk is not on the command-line 736 if (isGtk()) { 737 $isQt = 0; 738 return; 739 } 740 741 $isQt = defined($ENV{'QTDIR'}); 742} 743 744sub isGtk() 745{ 746 determineIsGtk(); 747 return $isGtk; 748} 749 750sub determineIsGtk() 751{ 752 return if defined($isGtk); 753 $isGtk = checkForArgumentAndRemoveFromARGV("--gtk"); 754} 755 756sub isWx() 757{ 758 determineIsWx(); 759 return $isWx; 760} 761 762sub determineIsWx() 763{ 764 return if defined($isWx); 765 $isWx = checkForArgumentAndRemoveFromARGV("--wx"); 766} 767 768sub getWxArgs() 769{ 770 if (!@wxArgs) { 771 @wxArgs = (""); 772 my $rawWxArgs = ""; 773 foreach my $opt (@ARGV) { 774 if ($opt =~ /^--wx-args/i ) { 775 @ARGV = grep(!/^--wx-args/i, @ARGV); 776 $rawWxArgs = $opt; 777 $rawWxArgs =~ s/--wx-args=//i; 778 } 779 } 780 @wxArgs = split(/,/, $rawWxArgs); 781 } 782 return @wxArgs; 783} 784 785# Determine if this is debian, ubuntu, linspire, or something similar. 786sub isDebianBased() 787{ 788 return -e "/etc/debian_version"; 789} 790 791sub isChromium() 792{ 793 determineIsChromium(); 794 return $isChromium; 795} 796 797sub determineIsChromium() 798{ 799 return if defined($isChromium); 800 $isChromium = checkForArgumentAndRemoveFromARGV("--chromium"); 801} 802 803sub isCygwin() 804{ 805 return ($^O eq "cygwin") || 0; 806} 807 808sub isDarwin() 809{ 810 return ($^O eq "darwin") || 0; 811} 812 813sub isAppleWebKit() 814{ 815 return !(isQt() or isGtk() or isWx() or isChromium()); 816} 817 818sub isAppleMacWebKit() 819{ 820 return isAppleWebKit() && isDarwin(); 821} 822 823sub isAppleWinWebKit() 824{ 825 return isAppleWebKit() && isCygwin(); 826} 827 828sub isPerianInstalled() 829{ 830 if (!isAppleWebKit()) { 831 return 0; 832 } 833 834 if (-d "/Library/QuickTime/Perian.component") { 835 return 1; 836 } 837 838 if (-d "$ENV{HOME}/Library/QuickTime/Perian.component") { 839 return 1; 840 } 841 842 return 0; 843} 844 845sub determineOSXVersion() 846{ 847 return if $osXVersion; 848 849 if (!isDarwin()) { 850 $osXVersion = -1; 851 return; 852 } 853 854 my $version = `sw_vers -productVersion`; 855 my @splitVersion = split(/\./, $version); 856 @splitVersion >= 2 or die "Invalid version $version"; 857 $osXVersion = { 858 "major" => $splitVersion[0], 859 "minor" => $splitVersion[1], 860 "subminor" => (defined($splitVersion[2]) ? $splitVersion[2] : 0), 861 }; 862} 863 864sub osXVersion() 865{ 866 determineOSXVersion(); 867 return $osXVersion; 868} 869 870sub isTiger() 871{ 872 return isDarwin() && osXVersion()->{"minor"} == 4; 873} 874 875sub isLeopard() 876{ 877 return isDarwin() && osXVersion()->{"minor"} == 5; 878} 879 880sub isSnowLeopard() 881{ 882 return isDarwin() && osXVersion()->{"minor"} == 6; 883} 884 885sub relativeScriptsDir() 886{ 887 my $scriptDir = File::Spec->catpath("", File::Spec->abs2rel(dirname($0), getcwd()), ""); 888 if ($scriptDir eq "") { 889 $scriptDir = "."; 890 } 891 return $scriptDir; 892} 893 894sub launcherPath() 895{ 896 my $relativeScriptsPath = relativeScriptsDir(); 897 if (isGtk() || isQt()) { 898 return "$relativeScriptsPath/run-launcher"; 899 } elsif (isAppleWebKit()) { 900 return "$relativeScriptsPath/run-safari"; 901 } 902} 903 904sub launcherName() 905{ 906 if (isGtk()) { 907 return "GtkLauncher"; 908 } elsif (isQt()) { 909 return "QtLauncher"; 910 } elsif (isAppleWebKit()) { 911 return "Safari"; 912 } 913} 914 915sub checkRequiredSystemConfig 916{ 917 if (isDarwin()) { 918 chomp(my $productVersion = `sw_vers -productVersion`); 919 if ($productVersion lt "10.4") { 920 print "*************************************************************\n"; 921 print "Mac OS X Version 10.4.0 or later is required to build WebKit.\n"; 922 print "You have " . $productVersion . ", thus the build will most likely fail.\n"; 923 print "*************************************************************\n"; 924 } 925 my $xcodeVersion = `xcodebuild -version`; 926 if ($xcodeVersion !~ /DevToolsCore-(\d+)/ || $1 < 747) { 927 print "*************************************************************\n"; 928 print "Xcode Version 2.3 or later is required to build WebKit.\n"; 929 print "You have an earlier version of Xcode, thus the build will\n"; 930 print "most likely fail. The latest Xcode is available from the web:\n"; 931 print "http://developer.apple.com/tools/xcode\n"; 932 print "*************************************************************\n"; 933 } 934 } elsif (isGtk() or isQt() or isWx()) { 935 my @cmds = qw(flex bison gperf); 936 my @missing = (); 937 foreach my $cmd (@cmds) { 938 if (not `$cmd --version`) { 939 push @missing, $cmd; 940 } 941 } 942 if (@missing) { 943 my $list = join ", ", @missing; 944 die "ERROR: $list missing but required to build WebKit.\n"; 945 } 946 } 947 # Win32 and other platforms may want to check for minimum config 948} 949 950sub setupCygwinEnv() 951{ 952 return if !isCygwin(); 953 return if $vcBuildPath; 954 955 my $programFilesPath = `cygpath "$ENV{'PROGRAMFILES'}"`; 956 chomp $programFilesPath; 957 $vcBuildPath = "$programFilesPath/Microsoft Visual Studio 8/Common7/IDE/devenv.com"; 958 if (-e $vcBuildPath) { 959 # Visual Studio is installed; we can use pdevenv to build. 960 $vcBuildPath = File::Spec->catfile(sourceDir(), qw(WebKitTools Scripts pdevenv)); 961 } else { 962 # Visual Studio not found, try VC++ Express 963 my $vsInstallDir; 964 if ($ENV{'VSINSTALLDIR'}) { 965 $vsInstallDir = $ENV{'VSINSTALLDIR'}; 966 } else { 967 $programFilesPath = $ENV{'PROGRAMFILES'} || "C:\\Program Files"; 968 $vsInstallDir = "$programFilesPath/Microsoft Visual Studio 8"; 969 } 970 $vsInstallDir = `cygpath "$vsInstallDir"`; 971 chomp $vsInstallDir; 972 $vcBuildPath = "$vsInstallDir/Common7/IDE/VCExpress.exe"; 973 if (! -e $vcBuildPath) { 974 print "*************************************************************\n"; 975 print "Cannot find '$vcBuildPath'\n"; 976 print "Please execute the file 'vcvars32.bat' from\n"; 977 print "'$programFilesPath\\Microsoft Visual Studio 8\\VC\\bin\\'\n"; 978 print "to setup the necessary environment variables.\n"; 979 print "*************************************************************\n"; 980 die; 981 } 982 } 983 984 my $qtSDKPath = "$programFilesPath/QuickTime SDK"; 985 if (0 && ! -e $qtSDKPath) { 986 print "*************************************************************\n"; 987 print "Cannot find '$qtSDKPath'\n"; 988 print "Please download the QuickTime SDK for Windows from\n"; 989 print "http://developer.apple.com/quicktime/download/\n"; 990 print "*************************************************************\n"; 991 die; 992 } 993 994 chomp($ENV{'WEBKITLIBRARIESDIR'} = `cygpath -wa "$sourceDir/WebKitLibraries/win"`) unless $ENV{'WEBKITLIBRARIESDIR'}; 995 996 $windowsTmpPath = `cygpath -w /tmp`; 997 chomp $windowsTmpPath; 998 print "Building results into: ", baseProductDir(), "\n"; 999 print "WEBKITOUTPUTDIR is set to: ", $ENV{"WEBKITOUTPUTDIR"}, "\n"; 1000 print "WEBKITLIBRARIESDIR is set to: ", $ENV{"WEBKITLIBRARIESDIR"}, "\n"; 1001} 1002 1003sub buildXCodeProject($$@) 1004{ 1005 my ($project, $clean, @extraOptions) = @_; 1006 1007 if ($clean) { 1008 push(@extraOptions, "-alltargets"); 1009 push(@extraOptions, "clean"); 1010 } 1011 1012 return system "xcodebuild", "-project", "$project.xcodeproj", @extraOptions; 1013} 1014 1015sub buildVisualStudioProject 1016{ 1017 my ($project, $clean) = @_; 1018 setupCygwinEnv(); 1019 1020 my $config = configurationForVisualStudio(); 1021 1022 chomp(my $winProjectPath = `cygpath -w "$project"`); 1023 1024 my $action = "/build"; 1025 if ($clean) { 1026 $action = "/clean"; 1027 } 1028 1029 my @command = ($vcBuildPath, $winProjectPath, $action, $config); 1030 1031 print join(" ", @command), "\n"; 1032 return system @command; 1033} 1034 1035sub retrieveQMakespecVar 1036{ 1037 my $mkspec = $_[0]; 1038 my $varname = $_[1]; 1039 1040 my $compiler = "unknown"; 1041 #print "retrieveMakespecVar " . $mkspec . ", " . $varname . "\n"; 1042 1043 local *SPEC; 1044 open SPEC, "<$mkspec" or return "make"; 1045 while (<SPEC>) { 1046 if ($_ =~ /\s*include\((.+)\)/) { 1047 # open the included mkspec 1048 my $oldcwd = getcwd(); 1049 (my $volume, my $directories, my $file) = File::Spec->splitpath($mkspec); 1050 my $newcwd = "$volume$directories"; 1051 chdir $newcwd if $newcwd; 1052 $compiler = retrieveQMakespecVar($1, $varname); 1053 chdir $oldcwd; 1054 } elsif ($_ =~ /$varname\s*=\s*([^\s]+)/) { 1055 $compiler = $1; 1056 last; 1057 } 1058 } 1059 close SPEC; 1060 return $compiler; 1061} 1062 1063sub qtMakeCommand($) 1064{ 1065 my ($qmakebin) = @_; 1066 chomp(my $mkspec = `$qmakebin -query QMAKE_MKSPECS`); 1067 $mkspec .= "/default"; 1068 my $compiler = retrieveQMakespecVar("$mkspec/qmake.conf", "QMAKE_CC"); 1069 1070 #print "default spec: " . $mkspec . "\n"; 1071 #print "compiler found: " . $compiler . "\n"; 1072 1073 if ($compiler eq "cl") { 1074 return "nmake"; 1075 } 1076 1077 return "make"; 1078} 1079 1080sub autotoolsFlag($$) 1081{ 1082 my ($flag, $feature) = @_; 1083 my $prefix = $flag ? "--enable" : "--disable"; 1084 1085 return $prefix . '-' . $feature; 1086} 1087 1088sub buildAutotoolsProject($@) 1089{ 1090 my ($clean, @buildParams) = @_; 1091 1092 my $make = 'make'; 1093 my $dir = productDir(); 1094 my $config = passedConfiguration() || configuration(); 1095 my $prefix = $ENV{"WebKitInstallationPrefix"}; 1096 1097 my @buildArgs = (); 1098 my $makeArgs = $ENV{"WebKitMakeArguments"} || ""; 1099 for my $i (0 .. $#buildParams) { 1100 my $opt = $buildParams[$i]; 1101 if ($opt =~ /^--makeargs=(.*)/i ) { 1102 $makeArgs = $makeArgs . " " . $1; 1103 } else { 1104 push @buildArgs, $opt; 1105 } 1106 } 1107 1108 push @buildArgs, "--prefix=" . $prefix if defined($prefix); 1109 1110 # check if configuration is Debug 1111 if ($config =~ m/debug/i) { 1112 push @buildArgs, "--enable-debug"; 1113 } else { 1114 push @buildArgs, "--disable-debug"; 1115 } 1116 1117 # Use rm to clean the build directory since distclean may miss files 1118 if ($clean && -d $dir) { 1119 system "rm", "-rf", "$dir"; 1120 } 1121 1122 if (! -d $dir) { 1123 system "mkdir", "-p", "$dir"; 1124 if (! -d $dir) { 1125 die "Failed to create build directory " . $dir; 1126 } 1127 } 1128 1129 chdir $dir or die "Failed to cd into " . $dir . "\n"; 1130 1131 my $result; 1132 if ($clean) { 1133 #$result = system $make, "distclean"; 1134 return 0; 1135 } 1136 1137 print "Calling configure in " . $dir . "\n\n"; 1138 print "Installation directory: $prefix\n" if(defined($prefix)); 1139 1140 # Make the path relative since it will appear in all -I compiler flags. 1141 # Long argument lists cause bizarre slowdowns in libtool. 1142 my $relSourceDir = File::Spec->abs2rel($sourceDir); 1143 $relSourceDir = "." if !$relSourceDir; 1144 1145 $result = system "$relSourceDir/autogen.sh", @buildArgs; 1146 if ($result ne 0) { 1147 die "Failed to setup build environment using 'autotools'!\n"; 1148 } 1149 1150 $result = system "$make $makeArgs"; 1151 if ($result ne 0) { 1152 die "\nFailed to build WebKit using '$make'!\n"; 1153 } 1154 1155 chdir ".." or die; 1156 return $result; 1157} 1158 1159sub buildQMakeProject($@) 1160{ 1161 my ($clean, @buildParams) = @_; 1162 1163 my @buildArgs = ("-r"); 1164 1165 my $qmakebin = "qmake"; # Allow override of the qmake binary from $PATH 1166 my $makeargs = ""; 1167 for my $i (0 .. $#buildParams) { 1168 my $opt = $buildParams[$i]; 1169 if ($opt =~ /^--qmake=(.*)/i ) { 1170 $qmakebin = $1; 1171 } elsif ($opt =~ /^--qmakearg=(.*)/i ) { 1172 push @buildArgs, $1; 1173 } elsif ($opt =~ /^--makeargs=(.*)/i ) { 1174 $makeargs = $1; 1175 } else { 1176 push @buildArgs, $opt; 1177 } 1178 } 1179 1180 my $make = qtMakeCommand($qmakebin); 1181 my $config = configuration(); 1182 my $prefix = $ENV{"WebKitInstallationPrefix"}; 1183 1184 push @buildArgs, "OUTPUT_DIR=" . baseProductDir() . "/$config"; 1185 push @buildArgs, sourceDir() . "/WebKit.pro"; 1186 if ($config =~ m/debug/i) { 1187 push @buildArgs, "CONFIG-=release"; 1188 push @buildArgs, "CONFIG+=debug"; 1189 } else { 1190 push @buildArgs, "CONFIG+=release"; 1191 my $passedConfig = passedConfiguration() || ""; 1192 if (!isDarwin() || $passedConfig =~ m/release/i) { 1193 push @buildArgs, "CONFIG-=debug"; 1194 } else { 1195 push @buildArgs, "CONFIG+=debug_and_release"; 1196 push @buildArgs, "CONFIG+=build_all"; 1197 } 1198 } 1199 1200 my $dir = baseProductDir(); 1201 if (! -d $dir) { 1202 system "mkdir", "-p", "$dir"; 1203 if (! -d $dir) { 1204 die "Failed to create product directory " . $dir; 1205 } 1206 } 1207 $dir = $dir . "/$config"; 1208 if (! -d $dir) { 1209 system "mkdir", "-p", "$dir"; 1210 if (! -d $dir) { 1211 die "Failed to create build directory " . $dir; 1212 } 1213 } 1214 1215 chdir $dir or die "Failed to cd into " . $dir . "\n"; 1216 1217 print "Calling '$qmakebin @buildArgs' in " . $dir . "\n\n"; 1218 print "Installation directory: $prefix\n" if(defined($prefix)); 1219 1220 my $result = system $qmakebin, @buildArgs; 1221 if ($result ne 0) { 1222 die "Failed to setup build environment using $qmakebin!\n"; 1223 } 1224 1225 if ($clean) { 1226 $result = system "$make $makeargs distclean"; 1227 } else { 1228 $result = system "$make $makeargs"; 1229 } 1230 1231 chdir ".." or die; 1232 return $result; 1233} 1234 1235sub buildQMakeQtProject($$@) 1236{ 1237 my ($project, $clean, @buildArgs) = @_; 1238 1239 return buildQMakeProject($clean, @buildArgs); 1240} 1241 1242sub buildGtkProject($$@) 1243{ 1244 my ($project, $clean, @buildArgs) = @_; 1245 1246 if ($project ne "WebKit") { 1247 die "The Gtk port builds JavaScriptCore, WebCore and WebKit in one shot! Only call it for 'WebKit'.\n"; 1248 } 1249 1250 return buildAutotoolsProject($clean, @buildArgs); 1251} 1252 1253sub setPathForRunningWebKitApp 1254{ 1255 my ($env) = @_; 1256 1257 return unless isAppleWinWebKit(); 1258 1259 $env->{PATH} = join(':', productDir(), dirname(installedSafariPath()), $env->{PATH} || ""); 1260} 1261 1262sub exitStatus($) 1263{ 1264 my ($returnvalue) = @_; 1265 if ($^O eq "MSWin32") { 1266 return $returnvalue >> 8; 1267 } 1268 return WEXITSTATUS($returnvalue); 1269} 1270 1271sub runSafari 1272{ 1273 my ($debugger) = @_; 1274 1275 if (isAppleMacWebKit()) { 1276 return system "$FindBin::Bin/gdb-safari", @ARGV if $debugger; 1277 1278 my $productDir = productDir(); 1279 print "Starting Safari with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n"; 1280 $ENV{DYLD_FRAMEWORK_PATH} = $productDir; 1281 $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES"; 1282 if (!isTiger() && architecture()) { 1283 return system "arch", "-" . architecture(), safariPath(), @ARGV; 1284 } else { 1285 return system safariPath(), @ARGV; 1286 } 1287 } 1288 1289 if (isAppleWinWebKit()) { 1290 my $script = "run-webkit-nightly.cmd"; 1291 my $result = system "cp", "$FindBin::Bin/$script", productDir(); 1292 return $result if $result; 1293 1294 my $cwd = getcwd(); 1295 chdir productDir(); 1296 1297 my $debuggerFlag = $debugger ? "/debugger" : ""; 1298 $result = system "cmd", "/c", "call $script $debuggerFlag"; 1299 chdir $cwd; 1300 return $result; 1301 } 1302 1303 return 1; 1304} 1305 13061; 1307