1 # Copyright (C) 2005, 2006, 2007, 2010, 2011, 2012 Apple Inc. All rights reserved. 2 # Copyright (C) 2009 Google Inc. All rights reserved. 3 # Copyright (C) 2011 Research In Motion Limited. All rights reserved. 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions 7 # are met: 8 # 9 # 1. Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # 2. Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 # its contributors may be used to endorse or promote products derived 16 # from this software without specific prior written permission. 17 # 18 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 # Module to share code to get to WebKit directories. 30 31 use strict; 32 use version; 33 use warnings; 34 use Config; 35 use Digest::MD5 qw(md5_hex); 36 use FindBin; 37 use File::Basename; 38 use File::Path qw(mkpath rmtree); 39 use File::Spec; 40 use File::stat; 41 use POSIX; 42 use VCSUtils; 43 44 BEGIN { 45 use Exporter (); 46 our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); 47 $VERSION = 1.00; 48 @ISA = qw(Exporter); 49 @EXPORT = qw( 50 &XcodeOptionString 51 &XcodeOptionStringNoConfig 52 &XcodeOptions 53 &baseProductDir 54 &chdirWebKit 55 &checkFrameworks 56 &cmakeBasedPortArguments 57 &cmakeBasedPortName 58 ¤tSVNRevision 59 &debugSafari 60 &nmPath 61 &passedConfiguration 62 &printHelpAndExitForRunAndDebugWebKitAppIfNeeded 63 &productDir 64 &runMacWebKitApp 65 &safariPath 66 &setConfiguration 67 USE_OPEN_COMMAND 68 ); 69 %EXPORT_TAGS = ( ); 70 @EXPORT_OK = (); 71 } 72 73 use constant USE_OPEN_COMMAND => 1; # Used in runMacWebKitApp(). 74 use constant INCLUDE_OPTIONS_FOR_DEBUGGING => 1; 75 76 our @EXPORT_OK; 77 78 my $architecture; 79 my $numberOfCPUs; 80 my $baseProductDir; 81 my @baseProductDirOption; 82 my $configuration; 83 my $xcodeSDK; 84 my $configurationForVisualStudio; 85 my $configurationProductDir; 86 my $sourceDir; 87 my $currentSVNRevision; 88 my $debugger; 89 my $nmPath; 90 my $osXVersion; 91 my $generateDsym; 92 my $isQt; 93 my $qmakebin = "qmake"; # Allow override of the qmake binary from $PATH 94 my $isGtk; 95 my $isWinCE; 96 my $isWinCairo; 97 my $isWx; 98 my $isEfl; 99 my @wxArgs; 100 my $isBlackBerry; 101 my $isChromium; 102 my $isChromiumAndroid; 103 my $isChromiumMacMake; 104 my $isChromiumNinja; 105 my $forceChromiumUpdate; 106 my $isInspectorFrontend; 107 my $isWK2; 108 my $shouldTargetWebProcess; 109 my $shouldUseXPCServiceForWebProcess; 110 my $shouldUseGuardMalloc; 111 my $xcodeVersion; 112 113 # Variables for Win32 support 114 my $vcBuildPath; 115 my $windowsSourceDir; 116 my $winVersion; 117 my $willUseVCExpressWhenBuilding = 0; 118 119 # Defined in VCSUtils. 120 sub exitStatus($); 121 122 sub determineSourceDir 123 { 124 return if $sourceDir; 125 $sourceDir = $FindBin::Bin; 126 $sourceDir =~ s|/Tools/Scripts/?$||; # Remove trailing '/' as we would die later 127 128 die "Could not find top level Blink directory using FindBin.\n" unless -d "$sourceDir/Tools"; 129 } 130 131 sub currentPerlPath() 132 { 133 my $thisPerl = $^X; 134 if ($^O ne 'VMS') { 135 $thisPerl .= $Config{_exe} unless $thisPerl =~ m/$Config{_exe}$/i; 136 } 137 return $thisPerl; 138 } 139 140 sub setQmakeBinaryPath($) 141 { 142 ($qmakebin) = @_; 143 } 144 145 # used for scripts which are stored in a non-standard location 146 sub setSourceDir($) 147 { 148 ($sourceDir) = @_; 149 } 150 151 sub determineXcodeVersion 152 { 153 return if defined $xcodeVersion; 154 my $xcodebuildVersionOutput = `xcodebuild -version`; 155 $xcodeVersion = ($xcodebuildVersionOutput =~ /Xcode ([0-9](\.[0-9]+)*)/) ? $1 : "3.0"; 156 } 157 158 sub readXcodeUserDefault($) 159 { 160 my ($unprefixedKey) = @_; 161 162 determineXcodeVersion(); 163 164 my $xcodeDefaultsDomain = (eval "v$xcodeVersion" lt v4) ? "com.apple.Xcode" : "com.apple.dt.Xcode"; 165 my $xcodeDefaultsPrefix = (eval "v$xcodeVersion" lt v4) ? "PBX" : "IDE"; 166 my $devnull = File::Spec->devnull(); 167 168 my $value = `defaults read $xcodeDefaultsDomain ${xcodeDefaultsPrefix}${unprefixedKey} 2> ${devnull}`; 169 return if $?; 170 171 chomp $value; 172 return $value; 173 } 174 175 sub determineBaseProductDir 176 { 177 return if defined $baseProductDir; 178 determineSourceDir(); 179 180 my $setSharedPrecompsDir; 181 $baseProductDir = $ENV{"WEBKITOUTPUTDIR"}; # FIXME: Switch to WEBKIT_OUTPUTDIR as part of https://bugs.webkit.org/show_bug.cgi?id=109472 182 183 if (!defined($baseProductDir) and isAppleMacWebKit()) { 184 # Silently remove ~/Library/Preferences/xcodebuild.plist which can 185 # cause build failure. The presence of 186 # ~/Library/Preferences/xcodebuild.plist can prevent xcodebuild from 187 # respecting global settings such as a custom build products directory 188 # (<rdar://problem/5585899>). 189 my $personalPlistFile = $ENV{HOME} . "/Library/Preferences/xcodebuild.plist"; 190 if (-e $personalPlistFile) { 191 unlink($personalPlistFile) || die "Could not delete $personalPlistFile: $!"; 192 } 193 194 determineXcodeVersion(); 195 196 if (eval "v$xcodeVersion" ge v4) { 197 my $buildLocationStyle = join '', readXcodeUserDefault("BuildLocationStyle"); 198 if ($buildLocationStyle eq "Custom") { 199 my $buildLocationType = join '', readXcodeUserDefault("CustomBuildLocationType"); 200 # FIXME: Read CustomBuildIntermediatesPath and set OBJROOT accordingly. 201 $baseProductDir = readXcodeUserDefault("CustomBuildProductsPath") if $buildLocationType eq "Absolute"; 202 } 203 204 # DeterminedByTargets corresponds to a setting of "Legacy" in Xcode. 205 # It is the only build location style for which SHARED_PRECOMPS_DIR is not 206 # overridden when building from within Xcode. 207 $setSharedPrecompsDir = 1 if $buildLocationStyle ne "DeterminedByTargets"; 208 } 209 210 if (!defined($baseProductDir)) { 211 $baseProductDir = join '', readXcodeUserDefault("ApplicationwideBuildSettings"); 212 $baseProductDir = $1 if $baseProductDir =~ /SYMROOT\s*=\s*\"(.*?)\";/s; 213 } 214 215 undef $baseProductDir unless $baseProductDir =~ /^\//; 216 } elsif (isChromium()) { 217 if (isLinux() || isChromiumAndroid() || isChromiumMacMake() || isChromiumNinja()) { 218 $baseProductDir = "$sourceDir/out"; 219 } elsif (isDarwin()) { 220 $baseProductDir = "$sourceDir/Source/WebKit/chromium/xcodebuild"; 221 } elsif (isWindows() || isCygwin()) { 222 $baseProductDir = "$sourceDir/Source/WebKit/chromium/build"; 223 } 224 } 225 226 if (!defined($baseProductDir)) { # Port-specific checks failed, use default 227 $baseProductDir = "$sourceDir/WebKitBuild"; 228 } 229 230 if (isBlackBerry()) { 231 my %archInfo = blackberryTargetArchitecture(); 232 $baseProductDir = "$baseProductDir/" . $archInfo{"cpuDir"}; 233 } 234 235 if (isGit() && isGitBranchBuild() && !isChromium()) { 236 my $branch = gitBranch(); 237 $baseProductDir = "$baseProductDir/$branch"; 238 } 239 240 if (isAppleMacWebKit()) { 241 $baseProductDir =~ s|^\Q$(SRCROOT)/..\E$|$sourceDir|; 242 $baseProductDir =~ s|^\Q$(SRCROOT)/../|$sourceDir/|; 243 $baseProductDir =~ s|^~/|$ENV{HOME}/|; 244 die "Can't handle Xcode product directory with a ~ in it.\n" if $baseProductDir =~ /~/; 245 die "Can't handle Xcode product directory with a variable in it.\n" if $baseProductDir =~ /\$/; 246 @baseProductDirOption = ("SYMROOT=$baseProductDir", "OBJROOT=$baseProductDir"); 247 push(@baseProductDirOption, "SHARED_PRECOMPS_DIR=${baseProductDir}/PrecompiledHeaders") if $setSharedPrecompsDir; 248 } 249 250 if (isCygwin()) { 251 my $dosBuildPath = `cygpath --windows \"$baseProductDir\"`; 252 chomp $dosBuildPath; 253 $ENV{"WEBKITOUTPUTDIR"} = $dosBuildPath; 254 $ENV{"WEBKIT_OUTPUTDIR"} = $dosBuildPath; 255 my $unixBuildPath = `cygpath --unix \"$baseProductDir\"`; 256 chomp $unixBuildPath; 257 $baseProductDir = $unixBuildPath; 258 } 259 } 260 261 sub setBaseProductDir($) 262 { 263 ($baseProductDir) = @_; 264 } 265 266 sub determineConfiguration 267 { 268 return if defined $configuration; 269 determineBaseProductDir(); 270 if (open CONFIGURATION, "$baseProductDir/Configuration") { 271 $configuration = <CONFIGURATION>; 272 close CONFIGURATION; 273 } 274 if ($configuration) { 275 chomp $configuration; 276 # compatibility for people who have old Configuration files 277 $configuration = "Release" if $configuration eq "Deployment"; 278 $configuration = "Debug" if $configuration eq "Development"; 279 } else { 280 $configuration = "Release"; 281 } 282 283 if ($configuration && isWinCairo()) { 284 unless ($configuration =~ /_Cairo_CFLite$/) { 285 $configuration .= "_Cairo_CFLite"; 286 } 287 } 288 } 289 290 sub determineArchitecture 291 { 292 return if defined $architecture; 293 # make sure $architecture is defined in all cases 294 $architecture = ""; 295 296 determineBaseProductDir(); 297 determineXcodeSDK(); 298 299 if (isGtk()) { 300 determineConfigurationProductDir(); 301 my $host_triple = `grep -E '^host = ' $configurationProductDir/GNUmakefile`; 302 if ($host_triple =~ m/^host = ([^-]+)-/) { 303 # We have a configured build tree; use it. 304 $architecture = $1; 305 } 306 } elsif (isAppleMacWebKit()) { 307 if (open ARCHITECTURE, "$baseProductDir/Architecture") { 308 $architecture = <ARCHITECTURE>; 309 close ARCHITECTURE; 310 } 311 if ($architecture) { 312 chomp $architecture; 313 } else { 314 if (not defined $xcodeSDK or $xcodeSDK =~ /^(\/$|macosx)/) { 315 my $supports64Bit = `sysctl -n hw.optional.x86_64`; 316 chomp $supports64Bit; 317 $architecture = 'x86_64' if $supports64Bit; 318 } elsif ($xcodeSDK =~ /^iphonesimulator/) { 319 $architecture = 'i386'; 320 } elsif ($xcodeSDK =~ /^iphoneos/) { 321 $architecture = 'armv7'; 322 } 323 } 324 } elsif (isEfl()) { 325 my $host_processor = ""; 326 $host_processor = `cmake --system-information | grep CMAKE_SYSTEM_PROCESSOR`; 327 if ($host_processor =~ m/^CMAKE_SYSTEM_PROCESSOR \"([^"]+)\"/) { 328 # We have a configured build tree; use it. 329 $architecture = $1; 330 $architecture = 'x86_64' if $architecture eq 'amd64'; 331 } 332 } 333 334 if (!$architecture && (isGtk() || isAppleMacWebKit() || isEfl())) { 335 # Fall back to output of `arch', if it is present. 336 $architecture = `arch`; 337 chomp $architecture; 338 } 339 340 if (!$architecture && (isGtk() || isAppleMacWebKit() || isEfl())) { 341 # Fall back to output of `uname -m', if it is present. 342 $architecture = `uname -m`; 343 chomp $architecture; 344 } 345 } 346 347 sub determineNumberOfCPUs 348 { 349 return if defined $numberOfCPUs; 350 if (defined($ENV{NUMBER_OF_PROCESSORS})) { 351 $numberOfCPUs = $ENV{NUMBER_OF_PROCESSORS}; 352 } elsif (isLinux()) { 353 # First try the nproc utility, if it exists. If we get no 354 # results fall back to just interpretting /proc directly. 355 chomp($numberOfCPUs = `nproc --all 2> /dev/null`); 356 if ($numberOfCPUs eq "") { 357 $numberOfCPUs = (grep /processor/, `cat /proc/cpuinfo`); 358 } 359 } elsif (isWindows() || isCygwin()) { 360 # Assumes cygwin 361 $numberOfCPUs = `ls /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor | wc -w`; 362 } elsif (isDarwin() || isFreeBSD()) { 363 chomp($numberOfCPUs = `sysctl -n hw.ncpu`); 364 } 365 } 366 367 sub jscPath($) 368 { 369 my ($productDir) = @_; 370 my $jscName = "jsc"; 371 $jscName .= "_debug" if configurationForVisualStudio() eq "Debug_All"; 372 $jscName .= ".exe" if (isWindows() || isCygwin()); 373 return "$productDir/$jscName" if -e "$productDir/$jscName"; 374 return "$productDir/JavaScriptCore.framework/Resources/$jscName"; 375 } 376 377 sub argumentsForConfiguration() 378 { 379 determineConfiguration(); 380 determineArchitecture(); 381 382 my @args = (); 383 push(@args, '--debug') if $configuration eq "Debug"; 384 push(@args, '--release') if $configuration eq "Release"; 385 push(@args, '--32-bit') if $architecture ne "x86_64"; 386 push(@args, '--qt') if isQt(); 387 push(@args, '--gtk') if isGtk(); 388 push(@args, '--efl') if isEfl(); 389 push(@args, '--wincairo') if isWinCairo(); 390 push(@args, '--wince') if isWinCE(); 391 push(@args, '--wx') if isWx(); 392 push(@args, '--blackberry') if isBlackBerry(); 393 push(@args, '--chromium') if isChromium() && !isChromiumAndroid(); 394 push(@args, '--chromium-android') if isChromiumAndroid(); 395 push(@args, '--inspector-frontend') if isInspectorFrontend(); 396 return @args; 397 } 398 399 sub determineXcodeSDK 400 { 401 return if defined $xcodeSDK; 402 for (my $i = 0; $i <= $#ARGV; $i++) { 403 my $opt = $ARGV[$i]; 404 if ($opt =~ /^--sdk$/i) { 405 splice(@ARGV, $i, 1); 406 $xcodeSDK = splice(@ARGV, $i, 1); 407 } elsif ($opt =~ /^--device$/i) { 408 splice(@ARGV, $i, 1); 409 $xcodeSDK = 'iphoneos.internal'; 410 } elsif ($opt =~ /^--sim(ulator)?/i) { 411 splice(@ARGV, $i, 1); 412 $xcodeSDK = 'iphonesimulator'; 413 } 414 } 415 } 416 417 sub xcodeSDK 418 { 419 determineXcodeSDK(); 420 return $xcodeSDK; 421 } 422 423 sub determineConfigurationForVisualStudio 424 { 425 return if defined $configurationForVisualStudio; 426 determineConfiguration(); 427 # FIXME: We should detect when Debug_All or Production has been chosen. 428 $configurationForVisualStudio = $configuration; 429 } 430 431 sub usesPerConfigurationBuildDirectory 432 { 433 # [Gtk] We don't have Release/Debug configurations in straight 434 # autotool builds (non build-webkit). In this case and if 435 # WEBKITOUTPUTDIR exist, use that as our configuration dir. This will 436 # allows us to run run-webkit-tests without using build-webkit. 437 return ($ENV{"WEBKITOUTPUTDIR"} && isGtk()) || isAppleWinWebKit(); 438 } 439 440 sub determineConfigurationProductDir 441 { 442 return if defined $configurationProductDir; 443 determineBaseProductDir(); 444 determineConfiguration(); 445 if (isAppleWinWebKit() && !isWx()) { 446 $configurationProductDir = File::Spec->catdir($baseProductDir, configurationForVisualStudio(), "bin"); 447 } else { 448 if (usesPerConfigurationBuildDirectory()) { 449 $configurationProductDir = "$baseProductDir"; 450 } else { 451 $configurationProductDir = "$baseProductDir/$configuration"; 452 } 453 } 454 } 455 456 sub setConfigurationProductDir($) 457 { 458 ($configurationProductDir) = @_; 459 } 460 461 sub determineCurrentSVNRevision 462 { 463 # We always update the current SVN revision here, and leave the caching 464 # to currentSVNRevision(), so that changes to the SVN revision while the 465 # script is running can be picked up by calling this function again. 466 determineSourceDir(); 467 $currentSVNRevision = svnRevisionForDirectory($sourceDir); 468 return $currentSVNRevision; 469 } 470 471 472 sub chdirWebKit 473 { 474 determineSourceDir(); 475 chdir $sourceDir or die; 476 } 477 478 sub baseProductDir 479 { 480 determineBaseProductDir(); 481 return $baseProductDir; 482 } 483 484 sub sourceDir 485 { 486 determineSourceDir(); 487 return $sourceDir; 488 } 489 490 sub productDir 491 { 492 determineConfigurationProductDir(); 493 return $configurationProductDir; 494 } 495 496 sub jscProductDir 497 { 498 my $productDir = productDir(); 499 $productDir .= "/bin" if (isQt() || isEfl()); 500 $productDir .= "/Programs" if isGtk(); 501 502 return $productDir; 503 } 504 505 sub configuration() 506 { 507 determineConfiguration(); 508 return $configuration; 509 } 510 511 sub configurationForVisualStudio() 512 { 513 determineConfigurationForVisualStudio(); 514 return $configurationForVisualStudio; 515 } 516 517 sub currentSVNRevision 518 { 519 determineCurrentSVNRevision() if not defined $currentSVNRevision; 520 return $currentSVNRevision; 521 } 522 523 sub generateDsym() 524 { 525 determineGenerateDsym(); 526 return $generateDsym; 527 } 528 529 sub determineGenerateDsym() 530 { 531 return if defined($generateDsym); 532 $generateDsym = checkForArgumentAndRemoveFromARGV("--dsym"); 533 } 534 535 sub argumentsForXcode() 536 { 537 my @args = (); 538 push @args, "DEBUG_INFORMATION_FORMAT=dwarf-with-dsym" if generateDsym(); 539 return @args; 540 } 541 542 sub XcodeOptions 543 { 544 determineBaseProductDir(); 545 determineConfiguration(); 546 determineArchitecture(); 547 determineXcodeSDK(); 548 549 my @sdkOption = ($xcodeSDK ? "SDKROOT=$xcodeSDK" : ()); 550 my @architectureOption = ($architecture ? "ARCHS=$architecture" : ()); 551 552 return (@baseProductDirOption, "-configuration", $configuration, @architectureOption, @sdkOption, argumentsForXcode()); 553 } 554 555 sub XcodeOptionString 556 { 557 return join " ", XcodeOptions(); 558 } 559 560 sub XcodeOptionStringNoConfig 561 { 562 return join " ", @baseProductDirOption; 563 } 564 565 sub XcodeCoverageSupportOptions() 566 { 567 my @coverageSupportOptions = (); 568 push @coverageSupportOptions, "GCC_GENERATE_TEST_COVERAGE_FILES=YES"; 569 push @coverageSupportOptions, "GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES"; 570 push @coverageSupportOptions, "EXTRA_LINK= \$(EXTRA_LINK) -ftest-coverage -fprofile-arcs"; 571 push @coverageSupportOptions, "OTHER_CFLAGS= \$(OTHER_CFLAGS) -DCOVERAGE -MD"; 572 push @coverageSupportOptions, "OTHER_LDFLAGS=\$(OTHER_LDFLAGS) -ftest-coverage -fprofile-arcs -lgcov"; 573 return @coverageSupportOptions; 574 } 575 576 my $passedConfiguration; 577 my $searchedForPassedConfiguration; 578 sub determinePassedConfiguration 579 { 580 return if $searchedForPassedConfiguration; 581 $searchedForPassedConfiguration = 1; 582 583 for my $i (0 .. $#ARGV) { 584 my $opt = $ARGV[$i]; 585 if ($opt =~ /^--debug$/i) { 586 splice(@ARGV, $i, 1); 587 $passedConfiguration = "Debug"; 588 $passedConfiguration .= "_Cairo_CFLite" if (isWinCairo() && isCygwin()); 589 return; 590 } 591 if ($opt =~ /^--release$/i) { 592 splice(@ARGV, $i, 1); 593 $passedConfiguration = "Release"; 594 $passedConfiguration .= "_Cairo_CFLite" if (isWinCairo() && isCygwin()); 595 return; 596 } 597 if ($opt =~ /^--profil(e|ing)$/i) { 598 splice(@ARGV, $i, 1); 599 $passedConfiguration = "Profiling"; 600 $passedConfiguration .= "_Cairo_CFLite" if (isWinCairo() && isCygwin()); 601 return; 602 } 603 } 604 $passedConfiguration = undef; 605 } 606 607 sub passedConfiguration 608 { 609 determinePassedConfiguration(); 610 return $passedConfiguration; 611 } 612 613 sub setConfiguration 614 { 615 setArchitecture(); 616 617 if (my $config = shift @_) { 618 $configuration = $config; 619 return; 620 } 621 622 determinePassedConfiguration(); 623 $configuration = $passedConfiguration if $passedConfiguration; 624 } 625 626 627 my $passedArchitecture; 628 my $searchedForPassedArchitecture; 629 sub determinePassedArchitecture 630 { 631 return if $searchedForPassedArchitecture; 632 $searchedForPassedArchitecture = 1; 633 634 for my $i (0 .. $#ARGV) { 635 my $opt = $ARGV[$i]; 636 if ($opt =~ /^--32-bit$/i) { 637 splice(@ARGV, $i, 1); 638 if (isAppleMacWebKit() || isWx()) { 639 $passedArchitecture = `arch`; 640 chomp $passedArchitecture; 641 } 642 return; 643 } 644 } 645 $passedArchitecture = undef; 646 } 647 648 sub passedArchitecture 649 { 650 determinePassedArchitecture(); 651 return $passedArchitecture; 652 } 653 654 sub architecture() 655 { 656 determineArchitecture(); 657 return $architecture; 658 } 659 660 sub numberOfCPUs() 661 { 662 determineNumberOfCPUs(); 663 return $numberOfCPUs; 664 } 665 666 sub setArchitecture 667 { 668 if (my $arch = shift @_) { 669 $architecture = $arch; 670 return; 671 } 672 673 determinePassedArchitecture(); 674 $architecture = $passedArchitecture if $passedArchitecture; 675 } 676 677 sub executableHasEntitlements 678 { 679 my $executablePath = shift; 680 return (`codesign -d --entitlements - $executablePath 2>&1` =~ /<key>/); 681 } 682 683 sub safariPathFromSafariBundle 684 { 685 my ($safariBundle) = @_; 686 687 if (isAppleMacWebKit()) { 688 my $safariPath = "$safariBundle/Contents/MacOS/Safari"; 689 my $safariForWebKitDevelopmentPath = "$safariBundle/Contents/MacOS/SafariForWebKitDevelopment"; 690 return $safariForWebKitDevelopmentPath if -f $safariForWebKitDevelopmentPath && executableHasEntitlements($safariPath); 691 return $safariPath; 692 } 693 return $safariBundle if isAppleWinWebKit(); 694 } 695 696 sub installedSafariPath 697 { 698 my $safariBundle; 699 700 if (isAppleMacWebKit()) { 701 $safariBundle = "/Applications/Safari.app"; 702 } elsif (isAppleWinWebKit()) { 703 $safariBundle = readRegistryString("/HKLM/SOFTWARE/Apple Computer, Inc./Safari/InstallDir"); 704 $safariBundle =~ s/[\r\n]+$//; 705 $safariBundle = `cygpath -u '$safariBundle'` if isCygwin(); 706 $safariBundle =~ s/[\r\n]+$//; 707 $safariBundle .= "Safari.exe"; 708 } 709 710 return safariPathFromSafariBundle($safariBundle); 711 } 712 713 # Locate Safari. 714 sub safariPath 715 { 716 # Use WEBKIT_SAFARI environment variable if present. 717 my $safariBundle = $ENV{WEBKIT_SAFARI}; 718 if (!$safariBundle) { 719 determineConfigurationProductDir(); 720 # Use Safari.app in product directory if present (good for Safari development team). 721 if (isAppleMacWebKit() && -d "$configurationProductDir/Safari.app") { 722 $safariBundle = "$configurationProductDir/Safari.app"; 723 } elsif (isAppleWinWebKit()) { 724 my $path = "$configurationProductDir/Safari.exe"; 725 my $debugPath = "$configurationProductDir/Safari_debug.exe"; 726 727 if (configurationForVisualStudio() eq "Debug_All" && -x $debugPath) { 728 $safariBundle = $debugPath; 729 } elsif (-x $path) { 730 $safariBundle = $path; 731 } 732 } 733 if (!$safariBundle) { 734 return installedSafariPath(); 735 } 736 } 737 my $safariPath = safariPathFromSafariBundle($safariBundle); 738 die "Can't find executable at $safariPath.\n" if isAppleMacWebKit() && !-x $safariPath; 739 return $safariPath; 740 } 741 742 sub builtDylibPathForName 743 { 744 my $libraryName = shift; 745 determineConfigurationProductDir(); 746 if (isChromium()) { 747 return "$configurationProductDir/$libraryName"; 748 } 749 if (isBlackBerry()) { 750 my $libraryExtension = $libraryName =~ /^WebKit$/i ? ".so" : ".a"; 751 return "$configurationProductDir/$libraryName/lib" . lc($libraryName) . $libraryExtension; 752 } 753 if (isQt()) { 754 my $isSearchingForWebCore = $libraryName =~ "WebCore"; 755 if (isDarwin()) { 756 $libraryName = "QtWebKitWidgets"; 757 } else { 758 $libraryName = "Qt5WebKitWidgets"; 759 } 760 my $result; 761 if (isDarwin() and -d "$configurationProductDir/lib/$libraryName.framework") { 762 $result = "$configurationProductDir/lib/$libraryName.framework/$libraryName"; 763 } elsif (isDarwin() and -d "$configurationProductDir/lib") { 764 $result = "$configurationProductDir/lib/lib$libraryName.dylib"; 765 } elsif (isWindows()) { 766 if (configuration() eq "Debug") { 767 # On Windows, there is a "d" suffix to the library name. See <http://trac.webkit.org/changeset/53924/>. 768 $libraryName .= "d"; 769 } 770 771 chomp(my $mkspec = `$qmakebin -query QT_HOST_DATA`); 772 $mkspec .= "/mkspecs"; 773 my $qtMajorVersion = retrieveQMakespecVar("$mkspec/qconfig.pri", "QT_MAJOR_VERSION"); 774 if (not $qtMajorVersion) { 775 $qtMajorVersion = ""; 776 } 777 778 $result = "$configurationProductDir/lib/$libraryName$qtMajorVersion.dll"; 779 } else { 780 $result = "$configurationProductDir/lib/lib$libraryName.so"; 781 } 782 783 if ($isSearchingForWebCore) { 784 # With CONFIG+=force_static_libs_as_shared we have a shared library for each subdir. 785 # For feature detection to work it is necessary to return the path of the WebCore library here. 786 my $replacedWithWebCore = $result; 787 $replacedWithWebCore =~ s/$libraryName/WebCore/g; 788 if (-e $replacedWithWebCore) { 789 return $replacedWithWebCore; 790 } 791 } 792 793 return $result; 794 } 795 if (isWx()) { 796 return "$configurationProductDir/libwxwebkit.dylib"; 797 } 798 if (isGtk()) { 799 # WebKitGTK+ for GTK2, WebKitGTK+ for GTK3, and WebKit2 respectively. 800 my @libraries = ("libwebkitgtk-1.0", "libwebkitgtk-3.0", "libwebkit2gtk-3.0"); 801 my $extension = isDarwin() ? ".dylib" : ".so"; 802 803 foreach $libraryName (@libraries) { 804 my $libraryPath = "$configurationProductDir/.libs/" . $libraryName . $extension; 805 return $libraryPath if -e $libraryPath; 806 } 807 return "NotFound"; 808 } 809 if (isEfl()) { 810 if (isWK2()) { 811 return "$configurationProductDir/lib/libewebkit2.so"; 812 } 813 return "$configurationProductDir/lib/libewebkit.so"; 814 } 815 if (isWinCE()) { 816 return "$configurationProductDir/$libraryName"; 817 } 818 if (isAppleMacWebKit()) { 819 return "$configurationProductDir/$libraryName.framework/Versions/A/$libraryName"; 820 } 821 if (isAppleWinWebKit()) { 822 if ($libraryName eq "JavaScriptCore") { 823 return "$baseProductDir/lib/$libraryName.lib"; 824 } else { 825 return "$baseProductDir/$libraryName.intermediate/$configuration/$libraryName.intermediate/$libraryName.lib"; 826 } 827 } 828 829 die "Unsupported platform, can't determine built library locations.\nTry `build-webkit --help` for more information.\n"; 830 } 831 832 # Check to see that all the frameworks are built. 833 sub checkFrameworks # FIXME: This is a poor name since only the Mac calls built WebCore a Framework. 834 { 835 return if isCygwin() || isWindows(); 836 my @frameworks = ("JavaScriptCore", "WebCore"); 837 push(@frameworks, "WebKit") if isAppleMacWebKit(); # FIXME: This seems wrong, all ports should have a WebKit these days. 838 for my $framework (@frameworks) { 839 my $path = builtDylibPathForName($framework); 840 die "Can't find built framework at \"$path\".\n" unless -e $path; 841 } 842 } 843 844 sub isInspectorFrontend() 845 { 846 determineIsInspectorFrontend(); 847 return $isInspectorFrontend; 848 } 849 850 sub determineIsInspectorFrontend() 851 { 852 return if defined($isInspectorFrontend); 853 $isInspectorFrontend = checkForArgumentAndRemoveFromARGV("--inspector-frontend"); 854 } 855 856 sub isQt() 857 { 858 determineIsQt(); 859 return $isQt; 860 } 861 862 sub getQtVersion() 863 { 864 my $qtVersion = `$qmakebin --version`; 865 $qtVersion =~ s/^(.*)Qt version (\d\.\d)(.*)/$2/s ; 866 return $qtVersion; 867 } 868 869 sub qtFeatureDefaults 870 { 871 die "ERROR: qmake missing but required to build WebKit.\n" if not commandExists($qmakebin); 872 873 my $oldQmakeEval = $ENV{QMAKE_CACHE_EVAL}; 874 $ENV{QMAKE_CACHE_EVAL} = "CONFIG+=print_defaults"; 875 876 my $originalCwd = getcwd(); 877 my $qmakepath = File::Spec->catfile(sourceDir(), "Tools", "qmake"); 878 chdir $qmakepath or die "Failed to cd into " . $qmakepath . "\n"; 879 880 my $file = File::Spec->catfile(sourceDir(), "WebKit.pro"); 881 882 my @buildArgs; 883 @buildArgs = (@buildArgs, @{$_[0]}) if (@_); 884 885 my @defaults = `$qmakebin @buildArgs $file 2>&1`; 886 887 my %qtFeatureDefaults; 888 for (@defaults) { 889 if (/DEFINES: /) { 890 while (/(\S+?)=(\S+?)/gi) { 891 $qtFeatureDefaults{$1}=$2; 892 } 893 } elsif (/Done computing defaults/) { 894 last; 895 } elsif (@_) { 896 print $_; 897 } 898 } 899 900 chdir $originalCwd; 901 $ENV{QMAKE_CACHE_EVAL} = $oldQmakeEval; 902 903 return %qtFeatureDefaults; 904 } 905 906 sub commandExists($) 907 { 908 my $command = shift; 909 my $devnull = File::Spec->devnull(); 910 return `$command --version 2> $devnull`; 911 } 912 913 sub checkForArgumentAndRemoveFromARGV 914 { 915 my $argToCheck = shift; 916 return checkForArgumentAndRemoveFromArrayRef($argToCheck, \@ARGV); 917 } 918 919 sub checkForArgumentAndRemoveFromArrayRef 920 { 921 my ($argToCheck, $arrayRef) = @_; 922 my @indicesToRemove; 923 foreach my $index (0 .. $#$arrayRef) { 924 my $opt = $$arrayRef[$index]; 925 if ($opt =~ /^$argToCheck$/i ) { 926 push(@indicesToRemove, $index); 927 } 928 } 929 foreach my $index (@indicesToRemove) { 930 splice(@$arrayRef, $index, 1); 931 } 932 return $#indicesToRemove > -1; 933 } 934 935 sub isWK2() 936 { 937 if (defined($isWK2)) { 938 return $isWK2; 939 } 940 if (checkForArgumentAndRemoveFromARGV("-2")) { 941 $isWK2 = 1; 942 } else { 943 $isWK2 = 0; 944 } 945 return $isWK2; 946 } 947 948 sub determineIsQt() 949 { 950 return if defined($isQt); 951 952 # Allow override in case QTDIR is not set. 953 if (checkForArgumentAndRemoveFromARGV("--qt")) { 954 $isQt = 1; 955 return; 956 } 957 958 # The presence of QTDIR only means Qt if --gtk or --wx or --efl or --blackberry or --chromium or --wincairo are not on the command-line 959 if (isGtk() || isWx() || isEfl() || isBlackBerry() || isChromium() || isWinCairo()) { 960 $isQt = 0; 961 return; 962 } 963 964 $isQt = defined($ENV{'QTDIR'}); 965 } 966 967 sub isBlackBerry() 968 { 969 determineIsBlackBerry(); 970 return $isBlackBerry; 971 } 972 973 sub determineIsBlackBerry() 974 { 975 return if defined($isBlackBerry); 976 $isBlackBerry = checkForArgumentAndRemoveFromARGV("--blackberry"); 977 } 978 979 sub blackberryTargetArchitecture() 980 { 981 my $arch = $ENV{"BLACKBERRY_ARCH_TYPE"} ? $ENV{"BLACKBERRY_ARCH_TYPE"} : "arm"; 982 my $cpu = $ENV{"BLACKBERRY_ARCH_CPU"} ? $ENV{"BLACKBERRY_ARCH_CPU"} : ""; 983 my $cpuDir; 984 my $buSuffix; 985 if (($cpu eq "v7le") || ($cpu eq "a9")) { 986 $cpuDir = $arch . "le-v7"; 987 $buSuffix = $arch . "v7"; 988 } else { 989 $cpu = $arch; 990 $cpuDir = $arch; 991 $buSuffix = $arch; 992 } 993 return ("arch" => $arch, 994 "cpu" => $cpu, 995 "cpuDir" => $cpuDir, 996 "buSuffix" => $buSuffix); 997 } 998 999 sub blackberryCMakeArguments() 1000 { 1001 my %archInfo = blackberryTargetArchitecture(); 1002 my $arch = $archInfo{"arch"}; 1003 my $cpu = $archInfo{"cpu"}; 1004 my $cpuDir = $archInfo{"cpuDir"}; 1005 my $buSuffix = $archInfo{"buSuffix"}; 1006 1007 my @cmakeExtraOptions; 1008 if ($cpu eq "a9") { 1009 $cpu = $arch . "v7le"; 1010 push @cmakeExtraOptions, '-DTARGETING_PLAYBOOK=1'; 1011 } 1012 1013 my $stageDir = $ENV{"STAGE_DIR"}; 1014 my $stageLib = File::Spec->catdir($stageDir, $cpuDir, "lib"); 1015 my $stageUsrLib = File::Spec->catdir($stageDir, $cpuDir, "usr", "lib"); 1016 my $stageInc = File::Spec->catdir($stageDir, "usr", "include"); 1017 1018 my $qnxHost = $ENV{"QNX_HOST"}; 1019 my $ccCommand; 1020 my $cxxCommand; 1021 if ($ENV{"USE_ICECC"}) { 1022 chomp($ccCommand = `which icecc`); 1023 $cxxCommand = $ccCommand; 1024 } else { 1025 $ccCommand = File::Spec->catfile($qnxHost, "usr", "bin", "qcc"); 1026 $cxxCommand = $ccCommand; 1027 } 1028 1029 if ($ENV{"CCWRAP"}) { 1030 $ccCommand = $ENV{"CCWRAP"}; 1031 push @cmakeExtraOptions, "-DCMAKE_C_COMPILER_ARG1=qcc"; 1032 push @cmakeExtraOptions, "-DCMAKE_CXX_COMPILER_ARG1=qcc"; 1033 } 1034 1035 push @cmakeExtraOptions, "-DCMAKE_SKIP_RPATH='ON'" if isDarwin(); 1036 push @cmakeExtraOptions, "-DPUBLIC_BUILD=1" if $ENV{"PUBLIC_BUILD"}; 1037 push @cmakeExtraOptions, "-DENABLE_GLES2=1" unless $ENV{"DISABLE_GLES2"}; 1038 1039 my @includeSystemDirectories; 1040 push @includeSystemDirectories, File::Spec->catdir($stageInc, "grskia", "skia"); 1041 push @includeSystemDirectories, File::Spec->catdir($stageInc, "grskia"); 1042 push @includeSystemDirectories, File::Spec->catdir($stageInc, "harfbuzz"); 1043 push @includeSystemDirectories, File::Spec->catdir($stageInc, "imf"); 1044 # We only use jpeg-turbo for device build 1045 push @includeSystemDirectories, File::Spec->catdir($stageInc, "jpeg-turbo") if $arch=~/arm/; 1046 push @includeSystemDirectories, $stageInc; 1047 push @includeSystemDirectories, File::Spec->catdir($stageInc, "browser", "platform"); 1048 push @includeSystemDirectories, File::Spec->catdir($stageInc, "browser", "platform", "graphics"); 1049 push @includeSystemDirectories, File::Spec->catdir($stageInc, "browser", "qsk"); 1050 push @includeSystemDirectories, File::Spec->catdir($stageInc, "ots"); 1051 1052 my @cxxFlags; 1053 push @cxxFlags, "-Wl,-rpath-link,$stageLib"; 1054 push @cxxFlags, "-Wl,-rpath-link," . File::Spec->catfile($stageUsrLib, "torch-webkit"); 1055 push @cxxFlags, "-Wl,-rpath-link,$stageUsrLib"; 1056 push @cxxFlags, "-L$stageLib"; 1057 push @cxxFlags, "-L$stageUsrLib"; 1058 1059 if ($ENV{"PROFILE"}) { 1060 push @cmakeExtraOptions, "-DPROFILING=1"; 1061 push @cxxFlags, "-p"; 1062 } 1063 1064 my @cmakeArgs; 1065 push @cmakeArgs, '-DCMAKE_SYSTEM_NAME="QNX"'; 1066 push @cmakeArgs, "-DCMAKE_SYSTEM_PROCESSOR=\"$cpuDir\""; 1067 push @cmakeArgs, '-DCMAKE_SYSTEM_VERSION="1"'; 1068 push @cmakeArgs, "-DCMAKE_C_COMPILER=\"$ccCommand\""; 1069 push @cmakeArgs, "-DCMAKE_CXX_COMPILER=\"$cxxCommand\""; 1070 push @cmakeArgs, "-DCMAKE_C_FLAGS=\"-Vgcc_nto${cpu} -g @cxxFlags\""; 1071 push @cmakeArgs, "-DCMAKE_CXX_FLAGS=\"-Vgcc_nto${cpu}_cpp-ne -g -lang-c++ @cxxFlags\""; 1072 1073 # We cannot use CMAKE_INCLUDE_PATH since this describes the search path for header files in user directories. 1074 # And the QNX system headers are in user directories on the host OS (i.e. they aren't installed in the host OS's 1075 # system header search path). So, we need to inform g++ that these user directories (@includeSystemDirectories) 1076 # are to be taken as the host OS's system header directories when building our port. 1077 # 1078 # Also, we cannot use CMAKE_SYSTEM_INCLUDE_PATH since that will override the entire system header path. 1079 # So, we define the additional system include paths in ADDITIONAL_SYSTEM_INCLUDE_PATH. This list will 1080 # be processed in OptionsBlackBerry.cmake. 1081 push @cmakeArgs, '-DADDITIONAL_SYSTEM_INCLUDE_PATH="' . join(';', @includeSystemDirectories) . '"'; 1082 1083 # FIXME: Make this more general purpose such that we can pass a list of directories and files. 1084 push @cmakeArgs, '-DTHIRD_PARTY_ICU_DIR="' . File::Spec->catdir($stageInc, "unicode") . '"'; 1085 push @cmakeArgs, '-DTHIRD_PARTY_UNICODE_FILE="' . File::Spec->catfile($stageInc, "unicode.h") . '"'; 1086 1087 push @cmakeArgs, "-DCMAKE_LIBRARY_PATH=\"$stageLib;$stageUsrLib\""; 1088 push @cmakeArgs, '-DCMAKE_AR="' . File::Spec->catfile($qnxHost, "usr", "bin", "nto${buSuffix}-ar") . '"'; 1089 push @cmakeArgs, '-DCMAKE_RANLIB="' . File::Spec->catfile($qnxHost, "usr", "bin", "nto${buSuffix}-ranlib") . '"'; 1090 push @cmakeArgs, '-DCMAKE_LD="'. File::Spec->catfile($qnxHost, "usr", "bin", "nto${buSuffix}-ld") . '"'; 1091 push @cmakeArgs, '-DCMAKE_LINKER="' . File::Spec->catfile($qnxHost, "usr", "bin", "nto${buSuffix}-ld") . '"'; 1092 push @cmakeArgs, "-DECLIPSE_CDT4_GENERATE_SOURCE_PROJECT=TRUE"; 1093 push @cmakeArgs, '-G"Eclipse CDT4 - Unix Makefiles"'; 1094 push @cmakeArgs, @cmakeExtraOptions; 1095 return @cmakeArgs; 1096 } 1097 1098 sub determineIsEfl() 1099 { 1100 return if defined($isEfl); 1101 $isEfl = checkForArgumentAndRemoveFromARGV("--efl"); 1102 } 1103 1104 sub isEfl() 1105 { 1106 determineIsEfl(); 1107 return $isEfl; 1108 } 1109 1110 sub isGtk() 1111 { 1112 determineIsGtk(); 1113 return $isGtk; 1114 } 1115 1116 sub determineIsGtk() 1117 { 1118 return if defined($isGtk); 1119 $isGtk = checkForArgumentAndRemoveFromARGV("--gtk"); 1120 } 1121 1122 sub isWinCE() 1123 { 1124 determineIsWinCE(); 1125 return $isWinCE; 1126 } 1127 1128 sub determineIsWinCE() 1129 { 1130 return if defined($isWinCE); 1131 $isWinCE = checkForArgumentAndRemoveFromARGV("--wince"); 1132 } 1133 1134 sub isWx() 1135 { 1136 determineIsWx(); 1137 return $isWx; 1138 } 1139 1140 sub determineIsWx() 1141 { 1142 return if defined($isWx); 1143 $isWx = checkForArgumentAndRemoveFromARGV("--wx"); 1144 } 1145 1146 sub getWxArgs() 1147 { 1148 if (!@wxArgs) { 1149 @wxArgs = (""); 1150 my $rawWxArgs = ""; 1151 foreach my $opt (@ARGV) { 1152 if ($opt =~ /^--wx-args/i ) { 1153 @ARGV = grep(!/^--wx-args/i, @ARGV); 1154 $rawWxArgs = $opt; 1155 $rawWxArgs =~ s/--wx-args=//i; 1156 } 1157 } 1158 @wxArgs = split(/,/, $rawWxArgs); 1159 } 1160 return @wxArgs; 1161 } 1162 1163 # Determine if this is debian, ubuntu, linspire, or something similar. 1164 sub isDebianBased() 1165 { 1166 return -e "/etc/debian_version"; 1167 } 1168 1169 sub isFedoraBased() 1170 { 1171 return -e "/etc/fedora-release"; 1172 } 1173 1174 sub isChromium() 1175 { 1176 determineIsChromium(); 1177 determineIsChromiumAndroid(); 1178 return $isChromium || $isChromiumAndroid; 1179 } 1180 1181 sub determineIsChromium() 1182 { 1183 return if defined($isChromium); 1184 $isChromium = checkForArgumentAndRemoveFromARGV("--chromium"); 1185 if ($isChromium) { 1186 $forceChromiumUpdate = checkForArgumentAndRemoveFromARGV("--force-update"); 1187 } 1188 } 1189 1190 sub isChromiumAndroid() 1191 { 1192 determineIsChromiumAndroid(); 1193 return $isChromiumAndroid; 1194 } 1195 1196 sub determineIsChromiumAndroid() 1197 { 1198 return if defined($isChromiumAndroid); 1199 $isChromiumAndroid = checkForArgumentAndRemoveFromARGV("--chromium-android"); 1200 } 1201 1202 sub isChromiumMacMake() 1203 { 1204 determineIsChromiumMacMake(); 1205 return $isChromiumMacMake; 1206 } 1207 1208 sub determineIsChromiumMacMake() 1209 { 1210 return if defined($isChromiumMacMake); 1211 1212 my $hasUpToDateMakefile = 0; 1213 if (-e 'Makefile.chromium') { 1214 unless (-e 'Source/WebKit/chromium/WebKit.xcodeproj') { 1215 $hasUpToDateMakefile = 1; 1216 } else { 1217 $hasUpToDateMakefile = stat('Makefile.chromium')->mtime > stat('Source/WebKit/chromium/WebKit.xcodeproj')->mtime; 1218 } 1219 } 1220 $isChromiumMacMake = isDarwin() && $hasUpToDateMakefile; 1221 } 1222 1223 sub isChromiumNinja() 1224 { 1225 determineIsChromiumNinja(); 1226 return $isChromiumNinja; 1227 } 1228 1229 sub determineIsChromiumNinja() 1230 { 1231 return if defined($isChromiumNinja); 1232 1233 # This function can be called from baseProductDir(), which in turn is 1234 # called by configuration(). So calling configuration() here leads to 1235 # infinite recursion. Gyp writes both Debug and Release at the same time 1236 # by default, so just check the timestamp on the Release build.ninja file. 1237 my $config = "Release"; 1238 1239 my $hasUpToDateNinjabuild = 0; 1240 if (-e "out/$config/build.ninja") { 1241 my $statNinja = stat("out/$config/build.ninja")->mtime; 1242 1243 my $statXcode = 0; 1244 if (-e 'Source/WebKit/chromium/WebKit.xcodeproj') { 1245 $statXcode = stat('Source/WebKit/chromium/WebKit.xcodeproj')->mtime; 1246 } 1247 1248 my $statMake = 0; 1249 if (-e 'Makefile.chromium') { 1250 $statMake = stat('Makefile.chromium')->mtime; 1251 } 1252 1253 my $statVisualStudio = 0; 1254 if (-e 'Source/WebKit/chromium/webkit.vcxproj') { 1255 $statVisualStudio = stat('Source/WebKit/chromium/webkit.vcxproj')->mtime; 1256 } 1257 1258 $hasUpToDateNinjabuild = $statNinja > $statXcode && $statNinja > $statMake && $statNinja > $statVisualStudio; 1259 } 1260 $isChromiumNinja = $hasUpToDateNinjabuild; 1261 } 1262 1263 sub forceChromiumUpdate() 1264 { 1265 determineIsChromium(); 1266 return $forceChromiumUpdate; 1267 } 1268 1269 sub isWinCairo() 1270 { 1271 determineIsWinCairo(); 1272 return $isWinCairo; 1273 } 1274 1275 sub determineIsWinCairo() 1276 { 1277 return if defined($isWinCairo); 1278 $isWinCairo = checkForArgumentAndRemoveFromARGV("--wincairo"); 1279 } 1280 1281 sub isCygwin() 1282 { 1283 return ($^O eq "cygwin") || 0; 1284 } 1285 1286 sub isAnyWindows() 1287 { 1288 return isWindows() || isCygwin(); 1289 } 1290 1291 sub determineWinVersion() 1292 { 1293 return if $winVersion; 1294 1295 if (!isAnyWindows()) { 1296 $winVersion = -1; 1297 return; 1298 } 1299 1300 my $versionString = `cmd /c ver`; 1301 $versionString =~ /(\d)\.(\d)\.(\d+)/; 1302 1303 $winVersion = { 1304 major => $1, 1305 minor => $2, 1306 build => $3, 1307 }; 1308 } 1309 1310 sub winVersion() 1311 { 1312 determineWinVersion(); 1313 return $winVersion; 1314 } 1315 1316 sub isWindows7SP0() 1317 { 1318 return isAnyWindows() && winVersion()->{major} == 6 && winVersion()->{minor} == 1 && winVersion()->{build} == 7600; 1319 } 1320 1321 sub isWindowsVista() 1322 { 1323 return isAnyWindows() && winVersion()->{major} == 6 && winVersion()->{minor} == 0; 1324 } 1325 1326 sub isWindowsXP() 1327 { 1328 return isAnyWindows() && winVersion()->{major} == 5 && winVersion()->{minor} == 1; 1329 } 1330 1331 sub isDarwin() 1332 { 1333 return ($^O eq "darwin") || 0; 1334 } 1335 1336 sub isWindows() 1337 { 1338 return ($^O eq "MSWin32") || 0; 1339 } 1340 1341 sub isLinux() 1342 { 1343 return ($^O eq "linux") || 0; 1344 } 1345 1346 sub isFreeBSD() 1347 { 1348 return ($^O eq "freebsd") || 0; 1349 } 1350 1351 sub isARM() 1352 { 1353 return $Config{archname} =~ /^arm[v\-]/; 1354 } 1355 1356 sub isCrossCompilation() 1357 { 1358 my $compiler = ""; 1359 $compiler = $ENV{'CC'} if (defined($ENV{'CC'})); 1360 if ($compiler =~ /gcc/) { 1361 my $compiler_options = `$compiler -v 2>&1`; 1362 my @host = $compiler_options =~ m/--host=(.*?)\s/; 1363 my @target = $compiler_options =~ m/--target=(.*?)\s/; 1364 1365 return ($host[0] ne "" && $target[0] ne "" && $host[0] ne $target[0]); 1366 } 1367 return 0; 1368 } 1369 1370 sub isAppleWebKit() 1371 { 1372 return !(isQt() or isGtk() or isWx() or isChromium() or isEfl() or isWinCE() or isBlackBerry()); 1373 } 1374 1375 sub isAppleMacWebKit() 1376 { 1377 return isAppleWebKit() && isDarwin(); 1378 } 1379 1380 sub isAppleWinWebKit() 1381 { 1382 return isAppleWebKit() && (isCygwin() || isWindows()); 1383 } 1384 1385 sub isPerianInstalled() 1386 { 1387 if (!isAppleWebKit()) { 1388 return 0; 1389 } 1390 1391 if (-d "/Library/QuickTime/Perian.component") { 1392 return 1; 1393 } 1394 1395 if (-d "$ENV{HOME}/Library/QuickTime/Perian.component") { 1396 return 1; 1397 } 1398 1399 return 0; 1400 } 1401 1402 sub determineNmPath() 1403 { 1404 return if $nmPath; 1405 1406 if (isAppleMacWebKit()) { 1407 $nmPath = `xcrun -find nm`; 1408 chomp $nmPath; 1409 } 1410 $nmPath = "nm" if !$nmPath; 1411 } 1412 1413 sub nmPath() 1414 { 1415 determineNmPath(); 1416 return $nmPath; 1417 } 1418 1419 sub determineOSXVersion() 1420 { 1421 return if $osXVersion; 1422 1423 if (!isDarwin()) { 1424 $osXVersion = -1; 1425 return; 1426 } 1427 1428 my $version = `sw_vers -productVersion`; 1429 my @splitVersion = split(/\./, $version); 1430 @splitVersion >= 2 or die "Invalid version $version"; 1431 $osXVersion = { 1432 "major" => $splitVersion[0], 1433 "minor" => $splitVersion[1], 1434 "subminor" => (defined($splitVersion[2]) ? $splitVersion[2] : 0), 1435 }; 1436 } 1437 1438 sub osXVersion() 1439 { 1440 determineOSXVersion(); 1441 return $osXVersion; 1442 } 1443 1444 sub isSnowLeopard() 1445 { 1446 return isDarwin() && osXVersion()->{"minor"} == 6; 1447 } 1448 1449 sub isLion() 1450 { 1451 return isDarwin() && osXVersion()->{"minor"} == 7; 1452 } 1453 1454 sub isWindowsNT() 1455 { 1456 return $ENV{'OS'} eq 'Windows_NT'; 1457 } 1458 1459 sub shouldTargetWebProcess 1460 { 1461 determineShouldTargetWebProcess(); 1462 return $shouldTargetWebProcess; 1463 } 1464 1465 sub determineShouldTargetWebProcess 1466 { 1467 return if defined($shouldTargetWebProcess); 1468 $shouldTargetWebProcess = checkForArgumentAndRemoveFromARGV("--target-web-process"); 1469 } 1470 1471 sub shouldUseXPCServiceForWebProcess 1472 { 1473 determineShouldUseXPCServiceForWebProcess(); 1474 return $shouldUseXPCServiceForWebProcess; 1475 } 1476 1477 sub determineShouldUseXPCServiceForWebProcess 1478 { 1479 return if defined($shouldUseXPCServiceForWebProcess); 1480 $shouldUseXPCServiceForWebProcess = checkForArgumentAndRemoveFromARGV("--use-web-process-xpc-service"); 1481 } 1482 1483 sub debugger 1484 { 1485 determineDebugger(); 1486 return $debugger; 1487 } 1488 1489 sub determineDebugger 1490 { 1491 return if defined($debugger); 1492 1493 determineXcodeVersion(); 1494 if (eval "v$xcodeVersion" ge v4.5) { 1495 $debugger = "lldb"; 1496 } else { 1497 $debugger = "gdb"; 1498 } 1499 1500 if (checkForArgumentAndRemoveFromARGV("--use-lldb")) { 1501 $debugger = "lldb"; 1502 } 1503 1504 if (checkForArgumentAndRemoveFromARGV("--use-gdb")) { 1505 $debugger = "gdb"; 1506 } 1507 } 1508 1509 sub appendToEnvironmentVariableList 1510 { 1511 my ($environmentVariableName, $value) = @_; 1512 1513 if (defined($ENV{$environmentVariableName})) { 1514 $ENV{$environmentVariableName} .= ":" . $value; 1515 } else { 1516 $ENV{$environmentVariableName} = $value; 1517 } 1518 } 1519 1520 sub setUpGuardMallocIfNeeded 1521 { 1522 if (!isDarwin()) { 1523 return; 1524 } 1525 1526 if (!defined($shouldUseGuardMalloc)) { 1527 $shouldUseGuardMalloc = checkForArgumentAndRemoveFromARGV("--guard-malloc"); 1528 } 1529 1530 if ($shouldUseGuardMalloc) { 1531 appendToEnvironmentVariableList("DYLD_INSERT_LIBRARIES", "/usr/lib/libgmalloc.dylib"); 1532 } 1533 } 1534 1535 sub relativeScriptsDir() 1536 { 1537 my $scriptDir = File::Spec->catpath("", File::Spec->abs2rel($FindBin::Bin, getcwd()), ""); 1538 if ($scriptDir eq "") { 1539 $scriptDir = "."; 1540 } 1541 return $scriptDir; 1542 } 1543 1544 sub launcherPath() 1545 { 1546 my $relativeScriptsPath = relativeScriptsDir(); 1547 if (isGtk() || isQt() || isWx() || isEfl() || isWinCE()) { 1548 return "$relativeScriptsPath/run-launcher"; 1549 } elsif (isAppleWebKit()) { 1550 return "$relativeScriptsPath/run-safari"; 1551 } 1552 } 1553 1554 sub launcherName() 1555 { 1556 if (isGtk()) { 1557 return "GtkLauncher"; 1558 } elsif (isQt()) { 1559 return "QtTestBrowser"; 1560 } elsif (isWx()) { 1561 return "wxBrowser"; 1562 } elsif (isAppleWebKit()) { 1563 return "Safari"; 1564 } elsif (isEfl()) { 1565 return "EWebLauncher/MiniBrowser"; 1566 } elsif (isWinCE()) { 1567 return "WinCELauncher"; 1568 } 1569 } 1570 1571 sub checkRequiredSystemConfig 1572 { 1573 if (isDarwin()) { 1574 chomp(my $productVersion = `sw_vers -productVersion`); 1575 if (eval "v$productVersion" lt v10.4) { 1576 print "*************************************************************\n"; 1577 print "Mac OS X Version 10.4.0 or later is required to build WebKit.\n"; 1578 print "You have " . $productVersion . ", thus the build will most likely fail.\n"; 1579 print "*************************************************************\n"; 1580 } 1581 my $xcodebuildVersionOutput = `xcodebuild -version`; 1582 my $devToolsCoreVersion = ($xcodebuildVersionOutput =~ /DevToolsCore-(\d+)/) ? $1 : undef; 1583 my $xcodeVersion = ($xcodebuildVersionOutput =~ /Xcode ([0-9](\.[0-9]+)*)/) ? $1 : undef; 1584 if (!$devToolsCoreVersion && !$xcodeVersion 1585 || $devToolsCoreVersion && $devToolsCoreVersion < 747 1586 || $xcodeVersion && eval "v$xcodeVersion" lt v2.3) { 1587 print "*************************************************************\n"; 1588 print "Xcode Version 2.3 or later is required to build WebKit.\n"; 1589 print "You have an earlier version of Xcode, thus the build will\n"; 1590 print "most likely fail. The latest Xcode is available from the web:\n"; 1591 print "http://developer.apple.com/tools/xcode\n"; 1592 print "*************************************************************\n"; 1593 } 1594 } elsif (isGtk() or isQt() or isWx() or isEfl()) { 1595 my @cmds = qw(bison gperf); 1596 if (isQt() and isWindows()) { 1597 push @cmds, "win_flex"; 1598 } else { 1599 push @cmds, "flex"; 1600 } 1601 my @missing = (); 1602 my $oldPath = $ENV{PATH}; 1603 if (isQt() and isWindows()) { 1604 chomp(my $gnuWin32Dir = `$qmakebin -query QT_HOST_DATA`); 1605 $gnuWin32Dir = File::Spec->catfile($gnuWin32Dir, "..", "gnuwin32", "bin"); 1606 if (-d "$gnuWin32Dir") { 1607 $ENV{PATH} = $gnuWin32Dir . ";" . $ENV{PATH}; 1608 } 1609 } 1610 foreach my $cmd (@cmds) { 1611 push @missing, $cmd if not commandExists($cmd); 1612 } 1613 1614 if (@missing) { 1615 my $list = join ", ", @missing; 1616 die "ERROR: $list missing but required to build WebKit.\n"; 1617 } 1618 if (isQt() and isWindows()) { 1619 $ENV{PATH} = $oldPath; 1620 } 1621 } 1622 # Win32 and other platforms may want to check for minimum config 1623 } 1624 1625 sub determineWindowsSourceDir() 1626 { 1627 return if $windowsSourceDir; 1628 $windowsSourceDir = sourceDir(); 1629 chomp($windowsSourceDir = `cygpath -w '$windowsSourceDir'`) if isCygwin(); 1630 } 1631 1632 sub windowsSourceDir() 1633 { 1634 determineWindowsSourceDir(); 1635 return $windowsSourceDir; 1636 } 1637 1638 sub windowsSourceSourceDir() 1639 { 1640 return windowsSourceDir() . "\\Source"; 1641 } 1642 1643 sub windowsLibrariesDir() 1644 { 1645 return windowsSourceDir() . "\\WebKitLibraries\\win"; 1646 } 1647 1648 sub windowsOutputDir() 1649 { 1650 return windowsSourceDir() . "\\WebKitBuild"; 1651 } 1652 1653 sub setupAppleWinEnv() 1654 { 1655 return unless isAppleWinWebKit(); 1656 1657 if (isWindowsNT()) { 1658 my $restartNeeded = 0; 1659 my %variablesToSet = (); 1660 1661 # FIXME: We should remove this explicit version check for cygwin once we stop supporting Cygwin 1.7.9 or older versions. 1662 # https://bugs.webkit.org/show_bug.cgi?id=85791 1663 my $uname_version = (POSIX::uname())[2]; 1664 $uname_version =~ s/\(.*\)//; # Remove the trailing cygwin version, if any. 1665 if (version->parse($uname_version) < version->parse("1.7.10")) { 1666 # Setting the environment variable 'CYGWIN' to 'tty' makes cygwin enable extra support (i.e., termios) 1667 # for UNIX-like ttys in the Windows console 1668 $variablesToSet{CYGWIN} = "tty" unless $ENV{CYGWIN}; 1669 } 1670 1671 # Those environment variables must be set to be able to build inside Visual Studio. 1672 $variablesToSet{WEBKITLIBRARIESDIR} = windowsLibrariesDir() unless $ENV{WEBKITLIBRARIESDIR}; 1673 $variablesToSet{WEBKIT_LIBRARIES} = windowsLibrariesDir() unless $ENV{WEBKIT_LIBRARIES}; 1674 $variablesToSet{WEBKITOUTPUTDIR} = windowsOutputDir() unless $ENV{WEBKITOUTPUTDIR}; 1675 $variablesToSet{WEBKIT_OUTPUTDIR} = windowsOutputDir() unless $ENV{WEBKIT_OUTPUTDIR}; 1676 $variablesToSet{WEBKIT_SOURCE} = windowsSourceSourceDir() unless $ENV{WEBKIT_SOURCE}; 1677 1678 foreach my $variable (keys %variablesToSet) { 1679 print "Setting the Environment Variable '" . $variable . "' to '" . $variablesToSet{$variable} . "'\n\n"; 1680 system qw(regtool -s set), '\\HKEY_CURRENT_USER\\Environment\\' . $variable, $variablesToSet{$variable}; 1681 $restartNeeded ||= $variable eq "WEBKITLIBRARIESDIR" || $variable eq "WEBKITOUTPUTDIR" || $variable eq "WEBKIT_LIBRARIES" || $variable eq "WEBKIT_OUTPUTDIR" || $variable eq "WEBKIT_SOURCE"; 1682 } 1683 1684 if ($restartNeeded) { 1685 print "Please restart your computer before attempting to build inside Visual Studio.\n\n"; 1686 } 1687 } else { 1688 if (!$ENV{'WEBKITLIBRARIESDIR'}) { 1689 # VS2005 version. This will be removed as part of https://bugs.webkit.org/show_bug.cgi?id=109472. 1690 print "Warning: You must set the 'WebKitLibrariesDir' environment variable\n"; 1691 print " to be able build WebKit from within Visual Studio 2005.\n"; 1692 print " Make sure that 'WebKitLibrariesDir' points to the\n"; 1693 print " 'WebKitLibraries/win' directory, not the 'WebKitLibraries/' directory.\n\n"; 1694 } 1695 if (!$ENV{'WEBKIT_LIBRARIES'}) { 1696 # VS2010 (and newer) version. This will replace the VS2005 version as part of 1697 # https://bugs.webkit.org/show_bug.cgi?id=109472. 1698 print "Warning: You must set the 'WebKit_Libraries' environment variable\n"; 1699 print " to be able build WebKit from within Visual Studio 2010 and newer.\n"; 1700 print " Make sure that 'WebKit_Libraries' points to the\n"; 1701 print " 'WebKitLibraries/win' directory, not the 'WebKitLibraries/' directory.\n\n"; 1702 } 1703 if (!$ENV{'WEBKITOUTPUTDIR'}) { 1704 # VS2005 version. This will be removed as part of https://bugs.webkit.org/show_bug.cgi?id=109472. 1705 print "Warning: You must set the 'WebKitOutputDir' environment variable\n"; 1706 print " to be able build WebKit from within Visual Studio 2005.\n\n"; 1707 } 1708 if (!$ENV{'WEBKIT_OUTPUTDIR'}) { 1709 # VS2010 (and newer) version. This will replace the VS2005 version as part of 1710 # https://bugs.webkit.org/show_bug.cgi?id=109472. 1711 print "Warning: You must set the 'WebKit_OutputDir' environment variable\n"; 1712 print " to be able build WebKit from within Visual Studio 2010 and newer.\n\n"; 1713 } 1714 if (!$ENV{'WEBKIT_SOURCE'}) { 1715 print "Warning: You must set the 'WebKit_Source' environment variable\n"; 1716 print " to be able build WebKit from within Visual Studio 2010 and newer.\n\n"; 1717 } 1718 } 1719 } 1720 1721 sub setupCygwinEnv() 1722 { 1723 return if !isCygwin() && !isWindows(); 1724 return if $vcBuildPath; 1725 1726 my $vsInstallDir; 1727 my $programFilesPath = $ENV{'PROGRAMFILES(X86)'} || $ENV{'PROGRAMFILES'} || "C:\\Program Files"; 1728 if ($ENV{'VSINSTALLDIR'}) { 1729 $vsInstallDir = $ENV{'VSINSTALLDIR'}; 1730 } else { 1731 $vsInstallDir = File::Spec->catdir($programFilesPath, "Microsoft Visual Studio 8"); 1732 } 1733 chomp($vsInstallDir = `cygpath "$vsInstallDir"`) if isCygwin(); 1734 $vcBuildPath = File::Spec->catfile($vsInstallDir, qw(Common7 IDE devenv.com)); 1735 if (-e $vcBuildPath) { 1736 # Visual Studio is installed; we can use pdevenv to build. 1737 # FIXME: Make pdevenv work with non-Cygwin Perl. 1738 $vcBuildPath = File::Spec->catfile(sourceDir(), qw(Tools Scripts pdevenv)) if isCygwin(); 1739 } else { 1740 # Visual Studio not found, try VC++ Express 1741 $vcBuildPath = File::Spec->catfile($vsInstallDir, qw(Common7 IDE VCExpress.exe)); 1742 if (! -e $vcBuildPath) { 1743 print "*************************************************************\n"; 1744 print "Cannot find '$vcBuildPath'\n"; 1745 print "Please execute the file 'vcvars32.bat' from\n"; 1746 print "'$programFilesPath\\Microsoft Visual Studio 8\\VC\\bin\\'\n"; 1747 print "to setup the necessary environment variables.\n"; 1748 print "*************************************************************\n"; 1749 die; 1750 } 1751 $willUseVCExpressWhenBuilding = 1; 1752 } 1753 1754 my $qtSDKPath = File::Spec->catdir($programFilesPath, "QuickTime SDK"); 1755 if (0 && ! -e $qtSDKPath) { 1756 print "*************************************************************\n"; 1757 print "Cannot find '$qtSDKPath'\n"; 1758 print "Please download the QuickTime SDK for Windows from\n"; 1759 print "http://developer.apple.com/quicktime/download/\n"; 1760 print "*************************************************************\n"; 1761 die; 1762 } 1763 1764 unless ($ENV{WEBKITLIBRARIESDIR}) { 1765 $ENV{'WEBKITLIBRARIESDIR'} = File::Spec->catdir($sourceDir, "WebKitLibraries", "win"); 1766 chomp($ENV{WEBKITLIBRARIESDIR} = `cygpath -wa '$ENV{WEBKITLIBRARIESDIR}'`) if isCygwin(); 1767 } 1768 unless ($ENV{WEBKIT_LIBRARIES}) { 1769 $ENV{'WEBKIT_LIBRARIES'} = File::Spec->catdir($sourceDir, "WebKitLibraries", "win"); 1770 chomp($ENV{WEBKIT_LIBRARIES} = `cygpath -wa '$ENV{WEBKIT_LIBRARIES}'`) if isCygwin(); 1771 } 1772 1773 print "Building results into: ", baseProductDir(), "\n"; 1774 print "WEBKITOUTPUTDIR is set to: ", $ENV{"WEBKITOUTPUTDIR"}, "\n"; 1775 print "WEBKIT_OUTPUTDIR is set to: ", $ENV{"WEBKIT_OUTPUTDIR"}, "\n"; 1776 print "WEBKITLIBRARIESDIR is set to: ", $ENV{"WEBKITLIBRARIESDIR"}, "\n"; 1777 print "WEBKIT_LIBRARIES is set to: ", $ENV{"WEBKIT_LIBRARIES"}, "\n"; 1778 } 1779 1780 sub dieIfWindowsPlatformSDKNotInstalled 1781 { 1782 my $registry32Path = "/proc/registry/"; 1783 my $registry64Path = "/proc/registry64/"; 1784 my $windowsPlatformSDKRegistryEntry = "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MicrosoftSDK/InstalledSDKs/D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1"; 1785 1786 # FIXME: It would be better to detect whether we are using 32- or 64-bit Windows 1787 # and only check the appropriate entry. But for now we just blindly check both. 1788 return if (-e $registry32Path . $windowsPlatformSDKRegistryEntry) || (-e $registry64Path . $windowsPlatformSDKRegistryEntry); 1789 1790 print "*************************************************************\n"; 1791 print "Cannot find registry entry '$windowsPlatformSDKRegistryEntry'.\n"; 1792 print "Please download and install the Microsoft Windows Server 2003 R2\n"; 1793 print "Platform SDK from <http://www.microsoft.com/downloads/details.aspx?\n"; 1794 print "familyid=0baf2b35-c656-4969-ace8-e4c0c0716adb&displaylang=en>.\n\n"; 1795 print "Then follow step 2 in the Windows section of the \"Installing Developer\n"; 1796 print "Tools\" instructions at <http://www.webkit.org/building/tools.html>.\n"; 1797 print "*************************************************************\n"; 1798 die; 1799 } 1800 1801 sub copyInspectorFrontendFiles 1802 { 1803 my $productDir = productDir(); 1804 my $sourceInspectorPath = sourceDir() . "/Source/WebCore/inspector/front-end/"; 1805 my $inspectorResourcesDirPath = $ENV{"WEBKITINSPECTORRESOURCESDIR"}; 1806 1807 if (!defined($inspectorResourcesDirPath)) { 1808 $inspectorResourcesDirPath = ""; 1809 } 1810 1811 if (isAppleMacWebKit()) { 1812 $inspectorResourcesDirPath = $productDir . "/WebCore.framework/Resources/inspector"; 1813 } elsif (isAppleWinWebKit()) { 1814 $inspectorResourcesDirPath = $productDir . "/WebKit.resources/inspector"; 1815 } elsif (isQt() || isGtk()) { 1816 my $prefix = $ENV{"WebKitInstallationPrefix"}; 1817 $inspectorResourcesDirPath = (defined($prefix) ? $prefix : "/usr/share") . "/webkit-1.0/webinspector"; 1818 } elsif (isEfl()) { 1819 my $prefix = $ENV{"WebKitInstallationPrefix"}; 1820 $inspectorResourcesDirPath = (defined($prefix) ? $prefix : "/usr/share") . "/ewebkit/webinspector"; 1821 } 1822 1823 if (! -d $inspectorResourcesDirPath) { 1824 print "*************************************************************\n"; 1825 print "Cannot find '$inspectorResourcesDirPath'.\n" if (defined($inspectorResourcesDirPath)); 1826 print "Make sure that you have built WebKit first.\n" if (! -d $productDir || defined($inspectorResourcesDirPath)); 1827 print "Optionally, set the environment variable 'WebKitInspectorResourcesDir'\n"; 1828 print "to point to the directory that contains the WebKit Inspector front-end\n"; 1829 print "files for the built WebCore framework.\n"; 1830 print "*************************************************************\n"; 1831 die; 1832 } 1833 1834 if (isAppleMacWebKit()) { 1835 my $sourceLocalizedStrings = sourceDir() . "/Source/WebCore/English.lproj/localizedStrings.js"; 1836 my $destinationLocalizedStrings = $productDir . "/WebCore.framework/Resources/English.lproj/localizedStrings.js"; 1837 system "ditto", $sourceLocalizedStrings, $destinationLocalizedStrings; 1838 } 1839 1840 return system "rsync", "-aut", "--exclude=/.DS_Store", "--exclude=*.re2js", "--exclude=.svn/", !isQt() ? "--exclude=/WebKit.qrc" : "", $sourceInspectorPath, $inspectorResourcesDirPath; 1841 } 1842 1843 sub buildXCodeProject($$@) 1844 { 1845 my ($project, $clean, @extraOptions) = @_; 1846 1847 if ($clean) { 1848 push(@extraOptions, "-alltargets"); 1849 push(@extraOptions, "clean"); 1850 } 1851 1852 return system "xcodebuild", "-project", "$project.xcodeproj", @extraOptions; 1853 } 1854 1855 sub usingVisualStudioExpress() 1856 { 1857 setupCygwinEnv(); 1858 return $willUseVCExpressWhenBuilding; 1859 } 1860 1861 sub buildVisualStudioProject 1862 { 1863 my ($project, $clean) = @_; 1864 setupCygwinEnv(); 1865 1866 my $config = configurationForVisualStudio(); 1867 1868 dieIfWindowsPlatformSDKNotInstalled() if $willUseVCExpressWhenBuilding; 1869 1870 chomp($project = `cygpath -w "$project"`) if isCygwin(); 1871 1872 my $action = "/build"; 1873 if ($clean) { 1874 $action = "/clean"; 1875 } 1876 1877 my @command = ($vcBuildPath, $project, $action, $config); 1878 1879 print join(" ", @command), "\n"; 1880 return system @command; 1881 } 1882 1883 sub downloadWafIfNeeded 1884 { 1885 # get / update waf if needed 1886 my $waf = "$sourceDir/Tools/waf/waf"; 1887 my $wafURL = 'http://wxwebkit.kosoftworks.com/downloads/deps/waf'; 1888 if (!-f $waf) { 1889 my $result = system "curl -o $waf $wafURL"; 1890 chmod 0755, $waf; 1891 } 1892 } 1893 1894 sub buildWafProject 1895 { 1896 my ($project, $shouldClean, @options) = @_; 1897 1898 # set the PYTHONPATH for waf 1899 my $pythonPath = $ENV{'PYTHONPATH'}; 1900 if (!defined($pythonPath)) { 1901 $pythonPath = ''; 1902 } 1903 my $sourceDir = sourceDir(); 1904 my $newPythonPath = "$sourceDir/Tools/waf/build:$pythonPath"; 1905 if (isCygwin()) { 1906 $newPythonPath = `cygpath --mixed --path $newPythonPath`; 1907 } 1908 $ENV{'PYTHONPATH'} = $newPythonPath; 1909 1910 print "Building $project\n"; 1911 1912 my $wafCommand = "$sourceDir/Tools/waf/waf"; 1913 if ($ENV{'WXWEBKIT_WAF'}) { 1914 $wafCommand = $ENV{'WXWEBKIT_WAF'}; 1915 } 1916 if (isCygwin()) { 1917 $wafCommand = `cygpath --windows "$wafCommand"`; 1918 chomp($wafCommand); 1919 } 1920 if ($shouldClean) { 1921 return system $wafCommand, "uninstall", "clean", "distclean"; 1922 } 1923 1924 return system $wafCommand, 'configure', 'build', 'install', @options; 1925 } 1926 1927 sub retrieveQMakespecVar 1928 { 1929 my $mkspec = $_[0]; 1930 my $varname = $_[1]; 1931 1932 my $varvalue = undef; 1933 #print "retrieveMakespecVar " . $mkspec . ", " . $varname . "\n"; 1934 1935 local *SPEC; 1936 open SPEC, "<$mkspec" or return $varvalue; 1937 while (<SPEC>) { 1938 if ($_ =~ /\s*include\((.+)\)/) { 1939 # open the included mkspec 1940 my $oldcwd = getcwd(); 1941 (my $volume, my $directories, my $file) = File::Spec->splitpath($mkspec); 1942 my $newcwd = "$volume$directories"; 1943 chdir $newcwd if $newcwd; 1944 $varvalue = retrieveQMakespecVar($1, $varname); 1945 chdir $oldcwd; 1946 } elsif ($_ =~ /$varname\s*=\s*([^\s]+)/) { 1947 $varvalue = $1; 1948 last; 1949 } 1950 } 1951 close SPEC; 1952 return $varvalue; 1953 } 1954 1955 sub qtMakeCommand($) 1956 { 1957 my ($qmakebin) = @_; 1958 chomp(my $hostDataPath = `$qmakebin -query QT_HOST_DATA`); 1959 my $mkspecPath = $hostDataPath . "/mkspecs/default/qmake.conf"; 1960 if (! -e $mkspecPath) { 1961 chomp(my $mkspec= `$qmakebin -query QMAKE_XSPEC`); 1962 $mkspecPath = $hostDataPath . "/mkspecs/" . $mkspec . "/qmake.conf"; 1963 } 1964 my $compiler = retrieveQMakespecVar($mkspecPath, "QMAKE_CC"); 1965 1966 #print "default spec: " . $mkspec . "\n"; 1967 #print "compiler found: " . $compiler . "\n"; 1968 1969 if ($compiler && $compiler eq "cl") { 1970 return "nmake"; 1971 } 1972 1973 return "make"; 1974 } 1975 1976 sub autotoolsFlag($$) 1977 { 1978 my ($flag, $feature) = @_; 1979 my $prefix = $flag ? "--enable" : "--disable"; 1980 1981 return $prefix . '-' . $feature; 1982 } 1983 1984 sub runAutogenForAutotoolsProjectIfNecessary($@) 1985 { 1986 my ($dir, $prefix, $sourceDir, $project, $joinedOverridableFeatures, @buildArgs) = @_; 1987 1988 my $joinedBuildArgs = join(" ", @buildArgs); 1989 1990 if (-e "GNUmakefile") { 1991 # Just assume that build-jsc will never be used to reconfigure JSC. Later 1992 # we can go back and make this more complicated if the demand is there. 1993 if ($project ne "WebKit") { 1994 return; 1995 } 1996 1997 # Run autogen.sh again if either the features overrided by build-webkit or build arguments have changed. 1998 if (!mustReRunAutogen($sourceDir, "WebKitFeatureOverrides.txt", $joinedOverridableFeatures) 1999 && !mustReRunAutogen($sourceDir, "previous-autogen-arguments.txt", $joinedBuildArgs)) { 2000 return; 2001 } 2002 } 2003 2004 print "Calling autogen.sh in " . $dir . "\n\n"; 2005 print "Installation prefix directory: $prefix\n" if(defined($prefix)); 2006 2007 # Only for WebKit, write the autogen.sh arguments to a file so that we can detect 2008 # when they change and automatically re-run it. 2009 if ($project eq 'WebKit') { 2010 open(OVERRIDABLE_FEATURES, ">WebKitFeatureOverrides.txt"); 2011 print OVERRIDABLE_FEATURES $joinedOverridableFeatures; 2012 close(OVERRIDABLE_FEATURES); 2013 2014 open(AUTOTOOLS_ARGUMENTS, ">previous-autogen-arguments.txt"); 2015 print AUTOTOOLS_ARGUMENTS $joinedBuildArgs; 2016 close(AUTOTOOLS_ARGUMENTS); 2017 } 2018 2019 # Make the path relative since it will appear in all -I compiler flags. 2020 # Long argument lists cause bizarre slowdowns in libtool. 2021 my $relSourceDir = File::Spec->abs2rel($sourceDir) || "."; 2022 2023 # Compiler options to keep floating point values consistent 2024 # between 32-bit and 64-bit architectures. The options are also 2025 # used on Chromium build. 2026 determineArchitecture(); 2027 if ($architecture ne "x86_64" && !isARM()) { 2028 $ENV{'CXXFLAGS'} = "-march=pentium4 -msse2 -mfpmath=sse " . ($ENV{'CXXFLAGS'} || ""); 2029 } 2030 2031 # Prefix the command with jhbuild run. 2032 unshift(@buildArgs, "$relSourceDir/autogen.sh"); 2033 unshift(@buildArgs, jhbuildWrapperPrefixIfNeeded()); 2034 if (system(@buildArgs) ne 0) { 2035 die "Calling autogen.sh failed!\n"; 2036 } 2037 } 2038 2039 sub getJhbuildPath() 2040 { 2041 return join('/', baseProductDir(), "Dependencies"); 2042 } 2043 2044 sub mustReRunAutogen($@) 2045 { 2046 my ($sourceDir, $filename, $currentContents) = @_; 2047 2048 if (! -e $filename) { 2049 return 1; 2050 } 2051 2052 open(CONTENTS_FILE, $filename); 2053 chomp(my $previousContents = <CONTENTS_FILE>); 2054 close(CONTENTS_FILE); 2055 2056 # We only care about the WebKit2 argument when we are building WebKit itself. 2057 # build-jsc never passes --enable-webkit2, so if we didn't do this, autogen.sh 2058 # would run for every single build on the bots, since it runs both build-webkit 2059 # and build-jsc. 2060 if ($previousContents ne $currentContents) { 2061 print "Contents for file $filename have changed.\n"; 2062 print "Previous contents were: $previousContents\n\n"; 2063 print "New contents are: $currentContents\n"; 2064 return 1; 2065 } 2066 2067 return 0; 2068 } 2069 2070 sub buildAutotoolsProject($@) 2071 { 2072 my ($project, $clean, $prefix, $makeArgs, $noWebKit1, $noWebKit2, @features) = @_; 2073 2074 my $make = 'make'; 2075 my $dir = productDir(); 2076 my $config = passedConfiguration() || configuration(); 2077 2078 # Use rm to clean the build directory since distclean may miss files 2079 if ($clean && -d $dir) { 2080 system "rm", "-rf", "$dir"; 2081 } 2082 2083 if (! -d $dir) { 2084 File::Path::mkpath($dir) or die "Failed to create build directory " . $dir 2085 } 2086 chdir $dir or die "Failed to cd into " . $dir . "\n"; 2087 2088 if ($clean) { 2089 return 0; 2090 } 2091 2092 my @buildArgs = @ARGV; 2093 if ($noWebKit1) { 2094 unshift(@buildArgs, "--disable-webkit1"); 2095 } 2096 if ($noWebKit2) { 2097 unshift(@buildArgs, "--disable-webkit2"); 2098 } 2099 2100 # Configurable features listed here should be kept in sync with the 2101 # features for which there exists a configuration option in configure.ac. 2102 my %configurableFeatures = ( 2103 "gamepad" => 1, 2104 "geolocation" => 1, 2105 "media-stream" => 1, 2106 "svg" => 1, 2107 "svg-fonts" => 1, 2108 "video" => 1, 2109 "webgl" => 1, 2110 "web-audio" => 1, 2111 "xslt" => 1, 2112 ); 2113 my @overridableFeatures = (); 2114 foreach (@features) { 2115 if ($configurableFeatures{$_->{option}}) { 2116 push @buildArgs, autotoolsFlag(${$_->{value}}, $_->{option});; 2117 } else { 2118 push @overridableFeatures, $_->{define} . "=" . (${$_->{value}} ? "1" : "0"); 2119 } 2120 } 2121 2122 $makeArgs = $makeArgs || ""; 2123 $makeArgs = $makeArgs . " " . $ENV{"WebKitMakeArguments"} if $ENV{"WebKitMakeArguments"}; 2124 2125 # Automatically determine the number of CPUs for make only 2126 # if make arguments haven't already been specified. 2127 if ($makeArgs eq "") { 2128 $makeArgs = "-j" . numberOfCPUs(); 2129 } 2130 2131 # WebKit is the default target, so we don't need to specify anything. 2132 if ($project eq "JavaScriptCore") { 2133 $makeArgs .= " jsc"; 2134 } elsif ($project eq "WTF") { 2135 $makeArgs .= " libWTF.la"; 2136 } 2137 2138 $prefix = $ENV{"WebKitInstallationPrefix"} if !defined($prefix); 2139 push @buildArgs, "--prefix=" . $prefix if defined($prefix); 2140 2141 # Check if configuration is Debug. 2142 my $debug = $config =~ m/debug/i; 2143 if ($debug) { 2144 push @buildArgs, "--enable-debug"; 2145 } else { 2146 push @buildArgs, "--disable-debug"; 2147 } 2148 2149 if (checkForArgumentAndRemoveFromArrayRef("--update-gtk", \@buildArgs)) { 2150 # Force autogen to run, to catch the possibly updated libraries. 2151 system("rm -f previous-autogen-arguments.txt"); 2152 2153 system("perl", "$sourceDir/Tools/Scripts/update-webkitgtk-libs") == 0 or die $!; 2154 } 2155 2156 # If GNUmakefile exists, don't run autogen.sh unless its arguments 2157 # have changed. The makefile should be smart enough to track autotools 2158 # dependencies and re-run autogen.sh when build files change. 2159 my $joinedOverridableFeatures = join(" ", @overridableFeatures); 2160 runAutogenForAutotoolsProjectIfNecessary($dir, $prefix, $sourceDir, $project, $joinedOverridableFeatures, @buildArgs); 2161 2162 my $runWithJhbuild = join(" ", jhbuildWrapperPrefixIfNeeded()); 2163 if (system("$runWithJhbuild $make $makeArgs") ne 0) { 2164 die "\nFailed to build WebKit using '$make'!\n"; 2165 } 2166 2167 chdir ".." or die; 2168 2169 if ($project eq 'WebKit' && !isCrossCompilation() && !($noWebKit1 && $noWebKit2)) { 2170 my @docGenerationOptions = ("$sourceDir/Tools/gtk/generate-gtkdoc", "--skip-html"); 2171 push(@docGenerationOptions, productDir()); 2172 2173 unshift(@docGenerationOptions, jhbuildWrapperPrefixIfNeeded()); 2174 2175 if (system(@docGenerationOptions)) { 2176 die "\n gtkdoc did not build without warnings\n"; 2177 } 2178 } 2179 2180 return 0; 2181 } 2182 2183 sub jhbuildWrapperPrefixIfNeeded() 2184 { 2185 if (-e getJhbuildPath()) { 2186 my @prefix = (File::Spec->catfile(sourceDir(), "Tools", "jhbuild", "jhbuild-wrapper")); 2187 if (isEfl()) { 2188 push(@prefix, "--efl"); 2189 } elsif (isGtk()) { 2190 push(@prefix, "--gtk"); 2191 } 2192 push(@prefix, "run"); 2193 2194 return @prefix; 2195 } 2196 2197 return (); 2198 } 2199 2200 sub removeCMakeCache() 2201 { 2202 my $cacheFilePath = File::Spec->catdir(baseProductDir(), configuration(), "CMakeCache.txt"); 2203 unlink($cacheFilePath) if -e $cacheFilePath; 2204 } 2205 2206 sub generateBuildSystemFromCMakeProject 2207 { 2208 my ($port, $prefixPath, @cmakeArgs, $additionalCMakeArgs) = @_; 2209 my $config = configuration(); 2210 my $buildPath = File::Spec->catdir(baseProductDir(), $config); 2211 File::Path::mkpath($buildPath) unless -d $buildPath; 2212 my $originalWorkingDirectory = getcwd(); 2213 chdir($buildPath) or die; 2214 2215 my @args; 2216 push @args, "-DPORT=\"$port\""; 2217 push @args, "-DCMAKE_INSTALL_PREFIX=\"$prefixPath\"" if $prefixPath; 2218 push @args, "-DSHARED_CORE=ON" if isEfl() && $ENV{"ENABLE_DRT"}; 2219 if ($config =~ /release/i) { 2220 push @args, "-DCMAKE_BUILD_TYPE=Release"; 2221 } elsif ($config =~ /debug/i) { 2222 push @args, "-DCMAKE_BUILD_TYPE=Debug"; 2223 } 2224 # Don't warn variables which aren't used by cmake ports. 2225 push @args, "--no-warn-unused-cli"; 2226 push @args, @cmakeArgs if @cmakeArgs; 2227 push @args, $additionalCMakeArgs if $additionalCMakeArgs; 2228 2229 push @args, '"' . sourceDir() . '"'; 2230 2231 # Compiler options to keep floating point values consistent 2232 # between 32-bit and 64-bit architectures. 2233 determineArchitecture(); 2234 if ($architecture ne "x86_64" && !isARM()) { 2235 $ENV{'CXXFLAGS'} = "-march=pentium4 -msse2 -mfpmath=sse " . ($ENV{'CXXFLAGS'} || ""); 2236 } 2237 2238 # We call system("cmake @args") instead of system("cmake", @args) so that @args is 2239 # parsed for shell metacharacters. 2240 my $wrapper = join(" ", jhbuildWrapperPrefixIfNeeded()) . " "; 2241 my $returnCode = system($wrapper . "cmake @args"); 2242 2243 chdir($originalWorkingDirectory); 2244 return $returnCode; 2245 } 2246 2247 sub buildCMakeGeneratedProject($) 2248 { 2249 my ($makeArgs) = @_; 2250 my $config = configuration(); 2251 my $buildPath = File::Spec->catdir(baseProductDir(), $config); 2252 if (! -d $buildPath) { 2253 die "Must call generateBuildSystemFromCMakeProject() before building CMake project."; 2254 } 2255 my @args = ("--build", $buildPath, "--config", $config); 2256 push @args, ("--", $makeArgs) if $makeArgs; 2257 2258 # We call system("cmake @args") instead of system("cmake", @args) so that @args is 2259 # parsed for shell metacharacters. In particular, $makeArgs may contain such metacharacters. 2260 my $wrapper = join(" ", jhbuildWrapperPrefixIfNeeded()) . " "; 2261 return system($wrapper . "cmake @args"); 2262 } 2263 2264 sub cleanCMakeGeneratedProject() 2265 { 2266 my $config = configuration(); 2267 my $buildPath = File::Spec->catdir(baseProductDir(), $config); 2268 if (-d $buildPath) { 2269 return system("cmake", "--build", $buildPath, "--config", $config, "--target", "clean"); 2270 } 2271 return 0; 2272 } 2273 2274 sub buildCMakeProjectOrExit($$$$@) 2275 { 2276 my ($clean, $port, $prefixPath, $makeArgs, @cmakeArgs) = @_; 2277 my $returnCode; 2278 2279 exit(exitStatus(cleanCMakeGeneratedProject())) if $clean; 2280 2281 if (isEfl() && checkForArgumentAndRemoveFromARGV("--update-efl")) { 2282 system("perl", "$sourceDir/Tools/Scripts/update-webkitefl-libs") == 0 or die $!; 2283 } 2284 2285 2286 $returnCode = exitStatus(generateBuildSystemFromCMakeProject($port, $prefixPath, @cmakeArgs)); 2287 exit($returnCode) if $returnCode; 2288 if (isBlackBerry()) { 2289 return 0 if (defined($ENV{"GENERATE_CMAKE_PROJECT_ONLY"}) eq '1'); 2290 } 2291 $returnCode = exitStatus(buildCMakeGeneratedProject($makeArgs)); 2292 exit($returnCode) if $returnCode; 2293 return 0; 2294 } 2295 2296 sub cmakeBasedPortArguments() 2297 { 2298 return blackberryCMakeArguments() if isBlackBerry(); 2299 return ('-G "Visual Studio 8 2005 STANDARDSDK_500 (ARMV4I)"') if isWinCE(); 2300 return (); 2301 } 2302 2303 sub cmakeBasedPortName() 2304 { 2305 return "BlackBerry" if isBlackBerry(); 2306 return "Efl" if isEfl(); 2307 return "WinCE" if isWinCE(); 2308 return ""; 2309 } 2310 2311 sub promptUser 2312 { 2313 my ($prompt, $default) = @_; 2314 my $defaultValue = $default ? "[$default]" : ""; 2315 print "$prompt $defaultValue: "; 2316 chomp(my $input = <STDIN>); 2317 return $input ? $input : $default; 2318 } 2319 2320 sub buildQMakeProjects 2321 { 2322 my ($projects, $clean, @buildParams) = @_; 2323 2324 my @buildArgs = (); 2325 my $qconfigs = ""; 2326 2327 my $make = qtMakeCommand($qmakebin); 2328 my $makeargs = ""; 2329 my $command; 2330 my $installHeaders; 2331 my $installLibs; 2332 for my $i (0 .. $#buildParams) { 2333 my $opt = $buildParams[$i]; 2334 if ($opt =~ /^--qmake=(.*)/i ) { 2335 $qmakebin = $1; 2336 } elsif ($opt =~ /^--qmakearg=(.*)/i ) { 2337 push @buildArgs, $1; 2338 } elsif ($opt =~ /^--makeargs=(.*)/i ) { 2339 $makeargs = $1; 2340 } elsif ($opt =~ /^--install-headers=(.*)/i ) { 2341 $installHeaders = $1; 2342 } elsif ($opt =~ /^--install-libs=(.*)/i ) { 2343 $installLibs = $1; 2344 } else { 2345 push @buildArgs, $opt; 2346 } 2347 } 2348 2349 # Automatically determine the number of CPUs for make only if this make argument haven't already been specified. 2350 if ($make eq "make" && $makeargs !~ /-j\s*\d+/i && (!defined $ENV{"MAKEFLAGS"} || ($ENV{"MAKEFLAGS"} !~ /-j\s*\d+/i ))) { 2351 $makeargs .= " -j" . numberOfCPUs(); 2352 } 2353 2354 $make = "$make $makeargs"; 2355 $make =~ s/\s+$//; 2356 2357 my $originalCwd = getcwd(); 2358 my $dir = File::Spec->canonpath(productDir()); 2359 File::Path::mkpath($dir); 2360 chdir $dir or die "Failed to cd into " . $dir . "\n"; 2361 2362 if ($clean) { 2363 $command = "$make distclean"; 2364 print "\nCalling '$command' in " . $dir . "\n\n"; 2365 return system $command; 2366 } 2367 2368 my $qmakepath = File::Spec->catfile(sourceDir(), "Tools", "qmake"); 2369 my $qmakecommand = $qmakebin; 2370 2371 my $config = configuration(); 2372 push @buildArgs, "INSTALL_HEADERS=" . $installHeaders if defined($installHeaders); 2373 push @buildArgs, "INSTALL_LIBS=" . $installLibs if defined($installLibs); 2374 2375 my $passedConfig = passedConfiguration() || ""; 2376 if ($passedConfig =~ m/debug/i) { 2377 push @buildArgs, "CONFIG-=release"; 2378 push @buildArgs, "CONFIG+=debug"; 2379 } elsif ($passedConfig =~ m/release/i) { 2380 push @buildArgs, "CONFIG+=release"; 2381 push @buildArgs, "CONFIG-=debug"; 2382 } elsif ($passedConfig) { 2383 die "Build type $passedConfig is not supported with --qt.\n"; 2384 } 2385 2386 # Using build-webkit to build assumes you want a developer-build 2387 push @buildArgs, "CONFIG-=production_build"; 2388 2389 my $svnRevision = currentSVNRevision(); 2390 my $previousSvnRevision = "unknown"; 2391 2392 my $buildHint = ""; 2393 2394 my $pathToBuiltRevisions = File::Spec->catfile($dir, ".builtRevisions.cache"); 2395 if (-e $pathToBuiltRevisions && open(BUILTREVISIONS, $pathToBuiltRevisions)) { 2396 while (<BUILTREVISIONS>) { 2397 if ($_ =~ m/^SVN_REVISION\s=\s(\d+)$/) { 2398 $previousSvnRevision = $1; 2399 } 2400 } 2401 close(BUILTREVISIONS); 2402 } 2403 2404 my $result = 0; 2405 2406 # Run qmake, regadless of having a makefile or not, so that qmake can 2407 # detect changes to the configuration. 2408 2409 push @buildArgs, "-after OVERRIDE_SUBDIRS=\"@{$projects}\"" if @{$projects}; 2410 unshift @buildArgs, File::Spec->catfile(sourceDir(), "WebKit.pro"); 2411 $command = "$qmakecommand @buildArgs"; 2412 print "Calling '$command' in " . $dir . "\n\n"; 2413 print "Installation headers directory: $installHeaders\n" if(defined($installHeaders)); 2414 print "Installation libraries directory: $installLibs\n" if(defined($installLibs)); 2415 2416 my $configChanged = 0; 2417 open(QMAKE, "$command 2>&1 |") || die "Could not execute qmake"; 2418 while (<QMAKE>) { 2419 $configChanged = 1 if $_ =~ m/The configuration was changed since the last build/; 2420 print $_; 2421 } 2422 2423 close(QMAKE); 2424 $result = $?; 2425 2426 if ($result ne 0) { 2427 die "\nFailed to set up build environment using $qmakebin!\n"; 2428 } 2429 2430 my $maybeNeedsCleanBuild = 0; 2431 my $needsIncrementalBuild = 0; 2432 2433 # Full incremental build (run qmake) needed on buildbots and EWS bots always. 2434 if (grep(/CONFIG\+=buildbot/,@buildParams)) { 2435 $needsIncrementalBuild = 1; 2436 } 2437 2438 if ($svnRevision ne $previousSvnRevision) { 2439 print "Last built revision was " . $previousSvnRevision . 2440 ", now at revision $svnRevision. Full incremental build needed.\n"; 2441 $needsIncrementalBuild = 1; 2442 2443 my @fileList = listOfChangedFilesBetweenRevisions(sourceDir(), $previousSvnRevision, $svnRevision); 2444 2445 foreach (@fileList) { 2446 if (m/\.pr[oif]$/ or 2447 m/\.qmake.conf$/ or 2448 m/^Tools\/qmake\// 2449 ) { 2450 print "Change to $_ detected, clean build may be needed.\n"; 2451 $maybeNeedsCleanBuild = 1; 2452 last; 2453 } 2454 } 2455 } 2456 2457 if ($configChanged) { 2458 print "Calling '$make wipeclean' in " . $dir . "\n\n"; 2459 $result = system "$make wipeclean"; 2460 } 2461 2462 $command = "$make"; 2463 if ($needsIncrementalBuild) { 2464 $command .= " incremental"; 2465 } 2466 2467 print "\nCalling '$command' in " . $dir . "\n\n"; 2468 $result = system $command; 2469 2470 chdir ".." or die; 2471 2472 if ($result eq 0) { 2473 # Now that the build completed successfully we can save the SVN revision 2474 open(BUILTREVISIONS, ">>$pathToBuiltRevisions"); 2475 print BUILTREVISIONS "SVN_REVISION = $svnRevision\n"; 2476 close(BUILTREVISIONS); 2477 } elsif (!$command =~ /incremental/ && exitStatus($result)) { 2478 my $exitCode = exitStatus($result); 2479 my $failMessage = <<EOF; 2480 2481 ===== BUILD FAILED ====== 2482 2483 The build failed with exit code $exitCode. This may have been because you 2484 2485 - added an #include to a source/header 2486 - added a Q_OBJECT macro to a class 2487 - added a new resource to a qrc file 2488 2489 as dependencies are not automatically re-computed for local developer builds. 2490 You may try computing dependencies manually by running 'make qmake_all' in: 2491 2492 $dir 2493 2494 or passing --makeargs="qmake_all" to build-webkit. 2495 2496 ========================= 2497 2498 EOF 2499 print "$failMessage"; 2500 } elsif ($maybeNeedsCleanBuild) { 2501 print "\nIncremental build failed, clean build needed. \n"; 2502 print "Calling '$make wipeclean' in " . $dir . "\n\n"; 2503 chdir $dir or die; 2504 system "$make wipeclean"; 2505 2506 print "\nCalling '$make' in " . $dir . "\n\n"; 2507 $result = system $make; 2508 } 2509 2510 return $result; 2511 } 2512 2513 sub buildGtkProject 2514 { 2515 my ($project, $clean, $prefix, $makeArgs, $noWebKit1, $noWebKit2, @features) = @_; 2516 2517 if ($project ne "WebKit" and $project ne "JavaScriptCore" and $project ne "WTF") { 2518 die "Unsupported project: $project. Supported projects: WebKit, JavaScriptCore, WTF\n"; 2519 } 2520 2521 return buildAutotoolsProject($project, $clean, $prefix, $makeArgs, $noWebKit1, $noWebKit2, @features); 2522 } 2523 2524 sub buildChromiumMakefile($$@) 2525 { 2526 my ($target, $clean, @options) = @_; 2527 if ($clean) { 2528 return system qw(rm -rf out); 2529 } 2530 my $config = configuration(); 2531 my $numCpus = numberOfCPUs(); 2532 my $makeArgs; 2533 for (@options) { 2534 $makeArgs = $1 if /^--makeargs=(.*)/i; 2535 } 2536 $makeArgs = "-j$numCpus" if not $makeArgs; 2537 my $command .= "make -fMakefile.chromium $makeArgs BUILDTYPE=$config $target"; 2538 2539 print "$command\n"; 2540 return system $command; 2541 } 2542 2543 sub buildChromiumNinja($$@) 2544 { 2545 # rm -rf out requires rerunning gyp, so don't support --clean for now. 2546 my ($target, @options) = @_; 2547 my $config = configuration(); 2548 my $makeArgs = ""; 2549 for (@options) { 2550 $makeArgs = $1 if /^--makeargs=(.*)/i; 2551 } 2552 my $command = ""; 2553 2554 # Find ninja. 2555 my $ninjaPath; 2556 if (commandExists('ninja')) { 2557 $ninjaPath = 'ninja'; 2558 } elsif (-e 'Source/WebKit/chromium/depot_tools/ninja') { 2559 $ninjaPath = 'Source/WebKit/chromium/depot_tools/ninja'; 2560 } else { 2561 die "ninja not found. Install chromium's depot_tools by running update-webkit first\n"; 2562 } 2563 2564 $command .= "$ninjaPath -C out/$config $target $makeArgs"; 2565 2566 print "$command\n"; 2567 return system $command; 2568 } 2569 2570 sub buildChromiumVisualStudioProject($$) 2571 { 2572 my ($projectPath, $clean) = @_; 2573 2574 my $config = configuration(); 2575 my $action = "/build"; 2576 $action = "/clean" if $clean; 2577 2578 # Find Visual Studio installation. 2579 my $vsInstallDir; 2580 my $programFilesPath = $ENV{'PROGRAMFILES'} || "C:\\Program Files"; 2581 if ($ENV{'VSINSTALLDIR'}) { 2582 $vsInstallDir = $ENV{'VSINSTALLDIR'}; 2583 } else { 2584 $vsInstallDir = "$programFilesPath/Microsoft Visual Studio 8"; 2585 } 2586 $vsInstallDir =~ s,\\,/,g; 2587 $vsInstallDir = `cygpath "$vsInstallDir"` if isCygwin(); 2588 chomp $vsInstallDir; 2589 $vcBuildPath = "$vsInstallDir/Common7/IDE/devenv.com"; 2590 if (! -e $vcBuildPath) { 2591 # Visual Studio not found, try VC++ Express 2592 $vcBuildPath = "$vsInstallDir/Common7/IDE/VCExpress.exe"; 2593 if (! -e $vcBuildPath) { 2594 print "*************************************************************\n"; 2595 print "Cannot find '$vcBuildPath'\n"; 2596 print "Please execute the file 'vcvars32.bat' from\n"; 2597 print "'$programFilesPath\\Microsoft Visual Studio 8\\VC\\bin\\'\n"; 2598 print "to setup the necessary environment variables.\n"; 2599 print "*************************************************************\n"; 2600 die; 2601 } 2602 } 2603 2604 # Create command line and execute it. 2605 my @command = ($vcBuildPath, $projectPath, $action, $config); 2606 print "Building results into: ", baseProductDir(), "\n"; 2607 print join(" ", @command), "\n"; 2608 return system @command; 2609 } 2610 2611 sub buildChromium($@) 2612 { 2613 my ($clean, @options) = @_; 2614 2615 # We might need to update DEPS or re-run GYP if things have changed. 2616 if (checkForArgumentAndRemoveFromArrayRef("--update-chromium", \@options)) { 2617 my @updateCommand = ("perl", "Tools/Scripts/update-webkit-chromium", "--force"); 2618 push @updateCommand, "--chromium-android" if isChromiumAndroid(); 2619 system(@updateCommand) == 0 or die $!; 2620 } 2621 2622 my $result = 1; 2623 if (isDarwin() && !isChromiumAndroid() && !isChromiumMacMake() && !isChromiumNinja()) { 2624 # Mac build - builds the root xcode project. 2625 $result = buildXCodeProject("Source/WebKit/chromium/All", $clean, "-configuration", configuration(), @options); 2626 } elsif ((isCygwin() || isWindows()) && !isChromiumNinja()) { 2627 # Windows build - builds the root visual studio solution. 2628 $result = buildChromiumVisualStudioProject("Source/WebKit/chromium/All.sln", $clean); 2629 } elsif (isChromiumNinja()) { 2630 $result = buildChromiumNinja("all", $clean, @options); 2631 } elsif (isLinux() || isChromiumAndroid() || isChromiumMacMake()) { 2632 # Linux build - build using make. 2633 $result = buildChromiumMakefile("all", $clean, @options); 2634 } else { 2635 print STDERR "This platform is not supported by chromium.\n"; 2636 } 2637 return $result; 2638 } 2639 2640 sub appleApplicationSupportPath 2641 { 2642 open INSTALL_DIR, "</proc/registry/HKEY_LOCAL_MACHINE/SOFTWARE/Apple\ Inc./Apple\ Application\ Support/InstallDir"; 2643 my $path = <INSTALL_DIR>; 2644 $path =~ s/[\r\n\x00].*//; 2645 close INSTALL_DIR; 2646 2647 my $unixPath = `cygpath -u '$path'`; 2648 chomp $unixPath; 2649 return $unixPath; 2650 } 2651 2652 sub setPathForRunningWebKitApp 2653 { 2654 my ($env) = @_; 2655 2656 if (isAppleWinWebKit()) { 2657 $env->{PATH} = join(':', productDir(), dirname(installedSafariPath()), appleApplicationSupportPath(), $env->{PATH} || ""); 2658 } elsif (isQt()) { 2659 my $qtLibs = `$qmakebin -query QT_INSTALL_LIBS`; 2660 $qtLibs =~ s/[\n|\r]$//g; 2661 $env->{PATH} = join(';', $qtLibs, productDir() . "/lib", $env->{PATH} || ""); 2662 } 2663 } 2664 2665 sub printHelpAndExitForRunAndDebugWebKitAppIfNeeded 2666 { 2667 return unless checkForArgumentAndRemoveFromARGV("--help"); 2668 2669 my ($includeOptionsForDebugging) = @_; 2670 2671 print STDERR <<EOF; 2672 Usage: @{[basename($0)]} [options] [args ...] 2673 --help Show this help message 2674 --no-saved-state Launch the application without state restoration (OS X 10.7 and later) 2675 --guard-malloc Enable Guard Malloc (OS X only) 2676 --use-web-process-xpc-service Launch the Web Process as an XPC Service (OS X only) 2677 EOF 2678 2679 if ($includeOptionsForDebugging) { 2680 print STDERR <<EOF; 2681 --target-web-process Debug the web process 2682 --use-gdb Use GDB (this is the default when using Xcode 4.4 or earlier) 2683 --use-lldb Use LLDB (this is the default when using Xcode 4.5 or later) 2684 EOF 2685 } 2686 2687 exit(1); 2688 } 2689 2690 sub argumentsForRunAndDebugMacWebKitApp() 2691 { 2692 my @args = (); 2693 push @args, ("-ApplePersistenceIgnoreState", "YES") if !isSnowLeopard() && checkForArgumentAndRemoveFromArrayRef("--no-saved-state", \@args); 2694 push @args, ("-WebKit2UseXPCServiceForWebProcess", "YES") if shouldUseXPCServiceForWebProcess(); 2695 unshift @args, @ARGV; 2696 2697 return @args; 2698 } 2699 2700 sub runMacWebKitApp($;$) 2701 { 2702 my ($appPath, $useOpenCommand) = @_; 2703 my $productDir = productDir(); 2704 print "Starting @{[basename($appPath)]} with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n"; 2705 $ENV{DYLD_FRAMEWORK_PATH} = $productDir; 2706 $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES"; 2707 2708 setUpGuardMallocIfNeeded(); 2709 2710 if (defined($useOpenCommand) && $useOpenCommand == USE_OPEN_COMMAND) { 2711 return system("open", "-W", "-a", $appPath, "--args", argumentsForRunAndDebugMacWebKitApp()); 2712 } 2713 if (architecture()) { 2714 return system "arch", "-" . architecture(), $appPath, argumentsForRunAndDebugMacWebKitApp(); 2715 } 2716 return system { $appPath } $appPath, argumentsForRunAndDebugMacWebKitApp(); 2717 } 2718 2719 sub execMacWebKitAppForDebugging($) 2720 { 2721 my ($appPath) = @_; 2722 my $architectureSwitch; 2723 my $argumentsSeparator; 2724 2725 if (debugger() eq "lldb") { 2726 $architectureSwitch = "--arch"; 2727 $argumentsSeparator = "--"; 2728 } elsif (debugger() eq "gdb") { 2729 $architectureSwitch = "-arch"; 2730 $argumentsSeparator = "--args"; 2731 } else { 2732 die "Unknown debugger $debugger.\n"; 2733 } 2734 2735 my $debuggerPath = `xcrun -find $debugger`; 2736 chomp $debuggerPath; 2737 die "Can't find the $debugger executable.\n" unless -x $debuggerPath; 2738 2739 my $productDir = productDir(); 2740 $ENV{DYLD_FRAMEWORK_PATH} = $productDir; 2741 $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES"; 2742 2743 setUpGuardMallocIfNeeded(); 2744 2745 my @architectureFlags = ($architectureSwitch, architecture()); 2746 if (!shouldTargetWebProcess()) { 2747 print "Starting @{[basename($appPath)]} under $debugger with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n"; 2748 exec { $debuggerPath } $debuggerPath, @architectureFlags, $argumentsSeparator, $appPath, argumentsForRunAndDebugMacWebKitApp() or die; 2749 } else { 2750 if (shouldUseXPCServiceForWebProcess()) { 2751 die "Targetting the Web Process is not compatible with using an XPC Service for the Web Process at this time."; 2752 } 2753 2754 my $webProcessShimPath = File::Spec->catfile($productDir, "SecItemShim.dylib"); 2755 my $webProcessPath = File::Spec->catdir($productDir, "WebProcess.app"); 2756 my $webKit2ExecutablePath = File::Spec->catfile($productDir, "WebKit2.framework", "WebKit2"); 2757 2758 appendToEnvironmentVariableList("DYLD_INSERT_LIBRARIES", $webProcessShimPath); 2759 2760 print "Starting WebProcess under $debugger with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n"; 2761 exec { $debuggerPath } $debuggerPath, @architectureFlags, $argumentsSeparator, $webProcessPath, $webKit2ExecutablePath, "-type", "webprocess", "-client-executable", $appPath or die; 2762 } 2763 } 2764 2765 sub debugSafari 2766 { 2767 if (isAppleMacWebKit()) { 2768 checkFrameworks(); 2769 execMacWebKitAppForDebugging(safariPath()); 2770 } 2771 2772 if (isAppleWinWebKit()) { 2773 setupCygwinEnv(); 2774 my $productDir = productDir(); 2775 chomp($ENV{WEBKITNIGHTLY} = `cygpath -wa "$productDir"`); 2776 my $safariPath = safariPath(); 2777 chomp($safariPath = `cygpath -wa "$safariPath"`); 2778 return system { $vcBuildPath } $vcBuildPath, "/debugexe", "\"$safariPath\"", @ARGV; 2779 } 2780 2781 return 1; # Unsupported platform; can't debug Safari on this platform. 2782 } 2783 2784 sub runSafari 2785 { 2786 2787 if (isAppleMacWebKit()) { 2788 return runMacWebKitApp(safariPath()); 2789 } 2790 2791 if (isAppleWinWebKit()) { 2792 my $result; 2793 my $productDir = productDir(); 2794 my $webKitLauncherPath = File::Spec->catfile(productDir(), "WebKit.exe"); 2795 return system { $webKitLauncherPath } $webKitLauncherPath, @ARGV; 2796 } 2797 2798 return 1; # Unsupported platform; can't run Safari on this platform. 2799 } 2800 2801 sub runMiniBrowser 2802 { 2803 if (isAppleMacWebKit()) { 2804 return runMacWebKitApp(File::Spec->catfile(productDir(), "MiniBrowser.app", "Contents", "MacOS", "MiniBrowser")); 2805 } 2806 2807 return 1; 2808 } 2809 2810 sub debugMiniBrowser 2811 { 2812 if (isAppleMacWebKit()) { 2813 execMacWebKitAppForDebugging(File::Spec->catfile(productDir(), "MiniBrowser.app", "Contents", "MacOS", "MiniBrowser")); 2814 } 2815 2816 return 1; 2817 } 2818 2819 sub runWebKitTestRunner 2820 { 2821 if (isAppleMacWebKit()) { 2822 return runMacWebKitApp(File::Spec->catfile(productDir(), "WebKitTestRunner")); 2823 } elsif (isGtk()) { 2824 my $productDir = productDir(); 2825 my $injectedBundlePath = "$productDir/Libraries/.libs/libTestRunnerInjectedBundle"; 2826 print "Starting WebKitTestRunner with TEST_RUNNER_INJECTED_BUNDLE_FILENAME set to point to $injectedBundlePath.\n"; 2827 $ENV{TEST_RUNNER_INJECTED_BUNDLE_FILENAME} = $injectedBundlePath; 2828 my @args = ("$productDir/Programs/WebKitTestRunner", @ARGV); 2829 return system {$args[0] } @args; 2830 } 2831 2832 return 1; 2833 } 2834 2835 sub debugWebKitTestRunner 2836 { 2837 if (isAppleMacWebKit()) { 2838 execMacWebKitAppForDebugging(File::Spec->catfile(productDir(), "WebKitTestRunner")); 2839 } 2840 2841 return 1; 2842 } 2843 2844 sub readRegistryString 2845 { 2846 my ($valueName) = @_; 2847 chomp(my $string = `regtool --wow32 get "$valueName"`); 2848 return $string; 2849 } 2850 2851 sub writeRegistryString 2852 { 2853 my ($valueName, $string) = @_; 2854 2855 my $error = system "regtool", "--wow32", "set", "-s", $valueName, $string; 2856 2857 # On Windows Vista/7 with UAC enabled, regtool will fail to modify the registry, but will still 2858 # return a successful exit code. So we double-check here that the value we tried to write to the 2859 # registry was really written. 2860 return !$error && readRegistryString($valueName) eq $string; 2861 } 2862 2863 1; 2864